refactor: add tr_torrentWebseed(), tr_torrentWebseedCount() (#2277)

* refactor: add tr_torrentWebseedCount()
This commit is contained in:
Charles Kerr
2021-12-07 12:11:28 -06:00
committed by GitHub
parent 89b0362bf2
commit c46ce2da06
9 changed files with 90 additions and 76 deletions

View File

@@ -1403,7 +1403,7 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& torrents)
{
int total = 0;
auto has_any_webseeds = bool{ false };
auto& hash = webseed_hash_;
auto& store = webseed_store_;
@@ -1416,13 +1416,11 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
/* step 2: add any new webseeds */
for (auto const* const tor : torrents)
{
auto const* inf = tr_torrentInfo(tor);
total += inf->webseedCount;
for (unsigned int j = 0; j < inf->webseedCount; ++j)
for (size_t j = 0, n = tr_torrentWebseedCount(tor); j < n; ++j)
{
char const* url = inf->webseeds[j];
has_any_webseeds = true;
auto const* const url = tr_torrentWebseed(tor, j).url;
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), url);
if (hash.find(key) == hash.end())
@@ -1438,27 +1436,23 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
/* step 3: update the webseeds */
for (auto const* const tor : torrents)
{
auto const* inf = tr_torrentInfo(tor);
double* speeds_KBps = tr_torrentWebSpeeds_KBps(tor);
for (unsigned int j = 0; j < inf->webseedCount; ++j)
for (size_t j = 0, n = tr_torrentWebseedCount(tor); j < n; ++j)
{
char const* const url = inf->webseeds[j];
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), url);
auto const webseed = tr_torrentWebseed(tor, j);
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), webseed.url);
auto const iter = store->get_iter(hash.at(key).get_path());
char buf[128] = { 0 };
if (speeds_KBps[j] > 0)
auto const KBps = double(webseed.download_bytes_per_second) / speed_K;
auto buf = std::array<char, 128>{};
if (webseed.is_downloading)
{
tr_formatter_speed_KBps(buf, speeds_KBps[j], sizeof(buf));
tr_formatter_speed_KBps(std::data(buf), KBps, std::size(buf));
}
(*iter)[webseed_cols.download_rate_double] = speeds_KBps[j];
(*iter)[webseed_cols.download_rate_string] = buf;
(*iter)[webseed_cols.download_rate_double] = KBps;
(*iter)[webseed_cols.download_rate_string] = std::data(buf);
(*iter)[webseed_cols.was_updated] = true;
}
tr_free(speeds_KBps);
}
/* step 4: remove webseeds that have disappeared */
@@ -1481,7 +1475,7 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
/* most of the time there are no webseeds...
don't waste space showing an empty list */
webseed_view_->set_visible(total > 0);
webseed_view_->set_visible(has_any_webseeds);
}
void DetailsDialog::Impl::refreshPeers(std::vector<tr_torrent*> const& torrents)

View File

@@ -1704,36 +1704,14 @@ uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor)
return desired_available;
}
double* tr_peerMgrWebSpeeds_KBps(tr_torrent const* tor)
tr_webseed_view tr_peerMgrWebseed(tr_torrent const* tor, size_t i)
{
TR_ASSERT(tr_isTorrent(tor));
TR_ASSERT(tor->swarm != nullptr);
size_t const n = tr_ptrArraySize(&tor->swarm->webseeds);
TR_ASSERT(i < n);
auto const now = tr_time_msec();
tr_swarm* const s = tor->swarm;
TR_ASSERT(s->manager != nullptr);
unsigned int n = tr_ptrArraySize(&s->webseeds);
TR_ASSERT(n == tor->info.webseedCount);
double* ret = tr_new0(double, n);
for (unsigned int i = 0; i < n; ++i)
{
unsigned int Bps = 0;
auto const* const peer = static_cast<tr_peer*>(tr_ptrArrayNth(&s->webseeds, i));
if (peer->is_transferring_pieces(now, TR_DOWN, &Bps))
{
ret[i] = Bps / (double)tr_speed_K;
}
else
{
ret[i] = -1.0;
}
}
return ret;
return i >= n ? tr_webseed_view{} : tr_webseedView(static_cast<tr_peer const*>(tr_ptrArrayNth(&tor->swarm->webseeds, i)));
}
static auto getPeerStats(tr_peerMsgs const* peer, time_t now, uint64_t now_msec)

View File

@@ -138,7 +138,7 @@ void tr_peerMgrOnBlocklistChanged(tr_peerMgr* manager);
struct tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, int* setmeCount);
double* tr_peerMgrWebSpeeds_KBps(tr_torrent const* tor);
tr_webseed_view tr_peerMgrWebseed(tr_torrent const* tor, size_t i);
unsigned int tr_peerGetPieceSpeed_Bps(tr_peer const* peer, uint64_t now, tr_direction direction);

View File

@@ -1241,17 +1241,22 @@ size_t tr_torrentFileCount(tr_torrent const* torrent)
return torrent->fileCount();
}
/***
****
***/
tr_webseed_view tr_torrentWebseed(tr_torrent const* tor, size_t i)
{
return tr_peerMgrWebseed(tor, i);
}
double* tr_torrentWebSpeeds_KBps(tr_torrent const* tor)
size_t tr_torrentWebseedCount(tr_torrent const* tor)
{
TR_ASSERT(tr_isTorrent(tor));
return tr_peerMgrWebSpeeds_KBps(tor);
return tor->webseedCount();
}
/***
****
***/
tr_peer_stat* tr_torrentPeers(tr_torrent const* tor, int* peerCount)
{
TR_ASSERT(tr_isTorrent(tor));

View File

@@ -327,6 +327,27 @@ public:
std::optional<tr_found_file_t> findFile(std::string& filename, tr_file_index_t i) const;
/// WEBSEEDS
auto webseedCount() const
{
return info.webseedCount;
}
auto const& webseed(size_t i) const
{
TR_ASSERT(i < webseedCount());
return info.webseeds[i];
}
auto& webseed(size_t i)
{
TR_ASSERT(i < webseedCount());
return info.webseeds[i];
}
/// CHECKSUMS
bool ensurePieceIsChecked(tr_piece_index_t piece)

View File

@@ -1501,18 +1501,6 @@ tr_tracker_stat* tr_torrentTrackers(tr_torrent const* torrent, int* setmeTracker
void tr_torrentTrackersFree(tr_tracker_stat* trackerStats, int trackerCount);
/**
* @brief get the download speeds for each of this torrent's webseed sources.
*
* @return an array of tor->info.webseedCount floats giving download speeds.
* Each speed in the array corresponds to the webseed at the same
* array index in tor->info.webseeds.
* To differentiate "idle" and "stalled" status, idle webseeds will
* return -1 instead of 0 KiB/s.
* NOTE: always free this array with tr_free() when you're done with it.
*/
double* tr_torrentWebSpeeds_KBps(tr_torrent const* torrent);
/*
* This view structure is intended for short-term use. Its pointers are owned
* by the torrent and may be invalidated if the torrent is edited or removed.
@@ -1530,6 +1518,21 @@ tr_file_view tr_torrentFile(tr_torrent const* torrent, tr_file_index_t file);
size_t tr_torrentFileCount(tr_torrent const* torrent);
/*
* This view structure is intended for short-term use. Its pointers are owned
* by the torrent and may be invalidated if the torrent is edited or removed.
*/
struct tr_webseed_view
{
char const* url; // the url to download from
bool is_downloading; // can be true even if speed is 0, e.g. slow download
unsigned download_bytes_per_second; // current download speed
};
struct tr_webseed_view tr_torrentWebseed(tr_torrent const* torrent, size_t nth);
size_t tr_torrentWebseedCount(tr_torrent const* torrent);
/***********************************************************************
* tr_torrentAvailability
***********************************************************************

View File

@@ -125,6 +125,19 @@ public:
} // namespace
tr_webseed_view tr_webseedView(tr_peer const* peer)
{
auto const* w = dynamic_cast<tr_webseed const*>(peer);
if (w == nullptr)
{
return {};
}
auto bytes_per_second = unsigned{ 0 };
auto const is_downloading = peer->is_transferring_pieces(tr_time_msec(), TR_DOWN, &bytes_per_second);
return { w->base_url.c_str(), is_downloading, bytes_per_second };
}
/***
****
***/

View File

@@ -17,3 +17,5 @@
#include "peer-common.h"
tr_peer* tr_webseedNew(struct tr_torrent* torrent, std::string_view, tr_peer_callback callback, void* callback_data);
tr_webseed_view tr_webseedView(tr_peer const* peer);

View File

@@ -1080,32 +1080,30 @@ bool trashDataFile(char const* filename, tr_error** error)
- (NSUInteger)webSeedCount
{
return fInfo->webseedCount;
return tr_torrentWebseedCount(fHandle);
}
- (NSArray*)webSeeds
{
NSMutableArray* webSeeds = [NSMutableArray arrayWithCapacity:fInfo->webseedCount];
NSUInteger n = tr_torrentWebseedCount(fHandle);
NSMutableArray* webSeeds = [NSMutableArray arrayWithCapacity:n];
double* dlSpeeds = tr_torrentWebSpeeds_KBps(fHandle);
for (NSInteger i = 0; i < fInfo->webseedCount; i++)
for (NSUInteger i = 0; i < n; ++i)
{
auto const webseed = tr_torrentWebseed(fHandle, i);
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:3];
dict[@"Name"] = self.name;
dict[@"Address"] = @(fInfo->webseeds[i]);
dict[@"Address"] = @(webseed.url);
if (dlSpeeds[i] != -1.0)
if (webseed.is_downloading)
{
dict[@"DL From Rate"] = @(dlSpeeds[i]);
dict[@"DL From Rate"] = @(double(webseed.download_bytes_per_second) / 1000);
}
[webSeeds addObject:dict];
}
tr_free(dlSpeeds);
return webSeeds;
}