forked from premiere/premiere-libtorrent
deliver notification of alerts being dropped via alerts_dropped_alert
This commit is contained in:
parent
f9b43f3511
commit
c56f6abf72
|
@ -1,10 +1,10 @@
|
|||
* deliver notification of alerts being dropped via alerts_dropped_alert
|
||||
* deprecated alert::progress_notification alert category, split into
|
||||
finer grained categories
|
||||
* update plugin interface functions for improved type-safety
|
||||
* implemented support magnet URI extension, select specific file indices
|
||||
for download, BEP53
|
||||
* make tracker keys multi-homed. remove set_key() function on session.
|
||||
* 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
|
||||
|
|
|
@ -54,10 +54,6 @@ 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:
|
||||
|
@ -69,8 +65,6 @@ namespace libtorrent {
|
|||
|
||||
~alert_manager();
|
||||
|
||||
dropped_alerts_t dropped_alerts();
|
||||
|
||||
template <class T, typename... Args>
|
||||
void emplace_alert(Args&&... args) try
|
||||
{
|
||||
|
@ -145,7 +139,7 @@ namespace libtorrent {
|
|||
// 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;
|
||||
std::bitset<num_alert_types> 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
|
||||
|
|
|
@ -59,6 +59,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/shared_array.hpp>
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
#define PROGRESS_NOTIFICATION | alert::progress_notification
|
||||
#else
|
||||
|
@ -72,8 +74,14 @@ namespace libtorrent {
|
|||
TORRENT_DEPRECATED_EXPORT char const* operation_name(int op);
|
||||
#endif
|
||||
|
||||
// internal
|
||||
TORRENT_EXTRA_EXPORT char const* alert_name(int alert_type);
|
||||
|
||||
// user defined alerts should use IDs greater than this
|
||||
static const int user_alert_id = 10000;
|
||||
constexpr int user_alert_id = 10000;
|
||||
|
||||
// this constant represents "max_alert_index" + 1
|
||||
constexpr int num_alert_types = 96;
|
||||
|
||||
enum alert_priority
|
||||
{
|
||||
|
@ -190,7 +198,7 @@ TORRENT_VERSION_NAMESPACE_2
|
|||
static const int alert_type = seq; \
|
||||
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; }
|
||||
virtual char const* what() const noexcept override { return alert_name(alert_type); }
|
||||
|
||||
#define TORRENT_DEFINE_ALERT(name, seq) \
|
||||
TORRENT_DEFINE_ALERT_IMPL(name, seq, alert_priority_normal)
|
||||
|
@ -1848,7 +1856,7 @@ TORRENT_VERSION_NAMESPACE_2
|
|||
};
|
||||
|
||||
// This alert is posted whenever a tracker responds with a ``trackerid``.
|
||||
// The tracker ID is like a cookie. The libtorrent will store the tracker ID
|
||||
// The tracker ID is like a cookie. libtorrent will store the tracker ID
|
||||
// for this tracker and repeat it in subsequent announces.
|
||||
struct TORRENT_EXPORT trackerid_alert final : tracker_alert
|
||||
{
|
||||
|
@ -2839,6 +2847,25 @@ TORRENT_VERSION_NAMESPACE_2
|
|||
piece_index_t const piece_index;
|
||||
};
|
||||
|
||||
// this alert is posted to indicate to the client that some alerts were
|
||||
// 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).
|
||||
struct TORRENT_EXPORT alerts_dropped_alert final : alert
|
||||
{
|
||||
explicit alerts_dropped_alert(aux::stack_allocator& alloc
|
||||
, std::bitset<num_alert_types> const&);
|
||||
TORRENT_DEFINE_ALERT_PRIO(alerts_dropped_alert, 95, alert_priority_critical + 1)
|
||||
|
||||
static constexpr alert_category_t static_category = alert::error_notification;
|
||||
std::string message() const override;
|
||||
|
||||
// a bitmask indicating which alerts were dropped. Each bit represents the
|
||||
// alert type ID, where bit 0 represents whether any alert of type 0 has
|
||||
// been dropped, and so on.
|
||||
std::bitset<num_alert_types> dropped_alerts;
|
||||
};
|
||||
|
||||
TORRENT_VERSION_NAMESPACE_2_END
|
||||
|
||||
#undef TORRENT_DEFINE_ALERT_IMPL
|
||||
|
@ -2846,7 +2873,6 @@ TORRENT_VERSION_NAMESPACE_2_END
|
|||
#undef TORRENT_DEFINE_ALERT_PRIO
|
||||
#undef PROGRESS_NOTIFICATION
|
||||
|
||||
constexpr int num_alert_types = 95; // this constant represents "max_alert_index" + 1
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,6 @@ 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"
|
||||
|
@ -933,21 +932,12 @@ namespace libtorrent {
|
|||
// 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();
|
||||
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
|
|
@ -2540,6 +2540,83 @@ namespace {
|
|||
return ret;
|
||||
}
|
||||
|
||||
alerts_dropped_alert::alerts_dropped_alert(aux::stack_allocator&
|
||||
, std::bitset<num_alert_types> const& dropped)
|
||||
: dropped_alerts(dropped)
|
||||
{}
|
||||
|
||||
char const* alert_name(int const alert_type)
|
||||
{
|
||||
static std::array<char const*, num_alert_types> const names = {{
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
"torrent", "peer", "tracker", "torrent_added",
|
||||
#else
|
||||
"", "", "", "",
|
||||
#endif
|
||||
"torrent_removed", "read_piece", "file_completed",
|
||||
"file_renamed", "file_rename_failed", "performance",
|
||||
"state_changed", "tracker_error", "tracker_warning",
|
||||
"scrape_reply", "scrape_failed", "tracker_reply",
|
||||
"dht_reply", "tracker_announce", "hash_failed",
|
||||
"peer_ban", "peer_unsnubbed", "peer_snubbed",
|
||||
"peer_error", "peer_connect", "peer_disconnected",
|
||||
"invalid_request", "torrent_finished", "piece_finished",
|
||||
"request_dropped", "block_timeout", "block_finished",
|
||||
"block_downloading", "unwanted_block", "storage_moved",
|
||||
"storage_moved_failed", "torrent_deleted",
|
||||
"torrent_delete_failed", "save_resume_data",
|
||||
"save_resume_data_failed", "torrent_paused",
|
||||
"torrent_resumed", "torrent_checked", "url_seed",
|
||||
"file_error", "metadata_failed", "metadata_received",
|
||||
"udp_error", "external_ip", "listen_failed",
|
||||
"listen_succeeded", "portmap_error", "portmap",
|
||||
"portmap_log", "fastresume_rejected", "peer_blocked",
|
||||
"dht_announce", "dht_get_peers", "stats",
|
||||
"cache_flushed", "anonymous_mode", "lsd_peer",
|
||||
"trackerid", "dht_bootstrap", "", "torrent_error",
|
||||
"torrent_need_cert", "incoming_connection",
|
||||
"add_torrent", "state_update",
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
"mmap_cache",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
"session_stats",
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
"torrent_update",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
"", "dht_error", "dht_immutable_item", "dht_mutable_item",
|
||||
"dht_put", "i2p", "dht_outgoing_get_peers", "log",
|
||||
"torrent_log", "peer_log", "lsd_error",
|
||||
"dht_stats", "incoming_request", "dht_log",
|
||||
"dht_pkt", "dht_get_peers_reply", "dht_direct_response",
|
||||
"picker_log", "session_error", "dht_live_nodes",
|
||||
"session_stats_header", "dht_sample_infohashes",
|
||||
"block_uploaded", "alerts_dropped"
|
||||
}};
|
||||
|
||||
TORRENT_ASSERT(alert_type >= 0);
|
||||
TORRENT_ASSERT(alert_type < num_alert_types);
|
||||
return names[std::size_t(alert_type)];
|
||||
}
|
||||
|
||||
std::string alerts_dropped_alert::message() const
|
||||
{
|
||||
std::string ret = "dropped alerts: ";
|
||||
|
||||
TORRENT_ASSERT(int(dropped_alerts.size()) == num_alert_types);
|
||||
for (int idx = 0; idx < num_alert_types; ++idx)
|
||||
{
|
||||
if (!dropped_alerts.test(std::size_t(idx))) continue;
|
||||
ret += alert_name(idx);
|
||||
ret += ' ';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// this will no longer be necessary in C++17
|
||||
constexpr alert_category_t torrent_removed_alert::static_category;
|
||||
constexpr alert_category_t read_piece_alert::static_category;
|
||||
|
@ -2628,6 +2705,7 @@ namespace {
|
|||
constexpr alert_category_t session_stats_header_alert::static_category;
|
||||
constexpr alert_category_t dht_sample_infohashes_alert::static_category;
|
||||
constexpr alert_category_t block_uploaded_alert::static_category;
|
||||
constexpr alert_category_t alerts_dropped_alert::static_category;
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
constexpr alert_category_t mmap_cache_alert::static_category;
|
||||
constexpr alert_category_t torrent_added_alert::static_category;
|
||||
|
|
|
@ -108,6 +108,11 @@ namespace libtorrent {
|
|||
|
||||
if (m_alerts[m_generation].empty()) return;
|
||||
|
||||
if (m_dropped.any()) {
|
||||
emplace_alert<alerts_dropped_alert>(m_dropped);
|
||||
m_dropped.reset();
|
||||
}
|
||||
|
||||
m_alerts[m_generation].get_pointers(alerts);
|
||||
|
||||
// swap buffers
|
||||
|
@ -130,12 +135,4 @@ 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::recursive_mutex> lock(m_mutex);
|
||||
dropped_alerts_t const ret = m_dropped;
|
||||
m_dropped.reset();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1144,13 +1144,6 @@ 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();
|
||||
}
|
||||
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
void session_handle::set_severity_level(alert::severity_t s)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/session.hpp" // for session::delete_files
|
||||
#include "libtorrent/stat_cache.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
#include "libtorrent/torrent_status.hpp"
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ TORRENT_TEST(limit)
|
|||
mgr.get_all(alerts);
|
||||
|
||||
// even though we posted 600, the limit was 500
|
||||
TEST_EQUAL(alerts.size(), 500);
|
||||
// +1 for the alerts_dropped_alert
|
||||
TEST_EQUAL(alerts.size(), 501);
|
||||
|
||||
TEST_EQUAL(mgr.pending(), false);
|
||||
|
||||
|
@ -75,7 +76,8 @@ TORRENT_TEST(limit)
|
|||
mgr.get_all(alerts);
|
||||
|
||||
// even though we posted 600, the limit was 200
|
||||
TEST_EQUAL(alerts.size(), 200);
|
||||
// +1 for the alerts_dropped_alert
|
||||
TEST_EQUAL(alerts.size(), 201);
|
||||
}
|
||||
|
||||
TORRENT_TEST(priority_limit)
|
||||
|
@ -97,7 +99,8 @@ TORRENT_TEST(priority_limit)
|
|||
|
||||
// even though we posted 500, the limit was 100 for half of them and
|
||||
// 100 + 200 for the other half, meaning we should have 300 alerts now
|
||||
TEST_EQUAL(alerts.size(), 300);
|
||||
// +1 for the alerts_dropped_alert
|
||||
TEST_EQUAL(alerts.size(), 301);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -260,22 +263,33 @@ 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());
|
||||
// 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 3
|
||||
auto const d = mgr.dropped_alerts();
|
||||
std::vector<alert*> alerts;
|
||||
mgr.get_all(alerts);
|
||||
auto const d = alert_cast<alerts_dropped_alert>(alerts.back())->dropped_alerts;
|
||||
TEST_EQUAL(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());
|
||||
TORRENT_TEST(alerts_dropped_alert)
|
||||
{
|
||||
alert_manager mgr(1, alert::all_categories);
|
||||
|
||||
mgr.emplace_alert<torrent_finished_alert>(torrent_handle());
|
||||
mgr.emplace_alert<torrent_finished_alert>(torrent_handle());
|
||||
mgr.emplace_alert<torrent_finished_alert>(torrent_handle());
|
||||
// that last alert got dropped though, since it would have brought the queue
|
||||
// size to 3
|
||||
std::vector<alert*> alerts;
|
||||
mgr.get_all(alerts);
|
||||
|
||||
TEST_EQUAL(alerts.back()->message(), "dropped alerts: torrent_finished ");
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
|
|
|
@ -58,6 +58,7 @@ TORRENT_TEST(alerts_types)
|
|||
TEST_EQUAL(name::alert_type, seq); \
|
||||
TEST_EQUAL(name::static_category, cat); \
|
||||
TEST_EQUAL(count_alert_types, seq); \
|
||||
TEST_EQUAL(std::string(alert_name(name::alert_type)) + "_alert", #name); \
|
||||
count_alert_types++;
|
||||
|
||||
#if TORRENT_ABI_VERSION == 1
|
||||
|
@ -171,10 +172,11 @@ TORRENT_TEST(alerts_types)
|
|||
TEST_ALERT_TYPE(session_stats_header_alert, 92, 0, alert::stats_notification);
|
||||
TEST_ALERT_TYPE(dht_sample_infohashes_alert, 93, 0, alert::dht_operation_notification);
|
||||
TEST_ALERT_TYPE(block_uploaded_alert, 94, 0, PROGRESS_NOTIFICATION alert::upload_notification);
|
||||
TEST_ALERT_TYPE(alerts_dropped_alert, 95, 3, alert::error_notification);
|
||||
|
||||
#undef TEST_ALERT_TYPE
|
||||
|
||||
TEST_EQUAL(num_alert_types, 95);
|
||||
TEST_EQUAL(num_alert_types, 96);
|
||||
TEST_EQUAL(num_alert_types, count_alert_types);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue