forked from premiere/premiere-libtorrent
add API to query whether alerts have been dropped or not
This commit is contained in:
parent
254f813626
commit
1c278cc697
|
@ -1,3 +1,4 @@
|
|||
* add API to query whether alerts have been dropped or not
|
||||
* add flags()/set_flags()/unset_flags() to torrent_handle, deprecate individual functions
|
||||
* added alert for block being sent to the send buffer
|
||||
* drop support for windows compilers without std::wstring
|
||||
|
|
|
@ -228,11 +228,11 @@ namespace libtorrent {
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
virtual int type() const = 0;
|
||||
virtual int type() const noexcept = 0;
|
||||
|
||||
// returns a string literal describing the type of the alert. It does
|
||||
// not include any information that might be bundled with the alert.
|
||||
virtual char const* what() const = 0;
|
||||
virtual char const* what() const noexcept = 0;
|
||||
|
||||
// generate a string describing the alert and the information bundled
|
||||
// with it. This is mainly intended for debug and development use. It is not suitable
|
||||
|
@ -242,7 +242,7 @@ namespace libtorrent {
|
|||
virtual std::string message() const = 0;
|
||||
|
||||
// returns a bitmask specifying which categories this alert belong to.
|
||||
virtual alert_category_t category() const = 0;
|
||||
virtual alert_category_t category() const noexcept = 0;
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/alert.hpp"
|
||||
#include "libtorrent/heterogeneous_queue.hpp"
|
||||
#include "libtorrent/stack_allocator.hpp"
|
||||
#include "libtorrent/alert_types.hpp" // for num_alert_types
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
@ -44,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
|
@ -51,6 +53,10 @@ namespace libtorrent {
|
|||
struct plugin;
|
||||
#endif
|
||||
|
||||
// this bitset is used to indicate which alert types have been dropped since
|
||||
// last queried.
|
||||
using dropped_alerts_t = std::bitset<num_alert_types>;
|
||||
|
||||
class TORRENT_EXTRA_EXPORT alert_manager
|
||||
{
|
||||
public:
|
||||
|
@ -58,8 +64,10 @@ namespace libtorrent {
|
|||
, alert_category_t alert_mask = alert::error_notification);
|
||||
~alert_manager();
|
||||
|
||||
dropped_alerts_t dropped_alerts();
|
||||
|
||||
template <class T, typename... Args>
|
||||
void emplace_alert(Args&&... args)
|
||||
void emplace_alert(Args&&... args) try
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
|
@ -69,12 +77,8 @@ namespace libtorrent {
|
|||
if (m_alerts[m_generation].size() >= m_queue_size_limit
|
||||
* (1 + T::priority))
|
||||
{
|
||||
// if (T::priority > 0)
|
||||
// {
|
||||
// TODO: there should be a way for the client to detect that an
|
||||
// alert was dropped. Maybe add a flag to each m_alerts
|
||||
// generation
|
||||
// }
|
||||
// record that we dropped an alert of this type
|
||||
m_dropped.set(T::alert_type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -83,6 +87,12 @@ namespace libtorrent {
|
|||
|
||||
maybe_notify(&alert, lock);
|
||||
}
|
||||
catch (std::bad_alloc const&)
|
||||
{
|
||||
// record that we dropped an alert of this type
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_dropped.set(T::alert_type);
|
||||
}
|
||||
|
||||
bool pending() const;
|
||||
void get_all(std::vector<alert*>& alerts);
|
||||
|
@ -105,12 +115,12 @@ namespace libtorrent {
|
|||
m_alert_mask = m;
|
||||
}
|
||||
|
||||
alert_category_t alert_mask() const
|
||||
alert_category_t alert_mask() const noexcept
|
||||
{
|
||||
return m_alert_mask;
|
||||
}
|
||||
|
||||
int alert_queue_size_limit() const { return m_queue_size_limit; }
|
||||
int alert_queue_size_limit() const noexcept { return m_queue_size_limit; }
|
||||
int set_alert_queue_size_limit(int queue_size_limit_);
|
||||
|
||||
void set_notify_function(std::function<void()> const& fun);
|
||||
|
@ -133,6 +143,12 @@ namespace libtorrent {
|
|||
std::atomic<alert_category_t> m_alert_mask;
|
||||
int m_queue_size_limit;
|
||||
|
||||
// a bitfield where each bit represents an alert type. Every time we drop
|
||||
// an alert (because the queue is full or of some other error) we set the
|
||||
// corresponding bit in this mask, to communicate to the client that it
|
||||
// may have missed an update.
|
||||
dropped_alerts_t m_dropped;
|
||||
|
||||
// this function (if set) is called whenever the number of alerts in
|
||||
// the alert queue goes from 0 to 1. The client is expected to wake up
|
||||
// its main message loop for it to poll for alerts (using get_alerts()).
|
||||
|
|
|
@ -161,9 +161,9 @@ namespace libtorrent {
|
|||
name(name&&) noexcept = default; \
|
||||
static const int priority = prio; \
|
||||
static const int alert_type = seq; \
|
||||
virtual int type() const override { return alert_type; } \
|
||||
virtual alert_category_t category() const override { return static_category; } \
|
||||
virtual char const* what() const override { return #name; }
|
||||
virtual int type() const noexcept override { return alert_type; } \
|
||||
virtual alert_category_t category() const noexcept override { return static_category; } \
|
||||
virtual char const* what() const noexcept override { return #name; }
|
||||
|
||||
#define TORRENT_DEFINE_ALERT(name, seq) \
|
||||
TORRENT_DEFINE_ALERT_IMPL(name, seq, 0)
|
||||
|
|
|
@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/io_service.hpp"
|
||||
#include "libtorrent/session_types.hpp"
|
||||
#include "libtorrent/portmap.hpp" // for portmap_protocol
|
||||
#include "libtorrent/alert_manager.hpp" // for dropped_alerts_t
|
||||
|
||||
#include "libtorrent/kademlia/dht_storage.hpp"
|
||||
#include "libtorrent/kademlia/dht_settings.hpp"
|
||||
|
@ -934,9 +935,22 @@ namespace libtorrent {
|
|||
// retrieval of alerts should not be done in the callback. In fact, the
|
||||
// callback should not block. It should not perform any expensive work.
|
||||
// It really should just notify the main application thread.
|
||||
//
|
||||
// The ``dropped_alerts()`` function returns a ``std::bitfield``
|
||||
// representing which types of alerts have been dropped. Dropped meaning
|
||||
// that the alert failed to be delivered to the client. The most common
|
||||
// cause of such failure is that the internal alert queue grew too big
|
||||
// (controlled by alert_queue_size). This call also clears the internal
|
||||
// bitfield, so the bitfield starts recording dropped alerts from this
|
||||
// point forward only.
|
||||
//
|
||||
// The type of an alert is returned by the polymorphic function
|
||||
// ``alert::type()`` but can also be queries from a concrete type via
|
||||
// ``T::alert_type``, as a static constant.
|
||||
void pop_alerts(std::vector<alert*>* alerts);
|
||||
alert* wait_for_alert(time_duration max_wait);
|
||||
void set_alert_notify(std::function<void()> const& fun);
|
||||
dropped_alerts_t dropped_alerts();
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
|
|
@ -1442,7 +1442,11 @@ namespace libtorrent {
|
|||
|
||||
// ``alert_queue_size`` is the maximum number of alerts queued up
|
||||
// internally. If alerts are not popped, the queue will eventually
|
||||
// fill up to this level.
|
||||
// fill up to this level. Once the alert queue is full, additional
|
||||
// alerts will be dropped, and not delievered to the client. Once the
|
||||
// client drains the queue, new alerts may be delivered again. In order
|
||||
// to know that alerts have been dropped, see
|
||||
// session_handle::dropped_alerts().
|
||||
alert_queue_size,
|
||||
|
||||
// ``max_metadata_size`` is the maximum allowed size (in bytes) to be
|
||||
|
|
|
@ -146,4 +146,12 @@ namespace libtorrent {
|
|||
std::swap(m_queue_size_limit, queue_size_limit_);
|
||||
return queue_size_limit_;
|
||||
}
|
||||
|
||||
dropped_alerts_t alert_manager::dropped_alerts()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
dropped_alerts_t const ret = m_dropped;
|
||||
m_dropped.reset();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1130,6 +1130,13 @@ namespace {
|
|||
s->alerts().set_notify_function(fun);
|
||||
}
|
||||
|
||||
dropped_alerts_t session_handle::dropped_alerts()
|
||||
{
|
||||
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||
return s->alerts().dropped_alerts();
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
void session_handle::set_severity_level(alert::severity_t s)
|
||||
{
|
||||
|
|
|
@ -248,3 +248,23 @@ TORRENT_TEST(alert_mask)
|
|||
TEST_CHECK(!mgr.should_post<torrent_paused_alert>());
|
||||
}
|
||||
|
||||
TORRENT_TEST(dropped_alerts)
|
||||
{
|
||||
alert_manager mgr(1, alert::all_categories);
|
||||
|
||||
// nothing has dropped yet
|
||||
TEST_CHECK(mgr.dropped_alerts().none());
|
||||
mgr.emplace_alert<torrent_finished_alert>(torrent_handle());
|
||||
// still nothing, there's space for one alert
|
||||
TEST_CHECK(mgr.dropped_alerts().none());
|
||||
mgr.emplace_alert<torrent_finished_alert>(torrent_handle());
|
||||
// that last alert got dropped though, since it would have brought the queue
|
||||
// size to 2
|
||||
auto const d = mgr.dropped_alerts();
|
||||
TEST_CHECK(d.count() == 1);
|
||||
TEST_CHECK(d.test(torrent_finished_alert::alert_type));
|
||||
|
||||
// it should have been cleared now though
|
||||
TEST_CHECK(mgr.dropped_alerts().none());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue