package org.klomp.snark; /** * This is the class passed from PeerCoordinator to PeerState so * PeerState may start requests. * * It is also passed from PeerState to PeerCoordinator when * a piece is not completely downloaded, for example * when the Peer disconnects or chokes. * * @since 0.8.2 */ class PartialPiece implements Comparable { private final int piece; private final byte[] bs; private final int off; private final long createdTime; /** * Used by PeerCoordinator. * Creates a new PartialPiece, with no chunks yet downloaded. * Allocates the data. * * @param piece Piece number requested. * @param len must be equal to the piece length */ public PartialPiece (int piece, int len) throws OutOfMemoryError { this.piece = piece; this.bs = new byte[len]; this.off = 0; this.createdTime = 0; } /** * Used by PeerState. * Creates a new PartialPiece, with chunks up to but not including * firstOutstandingRequest already downloaded and stored in the Request byte array. * * Note that this cannot handle gaps; chunks after a missing chunk cannot be saved. * That would be harder. * * @param firstOutstandingRequest the first request not fulfilled for the piece */ public PartialPiece (Request firstOutstandingRequest) { this.piece = firstOutstandingRequest.piece; this.bs = firstOutstandingRequest.bs; this.off = firstOutstandingRequest.off; this.createdTime = System.currentTimeMillis(); } /** * Convert this PartialPiece to a request for the next chunk. * Used by PeerState only. */ public Request getRequest() { return new Request(this.piece, this.bs, this.off, Math.min(this.bs.length - this.off, PeerState.PARTSIZE)); } /** piece number */ public int getPiece() { return this.piece; } /** how many bytes are good */ public int getDownloaded() { return this.off; } public long getCreated() { return this.createdTime; } /** * Highest downloaded first */ public int compareTo(Object o) throws ClassCastException { return ((PartialPiece)o).off - this.off; // reverse } @Override public int hashCode() { return piece * 7777; } /** * Make this simple so PeerCoordinator can keep a List. * Warning - compares piece number only! */ @Override public boolean equals(Object o) { if (o instanceof PartialPiece) { PartialPiece pp = (PartialPiece)o; return pp.piece == this.piece; } return false; } @Override public String toString() { return "Partial(" + piece + ',' + off + ',' + bs.length + ')'; } }