@@ -5630,6 +5701,7 @@ public:
virtual std::string message() const = 0;
virtual char const* what() const = 0;
virtual int category() const = 0;
+ virtual bool discardable() const;
virtual std::auto_ptr<alert> clone() const = 0;
};
@@ -5658,6 +5730,9 @@ switch (a->type())
not include any information that might be bundled with the alert.
benchmarking
-
There are a bunch of built-in instrumentation of libtorrent that can be used to get an insight
+
There is a bunch of built-in instrumentation of libtorrent that can be used to get an insight
into what it's doing and how well it performs. This instrumentation is enabled by defining
preprocessor symbols when building.
There are also a number of scripts that parses the log files and generates graphs (requires
diff --git a/docs/tuning.rst b/docs/tuning.rst
index 4936befae..35fb56dc9 100644
--- a/docs/tuning.rst
+++ b/docs/tuning.rst
@@ -343,10 +343,41 @@ torrent limits
To seed thousands of torrents, you need to increase the ``session_settings::active_limit``
and ``session_settings::active_seeds``.
+scalability
+===========
+
+In order to make more efficient use of the libtorrent interface when running a large
+number of torrents simultaneously, one can use the ``session::get_torrent_status()`` call
+together with ``session::refresh_torrent_status()``. Keep in mind that every call into
+libtorrent that return some value have to block your thread while posting a message to
+the main network thread and then wait for a response (calls that don't return any data
+will simply post the message and then immediately return). The time this takes might
+become significant once you reach a few hundred torrents (depending on how many calls
+you make to each torrent and how often). ``get_torrent_status`` lets you query the
+status of all torrents in a single call. This will actually loop through all torrents
+and run a provided predicate function to determine whether or not to include it in
+the returned vector. If you have a lot of torrents, you might want to update the status
+of only certain torrents. For instance, you might only be interested in torrents that
+are being downloaded.
+
+The intended use of these functions is to start off by calling ``get_torrent_status``
+to get a list of all torrents that match your criteria. Then call ``refresh_torrent_status``
+on that list. This will only refresh the status for the torrents in your list, and thus
+ignore all other torrents you might be running. This may save a significant amount of
+time, especially if the number of torrents you're interested in is small. In order to
+keep your list of interested torrents up to date, you can either call ``get_torrent_status``
+from time to time, to include torrents you might have become interested in since the last
+time. In order to stop refreshing a certain torrent, simply remove it from the list.
+
+A more efficient way however, would be to subscribe to status alert notifications, and
+update your list based on these alerts. There are alerts for when torrents are added, removed,
+paused, resumed, completed etc. Doing this ensures that you only query status for the
+minimal set of torrents you are actually interested in.
+
benchmarking
============
-There are a bunch of built-in instrumentation of libtorrent that can be used to get an insight
+There is a bunch of built-in instrumentation of libtorrent that can be used to get an insight
into what it's doing and how well it performs. This instrumentation is enabled by defining
preprocessor symbols when building.
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 284bfe04c..bfb84edde 100644
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -185,11 +185,15 @@ bool print_fails = false;
bool print_send_bufs = true;
enum {
- torrents_all = 0,
- torrents_downloading = 1,
- torrents_not_paused = 2,
- torrents_seeding = 3,
- torrents_paused = 4
+ torrents_all,
+ torrents_downloading,
+ torrents_not_paused,
+ torrents_seeding,
+ torrents_queued,
+ torrents_stopped,
+ torrents_checking,
+
+ torrents_max
};
int torrent_filter = torrents_not_paused;
@@ -201,13 +205,13 @@ struct torrent_entry
libtorrent::torrent_status status;
};
-typedef std::multimap handles_t;
+// maps filenames to torrent_handles
+typedef std::multimap handles_t;
-bool show_torrent(torrent_entry const& te)
+using libtorrent::torrent_status;
+
+bool show_torrent(libtorrent::torrent_status const& st, int torrent_filter)
{
- using libtorrent::torrent_status;
- torrent_status const& st = te.status;
-
switch (torrent_filter)
{
case torrents_all: return true;
@@ -220,11 +224,33 @@ bool show_torrent(torrent_entry const& te)
return !st.paused
&& (st.state == torrent_status::seeding
|| st.state == torrent_status::finished);
- case torrents_paused: return st.paused;
+ case torrents_queued: return st.paused && st.auto_managed;
+ case torrents_stopped: return st.paused && !st.auto_managed;
+ case torrents_checking: return st.state == torrent_status::checking_files
+ || st.state == torrent_status::queued_for_checking;
}
return true;
}
+bool yes(libtorrent::torrent_status const&)
+{ return true; }
+
+bool compare_torrent(torrent_status const& lhs, torrent_status const& rhs)
+{
+ if (lhs.queue_position != -1 && rhs.queue_position != -1)
+ {
+ // both are downloading, sort by queue pos
+ return lhs.queue_position < rhs.queue_position;
+ }
+ else if (lhs.queue_position == -1 && rhs.queue_position == -1)
+ {
+ // both are seeding, sort by seed-rank
+ return lhs.seed_rank > rhs.seed_rank;
+ }
+
+ return (lhs.queue_position == -1) < (rhs.queue_position == -1);
+}
+
FILE* g_log_file = 0;
int active_torrent = 0;
@@ -627,8 +653,11 @@ void add_torrent(libtorrent::session& ses
return;
}
- handles.insert(std::pair(
- monitored_dir?std::string(torrent):std::string(), h));
+ if (monitored_dir)
+ {
+ handles.insert(std::pair(
+ torrent, h));
+ }
h.set_max_connections(max_connections_per_torrent);
h.set_max_uploads(-1);
@@ -643,7 +672,7 @@ void add_torrent(libtorrent::session& ses
void scan_dir(std::string const& dir_path
, libtorrent::session& ses
- , handles_t& handles
+ , handles_t& files
, float preferred_ratio
, int allocation_mode
, std::string const& save_path
@@ -660,8 +689,8 @@ void scan_dir(std::string const& dir_path
std::string file = combine_path(dir_path, i.file());
if (extension(file) != ".torrent") continue;
- handles_t::iterator k = handles.find(file);
- if (k != handles.end())
+ handles_t::iterator k = files.find(file);
+ if (k != files.end())
{
valid.insert(file);
continue;
@@ -669,14 +698,14 @@ void scan_dir(std::string const& dir_path
// the file has been added to the dir, start
// downloading it.
- add_torrent(ses, handles, file, preferred_ratio, allocation_mode
+ add_torrent(ses, files, file, preferred_ratio, allocation_mode
, save_path, true, torrent_upload_limit, torrent_download_limit);
valid.insert(file);
}
// remove the torrents that are no longer in the directory
- for (handles_t::iterator i = handles.begin(); !handles.empty() && i != handles.end();)
+ for (handles_t::iterator i = files.begin(); !files.empty() && i != files.end();)
{
if (i->first.empty() || valid.find(i->first) != valid.end())
{
@@ -684,10 +713,10 @@ void scan_dir(std::string const& dir_path
continue;
}
- torrent_handle& h = i->second.handle;
+ torrent_handle& h = i->second;
if (!h.is_valid())
{
- handles.erase(i++);
+ files.erase(i++);
continue;
}
@@ -697,17 +726,17 @@ void scan_dir(std::string const& dir_path
// will save it to disk
if (h.need_save_resume_data()) h.save_resume_data();
- handles.erase(i++);
+ files.erase(i++);
}
}
-torrent_entry& get_active_torrent(handles_t const& handles)
+torrent_status const& get_active_torrent(std::vector const& torrents)
{
- if (active_torrent >= handles.size()
+ if (active_torrent >= torrents.size()
|| active_torrent < 0) active_torrent = 0;
- handles_t::const_iterator i = handles.begin();
+ std::vector::const_iterator i = torrents.begin();
std::advance(i, active_torrent);
- return const_cast(i->second);
+ return *i;
}
void print_alert(libtorrent::alert const* a, std::string& str)
@@ -752,7 +781,7 @@ int save_file(std::string const& filename, std::vector& v)
}
void handle_alert(libtorrent::session& ses, libtorrent::alert* a
- , handles_t const& handles)
+ , handles_t const& files)
{
using namespace libtorrent;
@@ -775,16 +804,16 @@ void handle_alert(libtorrent::session& ses, libtorrent::alert* a
std::vector out;
bencode(std::back_inserter(out), *p->resume_data);
save_file(combine_path(h.save_path(), ".resume/" + h.name() + ".resume"), out);
- if (std::find_if(handles.begin(), handles.end()
- , boost::bind(&torrent_entry::handle, boost::bind(&handles_t::value_type::second, _1)) == h) == handles.end())
+ if (std::find_if(files.begin(), files.end()
+ , boost::bind(&handles_t::value_type::second, _1) == h) == files.end())
ses.remove_torrent(h);
}
}
else if (save_resume_data_failed_alert* p = alert_cast(a))
{
torrent_handle h = p->handle;
- if (std::find_if(handles.begin(), handles.end()
- , boost::bind(&torrent_entry::handle, boost::bind(&handles_t::value_type::second, _1)) == h) == handles.end())
+ if (std::find_if(files.begin(), files.end()
+ , boost::bind(&handles_t::value_type::second, _1) == h) == files.end())
ses.remove_torrent(h);
}
}
@@ -880,7 +909,9 @@ int main(int argc, char* argv[])
// it was added through the directory monitor. It is used to
// be able to remove torrents that were added via the directory
// monitor when they're not in the directory anymore.
- handles_t handles;
+ std::vector handles;
+ handles_t files;
+
session ses(fingerprint("LT", LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
, session::add_default_plugins
, alert::all_categories
@@ -1107,8 +1138,6 @@ int main(int argc, char* argv[])
continue;
}
- handles.insert(std::pair(std::string(), h));
-
h.set_max_connections(max_connections_per_torrent);
h.set_max_uploads(-1);
h.set_ratio(preferred_ratio);
@@ -1139,8 +1168,6 @@ int main(int argc, char* argv[])
continue;
}
- handles.insert(std::pair(std::string(), h));
-
h.set_max_connections(max_connections_per_torrent);
h.set_max_uploads(-1);
h.set_ratio(preferred_ratio);
@@ -1151,7 +1178,7 @@ int main(int argc, char* argv[])
}
// if it's a torrent file, open it as usual
- add_torrent(ses, handles, i->c_str(), preferred_ratio
+ add_torrent(ses, files, i->c_str(), preferred_ratio
, allocation_mode, save_path, false
, torrent_upload_limit, torrent_download_limit);
}
@@ -1162,6 +1189,13 @@ int main(int argc, char* argv[])
while (loop_limit > 1 || loop_limit == 0)
{
+
+ handles.clear();
+ ses.get_torrent_status(&handles, boost::bind(&show_torrent, _1, torrent_filter));
+ if (active_torrent >= handles.size()) active_torrent = handles.size() - 1;
+
+ std::sort(handles.begin(), handles.end(), &compare_torrent);
+
if (loop_limit > 1) --loop_limit;
char c = 0;
while (sleep_and_input(&c, refresh_delay))
@@ -1183,30 +1217,38 @@ int main(int argc, char* argv[])
if (c == 68)
{
// arrow left
- if (torrent_filter > 0) --torrent_filter;
+ if (torrent_filter > 0)
+ {
+ --torrent_filter;
+ handles.clear();
+ ses.get_torrent_status(&handles, boost::bind(&show_torrent, _1, torrent_filter));
+ if (active_torrent >= handles.size()) active_torrent = handles.size() - 1;
+ std::sort(handles.begin(), handles.end(), &compare_torrent);
+ }
}
else if (c == 67)
{
// arrow right
- if (torrent_filter < torrents_paused) ++torrent_filter;
+ if (torrent_filter < torrents_max - 1)
+ {
+ ++torrent_filter;
+ handles.clear();
+ ses.get_torrent_status(&handles, boost::bind(&show_torrent, _1, torrent_filter));
+ if (active_torrent >= handles.size()) active_torrent = handles.size() - 1;
+ std::sort(handles.begin(), handles.end(), &compare_torrent);
+ }
}
else if (c == 65)
{
// arrow up
- int prev = active_torrent;
--active_torrent;
- while (active_torrent > 0 && !show_torrent(get_active_torrent(handles)))
- --active_torrent;
- if (active_torrent < 0) active_torrent = prev;
+ if (active_torrent < 0) active_torrent = 0;
}
else if (c == 66)
{
// arrow down
- int prev = active_torrent;
++active_torrent;
- while (active_torrent < handles.size() && !show_torrent(get_active_torrent(handles)))
- ++active_torrent;
- if (active_torrent >= handles.size()) active_torrent = prev;
+ if (active_torrent >= handles.size()) active_torrent = handles.size() - 1;
}
}
@@ -1221,11 +1263,12 @@ int main(int argc, char* argv[])
printf("saving peers for torrents\n");
std::vector peers;
- for (handles_t::iterator i = handles.begin();
- i != handles.end(); ++i)
+ std::vector torrents = ses.get_torrents();
+ for (std::vector::iterator i = torrents.begin();
+ i != torrents.end(); ++i)
{
- i->second.handle.get_full_peer_list(peers);
- FILE* f = fopen(("peers_" + i->second.handle.name()).c_str(), "w+");
+ i->get_full_peer_list(peers);
+ FILE* f = fopen(("peers_" + i->name()).c_str(), "w+");
if (!f) break;
for (std::vector::iterator k = peers.begin()
, end(peers.end()); k != end; ++k)
@@ -1255,59 +1298,59 @@ int main(int argc, char* argv[])
if (c == 's' && !handles.empty())
{
- torrent_entry& te = get_active_torrent(handles);
- te.handle.set_sequential_download(!te.status.sequential_download);
+ torrent_status const& ts = get_active_torrent(handles);
+ ts.handle.set_sequential_download(!ts.sequential_download);
}
if (c == 'R')
{
// save resume data for all torrents
- for (handles_t::iterator i = handles.begin()
+ for (std::vector::iterator i = handles.begin()
, end(handles.end()); i != end; ++i)
{
- if (i->second.status.need_save_resume)
- i->second.handle.save_resume_data();
+ if (i->need_save_resume)
+ i->handle.save_resume_data();
}
}
if (c == 'o' && !handles.empty())
{
- torrent_entry& te = get_active_torrent(handles);
- int num_pieces = te.handle.get_torrent_info().num_pieces();
+ torrent_status const& ts = get_active_torrent(handles);
+ int num_pieces = ts.num_pieces;
if (num_pieces > 300) num_pieces = 300;
for (int i = 0; i < num_pieces; ++i)
{
- te.handle.set_piece_deadline(i, (i+5) * 1000, torrent_handle::alert_when_available);
+ ts.handle.set_piece_deadline(i, (i+5) * 1000, torrent_handle::alert_when_available);
}
}
if (c == 'v' && !handles.empty())
{
- torrent_entry& te = get_active_torrent(handles);
- te.handle.scrape_tracker();
+ torrent_status const& ts = get_active_torrent(handles);
+ ts.handle.scrape_tracker();
}
if (c == 'p' && !handles.empty())
{
- torrent_entry& te = get_active_torrent(handles);
- if (!te.status.auto_managed && te.status.paused)
+ torrent_status const& ts = get_active_torrent(handles);
+ if (!ts.auto_managed && ts.paused)
{
- te.handle.auto_managed(true);
+ ts.handle.auto_managed(true);
}
else
{
- te.handle.auto_managed(false);
- te.handle.pause(torrent_handle::graceful_pause);
+ ts.handle.auto_managed(false);
+ ts.handle.pause(torrent_handle::graceful_pause);
}
// the alert handler for save_resume_data_alert
// will save it to disk
- if (te.status.need_save_resume) te.handle.save_resume_data();
+ if (ts.need_save_resume) ts.handle.save_resume_data();
}
if (c == 'c' && !handles.empty())
{
- torrent_entry& te = get_active_torrent(handles);
- te.handle.clear_error();
+ torrent_status const& ts = get_active_torrent(handles);
+ ts.handle.clear_error();
}
// toggle displays
@@ -1332,15 +1375,19 @@ int main(int argc, char* argv[])
if (c == 'q') break;
int terminal_width = 80;
+ int terminal_height = 50;
#ifndef _WIN32
{
winsize size;
ioctl(STDOUT_FILENO, TIOCGWINSZ, (char*)&size);
terminal_width = size.ws_col;
+ terminal_height = size.ws_row;
if (terminal_width < 64)
terminal_width = 64;
+ if (terminal_height < 25)
+ terminal_height = 25;
}
#endif
@@ -1353,7 +1400,7 @@ int main(int argc, char* argv[])
std::string event_string;
::print_alert(a.get(), event_string);
- ::handle_alert(ses, a.get(), handles);
+ ::handle_alert(ses, a.get(), files);
events.push_back(event_string);
if (events.size() >= 20) events.pop_front();
@@ -1370,7 +1417,7 @@ int main(int argc, char* argv[])
"[1] toggle IP [2] toggle AS [3] toggle timers [4] toggle block progress "
"[5] toggle peer rate [6] toggle failures [7] toggle send buffers [R] save resume data\n";
- char const* filter_names[] = { "all", "downloading", "non-paused", "seeding", "paused"};
+ char const* filter_names[] = { "all", "downloading", "non-paused", "seeding", "queued", "stopped", "checking"};
for (int i = 0; i < sizeof(filter_names)/sizeof(filter_names[0]); ++i)
{
out += '[';
@@ -1383,12 +1430,18 @@ int main(int argc, char* argv[])
char str[500];
int torrent_index = 0;
- torrent_handle active_handle;
- for (handles_t::iterator i = handles.begin();
+ int lines_printed = 3;
+ for (std::vector::iterator i = handles.begin();
i != handles.end(); ++torrent_index)
{
- torrent_entry& te = i->second;
- if (!te.handle.is_valid())
+ if (lines_printed >= terminal_height - 15)
+ {
+ out += "...\n";
+ break;
+ }
+
+ torrent_status& s = *i;
+ if (!s.handle.is_valid())
{
handles.erase(i++);
continue;
@@ -1398,12 +1451,6 @@ int main(int argc, char* argv[])
++i;
}
- te.status = te.handle.status();
- torrent_status const& s = te.status;
-
- if (!show_torrent(te))
- continue;
-
#ifdef ANSI_TERMINAL_COLORS
char const* term = "\x1b[0m";
#else
@@ -1420,7 +1467,7 @@ int main(int argc, char* argv[])
out += " ";
}
- int queue_pos = te.status.queue_position;
+ int queue_pos = s.queue_position;
if (queue_pos == -1) out += "- ";
else
{
@@ -1431,7 +1478,7 @@ int main(int argc, char* argv[])
if (s.paused) out += esc("34");
else out += esc("37");
- std::string name = te.handle.name();
+ std::string name = s.handle.name();
if (name.size() > 40) name.resize(40);
snprintf(str, sizeof(str), "%-40s %s ", name.c_str(), term);
out += str;
@@ -1443,6 +1490,7 @@ int main(int argc, char* argv[])
out += s.error;
out += esc("0");
out += "\n";
+ ++lines_printed;
continue;
}
@@ -1467,8 +1515,9 @@ int main(int argc, char* argv[])
, s.up_bandwidth_queue, s.down_bandwidth_queue
, esc("32"), add_suffix(s.all_time_download).c_str(), term
, esc("31"), add_suffix(s.all_time_upload).c_str(), term
- , s.seed_rank, te.status.need_save_resume?'S':' ', esc("0"));
+ , s.seed_rank, s.need_save_resume?'S':' ', esc("0"));
out += str;
+ ++lines_printed;
if (torrent_index != active_torrent && s.state == torrent_status::seeding) continue;
char const* progress_bar_color = "33"; // yellow
@@ -1499,12 +1548,14 @@ int main(int argc, char* argv[])
, progress_bar(s.progress_ppm / 1000, terminal_width - 43 - 20, "35").c_str());
out += str;
}
+ ++lines_printed;
if (print_piece_bar && s.state != torrent_status::seeding)
{
out += " ";
out += piece_bar(s.pieces, terminal_width - 7);
out += "\n";
+ ++lines_printed;
}
if (s.state != torrent_status::queued_for_checking && s.state != torrent_status::checking_files)
@@ -1523,10 +1574,8 @@ int main(int argc, char* argv[])
, esc("37"), t.hours(), t.minutes(), t.seconds(), esc("0")
, esc("36"), s.current_tracker.c_str(), esc("0"));
out += str;
+ ++lines_printed;
}
-
- if (torrent_index != active_torrent) continue;
- active_handle = te.handle;
}
cache_status cs = ses.get_cache_status();
@@ -1624,10 +1673,12 @@ int main(int argc, char* argv[])
out += str;
}
- if (active_handle.is_valid())
+ torrent_status const* st = 0;
+ if (!handles.empty()) st = &get_active_torrent(handles);
+ if (st && st->handle.is_valid())
{
- torrent_handle h = active_handle;
- torrent_status s = h.status();
+ torrent_handle h = st->handle;
+ torrent_status const& s = *st;
if ((print_downloads && s.state != torrent_status::seeding)
|| print_peers)
@@ -1804,7 +1855,7 @@ int main(int argc, char* argv[])
if (!monitor_dir.empty()
&& next_dir_scan < time_now())
{
- scan_dir(monitor_dir, ses, handles, preferred_ratio
+ scan_dir(monitor_dir, ses, files, preferred_ratio
, allocation_mode, save_path, torrent_upload_limit
, torrent_download_limit);
next_dir_scan = time_now() + seconds(poll_interval);
@@ -1819,17 +1870,18 @@ int main(int argc, char* argv[])
ses.pause();
printf("saving resume data\n");
- for (handles_t::iterator i = handles.begin();
- i != handles.end(); ++i)
+ std::vector temp;
+ ses.get_torrent_status(&temp, &yes, 0);
+ for (std::vector::iterator i = temp.begin();
+ i != temp.end(); ++i)
{
- torrent_entry& te = i->second;
- if (!te.handle.is_valid()) continue;
- te.status = te.handle.status();
- if (te.status.paused) continue;
- if (!te.status.has_metadata) continue;
+ torrent_status& st = *i;
+ if (!st.handle.is_valid()) continue;
+ if (st.paused) continue;
+ if (!st.has_metadata) continue;
// save_resume_data will generate an alert when it's done
- te.handle.save_resume_data();
+ st.handle.save_resume_data();
++num_resume_data;
printf("\r%d ", num_resume_data);
}
diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp
index 3f5dde957..c3197cb3a 100644
--- a/include/libtorrent/aux_/session_impl.hpp
+++ b/include/libtorrent/aux_/session_impl.hpp
@@ -274,7 +274,13 @@ namespace libtorrent
void remove_torrent(torrent_handle const& h, int options);
- std::vector get_torrents();
+ void get_torrent_status(std::vector* ret
+ , boost::function const& pred
+ , boost::uint32_t flags) const;
+ void refresh_torrent_status(std::vector* ret
+ , boost::uint32_t flags) const;
+
+ std::vector get_torrents() const;
void queue_check_torrent(boost::shared_ptr const& t);
void dequeue_check_torrent(boost::shared_ptr const& t);
diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp
index 752432c15..759cd9036 100644
--- a/include/libtorrent/session.hpp
+++ b/include/libtorrent/session.hpp
@@ -176,6 +176,12 @@ namespace libtorrent
void save_state(entry& e, boost::uint32_t flags = 0xffffffff) const;
void load_state(lazy_entry const& e);
+ void get_torrent_status(std::vector* ret
+ , boost::function const& pred
+ , boost::uint32_t flags = 0) const;
+ void refresh_torrent_status(std::vector* ret
+ , boost::uint32_t flags = 0) const;
+
// returns a list of all torrents in this session
std::vector get_torrents() const;
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index 269ef5eb1..9b06102a2 100644
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -300,7 +300,7 @@ namespace libtorrent
void set_piece_deadline(int piece, int t, int flags);
void update_piece_priorities();
- torrent_status status(boost::uint32_t flags) const;
+ void status(torrent_status* st, boost::uint32_t flags);
void file_progress(std::vector& fp, int flags = 0) const;
diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp
index 63fbc7af3..7bf483e30 100644
--- a/include/libtorrent/torrent_handle.hpp
+++ b/include/libtorrent/torrent_handle.hpp
@@ -69,6 +69,7 @@ namespace libtorrent
struct torrent_plugin;
struct peer_info;
struct peer_list_entry;
+ struct torrent_status;
#ifndef BOOST_NO_EXCEPTIONS
// for compatibility with 0.14
@@ -77,273 +78,6 @@ namespace libtorrent
void throw_invalid_handle();
#endif
- struct TORRENT_EXPORT torrent_status
- {
- torrent_status()
- : state(checking_resume_data)
- , paused(false)
- , auto_managed(false)
- , sequential_download(false)
- , is_seeding(false)
- , is_finished(false)
- , has_metadata(false)
- , progress(0.f)
- , progress_ppm(0)
- , total_download(0)
- , total_upload(0)
- , total_payload_download(0)
- , total_payload_upload(0)
- , total_failed_bytes(0)
- , total_redundant_bytes(0)
- , download_rate(0)
- , upload_rate(0)
- , download_payload_rate(0)
- , upload_payload_rate(0)
- , num_seeds(0)
- , num_peers(0)
- , num_complete(-1)
- , num_incomplete(-1)
- , list_seeds(0)
- , list_peers(0)
- , num_pieces(0)
- , total_done(0)
- , total_wanted_done(0)
- , total_wanted(0)
- , distributed_copies(0.f)
- , block_size(0)
- , num_uploads(0)
- , num_connections(0)
- , uploads_limit(0)
- , connections_limit(0)
- , storage_mode(storage_mode_sparse)
- , up_bandwidth_queue(0)
- , down_bandwidth_queue(0)
- , all_time_upload(0)
- , all_time_download(0)
- , active_time(0)
- , finished_time(0)
- , seeding_time(0)
- , seed_rank(0)
- , last_scrape(0)
- , has_incoming(false)
- , sparse_regions(0)
- , seed_mode(false)
- , upload_mode(false)
- , share_mode(false)
- , priority(0)
- , added_time(0)
- , completed_time(0)
- , last_seen_complete(0)
- , time_since_upload(0)
- , time_since_download(0)
- , queue_position(0)
- {}
-
- enum state_t
- {
- queued_for_checking,
- checking_files,
- downloading_metadata,
- downloading,
- finished,
- seeding,
- allocating,
- checking_resume_data
- };
-
- state_t state;
- bool paused;
- bool auto_managed;
- bool sequential_download;
- bool is_seeding;
- bool is_finished;
- bool has_metadata;
-
- float progress;
- // progress parts per million (progress * 1000000)
- // when disabling floating point operations, this is
- // the only option to query progress
- int progress_ppm;
- std::string error;
-
- boost::posix_time::time_duration next_announce;
- boost::posix_time::time_duration announce_interval;
-
- std::string current_tracker;
-
- // transferred this session!
- // total, payload plus protocol
- size_type total_download;
- size_type total_upload;
-
- // payload only
- size_type total_payload_download;
- size_type total_payload_upload;
-
- // the amount of payload bytes that
- // has failed their hash test
- size_type total_failed_bytes;
-
- // the number of payload bytes that
- // has been received redundantly.
- size_type total_redundant_bytes;
-
- // current transfer rate
- // payload plus protocol
- int download_rate;
- int upload_rate;
-
- // the rate of payload that is
- // sent and received
- int download_payload_rate;
- int upload_payload_rate;
-
- // the number of peers this torrent is connected to
- // that are seeding.
- int num_seeds;
-
- // the number of peers this torrent
- // is connected to (including seeds).
- int num_peers;
-
- // if the tracker sends scrape info in its
- // announce reply, these fields will be
- // set to the total number of peers that
- // have the whole file and the total number
- // of peers that are still downloading
- int num_complete;
- int num_incomplete;
-
- // this is the number of seeds whose IP we know
- // but are not necessarily connected to
- int list_seeds;
-
- // this is the number of peers whose IP we know
- // (including seeds), but are not necessarily
- // connected to
- int list_peers;
-
- // the number of peers in our peerlist that
- // we potentially could connect to
- int connect_candidates;
-
- bitfield pieces;
-
- // this is the number of pieces the client has
- // downloaded. it is equal to:
- // std::accumulate(pieces->begin(), pieces->end());
- int num_pieces;
-
- // the number of bytes of the file we have
- // including pieces that may have been filtered
- // after we downloaded them
- size_type total_done;
-
- // the number of bytes we have of those that we
- // want. i.e. not counting bytes from pieces that
- // are filtered as not wanted.
- size_type total_wanted_done;
-
- // the total number of bytes we want to download
- // this may be smaller than the total torrent size
- // in case any pieces are filtered as not wanted
- size_type total_wanted;
-
- // the number of distributed copies of the file.
- // note that one copy may be spread out among many peers.
- //
- // the integer part tells how many copies
- // there are of the rarest piece(s)
- //
- // the fractional part tells the fraction of pieces that
- // have more copies than the rarest piece(s).
-
- // the number of full distributed copies (i.e. the number
- // of peers that have the rarest piece)
- int distributed_full_copies;
-
- // the fraction of pieces that more peers has than the
- // rarest pieces. This indicates how close the swarm is
- // to have one more full distributed copy
- int distributed_fraction;
-
- float distributed_copies;
-
- // the block size that is used in this torrent. i.e.
- // the number of bytes each piece request asks for
- // and each bit in the download queue bitfield represents
- int block_size;
-
- int num_uploads;
- int num_connections;
- int uploads_limit;
- int connections_limit;
-
- // true if the torrent is saved in compact mode
- // false if it is saved in full allocation mode
- storage_mode_t storage_mode;
-
- int up_bandwidth_queue;
- int down_bandwidth_queue;
-
- // number of bytes downloaded since torrent was started
- // saved and restored from resume data
- size_type all_time_upload;
- size_type all_time_download;
-
- // the number of seconds of being active
- // and as being a seed, saved and restored
- // from resume data
- int active_time;
- int finished_time;
- int seeding_time;
-
- // higher value means more important to seed
- int seed_rank;
-
- // number of seconds since last scrape, or -1 if
- // there hasn't been a scrape
- int last_scrape;
-
- // true if there are incoming connections to this
- // torrent
- bool has_incoming;
-
- // the number of "holes" in the torrent
- int sparse_regions;
-
- // is true if this torrent is (still) in seed_mode
- bool seed_mode;
-
- // this is set to true when the torrent is blocked
- // from downloading, typically caused by a file
- // write operation failing
- bool upload_mode;
-
- // this is true if the torrent is in share-mode
- bool share_mode;
-
- // the priority of this torrent
- int priority;
-
- // the time this torrent was added and completed
- time_t added_time;
- time_t completed_time;
- time_t last_seen_complete;
-
- // number of seconds since last upload or download activity
- int time_since_upload;
- int time_since_download;
-
- // the position in the download queue where this torrent is
- // this is -1 for seeds and finished torrents
- int queue_position;
-
- // true if this torrent has had changes since the last
- // time resume data was saved
- bool need_save_resume;
- };
-
struct TORRENT_EXPORT block_info
{
enum block_state_t
@@ -677,6 +411,275 @@ namespace libtorrent
};
+ struct TORRENT_EXPORT torrent_status
+ {
+ torrent_status()
+ : state(checking_resume_data)
+ , paused(false)
+ , auto_managed(false)
+ , sequential_download(false)
+ , is_seeding(false)
+ , is_finished(false)
+ , has_metadata(false)
+ , progress(0.f)
+ , progress_ppm(0)
+ , total_download(0)
+ , total_upload(0)
+ , total_payload_download(0)
+ , total_payload_upload(0)
+ , total_failed_bytes(0)
+ , total_redundant_bytes(0)
+ , download_rate(0)
+ , upload_rate(0)
+ , download_payload_rate(0)
+ , upload_payload_rate(0)
+ , num_seeds(0)
+ , num_peers(0)
+ , num_complete(-1)
+ , num_incomplete(-1)
+ , list_seeds(0)
+ , list_peers(0)
+ , num_pieces(0)
+ , total_done(0)
+ , total_wanted_done(0)
+ , total_wanted(0)
+ , distributed_copies(0.f)
+ , block_size(0)
+ , num_uploads(0)
+ , num_connections(0)
+ , uploads_limit(0)
+ , connections_limit(0)
+ , storage_mode(storage_mode_sparse)
+ , up_bandwidth_queue(0)
+ , down_bandwidth_queue(0)
+ , all_time_upload(0)
+ , all_time_download(0)
+ , active_time(0)
+ , finished_time(0)
+ , seeding_time(0)
+ , seed_rank(0)
+ , last_scrape(0)
+ , has_incoming(false)
+ , sparse_regions(0)
+ , seed_mode(false)
+ , upload_mode(false)
+ , share_mode(false)
+ , priority(0)
+ , added_time(0)
+ , completed_time(0)
+ , last_seen_complete(0)
+ , time_since_upload(0)
+ , time_since_download(0)
+ , queue_position(0)
+ {}
+
+ // handle to the torrent
+ torrent_handle handle;
+
+ enum state_t
+ {
+ queued_for_checking,
+ checking_files,
+ downloading_metadata,
+ downloading,
+ finished,
+ seeding,
+ allocating,
+ checking_resume_data
+ };
+
+ state_t state;
+ bool paused;
+ bool auto_managed;
+ bool sequential_download;
+ bool is_seeding;
+ bool is_finished;
+ bool has_metadata;
+
+ float progress;
+ // progress parts per million (progress * 1000000)
+ // when disabling floating point operations, this is
+ // the only option to query progress
+ int progress_ppm;
+ std::string error;
+
+ boost::posix_time::time_duration next_announce;
+ boost::posix_time::time_duration announce_interval;
+
+ std::string current_tracker;
+
+ // transferred this session!
+ // total, payload plus protocol
+ size_type total_download;
+ size_type total_upload;
+
+ // payload only
+ size_type total_payload_download;
+ size_type total_payload_upload;
+
+ // the amount of payload bytes that
+ // has failed their hash test
+ size_type total_failed_bytes;
+
+ // the number of payload bytes that
+ // has been received redundantly.
+ size_type total_redundant_bytes;
+
+ // current transfer rate
+ // payload plus protocol
+ int download_rate;
+ int upload_rate;
+
+ // the rate of payload that is
+ // sent and received
+ int download_payload_rate;
+ int upload_payload_rate;
+
+ // the number of peers this torrent is connected to
+ // that are seeding.
+ int num_seeds;
+
+ // the number of peers this torrent
+ // is connected to (including seeds).
+ int num_peers;
+
+ // if the tracker sends scrape info in its
+ // announce reply, these fields will be
+ // set to the total number of peers that
+ // have the whole file and the total number
+ // of peers that are still downloading
+ int num_complete;
+ int num_incomplete;
+
+ // this is the number of seeds whose IP we know
+ // but are not necessarily connected to
+ int list_seeds;
+
+ // this is the number of peers whose IP we know
+ // (including seeds), but are not necessarily
+ // connected to
+ int list_peers;
+
+ // the number of peers in our peerlist that
+ // we potentially could connect to
+ int connect_candidates;
+
+ bitfield pieces;
+
+ // this is the number of pieces the client has
+ // downloaded. it is equal to:
+ // std::accumulate(pieces->begin(), pieces->end());
+ int num_pieces;
+
+ // the number of bytes of the file we have
+ // including pieces that may have been filtered
+ // after we downloaded them
+ size_type total_done;
+
+ // the number of bytes we have of those that we
+ // want. i.e. not counting bytes from pieces that
+ // are filtered as not wanted.
+ size_type total_wanted_done;
+
+ // the total number of bytes we want to download
+ // this may be smaller than the total torrent size
+ // in case any pieces are filtered as not wanted
+ size_type total_wanted;
+
+ // the number of distributed copies of the file.
+ // note that one copy may be spread out among many peers.
+ //
+ // the integer part tells how many copies
+ // there are of the rarest piece(s)
+ //
+ // the fractional part tells the fraction of pieces that
+ // have more copies than the rarest piece(s).
+
+ // the number of full distributed copies (i.e. the number
+ // of peers that have the rarest piece)
+ int distributed_full_copies;
+
+ // the fraction of pieces that more peers has than the
+ // rarest pieces. This indicates how close the swarm is
+ // to have one more full distributed copy
+ int distributed_fraction;
+
+ float distributed_copies;
+
+ // the block size that is used in this torrent. i.e.
+ // the number of bytes each piece request asks for
+ // and each bit in the download queue bitfield represents
+ int block_size;
+
+ int num_uploads;
+ int num_connections;
+ int uploads_limit;
+ int connections_limit;
+
+ // true if the torrent is saved in compact mode
+ // false if it is saved in full allocation mode
+ storage_mode_t storage_mode;
+
+ int up_bandwidth_queue;
+ int down_bandwidth_queue;
+
+ // number of bytes downloaded since torrent was started
+ // saved and restored from resume data
+ size_type all_time_upload;
+ size_type all_time_download;
+
+ // the number of seconds of being active
+ // and as being a seed, saved and restored
+ // from resume data
+ int active_time;
+ int finished_time;
+ int seeding_time;
+
+ // higher value means more important to seed
+ int seed_rank;
+
+ // number of seconds since last scrape, or -1 if
+ // there hasn't been a scrape
+ int last_scrape;
+
+ // true if there are incoming connections to this
+ // torrent
+ bool has_incoming;
+
+ // the number of "holes" in the torrent
+ int sparse_regions;
+
+ // is true if this torrent is (still) in seed_mode
+ bool seed_mode;
+
+ // this is set to true when the torrent is blocked
+ // from downloading, typically caused by a file
+ // write operation failing
+ bool upload_mode;
+
+ // this is true if the torrent is in share-mode
+ bool share_mode;
+
+ // the priority of this torrent
+ int priority;
+
+ // the time this torrent was added and completed
+ time_t added_time;
+ time_t completed_time;
+ time_t last_seen_complete;
+
+ // number of seconds since last upload or download activity
+ int time_since_upload;
+ int time_since_download;
+
+ // the position in the download queue where this torrent is
+ // this is -1 for seeds and finished torrents
+ int queue_position;
+
+ // true if this torrent has had changes since the last
+ // time resume data was saved
+ bool need_save_resume;
+ };
}
diff --git a/src/session.cpp b/src/session.cpp
index 6820347ad..9af0160db 100644
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -300,6 +300,12 @@ namespace libtorrent
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function(boost::bind(&session_impl:: x, m_impl.get(), a1, a2)))); \
do { m_impl->cond.wait(l); } while(!done)
+#define TORRENT_SYNC_CALL3(x, a1, a2, a3) \
+ bool done = false; \
+ mutex::scoped_lock l(m_impl->mut); \
+ m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3)))); \
+ do { m_impl->cond.wait(l); } while(!done)
+
#define TORRENT_SYNC_CALL_RET(type, x) \
bool done = false; \
type r; \
@@ -509,6 +515,19 @@ namespace libtorrent
TORRENT_ASYNC_CALL1(set_key, key);
}
+ void session::get_torrent_status(std::vector* ret
+ , boost::function const& pred
+ , boost::uint32_t flags) const
+ {
+ TORRENT_SYNC_CALL3(get_torrent_status, ret, boost::ref(pred), flags);
+ }
+
+ void session::refresh_torrent_status(std::vector* ret
+ , boost::uint32_t flags) const
+ {
+ TORRENT_SYNC_CALL2(refresh_torrent_status, ret, flags);
+ }
+
std::vector session::get_torrents() const
{
TORRENT_SYNC_CALL_RET(std::vector, get_torrents);
diff --git a/src/session_impl.cpp b/src/session_impl.cpp
index b0f4619cc..c1ed1ad36 100644
--- a/src/session_impl.cpp
+++ b/src/session_impl.cpp
@@ -3592,11 +3592,39 @@ namespace aux {
}
#endif
- std::vector session_impl::get_torrents()
+ void session_impl::get_torrent_status(std::vector* ret
+ , boost::function const& pred
+ , boost::uint32_t flags) const
+ {
+ for (session_impl::torrent_map::const_iterator i
+ = m_torrents.begin(), end(m_torrents.end());
+ i != end; ++i)
+ {
+ if (i->second->is_aborted()) continue;
+ torrent_status st;
+ i->second->status(&st, flags);
+ if (!pred(st)) continue;
+ ret->push_back(st);
+ }
+ }
+
+ void session_impl::refresh_torrent_status(std::vector* ret
+ , boost::uint32_t flags) const
+ {
+ for (std::vector::iterator i
+ = ret->begin(), end(ret->end()); i != end; ++i)
+ {
+ boost::shared_ptr t = i->handle.m_torrent.lock();
+ if (!t) continue;
+ t->status(&*i, flags);
+ }
+ }
+
+ std::vector session_impl::get_torrents() const
{
std::vector ret;
- for (session_impl::torrent_map::iterator i
+ for (session_impl::torrent_map::const_iterator i
= m_torrents.begin(), end(m_torrents.end());
i != end; ++i)
{
diff --git a/src/torrent.cpp b/src/torrent.cpp
index 663624324..cb21a194e 100644
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -7139,96 +7139,96 @@ namespace libtorrent
#endif
}
- torrent_status torrent::status(boost::uint32_t flags) const
+ void torrent::status(torrent_status* st, boost::uint32_t flags)
{
INVARIANT_CHECK;
ptime now = time_now();
- torrent_status st;
+ st->handle = get_handle();
- st.has_incoming = m_has_incoming;
- if (m_error) st.error = m_error.message() + ": " + m_error_file;
- st.seed_mode = m_seed_mode;
+ st->has_incoming = m_has_incoming;
+ if (m_error) st->error = m_error.message() + ": " + m_error_file;
+ st->seed_mode = m_seed_mode;
- st.added_time = m_added_time;
- st.completed_time = m_completed_time;
+ st->added_time = m_added_time;
+ st->completed_time = m_completed_time;
- st.last_scrape = m_last_scrape;
- st.share_mode = m_share_mode;
- st.upload_mode = m_upload_mode;
- st.up_bandwidth_queue = 0;
- st.down_bandwidth_queue = 0;
- st.priority = m_priority;
+ st->last_scrape = m_last_scrape;
+ st->share_mode = m_share_mode;
+ st->upload_mode = m_upload_mode;
+ st->up_bandwidth_queue = 0;
+ st->down_bandwidth_queue = 0;
+ st->priority = m_priority;
- st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
+ st->num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
, !boost::bind(&peer_connection::is_connecting, _1));
- st.list_peers = m_policy.num_peers();
- st.list_seeds = m_policy.num_seeds();
- st.connect_candidates = m_policy.num_connect_candidates();
- st.seed_rank = seed_rank(settings());
+ st->list_peers = m_policy.num_peers();
+ st->list_seeds = m_policy.num_seeds();
+ st->connect_candidates = m_policy.num_connect_candidates();
+ st->seed_rank = seed_rank(settings());
- st.all_time_upload = m_total_uploaded;
- st.all_time_download = m_total_downloaded;
+ st->all_time_upload = m_total_uploaded;
+ st->all_time_download = m_total_downloaded;
// activity time
- st.active_time = m_active_time;
- st.active_time = m_active_time;
- st.seeding_time = m_seeding_time;
- st.time_since_upload = m_last_upload;
- st.time_since_download = m_last_download;
+ st->active_time = m_active_time;
+ st->active_time = m_active_time;
+ st->seeding_time = m_seeding_time;
+ st->time_since_upload = m_last_upload;
+ st->time_since_download = m_last_download;
- st.storage_mode = (storage_mode_t)m_storage_mode;
+ st->storage_mode = (storage_mode_t)m_storage_mode;
- st.num_complete = (m_complete == 0xffffff) ? -1 : m_complete;
- st.num_incomplete = (m_incomplete == 0xffffff) ? -1 : m_incomplete;
- st.paused = is_torrent_paused();
- st.auto_managed = m_auto_managed;
- st.sequential_download = m_sequential_download;
- st.is_seeding = is_seed();
- st.is_finished = is_finished();
- st.has_metadata = valid_metadata();
- bytes_done(st, flags & torrent_handle::query_accurate_download_counters);
- TORRENT_ASSERT(st.total_wanted_done >= 0);
- TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
+ st->num_complete = (m_complete == 0xffffff) ? -1 : m_complete;
+ st->num_incomplete = (m_incomplete == 0xffffff) ? -1 : m_incomplete;
+ st->paused = is_torrent_paused();
+ st->auto_managed = m_auto_managed;
+ st->sequential_download = m_sequential_download;
+ st->is_seeding = is_seed();
+ st->is_finished = is_finished();
+ st->has_metadata = valid_metadata();
+ bytes_done(*st, flags & torrent_handle::query_accurate_download_counters);
+ TORRENT_ASSERT(st->total_wanted_done >= 0);
+ TORRENT_ASSERT(st->total_done >= st->total_wanted_done);
// payload transfer
- st.total_payload_download = m_stat.total_payload_download();
- st.total_payload_upload = m_stat.total_payload_upload();
+ st->total_payload_download = m_stat.total_payload_download();
+ st->total_payload_upload = m_stat.total_payload_upload();
// total transfer
- st.total_download = m_stat.total_payload_download()
+ st->total_download = m_stat.total_payload_download()
+ m_stat.total_protocol_download();
- st.total_upload = m_stat.total_payload_upload()
+ st->total_upload = m_stat.total_payload_upload()
+ m_stat.total_protocol_upload();
// failed bytes
- st.total_failed_bytes = m_total_failed_bytes;
- st.total_redundant_bytes = m_total_redundant_bytes;
+ st->total_failed_bytes = m_total_failed_bytes;
+ st->total_redundant_bytes = m_total_redundant_bytes;
// transfer rate
- st.download_rate = m_stat.download_rate();
- st.upload_rate = m_stat.upload_rate();
- st.download_payload_rate = m_stat.download_payload_rate();
- st.upload_payload_rate = m_stat.upload_payload_rate();
+ st->download_rate = m_stat.download_rate();
+ st->upload_rate = m_stat.upload_rate();
+ st->download_payload_rate = m_stat.download_payload_rate();
+ st->upload_payload_rate = m_stat.upload_payload_rate();
if (m_waiting_tracker && !is_paused())
- st.next_announce = boost::posix_time::seconds(
+ st->next_announce = boost::posix_time::seconds(
total_seconds(next_announce() - now));
else
- st.next_announce = boost::posix_time::seconds(0);
+ st->next_announce = boost::posix_time::seconds(0);
- if (st.next_announce.is_negative())
- st.next_announce = boost::posix_time::seconds(0);
+ if (st->next_announce.is_negative())
+ st->next_announce = boost::posix_time::seconds(0);
- st.announce_interval = boost::posix_time::seconds(0);
+ st->announce_interval = boost::posix_time::seconds(0);
- st.current_tracker.clear();
+ st->current_tracker.clear();
if (m_last_working_tracker >= 0)
{
TORRENT_ASSERT(m_last_working_tracker < int(m_trackers.size()));
- st.current_tracker = m_trackers[m_last_working_tracker].url;
+ st->current_tracker = m_trackers[m_last_working_tracker].url;
}
else
{
@@ -7236,82 +7236,82 @@ namespace libtorrent
for (i = m_trackers.begin(); i != m_trackers.end(); ++i)
{
if (!i->updating) continue;
- st.current_tracker = i->url;
+ st->current_tracker = i->url;
break;
}
}
- st.num_uploads = m_num_uploads;
- st.uploads_limit = m_max_uploads;
- st.num_connections = int(m_connections.size());
- st.connections_limit = m_max_connections;
+ st->num_uploads = m_num_uploads;
+ st->uploads_limit = m_max_uploads;
+ st->num_connections = int(m_connections.size());
+ st->connections_limit = m_max_connections;
// if we don't have any metadata, stop here
- st.queue_position = queue_position();
- st.need_save_resume = need_save_resume_data();
+ st->queue_position = queue_position();
+ st->need_save_resume = need_save_resume_data();
- st.state = (torrent_status::state_t)m_state;
+ st->state = (torrent_status::state_t)m_state;
if (!valid_metadata())
{
- st.state = torrent_status::downloading_metadata;
- st.progress_ppm = m_progress_ppm;
+ st->state = torrent_status::downloading_metadata;
+ st->progress_ppm = m_progress_ppm;
#if !TORRENT_NO_FPU
- st.progress = m_progress_ppm / 1000000.f;
+ st->progress = m_progress_ppm / 1000000.f;
#endif
- st.block_size = 0;
- return st;
+ st->block_size = 0;
+ return;
}
- st.block_size = block_size();
+ st->block_size = block_size();
if (m_state == torrent_status::checking_files)
{
- st.progress_ppm = m_progress_ppm;
+ st->progress_ppm = m_progress_ppm;
#if !TORRENT_NO_FPU
- st.progress = m_progress_ppm / 1000000.f;
+ st->progress = m_progress_ppm / 1000000.f;
#endif
}
- else if (st.total_wanted == 0)
+ else if (st->total_wanted == 0)
{
- st.progress_ppm = 1000000;
- st.progress = 1.f;
+ st->progress_ppm = 1000000;
+ st->progress = 1.f;
}
else
{
- st.progress_ppm = st.total_wanted_done * 1000000
- / st.total_wanted;
+ st->progress_ppm = st->total_wanted_done * 1000000
+ / st->total_wanted;
#if !TORRENT_NO_FPU
- st.progress = st.progress_ppm / 1000000.f;
+ st->progress = st->progress_ppm / 1000000.f;
#endif
}
if (has_picker())
{
- st.sparse_regions = m_picker->sparse_regions();
+ st->sparse_regions = m_picker->sparse_regions();
int num_pieces = m_picker->num_pieces();
- st.pieces.resize(num_pieces, false);
+ st->pieces.resize(num_pieces, false);
for (int i = 0; i < num_pieces; ++i)
- if (m_picker->have_piece(i)) st.pieces.set_bit(i);
+ if (m_picker->have_piece(i)) st->pieces.set_bit(i);
}
- st.num_pieces = num_have();
- st.num_seeds = num_seeds();
+ st->num_pieces = num_have();
+ st->num_seeds = num_seeds();
if ((flags & torrent_handle::query_distributed_copies) && m_picker.get())
{
- boost::tie(st.distributed_full_copies, st.distributed_fraction) =
+ boost::tie(st->distributed_full_copies, st->distributed_fraction) =
m_picker->distributed_copies();
#if TORRENT_NO_FPU
- st.distributed_copies = -1.f;
+ st->distributed_copies = -1.f;
#else
- st.distributed_copies = st.distributed_full_copies
- + float(st.distributed_fraction) / 1000;
+ st->distributed_copies = st->distributed_full_copies
+ + float(st->distributed_fraction) / 1000;
#endif
}
else
{
- st.distributed_full_copies = -1;
- st.distributed_fraction = -1;
- st.distributed_copies = -1.f;
+ st->distributed_full_copies = -1;
+ st->distributed_fraction = -1;
+ st->distributed_copies = -1.f;
}
if (flags & torrent_handle::query_last_seen_complete)
@@ -7322,13 +7322,12 @@ namespace libtorrent
{
last = (std::max)(last, (*i)->last_seen_complete());
}
- st.last_seen_complete = last;
+ st->last_seen_complete = last;
}
else
{
- st.last_seen_complete = 0;
+ st->last_seen_complete = 0;
}
- return st;
}
void torrent::add_redundant_bytes(int b)
diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp
index a4c81361c..c7d7e53a2 100644
--- a/src/torrent_handle.cpp
+++ b/src/torrent_handle.cpp
@@ -469,8 +469,9 @@ namespace libtorrent
torrent_status torrent_handle::status(boost::uint32_t flags) const
{
INVARIANT_CHECK;
- TORRENT_SYNC_CALL_RET1(torrent_status, torrent_status(), status, flags);
- return r;
+ torrent_status st;
+ TORRENT_SYNC_CALL2(status, &st, flags);
+ return st;
}
void torrent_handle::set_sequential_download(bool sd) const