introduced pop_alerts() which pops the entire alert queue in a single call
This commit is contained in:
parent
a18f047311
commit
27c1bc632d
|
@ -1,3 +1,4 @@
|
||||||
|
* introduced pop_alerts() which pops the entire alert queue in a single call
|
||||||
* support saving metadata in resume file, enable it by default for magnet links
|
* support saving metadata in resume file, enable it by default for magnet links
|
||||||
* support for receiving multi announce messages for local peer discovery
|
* support for receiving multi announce messages for local peer discovery
|
||||||
* added session::listen_no_system_port flag to prevent libtorrent from ever binding the listen socket to port 0
|
* added session::listen_no_system_port flag to prevent libtorrent from ever binding the listen socket to port 0
|
||||||
|
|
|
@ -1013,18 +1013,36 @@ Changes the mask of which alerts to receive. By default only errors are reported
|
||||||
|
|
||||||
See alerts_ for mor information on the alert categories.
|
See alerts_ for mor information on the alert categories.
|
||||||
|
|
||||||
pop_alert() wait_for_alert()
|
pop_alerts() pop_alert() wait_for_alert()
|
||||||
----------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
std::auto_ptr<alert> pop_alert();
|
std::auto_ptr<alert> pop_alert();
|
||||||
|
void pop_alerts(std::deque<alert*>* alerts);
|
||||||
alert const* wait_for_alert(time_duration max_wait);
|
alert const* wait_for_alert(time_duration max_wait);
|
||||||
|
|
||||||
``pop_alert()`` is used to ask the session if any errors or events has occurred. With
|
``pop_alert()`` is used to ask the session if any errors or events has occurred. With
|
||||||
`set_alert_mask()`_ you can filter which alerts to receive through ``pop_alert()``.
|
`set_alert_mask()`_ you can filter which alerts to receive through ``pop_alert()``.
|
||||||
For information about the alert categories, see alerts_.
|
For information about the alert categories, see alerts_.
|
||||||
|
|
||||||
|
``pop_alerts()`` pops all pending alerts in a single call. In high performance environments
|
||||||
|
with a very high alert churn rate, this can save significant amount of time compared to
|
||||||
|
popping alerts one at a time. Each call requires one round-trip to the network thread. If
|
||||||
|
alerts are produced in a higher rate than they can be popped (when popped one at a time)
|
||||||
|
it's easy to get stuck in an infinite loop, trying to drain the alert queue. Popping the entire
|
||||||
|
queue at once avoids this problem.
|
||||||
|
|
||||||
|
However, the ``pop_alerts`` function comes with significantly more responsibility. You pass
|
||||||
|
in an *empty* ``std::dequeue<alert*>`` to it. If it's not empty, all elements in it will
|
||||||
|
be deleted and then cleared. All currently pending alerts are returned by being swapped
|
||||||
|
into the passed in container. The responsibility of deleting the alerts is transferred
|
||||||
|
to the caller. This means you need to call delete for each item in the returned dequeue.
|
||||||
|
It's probably a good idea to delete the alerts as you handle them, to save one extra
|
||||||
|
pass over the dequeue.
|
||||||
|
|
||||||
|
Alternatively, you can pass in the same container the next time you call ``pop_alerts``.
|
||||||
|
|
||||||
``wait_for_alert`` blocks until an alert is available, or for no more than ``max_wait``
|
``wait_for_alert`` blocks until an alert is available, or for no more than ``max_wait``
|
||||||
time. If ``wait_for_alert`` returns because of the time-out, and no alerts are available,
|
time. If ``wait_for_alert`` returns because of the time-out, and no alerts are available,
|
||||||
it returns 0. If at least one alert was generated, a pointer to that alert is returned.
|
it returns 0. If at least one alert was generated, a pointer to that alert is returned.
|
||||||
|
|
|
@ -1468,21 +1468,22 @@ int main(int argc, char* argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// loop through the alert queue to see if anything has happened.
|
// loop through the alert queue to see if anything has happened.
|
||||||
std::auto_ptr<alert> a;
|
std::deque<alert*> alerts;
|
||||||
a = ses.pop_alert();
|
ses.pop_alerts(&alerts);
|
||||||
std::string now = time_now_string();
|
std::string now = time_now_string();
|
||||||
while (a.get())
|
for (std::deque<alert*>::iterator i = alerts.begin()
|
||||||
|
, end(alerts.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
std::string event_string;
|
std::string event_string;
|
||||||
|
|
||||||
::print_alert(a.get(), event_string);
|
::print_alert(*i, event_string);
|
||||||
::handle_alert(ses, a.get(), files, non_files);
|
::handle_alert(ses, *i, files, non_files);
|
||||||
|
|
||||||
events.push_back(event_string);
|
events.push_back(event_string);
|
||||||
if (events.size() >= 20) events.pop_front();
|
if (events.size() >= 20) events.pop_front();
|
||||||
|
delete *i;
|
||||||
a = ses.pop_alert();
|
|
||||||
}
|
}
|
||||||
|
alerts.clear();
|
||||||
|
|
||||||
session_status sess_stat = ses.status();
|
session_status sess_stat = ses.status();
|
||||||
|
|
||||||
|
@ -1967,46 +1968,48 @@ int main(int argc, char* argv[])
|
||||||
alert const* a = ses.wait_for_alert(seconds(10));
|
alert const* a = ses.wait_for_alert(seconds(10));
|
||||||
if (a == 0) continue;
|
if (a == 0) continue;
|
||||||
|
|
||||||
std::auto_ptr<alert> holder = ses.pop_alert();
|
std::deque<alert*> alerts;
|
||||||
|
ses.pop_alerts(&alerts);
|
||||||
|
std::string now = time_now_string();
|
||||||
|
for (std::deque<alert*>::iterator i = alerts.begin()
|
||||||
|
, end(alerts.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
// make sure to delete each alert
|
||||||
|
std::auto_ptr<alert> a(*i);
|
||||||
|
|
||||||
torrent_paused_alert const* tp = alert_cast<torrent_paused_alert>(a);
|
torrent_paused_alert const* tp = alert_cast<torrent_paused_alert>(*i);
|
||||||
if (tp)
|
if (tp)
|
||||||
{
|
{
|
||||||
++num_paused;
|
++num_paused;
|
||||||
printf("\rleft: %d failed: %d pause: %d "
|
printf("\rleft: %d failed: %d pause: %d "
|
||||||
, num_resume_data, num_failed, num_paused);
|
, num_resume_data, num_failed, num_paused);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(a);
|
save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(*i);
|
||||||
/* if (!rd)
|
if (alert_cast<save_resume_data_failed_alert>(*i))
|
||||||
{
|
{
|
||||||
std::string log;
|
++num_failed;
|
||||||
::print_alert(a, log);
|
--num_resume_data;
|
||||||
printf("\n%s\n", log.c_str());
|
printf("\rleft: %d failed: %d pause: %d "
|
||||||
}
|
, num_resume_data, num_failed, num_paused);
|
||||||
*/
|
continue;
|
||||||
if (alert_cast<save_resume_data_failed_alert>(a))
|
}
|
||||||
{
|
|
||||||
++num_failed;
|
if (!rd) continue;
|
||||||
--num_resume_data;
|
--num_resume_data;
|
||||||
printf("\rleft: %d failed: %d pause: %d "
|
printf("\rleft: %d failed: %d pause: %d "
|
||||||
, num_resume_data, num_failed, num_paused);
|
, num_resume_data, num_failed, num_paused);
|
||||||
continue;
|
|
||||||
|
if (!rd->resume_data) continue;
|
||||||
|
|
||||||
|
torrent_handle h = rd->handle;
|
||||||
|
std::vector<char> out;
|
||||||
|
bencode(std::back_inserter(out), *rd->resume_data);
|
||||||
|
save_file(combine_path(h.save_path(), ".resume/" + to_hex(h.info_hash().to_string()) + ".resume"), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rd) continue;
|
|
||||||
--num_resume_data;
|
|
||||||
printf("\rleft: %d failed: %d pause: %d "
|
|
||||||
, num_resume_data, num_failed, num_paused);
|
|
||||||
|
|
||||||
if (!rd->resume_data) continue;
|
|
||||||
|
|
||||||
torrent_handle h = rd->handle;
|
|
||||||
std::vector<char> out;
|
|
||||||
bencode(std::back_inserter(out), *rd->resume_data);
|
|
||||||
save_file(combine_path(h.save_path(), ".resume/" + to_hex(h.info_hash().to_string()) + ".resume"), out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_log_file) fclose(g_log_file);
|
if (g_log_file) fclose(g_log_file);
|
||||||
printf("\nsaving session state\n");
|
printf("\nsaving session state\n");
|
||||||
{
|
{
|
||||||
|
|
|
@ -134,6 +134,7 @@ namespace libtorrent {
|
||||||
void post_alert(const alert& alert_);
|
void post_alert(const alert& alert_);
|
||||||
bool pending() const;
|
bool pending() const;
|
||||||
std::auto_ptr<alert> get();
|
std::auto_ptr<alert> get();
|
||||||
|
void get_all(std::deque<alert*>* alerts);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool should_post() const
|
bool should_post() const
|
||||||
|
|
|
@ -285,6 +285,7 @@ namespace libtorrent
|
||||||
void set_alert_mask(int m);
|
void set_alert_mask(int m);
|
||||||
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
|
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
|
||||||
std::auto_ptr<alert> pop_alert();
|
std::auto_ptr<alert> pop_alert();
|
||||||
|
void pop_alerts(std::deque<alert*>* alerts);
|
||||||
void set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const&);
|
void set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const&);
|
||||||
void post_alert(const alert& alert_);
|
void post_alert(const alert& alert_);
|
||||||
|
|
||||||
|
|
|
@ -430,7 +430,20 @@ namespace libtorrent
|
||||||
int max_uploads() const TORRENT_DEPRECATED;
|
int max_uploads() const TORRENT_DEPRECATED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// pop one alert from the alert queue, or do nothing
|
||||||
|
// and return a NULL pointer if there are no alerts
|
||||||
|
// in the queue
|
||||||
std::auto_ptr<alert> pop_alert();
|
std::auto_ptr<alert> pop_alert();
|
||||||
|
|
||||||
|
// pop all alerts in the alert queue and returns them
|
||||||
|
// in the supplied dequeue 'alerts'. The passed in
|
||||||
|
// queue must be empty when passed in.
|
||||||
|
// the responsibility of individual alerts returned
|
||||||
|
// in the dequeue is passed on to the caller of this function.
|
||||||
|
// when you're done with reacting to the alerts, you need to
|
||||||
|
// delete them all.
|
||||||
|
void pop_alerts(std::deque<alert*>* alerts);
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
TORRENT_DEPRECATED_PREFIX
|
TORRENT_DEPRECATED_PREFIX
|
||||||
void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED;
|
void set_severity_level(alert::severity_t s) TORRENT_DEPRECATED;
|
||||||
|
|
|
@ -446,6 +446,13 @@ namespace libtorrent {
|
||||||
return std::auto_ptr<alert>(result);
|
return std::auto_ptr<alert>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void alert_manager::get_all(std::deque<alert*>* alerts)
|
||||||
|
{
|
||||||
|
mutex::scoped_lock lock(m_mutex);
|
||||||
|
if (m_alerts.empty()) return;
|
||||||
|
m_alerts.swap(*alerts);
|
||||||
|
}
|
||||||
|
|
||||||
bool alert_manager::pending() const
|
bool alert_manager::pending() const
|
||||||
{
|
{
|
||||||
mutex::scoped_lock lock(m_mutex);
|
mutex::scoped_lock lock(m_mutex);
|
||||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <deque>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -978,6 +979,15 @@ namespace libtorrent
|
||||||
return m_impl->pop_alert();
|
return m_impl->pop_alert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session::pop_alerts(std::deque<alert*>* alerts)
|
||||||
|
{
|
||||||
|
for (std::deque<alert*>::iterator i = alerts->begin()
|
||||||
|
, end(alerts->end()); i != end; ++i)
|
||||||
|
delete *i;
|
||||||
|
alerts->clear();
|
||||||
|
m_impl->pop_alerts(alerts);
|
||||||
|
}
|
||||||
|
|
||||||
alert const* session::wait_for_alert(time_duration max_wait)
|
alert const* session::wait_for_alert(time_duration max_wait)
|
||||||
{
|
{
|
||||||
return m_impl->wait_for_alert(max_wait);
|
return m_impl->wait_for_alert(max_wait);
|
||||||
|
|
|
@ -4766,12 +4766,14 @@ namespace aux {
|
||||||
|
|
||||||
std::auto_ptr<alert> session_impl::pop_alert()
|
std::auto_ptr<alert> session_impl::pop_alert()
|
||||||
{
|
{
|
||||||
// too expensive
|
|
||||||
// INVARIANT_CHECK;
|
|
||||||
|
|
||||||
return m_alerts.get();
|
return m_alerts.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session_impl::pop_alerts(std::deque<alert*>* alerts)
|
||||||
|
{
|
||||||
|
m_alerts.get_all(alerts);
|
||||||
|
}
|
||||||
|
|
||||||
alert const* session_impl::wait_for_alert(time_duration max_wait)
|
alert const* session_impl::wait_for_alert(time_duration max_wait)
|
||||||
{
|
{
|
||||||
return m_alerts.wait_for_alert(max_wait);
|
return m_alerts.wait_for_alert(max_wait);
|
||||||
|
|
|
@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
#include "libtorrent/session.hpp"
|
#include "libtorrent/session.hpp"
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
|
@ -80,24 +81,24 @@ bool print_alerts(libtorrent::session& ses, char const* name
|
||||||
TEST_CHECK(!handles.empty() || allow_no_torrents);
|
TEST_CHECK(!handles.empty() || allow_no_torrents);
|
||||||
torrent_handle h;
|
torrent_handle h;
|
||||||
if (!handles.empty()) h = handles[0];
|
if (!handles.empty()) h = handles[0];
|
||||||
std::auto_ptr<alert> a;
|
std::deque<alert*> alerts;
|
||||||
a = ses.pop_alert();
|
ses.pop_alerts(&alerts);
|
||||||
while (a.get())
|
for (std::deque<alert*>::iterator i = alerts.begin(); i != alerts.end(); ++i)
|
||||||
{
|
{
|
||||||
if (predicate && predicate(a.get())) ret = true;
|
if (predicate && predicate(*i)) ret = true;
|
||||||
if (peer_disconnected_alert* p = alert_cast<peer_disconnected_alert>(a.get()))
|
if (peer_disconnected_alert* p = alert_cast<peer_disconnected_alert>(*i))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s(%s): %s\n", name, print_endpoint(p->ip).c_str(), p->message().c_str());
|
fprintf(stderr, "%s(%s): %s\n", name, print_endpoint(p->ip).c_str(), p->message().c_str());
|
||||||
}
|
}
|
||||||
else if (a->message() != "block downloading"
|
else if ((*i)->message() != "block downloading"
|
||||||
&& a->message() != "block finished"
|
&& (*i)->message() != "block finished"
|
||||||
&& a->message() != "piece finished")
|
&& (*i)->message() != "piece finished")
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: %s\n", name, a->message().c_str());
|
fprintf(stderr, "%s: %s\n", name, (*i)->message().c_str());
|
||||||
}
|
}
|
||||||
TEST_CHECK(alert_cast<fastresume_rejected_alert>(a.get()) == 0 || allow_failed_fastresume);
|
TEST_CHECK(alert_cast<fastresume_rejected_alert>(*i) == 0 || allow_failed_fastresume);
|
||||||
|
|
||||||
peer_error_alert* pea = alert_cast<peer_error_alert>(a.get());
|
peer_error_alert* pea = alert_cast<peer_error_alert>(*i);
|
||||||
TEST_CHECK(pea == 0
|
TEST_CHECK(pea == 0
|
||||||
|| (!handles.empty() && h.status().is_seeding)
|
|| (!handles.empty() && h.status().is_seeding)
|
||||||
|| pea->error.message() == "connecting to peer"
|
|| pea->error.message() == "connecting to peer"
|
||||||
|
@ -109,7 +110,7 @@ bool print_alerts(libtorrent::session& ses, char const* name
|
||||||
|| (allow_disconnects && pea->error.message() == "Broken pipe")
|
|| (allow_disconnects && pea->error.message() == "Broken pipe")
|
||||||
|| (allow_disconnects && pea->error.message() == "Connection reset by peer")
|
|| (allow_disconnects && pea->error.message() == "Connection reset by peer")
|
||||||
|| (allow_disconnects && pea->error.message() == "End of file."));
|
|| (allow_disconnects && pea->error.message() == "End of file."));
|
||||||
a = ses.pop_alert();
|
delete *i;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue