refactor: replace tr_torrentFiles() with tr_torrentFileProgress() (#1994)
* refactor: s/tr_torrentFiles/tr_torrentFileProgress Replace tr_torrentFiles() with a new function, tr_torrentFileProgress(). tr_torrentFiles() heap-allocated an array of progress structs. There is nothing intrinsic in tr_torrent making batch computation more efficient, so this PR replaces it with tr_torrentFileProgress(), a per-file variant that doesn't use the heap.
This commit is contained in:
parent
b0fd4b474a
commit
8cdc2c633e
|
@ -131,8 +131,6 @@ struct RefreshData
|
|||
{
|
||||
int sort_column_id;
|
||||
bool resort_needed;
|
||||
|
||||
tr_file_stat* refresh_file_stat;
|
||||
tr_torrent* tor;
|
||||
};
|
||||
|
||||
|
@ -156,8 +154,9 @@ bool refreshFilesForeach(
|
|||
auto const* inf = tr_torrentInfo(tor);
|
||||
int const enabled = inf->files[index].dnd ? 0 : 1;
|
||||
int const priority = inf->files[index].priority;
|
||||
uint64_t const have = refresh_data.refresh_file_stat[index].bytesCompleted;
|
||||
int const prog = size != 0 ? (int)(100.0 * have / size) : 1;
|
||||
auto const progress = tr_torrentFileProgress(tor, index);
|
||||
uint64_t const have = progress.bytes_completed;
|
||||
int const prog = std::clamp(int(100 * progress.progress), 0, 100);
|
||||
|
||||
if (priority != old_priority || enabled != old_enabled || have != old_have || prog != old_prog)
|
||||
{
|
||||
|
@ -276,15 +275,9 @@ void FileList::Impl::refresh()
|
|||
{
|
||||
Gtk::SortType order;
|
||||
int sort_column_id;
|
||||
tr_file_index_t fileCount;
|
||||
RefreshData refresh_data;
|
||||
store_->get_sort_column_id(sort_column_id, order);
|
||||
|
||||
refresh_data.sort_column_id = sort_column_id;
|
||||
refresh_data.resort_needed = false;
|
||||
refresh_data.refresh_file_stat = tr_torrentFiles(tor, &fileCount);
|
||||
refresh_data.tor = tor;
|
||||
|
||||
RefreshData refresh_data{ sort_column_id, false, tor };
|
||||
gtr_tree_model_foreach_postorder(
|
||||
store_,
|
||||
[this, &refresh_data](Gtk::TreeModel::iterator const& iter)
|
||||
|
@ -294,8 +287,6 @@ void FileList::Impl::refresh()
|
|||
{
|
||||
store_->set_sort_column(sort_column_id, order);
|
||||
}
|
||||
|
||||
tr_torrentFilesFree(refresh_data.refresh_file_stat, fileCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -384,38 +384,28 @@ static void addLabels(tr_torrent const* tor, tr_variant* list)
|
|||
|
||||
static void addFileStats(tr_torrent const* tor, tr_variant* list)
|
||||
{
|
||||
auto n = tr_file_index_t{};
|
||||
auto* files = tr_torrentFiles(tor, &n);
|
||||
|
||||
auto const* const info = tr_torrentInfo(tor);
|
||||
for (tr_file_index_t i = 0; i < info->fileCount; ++i)
|
||||
{
|
||||
tr_file const* file = &info->files[i];
|
||||
tr_variant* d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
|
||||
auto const* const file = &info->files[i];
|
||||
tr_variant* const d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, tr_torrentFileProgress(tor, i).bytes_completed);
|
||||
tr_variantDictAddInt(d, TR_KEY_priority, file->priority);
|
||||
tr_variantDictAddBool(d, TR_KEY_wanted, !file->dnd);
|
||||
}
|
||||
|
||||
tr_torrentFilesFree(files, n);
|
||||
}
|
||||
|
||||
static void addFiles(tr_torrent const* tor, tr_variant* list)
|
||||
{
|
||||
auto n = tr_file_index_t{};
|
||||
auto* const files = tr_torrentFiles(tor, &n);
|
||||
|
||||
auto const* const info = tr_torrentInfo(tor);
|
||||
for (tr_file_index_t i = 0; i < info->fileCount; ++i)
|
||||
{
|
||||
tr_file const* file = &info->files[i];
|
||||
tr_variant* d = tr_variantListAddDict(list, 3);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, files[i].bytesCompleted);
|
||||
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, tr_torrentFileProgress(tor, i).bytes_completed);
|
||||
tr_variantDictAddInt(d, TR_KEY_length, file->length);
|
||||
tr_variantDictAddStr(d, TR_KEY_name, file->name);
|
||||
}
|
||||
|
||||
tr_torrentFilesFree(files, n);
|
||||
}
|
||||
|
||||
static void addWebseeds(tr_info const* info, tr_variant* webseeds)
|
||||
|
|
|
@ -1468,35 +1468,20 @@ static uint64_t countFileBytesCompleted(tr_torrent const* tor, tr_file_index_t i
|
|||
return total;
|
||||
}
|
||||
|
||||
tr_file_stat* tr_torrentFiles(tr_torrent const* tor, tr_file_index_t* fileCount)
|
||||
tr_file_progress tr_torrentFileProgress(tr_torrent const* torrent, tr_file_index_t file)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
TR_ASSERT(tr_isTorrent(torrent));
|
||||
TR_ASSERT(file < torrent->info.fileCount);
|
||||
|
||||
tr_file_index_t const n = tor->info.fileCount;
|
||||
tr_file_stat* files = tr_new0(tr_file_stat, n);
|
||||
tr_file_stat* walk = files;
|
||||
bool const isSeed = tor->completeness == TR_SEED;
|
||||
tr_file_index_t const total = torrent->info.files[file].length;
|
||||
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
if (torrent->completeness == TR_SEED || total == 0)
|
||||
{
|
||||
uint64_t const length = tor->info.files[i].length;
|
||||
uint64_t const b = isSeed ? length : countFileBytesCompleted(tor, i);
|
||||
walk->bytesCompleted = b;
|
||||
walk->progress = length > 0 ? (float)b / (float)length : 1.0F;
|
||||
++walk;
|
||||
return { total, total, 1.0 };
|
||||
}
|
||||
|
||||
if (fileCount != nullptr)
|
||||
{
|
||||
*fileCount = n;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
void tr_torrentFilesFree(tr_file_stat* files, [[maybe_unused]] tr_file_index_t fileCount)
|
||||
{
|
||||
tr_free(files);
|
||||
auto const have = countFileBytesCompleted(torrent, file);
|
||||
return { have, total, have >= total ? 1.0 : have / double(total) };
|
||||
}
|
||||
|
||||
/***
|
||||
|
|
|
@ -1536,15 +1536,14 @@ void tr_torrentTrackersFree(tr_tracker_stat* trackerStats, int trackerCount);
|
|||
*/
|
||||
double* tr_torrentWebSpeeds_KBps(tr_torrent const* torrent);
|
||||
|
||||
struct tr_file_stat
|
||||
struct tr_file_progress
|
||||
{
|
||||
uint64_t bytesCompleted;
|
||||
float progress;
|
||||
uint64_t bytes_completed;
|
||||
uint64_t bytes_total;
|
||||
double progress;
|
||||
};
|
||||
|
||||
tr_file_stat* tr_torrentFiles(tr_torrent const* torrent, tr_file_index_t* fileCount);
|
||||
|
||||
void tr_torrentFilesFree(tr_file_stat* files, tr_file_index_t fileCount);
|
||||
tr_file_progress tr_torrentFileProgress(tr_torrent const* torrent, tr_file_index_t file);
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentAvailability
|
||||
|
|
|
@ -213,8 +213,6 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
- (void)refresh
|
||||
{
|
||||
[fTorrent updateFileStat];
|
||||
|
||||
fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,6 @@ typedef NS_ENUM(unsigned int, TorrentDeterminationType) {
|
|||
@property(nonatomic, readonly) NSArray* fileList;
|
||||
@property(nonatomic, readonly) NSArray* flatFileList;
|
||||
@property(nonatomic, readonly) NSInteger fileCount;
|
||||
- (void)updateFileStat;
|
||||
|
||||
//methods require fileStats to have been updated recently to be accurate
|
||||
- (CGFloat)fileProgress:(FileListNode*)node;
|
||||
|
|
|
@ -158,7 +158,6 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
|
||||
NSString* fHashString;
|
||||
|
||||
tr_file_stat* fFileStat;
|
||||
NSArray* fFileList;
|
||||
NSArray* fFlatFileList;
|
||||
|
||||
|
@ -293,11 +292,6 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
- (void)dealloc
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
|
||||
if (fFileStat)
|
||||
{
|
||||
tr_torrentFilesFree(fFileStat, self.fileCount);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
|
@ -1561,16 +1555,6 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
return fInfo->fileCount;
|
||||
}
|
||||
|
||||
- (void)updateFileStat
|
||||
{
|
||||
if (fFileStat)
|
||||
{
|
||||
tr_torrentFilesFree(fFileStat, self.fileCount);
|
||||
}
|
||||
|
||||
fFileStat = tr_torrentFiles(fHandle, NULL);
|
||||
}
|
||||
|
||||
- (CGFloat)fileProgress:(FileListNode*)node
|
||||
{
|
||||
if (self.fileCount == 1 || self.complete)
|
||||
|
@ -1578,28 +1562,17 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
return self.progress;
|
||||
}
|
||||
|
||||
if (!fFileStat)
|
||||
{
|
||||
[self updateFileStat];
|
||||
}
|
||||
|
||||
// #5501
|
||||
if (node.size == 0)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
NSIndexSet* indexSet = node.indexes;
|
||||
|
||||
if (indexSet.count == 1)
|
||||
{
|
||||
return fFileStat[indexSet.firstIndex].progress;
|
||||
}
|
||||
|
||||
uint64_t have = 0;
|
||||
NSIndexSet* indexSet = node.indexes;
|
||||
for (NSInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
||||
{
|
||||
have += fFileStat[index].bytesCompleted;
|
||||
have += tr_torrentFileProgress(fHandle, index).bytes_completed;
|
||||
}
|
||||
|
||||
return (CGFloat)have / node.size;
|
||||
|
@ -1619,14 +1592,10 @@ bool trashDataFile(char const* filename, tr_error** error)
|
|||
return NO;
|
||||
}
|
||||
|
||||
if (!fFileStat)
|
||||
{
|
||||
[self updateFileStat];
|
||||
}
|
||||
|
||||
__block BOOL canChange = NO;
|
||||
[indexSet enumerateIndexesWithOptions:NSEnumerationConcurrent usingBlock:^(NSUInteger index, BOOL* stop) {
|
||||
if (fFileStat[index].progress < 1.0)
|
||||
auto const progress = tr_torrentFileProgress(fHandle, index);
|
||||
if (progress.bytes_completed < progress.bytes_total)
|
||||
{
|
||||
canChange = YES;
|
||||
*stop = YES;
|
||||
|
|
|
@ -478,15 +478,15 @@ TEST_F(RenameTest, partialFile)
|
|||
{
|
||||
auto constexpr PieceCount = uint32_t{ 33 };
|
||||
auto constexpr PieceSize = uint32_t{ 32768 };
|
||||
auto const length = std::array<uint32_t, 3>{ 1048576, 4096, 512 };
|
||||
auto const total_size = uint64_t(length[0]) + length[1] + length[2];
|
||||
auto constexpr Length = std::array<uint32_t, 3>{ 1048576, 4096, 512 };
|
||||
auto constexpr TotalSize = uint64_t(Length[0]) + Length[1] + Length[2];
|
||||
|
||||
/***
|
||||
**** create our test torrent with an incomplete .part file
|
||||
***/
|
||||
|
||||
auto* tor = zeroTorrentInit();
|
||||
EXPECT_EQ(total_size, tor->info.totalSize);
|
||||
EXPECT_EQ(TotalSize, tor->info.totalSize);
|
||||
EXPECT_EQ(PieceSize, tor->info.pieceSize);
|
||||
EXPECT_EQ(PieceCount, tor->info.pieceCount);
|
||||
EXPECT_STREQ("files-filled-with-zeroes/1048576", tor->info.files[0].name);
|
||||
|
@ -494,13 +494,11 @@ TEST_F(RenameTest, partialFile)
|
|||
EXPECT_STREQ("files-filled-with-zeroes/512", tor->info.files[2].name);
|
||||
|
||||
zeroTorrentPopulate(tor, false);
|
||||
auto* fst = tr_torrentFiles(tor, nullptr);
|
||||
EXPECT_EQ(length[0] - PieceSize, fst[0].bytesCompleted);
|
||||
EXPECT_EQ(length[1], fst[1].bytesCompleted);
|
||||
EXPECT_EQ(length[2], fst[2].bytesCompleted);
|
||||
tr_torrentFilesFree(fst, tor->info.fileCount);
|
||||
EXPECT_EQ(Length[0], tr_torrentFileProgress(tor, 0).bytes_completed + PieceSize);
|
||||
EXPECT_EQ(Length[1], tr_torrentFileProgress(tor, 1).bytes_completed);
|
||||
EXPECT_EQ(Length[2], tr_torrentFileProgress(tor, 2).bytes_completed);
|
||||
auto const* st = tr_torrentStat(tor);
|
||||
EXPECT_EQ(total_size, st->sizeWhenDone);
|
||||
EXPECT_EQ(TotalSize, st->sizeWhenDone);
|
||||
EXPECT_EQ(PieceSize, st->leftUntilDone);
|
||||
|
||||
/***
|
||||
|
|
Loading…
Reference in New Issue