Skip to content

Feature request: per-peer piece availability in PeerStats #643

Description

@adamgreenwell

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions