diff --git a/docs/rpc-spec.md b/docs/rpc-spec.md index 11bb541f0..50732bbdf 100644 --- a/docs/rpc-spec.md +++ b/docs/rpc-spec.md @@ -196,6 +196,7 @@ The 'source' column here corresponds to the data structure there. |:--|:--|:-- | `activityDate` | number | tr_stat | `addedDate` | number | tr_stat +| `availability` | array (see below)| tr_torrentAvailability() | `bandwidthPriority` | number | tr_priority_t | `comment` | string | tr_torrent_view | `corruptEver`| number | tr_stat @@ -270,6 +271,7 @@ The 'source' column here corresponds to the data structure there. | `webseeds`| array of strings | tr_tracker_view | `webseedsSendingToUs`| number| tr_stat +`availability`: An array of `pieceCount` numbers representing the number of connected peers that have each piece, or -1 if we already have the piece ourselves. `files`: array of objects, each containing: @@ -969,6 +971,7 @@ Transmission 4.0.0 (`rpc-version-semver` 5.3.0, `rpc-version`: 17) | `session-get` | new arg `script-torrent-done-seeding-enabled` | `session-get` | new arg `script-torrent-done-seeding-filename` | `torrent-add` | new arg `labels` +| `torrent-get` | new arg `availability` | `torrent-get` | new arg `file-count` | `torrent-get` | new arg `group` | `torrent-get` | new arg `percentComplete` diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc index 330857332..6a9693bf8 100644 --- a/libtransmission/peer-mgr.cc +++ b/libtransmission/peer-mgr.cc @@ -1482,36 +1482,35 @@ void tr_peerMgrOnTorrentGotMetainfo(tr_torrent* tor) } } -void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned int tabCount) +int8_t tr_peerMgrPieceAvailability(tr_torrent const* tor, tr_piece_index_t piece) +{ + if (!tor->hasMetainfo()) + { + return 0; + } + + if (tor->isSeed() || tor->hasPiece(piece)) + { + return -1; + } + + auto const& peers = tor->swarm->peers; + return std::count_if(std::begin(peers), std::end(peers), [piece](auto const* peer) { return peer->have.test(piece); }); +} + +void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned int n_tabs) { TR_ASSERT(tr_isTorrent(tor)); TR_ASSERT(tab != nullptr); - TR_ASSERT(tabCount > 0); + TR_ASSERT(n_tabs > 0); - std::fill_n(tab, tabCount, int8_t{}); + std::fill_n(tab, n_tabs, int8_t{}); - if (tor->hasMetainfo()) + auto const interval = tor->pieceCount() / static_cast(n_tabs); + for (tr_piece_index_t i = 0; i < n_tabs; ++i) { - auto const& peers = tor->swarm->peers; - float const interval = tor->pieceCount() / (float)tabCount; - auto const isSeed = tor->isSeed(); - - for (tr_piece_index_t i = 0; i < tabCount; ++i) - { - int const piece = i * interval; - - if (isSeed || tor->hasPiece(piece)) - { - tab[i] = -1; - } - else - { - tab[i] = std::count_if( - std::begin(peers), - std::end(peers), - [piece](auto const* peer) { return peer->have.test(piece); }); - } - } + auto const piece = static_cast(i * interval); + tab[i] = tr_peerMgrPieceAvailability(tor, piece); } } diff --git a/libtransmission/peer-mgr.h b/libtransmission/peer-mgr.h index 12aab2b75..3be2c7070 100644 --- a/libtransmission/peer-mgr.h +++ b/libtransmission/peer-mgr.h @@ -154,6 +154,9 @@ void tr_peerMgrAddTorrent(tr_peerMgr* manager, struct tr_torrent* tor); void tr_peerMgrRemoveTorrent(tr_torrent* tor); +// return the number of connected peers that have `piece`, or -1 if we already have it +int8_t tr_peerMgrPieceAvailability(tr_torrent const* tor, tr_piece_index_t piece); + void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned int tabCount); uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor); diff --git a/libtransmission/quark.cc b/libtransmission/quark.cc index f16c2e14f..8d0990bff 100644 --- a/libtransmission/quark.cc +++ b/libtransmission/quark.cc @@ -18,7 +18,7 @@ using namespace std::literals; namespace { -auto constexpr my_static = std::array{ ""sv, +auto constexpr my_static = std::array{ ""sv, "activeTorrentCount"sv, "activity-date"sv, "activityDate"sv, @@ -42,6 +42,7 @@ auto constexpr my_static = std::array{ ""sv, "anti-brute-force-enabled"sv, "anti-brute-force-threshold"sv, "arguments"sv, + "availability"sv, "bandwidth-priority"sv, "bandwidthPriority"sv, "bind-address-ipv4"sv, diff --git a/libtransmission/quark.h b/libtransmission/quark.h index f279608a6..f1f94d547 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -45,6 +45,7 @@ enum TR_KEY_anti_brute_force_enabled, /* rpc */ TR_KEY_anti_brute_force_threshold, /* rpc */ TR_KEY_arguments, /* rpc */ + TR_KEY_availability, // rpc TR_KEY_bandwidth_priority, TR_KEY_bandwidthPriority, TR_KEY_bind_address_ipv4, diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index 5e0491d62..42ab5cc57 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -25,7 +25,7 @@ #include "error.h" #include "file.h" #include "log.h" -#include "platform-quota.h" /* tr_device_info_get_disk_space() */ +#include "peer-mgr.h" #include "quark.h" #include "rpcimpl.h" #include "session-id.h" @@ -490,6 +490,14 @@ static void initField(tr_torrent const* const tor, tr_stat const* const st, tr_v tr_variantInitInt(initme, st->addedDate); break; + case TR_KEY_availability: + tr_variantInitList(initme, tor->pieceCount()); + for (tr_piece_index_t piece = 0, n = tor->pieceCount(); piece < n; ++piece) + { + tr_variantListAddInt(initme, tr_peerMgrPieceAvailability(tor, piece)); + } + break; + case TR_KEY_bandwidthPriority: tr_variantInitInt(initme, tr_torrentGetPriority(tor)); break;