/** * Display information about the BitTorrent client state. * * <p>This emits an information line in the log about this client's state. It includes the number * of choked peers, number of connected peers, number of known peers, information about the * torrent availability and completion and current transmission rates. */ public synchronized void info() { float dl = 0; float ul = 0; int numConnected = 0; for (SharingPeer peer : getConnectedPeers()) { dl += peer.getDLRate().get(); ul += peer.getULRate().get(); numConnected++; } for (SharedTorrent torrent : this.torrents.values()) { logger.debug( "{} {}/{} pieces ({}%) [{}/{}] with {}/{} peers at {}/{} kB/s.", new Object[] { torrent.getClientState().name(), torrent.getCompletedPieces().cardinality(), torrent.getPieceCount(), String.format("%.2f", torrent.getCompletion()), torrent.getAvailablePieces().cardinality(), torrent.getRequestedPieces().cardinality(), numConnected, this.peers.size(), String.format("%.2f", dl / 1024.0), String.format("%.2f", ul / 1024.0), }); } }
/** * Piece download completion handler. * * <p>When a piece is completed, and valid, we announce to all connected peers that we now have * this piece. * * <p>We use this handler to identify when all of the pieces have been downloaded. When that's the * case, we can start the seeding period, if any. * * @param peer The peer we got the piece from. * @param piece The piece in question. */ @Override public void handlePieceCompleted(SharingPeer peer, Piece piece) throws IOException { final SharedTorrent torrent = peer.getTorrent(); synchronized (torrent) { if (piece.isValid()) { // Make sure the piece is marked as completed in the torrent // Note: this is required because the order the // PeerActivityListeners are called is not defined, and we // might be called before the torrent's piece completion // handler is. torrent.markCompleted(piece); logger.debug( "Completed download of {}, now has {}/{} pieces.", new Object[] { piece, torrent.getCompletedPieces().cardinality(), torrent.getPieceCount() }); // Send a HAVE message to all connected peers PeerMessage have = PeerMessage.HaveMessage.craft(piece.getIndex()); for (SharingPeer remote : getConnectedPeers()) { remote.send(have); } } if (torrent.isComplete()) { logger.info("Last piece validated and completed, " + "download is complete."); torrent.finish(); try { this.announce .getCurrentTrackerClient(torrent) .announce( TrackerMessage.AnnounceRequestMessage.RequestEvent.COMPLETED, true, torrent); } catch (AnnounceException ae) { logger.warn("Error announcing completion event to " + "tracker: {}", ae.getMessage()); } torrent.setClientState(ClientState.SEEDING); if (seed == 0) { peer.unbind(false); this.announce.removeTorrent(torrent); } } } }