From 01405f32ee6b153a46c364585798495172ead322 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 12 Oct 2011 10:27:17 +0000 Subject: [PATCH] added async_add_torrent for increased performance when adding many torrents (no documentation yet though) --- examples/client_test.cpp | 50 +++++++++++++++++------- include/libtorrent/alert_types.hpp | 17 ++++++++ include/libtorrent/aux_/session_impl.hpp | 1 + include/libtorrent/file_storage.hpp | 1 + include/libtorrent/session.hpp | 1 + src/alert.cpp | 14 +++++++ src/file_storage.cpp | 5 +++ src/session.cpp | 9 +++++ src/session_impl.cpp | 11 ++++++ src/torrent.cpp | 10 +++-- 10 files changed, 100 insertions(+), 19 deletions(-) diff --git a/examples/client_test.cpp b/examples/client_test.cpp index fe580286a..337bf3e5d 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -661,7 +661,7 @@ using boost::bind; // is, it should be remembered so that it can be removed // if it's no longer in that directory. void add_torrent(libtorrent::session& ses - , handles_t& handles + , handles_t& files , std::set& non_files , std::string const& torrent , float preferred_ratio @@ -702,22 +702,16 @@ void add_torrent(libtorrent::session& ses p.paused = true; p.duplicate_is_error = false; p.auto_managed = true; - torrent_handle h = ses.add_torrent(p, ec); - if (ec) + if (monitored_dir) { - fprintf(stderr, "failed to add torrent: %s\n", ec.message().c_str()); + p.userdata = (void*)strdup(torrent.c_str()); + ses.async_add_torrent(p); return; } - if (monitored_dir) - { - handles.insert(std::pair( - torrent, h)); - } - else - { - non_files.insert(h); - } + torrent_handle h = ses.add_torrent(p, ec); + + non_files.insert(h); h.set_max_connections(max_connections_per_torrent); h.set_max_uploads(-1); @@ -846,7 +840,7 @@ int save_file(std::string const& filename, std::vector& v) } void handle_alert(libtorrent::session& ses, libtorrent::alert* a - , handles_t const& files, std::set const& non_files) + , handles_t& files, std::set const& non_files) { using namespace libtorrent; @@ -884,7 +878,33 @@ void handle_alert(libtorrent::session& ses, libtorrent::alert* a } #endif - if (torrent_finished_alert* p = alert_cast(a)) + if (add_torrent_alert* p = alert_cast(a)) + { + std::string filename = (char*)p->params.userdata; + free(p->params.userdata); + + if (p->error) + { + fprintf(stderr, "failed to add torrent: %s %s\n", filename.c_str(), p->error.message().c_str()); + } + else + { + torrent_handle h = p->handle; + + files.insert(std::pair(filename, h)); + + h.set_max_connections(max_connections_per_torrent); + h.set_max_uploads(-1); + h.set_ratio(preferred_ratio); + h.set_upload_limit(torrent_upload_limit); + h.set_download_limit(torrent_download_limit); + h.use_interface(outgoing_interface.c_str()); +#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + h.resolve_countries(true); +#endif + } + } + else if (torrent_finished_alert* p = alert_cast(a)) { p->handle.set_max_connections(max_connections_per_torrent / 2); diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 8b3ffdfd9..ab4aaaffc 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -1294,6 +1294,23 @@ namespace libtorrent tcp::endpoint ip; }; + struct TORRENT_EXPORT add_torrent_alert : torrent_alert + { + add_torrent_alert(torrent_handle h, add_torrent_params const& p, error_code ec) + : torrent_alert(h) + , params(p) + , error(ec) + {} + + TORRENT_DEFINE_ALERT(add_torrent_alert); + + const static int static_category = alert::status_notification; + virtual std::string message() const; + virtual bool discardable() const { return false; } + + add_torrent_params params; + error_code error; + }; } diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 956f6404b..7021d371c 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -310,6 +310,7 @@ namespace libtorrent bool is_listening() const; torrent_handle add_torrent(add_torrent_params const&, error_code& ec); + void async_add_torrent(add_torrent_params* params); void remove_torrent(torrent_handle const& h, int options); void remove_torrent_impl(boost::shared_ptr tptr, int options); diff --git a/include/libtorrent/file_storage.hpp b/include/libtorrent/file_storage.hpp index b7b4a6a4f..d3f348a84 100644 --- a/include/libtorrent/file_storage.hpp +++ b/include/libtorrent/file_storage.hpp @@ -250,6 +250,7 @@ namespace libtorrent size_type file_base(internal_file_entry const& fe) const; void set_file_base(internal_file_entry const& fe, size_type off); std::string file_path(internal_file_entry const& fe) const; + size_type file_size(internal_file_entry const& fe) const; #if !defined TORRENT_VERBOSE_LOGGING \ && !defined TORRENT_LOGGING \ diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 3a71bb11c..17201b298 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -198,6 +198,7 @@ namespace libtorrent torrent_handle add_torrent(add_torrent_params const& params); #endif torrent_handle add_torrent(add_torrent_params const& params, error_code& ec); + void async_add_torrent(add_torrent_params const& params); #ifndef BOOST_NO_EXCEPTIONS #ifndef TORRENT_NO_DEPRECATE diff --git a/src/alert.cpp b/src/alert.cpp index 2e6984c83..6b31de3df 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -587,5 +587,19 @@ namespace libtorrent { return msg; } + std::string add_torrent_alert::message() const + { + char msg[600]; + if (error) + { + snprintf(msg, sizeof(msg), "failed to add torrent: %s", error.message().c_str()); + } + else + { + snprintf(msg, sizeof(msg), "added torrent: %s", !params.url.empty() ? params.url.c_str() : params.ti->name().c_str()); + } + return msg; + } + } // namespace libtorrent diff --git a/src/file_storage.cpp b/src/file_storage.cpp index 49c8148fc..1fd4c39a2 100644 --- a/src/file_storage.cpp +++ b/src/file_storage.cpp @@ -275,6 +275,11 @@ namespace libtorrent return combine_path(m_paths[fe.path_index], fe.filename()); } + size_type file_storage::file_size(internal_file_entry const& fe) const + { + return fe.size; + } + peer_request file_storage::map_file(int file_index, size_type file_offset , int size) const { diff --git a/src/session.cpp b/src/session.cpp index a54309ec2..d3429c8ea 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -610,6 +610,15 @@ namespace libtorrent return r; } + void session::async_add_torrent(add_torrent_params const& params) + { + add_torrent_params* p = new add_torrent_params(params); + if (params.resume_data) p->resume_data = new std::vector(*params.resume_data); + if (params.tracker_url) p->tracker_url = strdup(params.tracker_url); + if (params.name) p->name = strdup(params.name); + TORRENT_ASYNC_CALL1(async_add_torrent, p); + } + #ifndef BOOST_NO_EXCEPTIONS #ifndef TORRENT_NO_DEPRECATE // if the torrent already exists, this will throw duplicate_torrent diff --git a/src/session_impl.cpp b/src/session_impl.cpp index cc4fc2b0d..c3e4c0d59 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -4251,6 +4251,17 @@ namespace aux { return torrent_handle(find_torrent(info_hash)); } + void session_impl::async_add_torrent(add_torrent_params* params) + { + error_code ec; + torrent_handle handle = add_torrent(*params, ec); + m_alerts.post_alert(add_torrent_alert(handle, *params, ec)); + delete params->resume_data; + free((char*)params->tracker_url); + free((char*)params->name); + delete params; + } + torrent_handle session_impl::add_torrent(add_torrent_params const& params , error_code& ec) { diff --git a/src/torrent.cpp b/src/torrent.cpp index cd3cb5e16..d3c059cc6 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3936,13 +3936,15 @@ ctx->set_verify_callback(verify_function, ec); // initialize the piece priorities to 0, then only allow // setting higher priorities std::vector pieces(m_torrent_file->num_pieces(), 0); - for (int i = 0; i < int(m_file_priority.size()); ++i) + int index = 0; + for (file_storage::iterator i = m_torrent_file->files().begin() + , end(m_torrent_file->files().end()); i != end; ++i, ++index) { size_type start = position; - size_type size = m_torrent_file->files().at(i).size; + size_type size = m_torrent_file->files().file_size(*i); if (size == 0) continue; position += size; - if (m_file_priority[i] == 0) continue; + if (m_file_priority[index] == 0) continue; // mark all pieces of the file with this file's priority // but only if the priority is higher than the pieces @@ -3954,7 +3956,7 @@ ctx->set_verify_callback(verify_function, ec); // come here several times with the same start_piece, end_piece std::for_each(pieces.begin() + start_piece , pieces.begin() + last_piece + 1 - , boost::bind(&set_if_greater, _1, m_file_priority[i])); + , boost::bind(&set_if_greater, _1, m_file_priority[index])); } prioritize_pieces(pieces); }