java.lang.Object
org.klomp.snark.PartialPiece
All Implemented Interfaces:
Comparable<PartialPiece>

class PartialPieceextends Object implements Comparable<PartialPiece>
Represents a piece of a torrent being downloaded, storing partial data either on the heap or in a temporary file if the piece is large.

Handles out-of-order chunk reception and manages a BitField tracking received chunks. Implements Comparable for prioritization by piece number and completeness.

Usage Notes: - Not thread-safe except for synchronized public methods. - Objects for the same piece should not be shared between peers. - Used extensively by PeerCoordinator and PeerState for request management.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final ByteCache
    Cache supplying the chunk buffers.
    private final MetaInfo
    BEP 47: to recognize padding-only chunks and skip requesting them; may be null.
    private BitField
    BEP 47: per-piece padding sub-block mask, lazily computed; null until first use.
    private final BitField
    Which chunks have arrived so far.
    private final byte[]
    In-memory storage if the piece is small.
    private static final int
    Size of a chunk part.
    private static final int
    Largest piece kept in memory by default.
    private static int
    Threshold below which pieces are kept in memory rather than a temp file, can be reduced dynamically.
    private int
    Offset of the next expected chunk start.
    private final int
    Length of the piece in bytes.
    private final Piece
    The piece being filled in.
    File the piece data is written through.
    private static final int
    BEP 47: sub-block granularity for requests that straddle padding files.
    private final File
    Directory for the temp file of a large piece.
    private File
    The temp file holding the piece data.
  • Constructor Summary

    Constructors
    Constructor
    Description
    PartialPiece(Piece piece, int len, File tempDir)
    A PartialPiece for the given piece with the specified length.
    PartialPiece(Piece piece, int len, File tempDir, MetaInfo meta)
    A PartialPiece for the given piece with the specified length.
  • Method Summary

    Modifier and Type
    Method
    Description
    int
    Compares this piece with another by piece number, highest priority first, then by highest downloaded first.
    private void
    Creates the temporary file and opens a RandomAccessFile.
    static void
    Logs a debug message for this class.
    boolean
    Equality based on piece ID only.
    int
    Returns the total number of bytes downloaded in this piece, accurately accounting for holes.
    byte[]
    Computes and returns the SHA1 hash of the complete piece data.
    int
    Returns the length of the piece in bytes.
    int
    Returns the piece number.
    Creates a Request object for the next missing chunk in this piece.
    getRequest(int minOffset)
    Creates a Request object for the next missing chunk at or after the given offset.
    private void
    handleChunkReception(int subBlock, int offset, int len)
    Handles updating the bitfield and offset when a chunk is received.
    boolean
    Checks if any chunks of this piece have been downloaded.
    int
     
    boolean
    hasSubBlock(int subBlock)
    Checks if the given sub-block index has been downloaded.
    static void
    Logs an info message for this class.
    boolean
    Checks if the entire piece has been downloaded.
    (package private) boolean
    isPaddingSubBlock(int subBlock)
    True if the sub-block lies entirely within BEP 47 padding files.
    void
    markSubBlock(int subBlock)
    Marks a sub-block as received without any data, for BEP 47 padding-only sub-blocks whose bytes are all zeros.
    void
    read(DataInputStream din, int offset, int len, BandwidthListener bwl)
    Reads data from the input stream into this piece starting at offset.
    void
    Releases temporary file and resources associated with this piece.
     
    static void
    Logs a warning message for this class.
    void
    write(DataOutput out, int offset, int len)
    Writes piece data from the given offset and length to the output.

    Methods inherited from class Object

    clone, getClass, notify, notifyAll, wait, wait, wait
  • Field Details

    • piece

      private final Piece piece
      The piece being filled in.
    • bs

      private final byte[] bs
      In-memory storage if the piece is small.
    • pclen

      private final int pclen
      Length of the piece in bytes.
    • tempDir

      private final File tempDir
      Directory for the temp file of a large piece.
    • _meta

      private final MetaInfo _meta
      BEP 47: to recognize padding-only chunks and skip requesting them; may be null.
    • _paddingMask

      private volatile BitField _paddingMask
      BEP 47: per-piece padding sub-block mask, lazily computed; null until first use.
    • tempfile

      private File tempfile
      The temp file holding the piece data.
    • raf

      private RandomAccessFile raf
      File the piece data is written through.
    • bitfield

      private final BitField bitfield
      Which chunks have arrived so far.
    • off

      private int off
      Offset of the next expected chunk start.
    • BUFSIZE

      private static final int BUFSIZE
      Size of a chunk part.
    • _cache

      private static final ByteCache _cache
      Cache supplying the chunk buffers.
    • SUB_PARTSIZE

      private static final int SUB_PARTSIZE
      BEP 47: sub-block granularity for requests that straddle padding files. A request is a run of consecutive real sub-blocks capped at PARTSIZE, so at most SUB_PARTSIZE bytes of padding are ever requested per boundary. A power of two, so it is the same class of block size as the short tail block every client accepts.

      Next logical step: request the exact real sub-range of a straddling sub-block instead of the whole sub-block, eliminating the remaining pad waste entirely. Risk: arbitrary (non power-of-two) block sizes are rejected by a few strict peers; reward: up to ~2K average pad bytes per boundary, tens of MB on pad-heavy torrents. Would require a per-peer fallback to sub-block requests.

    • MAX_IN_MEM

      private static final int MAX_IN_MEM
      Largest piece kept in memory by default.
      See Also:
    • maxInMem

      private static int maxInMem
      Threshold below which pieces are kept in memory rather than a temp file, can be reduced dynamically.
  • Constructor Details

    • PartialPiece

      public PartialPiece(Piece piece, int len, File tempDir)
      A PartialPiece for the given piece with the specified length. If piece length exceeds threshold or memory is constrained, stores on disk.
      Parameters:
      piece - The Piece identifier object
      len - Length of this piece in bytes (must match piece length)
      tempDir - Directory for temporary file storage if needed
    • PartialPiece

      public PartialPiece(Piece piece, int len, File tempDir, MetaInfo meta)
      A PartialPiece for the given piece with the specified length. If piece length exceeds threshold or memory is constrained, stores on disk.
      Parameters:
      piece - The Piece identifier object
      len - Length of this piece in bytes (must match piece length)
      tempDir - Directory for temporary file storage if needed
      meta - the torrent meta info, for skipping BEP 47 padding-only chunks, or null
  • Method Details

    • createTemp

      private void createTemp() throws IOException
      Creates the temporary file and opens a RandomAccessFile. Synchronized for safe concurrent use.
      Throws:
      IOException - if file creation or opening fails
    • getRequest

      public Request getRequest()
      Creates a Request object for the next missing chunk in this piece. Returns null if the entire piece is complete. Chunks lying entirely within BEP 47 padding files are marked as received (their data is all zeros) and never requested.
      Returns:
      the next Request for downloading or null if complete
    • getRequest

      public Request getRequest(int minOffset)
      Creates a Request object for the next missing chunk at or after the given offset. Chunks lying entirely within BEP 47 padding files are marked as received (their data is all zeros) and never requested. A request is a run of consecutive real sub-blocks capped at PARTSIZE, so a chunk straddling a padding file is fetched at sub-block granularity, wasting at most SUB_PARTSIZE bytes of padding.
      Parameters:
      minOffset - byte offset to start scanning at, rounded up to a sub-block boundary; the caller advances it past the last request (callers pass 0 or off + len, both already sub-block aligned) so in-flight chunks are not re-requested
      Returns:
      the next Request for downloading or null if complete
    • markSubBlock

      public void markSubBlock(int subBlock)
      Marks a sub-block as received without any data, for BEP 47 padding-only sub-blocks whose bytes are all zeros. The in-memory buffer stays zero-filled, so the piece hashes correctly once the remaining sub-blocks arrive. Does not advance the sequential offset; the caller's scan does that.
      Parameters:
      subBlock - zero-based sub-block index
    • isPaddingSubBlock

      boolean isPaddingSubBlock(int subBlock)
      True if the sub-block lies entirely within BEP 47 padding files. The padding layout of a piece never changes, so the sub-block mask is computed once on first use.
      Parameters:
      subBlock - zero-based sub-block index
      Returns:
      true if the whole sub-block falls inside the padded range of the file, false if it carries real data
    • getPiece

      public int getPiece()
      Returns the piece number.
      Returns:
      piece number identifier
    • getLength

      public int getLength()
      Returns the length of the piece in bytes.
      Returns:
      the piece length; the last piece of a torrent may be shorter
    • isComplete

      public boolean isComplete()
      Checks if the entire piece has been downloaded.
      Returns:
      true if complete, else false
    • hasData

      public boolean hasData()
      Checks if any chunks of this piece have been downloaded.
      Returns:
      true if any data present, false if none
    • hasSubBlock

      public boolean hasSubBlock(int subBlock)
      Checks if the given sub-block index has been downloaded.
      Parameters:
      subBlock - zero-based sub-block index
      Returns:
      true if sub-block downloaded, false otherwise
    • getDownloaded

      public int getDownloaded()
      Returns the total number of bytes downloaded in this piece, accurately accounting for holes.
      Returns:
      number of bytes downloaded
    • getHash

      public byte[] getHash() throws IOException
      Computes and returns the SHA1 hash of the complete piece data. Caller must ensure piece completeness and synchronize before calling.
      Returns:
      the 20 byte SHA1 of the piece data
      Throws:
      IOException - if data is incomplete or read fails
    • read

      public void read(DataInputStream din, int offset, int len, BandwidthListener bwl) throws IOException
      Reads data from the input stream into this piece starting at offset. Marks chunks as downloaded in the bitfield. Handles out-of-order chunks by logging warnings.
      Parameters:
      din - input stream to read from
      offset - offset to read into the piece (must be multiple of chunk size)
      len - length of data to read
      bwl - bandwidth listener to report downloaded bytes
      Throws:
      IOException - on I/O errors or incorrect offset
    • handleChunkReception

      private void handleChunkReception(int subBlock, int offset, int len)
      Handles updating the bitfield and offset when a chunk is received. Logs warnings if out-of-order chunks or holes are detected. Caller must synchronize before calling.
      Parameters:
      subBlock - first sub-block index received (may span several)
      offset - byte offset in the piece corresponding to the sub-block
      len - length of data in bytes
    • write

      public void write(DataOutput out, int offset, int len) throws IOException
      Writes piece data from the given offset and length to the output. Caller must synchronize on the output stream and piece for thread safety.
      Parameters:
      out - destination output to write data to
      offset - offset in this piece to start writing from
      len - length of data to write
      Throws:
      IOException - on I/O failure
    • release

      public void release()
      Releases temporary file and resources associated with this piece. Safe to call multiple times.
    • compareTo

      public int compareTo(PartialPiece other)
      Compares this piece with another by piece number, highest priority first, then by highest downloaded first.
      Specified by:
      compareTo in interface Comparable<PartialPiece>
      Parameters:
      other - the other PartialPiece to compare to
      Returns:
      negative if this piece has higher priority, positive if lower, zero if equal
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • equals

      public boolean equals(Object o)
      Equality based on piece ID only.
      Overrides:
      equals in class Object
      Parameters:
      o - Object to compare
      Returns:
      true if representing the same piece ID, else false
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • warn

      public static void warn(String s)
      Logs a warning message for this class.
      Parameters:
      s - warning message string
    • debug

      public static void debug(String s)
      Logs a debug message for this class.
      Parameters:
      s - debug message string
    • info

      public static void info(String s)
      Logs an info message for this class.
      Parameters:
      s - info message string