Expose files' begin and end pieces via RPC (#5578)

* Expose files' begin and end pieces via RPC

This adds two arguments, `beginPiece` and `endPiece`, for each of the entries
in the `files` array of the RPC's `torrent-`get` method.

The point is to allow RPC clients to display a file's completion progress as
piece-based in addition to byte-based.
This commit is contained in:
Daniel Kamil Kozar 2023-06-05 20:15:32 +02:00 committed by GitHub
parent 61679e1adc
commit c1c27f3da0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 29 additions and 4 deletions

View File

@ -294,6 +294,8 @@ The 'source' column here corresponds to the data structure there.
| `bytesCompleted` | number | tr_file_view
| `length` | number | tr_file_view
| `name` | string | tr_file_view
| `beginPiece` | number | tr_file_view
| `endPiece` | number | tr_file_view
`fileStats`: a file's non-constant properties. An array of `tr_info.filecount` objects, each containing:
@ -1009,3 +1011,5 @@ Transmission 4.1.0 (`rpc-version-semver` 5.4.0, `rpc-version`: 18)
|:---|:---
| `torrent-get` | new arg `sequentialDownload`
| `torrent-set` | new arg `sequentialDownload`
| `torrent-get` | new arg `files.beginPiece`
| `torrent-get` | new arg `files.endPiece`

View File

@ -18,7 +18,7 @@ using namespace std::literals;
namespace
{
auto constexpr MyStatic = std::array<std::string_view, 402>{ ""sv,
auto constexpr MyStatic = std::array<std::string_view, 404>{ ""sv,
"activeTorrentCount"sv,
"activity-date"sv,
"activityDate"sv,
@ -47,6 +47,7 @@ auto constexpr MyStatic = std::array<std::string_view, 402>{ ""sv,
"availability"sv,
"bandwidth-priority"sv,
"bandwidthPriority"sv,
"beginPiece"sv,
"bind-address-ipv4"sv,
"bind-address-ipv6"sv,
"bitfield"sv,
@ -108,6 +109,7 @@ auto constexpr MyStatic = std::array<std::string_view, 402>{ ""sv,
"editDate"sv,
"encoding"sv,
"encryption"sv,
"endPiece"sv,
"error"sv,
"errorString"sv,
"eta"sv,

View File

@ -50,6 +50,7 @@ enum
TR_KEY_availability, // rpc
TR_KEY_bandwidth_priority,
TR_KEY_bandwidthPriority,
TR_KEY_beginPiece,
TR_KEY_bind_address_ipv4,
TR_KEY_bind_address_ipv6,
TR_KEY_bitfield,
@ -111,6 +112,7 @@ enum
TR_KEY_editDate,
TR_KEY_encoding,
TR_KEY_encryption,
TR_KEY_endPiece,
TR_KEY_error,
TR_KEY_errorString,
TR_KEY_eta,

View File

@ -326,8 +326,10 @@ void addFiles(tr_torrent const* tor, tr_variant* list)
for (tr_file_index_t i = 0, n = tor->file_count(); i < n; ++i)
{
auto const file = tr_torrentFile(tor, i);
tr_variant* d = tr_variantListAddDict(list, 3);
tr_variant* d = tr_variantListAddDict(list, 5);
tr_variantDictAddInt(d, TR_KEY_beginPiece, file.beginPiece);
tr_variantDictAddInt(d, TR_KEY_bytesCompleted, file.have);
tr_variantDictAddInt(d, TR_KEY_endPiece, file.endPiece);
tr_variantDictAddInt(d, TR_KEY_length, file.length);
tr_variantDictAddStr(d, TR_KEY_name, file.name);
}

View File

@ -1615,14 +1615,15 @@ tr_file_view tr_torrentFile(tr_torrent const* tor, tr_file_index_t file)
auto const priority = tor->file_priorities_.file_priority(file);
auto const wanted = tor->files_wanted_.file_wanted(file);
auto const length = tor->file_size(file);
auto const [begin, end] = tor->pieces_in_file(file);
if (tor->completeness == TR_SEED || length == 0)
{
return { subpath.c_str(), length, length, 1.0, priority, wanted };
return { subpath.c_str(), length, length, 1.0, begin, end, priority, wanted };
}
auto const have = tor->completion.count_has_bytes_in_span(tor->fpm_.byte_span(file));
return { subpath.c_str(), have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
return { subpath.c_str(), have, length, have >= length ? 1.0 : have / double(length), begin, end, priority, wanted };
}
size_t tr_torrentFileCount(tr_torrent const* torrent)

View File

@ -1334,6 +1334,8 @@ struct tr_file_view
uint64_t have; // the current size of the file, i.e. how much we've downloaded
uint64_t length; // the total size of the file
double progress; // have / length
tr_piece_index_t beginPiece; // piece index where this file starts
tr_piece_index_t endPiece; // piece index where this file ends (exclusive)
tr_priority_t priority; // the file's priority
bool wanted; // do we want to download this file?
};

View File

@ -14,6 +14,8 @@
#include "gtest/gtest.h"
#include "test-fixtures.h"
using namespace std::literals;
using TorrentsTest = ::testing::Test;
@ -128,3 +130,13 @@ TEST_F(TorrentsTest, removedSince)
remove = { torrents_v[0]->id(), torrents_v[1]->id(), torrents_v[2]->id(), torrents_v[3]->id() };
EXPECT_EQ(remove, torrents.removedSince(50));
}
using TorrentsPieceSpanTest = libtransmission::test::SessionTest;
TEST_F(TorrentsPieceSpanTest, exposesFilePieceSpan)
{
auto tor = zeroTorrentInit(ZeroTorrentState::Complete);
auto file_view = tr_torrentFile(tor, 0);
EXPECT_EQ(file_view.beginPiece, 0);
EXPECT_EQ(file_view.endPiece, 32);
}