What I am trying to do
I am embedding librqbit in a desktop application and would like to answer,
for a running torrent: will this finish?
That turns out to be a different question from "is it downloading". A torrent
connected to forty peers who all stopped at 6% will not finish; one connected
to six peers who between them hold every piece will. Distinguishing those needs
piece availability — the union of the connected peers' bitfields, or at minimum
a rarest-piece copy count.
What I found
PeerStats (torrent_state/live/peer/stats/snapshot.rs) currently carries:
pub struct PeerStats {
pub counters: PeerCounters,
pub state: &'static str,
pub conn_kind: Option<ConnectionKind>,
pub client_name: Option<String>,
}
PeerCounters::downloaded_and_checked_pieces is how many pieces a peer has
sent me, rather than how many that peer holds. api_dump_haves returns my own
bitfield. So I do not think either gets me there, though I would be glad to be
wrong about that.
I looked at main as well as 9.0.0 and PeerStats reads the same on both.
The underlying data seems to be present
LivePeerState (torrent_state/live/peer/mod.rs) has, per peer:
// This is used to track the pieces the peer has.
pub bitfield: BF,
which is maintained for piece picking. So the tracking already happens; what I
am missing is a way to read it from outside.
Things I tried first
I looked for a way to do this without changing the crate:
PeerConnectionHandler::on_received_message receives Bitfield and Have,
which would be ideal, but mod peer_connection is private so the trait is
not reachable from a dependent crate.
StorageFactory / TorrentStorage are public and injectable through
SessionOptions.default_storage_factory, but they see disk I/O rather than
peer messages.
BitV / BitVFactory are in private modules and relate to persisting my own
bitfield.
- I could not find an observer or callback field on
SessionOptions.
If there is an approach I have overlooked, I would much rather use it than ask
for an API change.
Possible shapes
A count on PeerStats:
pub struct PeerStats {
// ...
/// How many pieces this peer has, from its bitfield.
pub have_pieces: u32,
}
populated in impl From<&Peer> for PeerStats. This would be enough for a
rarest-piece copy count and a swarm-health verdict, which is all I need.
The bitfield itself, e.g. as Option<Vec<u8>> or behind an accessor. A
larger payload, but it would also allow a per-region availability histogram
rather than a single number. I mention it only because it is the same data; the
count alone would cover my use case.
A third option would be making PeerConnectionHandler reachable so embedders
can observe protocol messages directly, though that is a much larger surface to
commit to.
Offer
If one of these looks reasonable, I am happy to put together a PR — or to adapt
to a different shape if you have one in mind. I did not want to send an
unsolicited patch that changes a public type without checking what you would
prefer first.
Either way, no urgency from my side.
Checked against 9.0.0 and main. Thanks for the library; the v9 reorganisation
made embedding it noticeably cleaner.
What I am trying to do
I am embedding
librqbitin a desktop application and would like to answer,for a running torrent: will this finish?
That turns out to be a different question from "is it downloading". A torrent
connected to forty peers who all stopped at 6% will not finish; one connected
to six peers who between them hold every piece will. Distinguishing those needs
piece availability — the union of the connected peers' bitfields, or at minimum
a rarest-piece copy count.
What I found
PeerStats(torrent_state/live/peer/stats/snapshot.rs) currently carries:PeerCounters::downloaded_and_checked_piecesis how many pieces a peer hassent me, rather than how many that peer holds.
api_dump_havesreturns my ownbitfield. So I do not think either gets me there, though I would be glad to be
wrong about that.
I looked at
mainas well as 9.0.0 andPeerStatsreads the same on both.The underlying data seems to be present
LivePeerState(torrent_state/live/peer/mod.rs) has, per peer:which is maintained for piece picking. So the tracking already happens; what I
am missing is a way to read it from outside.
Things I tried first
I looked for a way to do this without changing the crate:
PeerConnectionHandler::on_received_messagereceivesBitfieldandHave,which would be ideal, but
mod peer_connectionis private so the trait isnot reachable from a dependent crate.
StorageFactory/TorrentStorageare public and injectable throughSessionOptions.default_storage_factory, but they see disk I/O rather thanpeer messages.
BitV/BitVFactoryare in private modules and relate to persisting my ownbitfield.
SessionOptions.If there is an approach I have overlooked, I would much rather use it than ask
for an API change.
Possible shapes
A count on
PeerStats:populated in
impl From<&Peer> for PeerStats. This would be enough for ararest-piece copy count and a swarm-health verdict, which is all I need.
The bitfield itself, e.g. as
Option<Vec<u8>>or behind an accessor. Alarger payload, but it would also allow a per-region availability histogram
rather than a single number. I mention it only because it is the same data; the
count alone would cover my use case.
A third option would be making
PeerConnectionHandlerreachable so embedderscan observe protocol messages directly, though that is a much larger surface to
commit to.
Offer
If one of these looks reasonable, I am happy to put together a PR — or to adapt
to a different shape if you have one in mind. I did not want to send an
unsolicited patch that changes a public type without checking what you would
prefer first.
Either way, no urgency from my side.
Checked against 9.0.0 and
main. Thanks for the library; the v9 reorganisationmade embedding it noticeably cleaner.