## org.klomp.snark
Class PeerCoordinator

    java.lang.Object
      org.klomp.snark.PeerCoordinator

All Implemented Interfaces:
  PeerListener

    public class PeerCoordinator

extends Object
implements PeerListener

Coordinates what peer does what.

Field Summary
`(package private) static long` `CHECK_PERIOD`
`(package private) int` `interestedAndChoking` External use by PeerCheckerTask only.
`(package private) static int` `MAX_UPLOADERS`
`(package private) MetaInfo` `metainfo` External use by PeerMonitorTask only.
`(package private) Queue<Peer>` `peers` synchronize on this when changing peers or downloaders.
`(package private) static int` `RATE_DEPTH`
`(package private) Storage` `storage` External use by PeerMonitorTask only.
`(package private) int` `uploaders` Approximation of the number of current uploaders.

Constructor Summary
`PeerCoordinator(I2PSnarkUtil util, byte[] id, byte[] infohash, MetaInfo metainfo, Storage storage, CoordinatorListener listener, Snark torrent)`

Method Summary
`boolean` `addPeer(Peer peer)`
`int` `allowedUploaders()` Return number of allowed uploaders for this torrent.
`boolean` `completed()`
`void` `connected(Peer peer)` Called when the connection to the peer has started and the handshake was successfull.
`void` `disconnected(Peer peer)` Called when the connection to the peer was terminated or the connection handshake failed.
`void` `downloaded(Peer peer, int size)` Called when a peer has downloaded some bytes of a piece.
`long` `getCurrentUploadRate()`
`long` `getDownloaded()` Returns the total number of downloaded bytes of all peers.
`long` `getDownloadRate()` Returns the 4-minute-average rate in Bps
`byte[]` `getID()`
`byte[]` `getInfoHash()`
`long` `getLeft()` Returns how many bytes are still needed to get the complete file.
`MetaInfo` `getMetaInfo()`
`String` `getName()`
`PartialPiece` `getPartialPiece(Peer peer, BitField havePieces)` Return partial piece to the PeerState if it's still wanted and peer has it.
`int` `getPeerCount()` might be wrong
`int` `getPeers()` should be right
`(package private) Set<PeerID>` `getPEXPeers()` Called by TrackerClient
`(package private) static long` `getRate(long[] array)`
`Storage` `getStorage()`
`long` `getUploaded()` Returns the total number of uploaded bytes of all peers.
`int` `getUploaders()`
`long` `getUploadRate()`
`boolean` `gotBitField(Peer peer, BitField bitfield)` Returns true if the given bitfield contains at least one piece we are interested in.
`void` `gotChoke(Peer peer, boolean choke)` this does nothing but logging
`void` `gotExtension(Peer peer, int id, byte[] bs)` PeerListener callback
`boolean` `gotHave(Peer peer, int piece)` Called when a have piece message is received.
`void` `gotInterest(Peer peer, boolean interest)` Called when an interested message is received.
`void` `gotPeers(Peer peer, List<PeerID> peers)` PeerListener callback
`boolean` `gotPiece(Peer peer, int piece, byte[] bs)` Returns false if the piece is no good (according to the hash).
`void` `gotPort(Peer peer, int port)` PeerListener callback Tell the DHT to ping it, this will get back the node info
`byte[]` `gotRequest(Peer peer, int piece, int off, int len)` Returns a byte array containing the requested piece or null of the piece is unknown.
`void` `halt()`
`boolean` `halted()`
`boolean` `needPeers()`
`boolean` `needPiece(Peer peer, BitField havePieces)` Called when we are downloading from the peer and may need to ask for a new piece.
`boolean` `overUpBWLimit()`
`boolean` `overUpBWLimit(long total)`
`List<Peer>` `peerList()`
`void` `removePeerFromPieces(Peer peer)` Called when a peer is removed, to prevent it from being used in rarest-first calculations.
`void` `savePartialPieces(Peer peer, List<PartialPiece> partials)` Save partial pieces on peer disconnection and hopefully restart it later.
`(package private) void` `sendPeers(Peer peer)` Send a PEX message to the peer, if he supports PEX.
`(package private) static void` `setRate(long val, long[] array)`
`void` `setRateHistory(long up, long down)` Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
`void` `setStorage(Storage stg)` Sets the storage after transition out of magnet mode Snark calls this after we call gotMetaInfo()
`void` `setWantedPieces()`
`(package private) void` `unchokePeer()`
`void` `updatePiecePriorities()` Maps file priorities to piece priorities.
`void` `uploaded(Peer peer, int size)` Called when a peer has uploaded some bytes of a piece.
`int` `wantPiece(Peer peer, BitField havePieces)` Returns one of pieces in the given BitField that is still wanted or -1 if none of the given pieces are wanted.

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Field Detail

### metainfo

    MetaInfo metainfo

  External use by PeerMonitorTask only. Will be null when in magnet mode.

### storage

    Storage storage

  External use by PeerMonitorTask only. Will be null when in magnet mode.

### CHECK_PERIOD

    static final long CHECK_PERIOD

See Also:
  Constant Field Values

### MAX_UPLOADERS

    static final int MAX_UPLOADERS

See Also:
  Constant Field Values

### uploaders

    int uploaders

  Approximation of the number of current uploaders. Resynced by PeerChecker once in a while. External use by PeerCheckerTask only.

### interestedAndChoking

    int interestedAndChoking

  External use by PeerCheckerTask only.

### RATE_DEPTH

    static final int RATE_DEPTH

See Also:
  Constant Field Values

### peers

    final Queue<Peer> peers

  synchronize on this when changing peers or downloaders. This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking. External use by PeerMonitorTask only.

Constructor Detail

### PeerCoordinator

    public PeerCoordinator(I2PSnarkUtil util,
                           byte[] id,
                           byte[] infohash,
                           MetaInfo metainfo,
                           Storage storage,
                           CoordinatorListener listener,
                           Snark torrent)

Parameters:
  `metainfo` - null if in magnet mode
  `storage` - null if in magnet mode

Method Detail

### setWantedPieces

    public void setWantedPieces()

### getStorage

    public Storage getStorage()

### peerList

    public List<Peer> peerList()

### getID

    public byte[] getID()

### getName

    public String getName()

### completed

    public boolean completed()

### getPeerCount

    public int getPeerCount()

  might be wrong

### getPeers

    public int getPeers()

  should be right

### getLeft

    public long getLeft()

  Returns how many bytes are still needed to get the complete file.

  Returns:
    -1 if in magnet mode

### getUploaded

    public long getUploaded()

  Returns the total number of uploaded bytes of all peers.

### getDownloaded

    public long getDownloaded()

  Returns the total number of downloaded bytes of all peers.

### setRateHistory

    public void setRateHistory(long up,
                               long down)

  Push the total uploaded/downloaded onto a RATE_DEPTH deep stack

### setRate

    static void setRate(long val,
                        long[] array)

### getDownloadRate

    public long getDownloadRate()

  Returns the 4-minute-average rate in Bps

### getUploadRate

    public long getUploadRate()

### getCurrentUploadRate

    public long getCurrentUploadRate()

### getRate

    static long getRate(long[] array)

### getMetaInfo

    public MetaInfo getMetaInfo()

### getInfoHash

    public byte[] getInfoHash()

  Since:
    0.8.4

### needPeers

    public boolean needPeers()

### halted

    public boolean halted()

### halt

    public void halt()

### connected

    public void connected(Peer peer)

  Description copied from interface: `PeerListener`
  Called when the connection to the peer has started and the handshake was successfull.

  Specified by:
    `connected` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that just got connected.

### addPeer

    public boolean addPeer(Peer peer)

### unchokePeer

    void unchokePeer()

### gotHave

    public boolean gotHave(Peer peer,
                           int piece)

  Description copied from interface: `PeerListener`
  Called when a have piece message is received. If the method returns true and the peer has not yet received a interested message or we indicated earlier to be not interested then an interested message will be send.

  Specified by:
    `gotHave` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `piece` - the piece number that the per just got.
  Returns:
    true if we still want the given piece

### gotBitField

    public boolean gotBitField(Peer peer,
                               BitField bitfield)

  Returns true if the given bitfield contains at least one piece we are interested in.

  Specified by:
    `gotBitField` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `bitfield` - a BitField containing the pieces that the other side has.
  Returns:
    true when the BitField contains pieces we want, false if the piece is already known.

### wantPiece

    public int wantPiece(Peer peer,
                         BitField havePieces)

  Returns one of pieces in the given BitField that is still wanted or -1 if none of the given pieces are wanted.

  Specified by:
    `wantPiece` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that will be asked to provide the piece.
    `havePieces` - a BitField containing the pieces that the other side has.
  Returns:
    one of the pieces from the bitfield that we want or -1 if we are no longer interested in the peer.

### updatePiecePriorities

    public void updatePiecePriorities()

  Maps file priorities to piece priorities. Call after updating file priorities Storage.setPriority()

  Since:
    0.8.1

### gotRequest

    public byte[] gotRequest(Peer peer,
                             int piece,
                             int off,
                             int len)

  Returns a byte array containing the requested piece or null of the piece is unknown.

  Specified by:
    `gotRequest` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that wants the piece.
    `piece` - the piece number requested.
    `off` - byte offset into the piece.
    `len` - length of the chunk requested.
  Returns:
    a byte array containing the piece or null when the piece is not available (which is a protocol error).
  Throws:
    `RuntimeException` - on IOE getting the data

### uploaded

    public void uploaded(Peer peer,
                         int size)

  Called when a peer has uploaded some bytes of a piece.

  Specified by:
    `uploaded` in interface `PeerListener`
  Parameters:
    `peer` - the Peer to which size bytes where uploaded.
    `size` - the number of bytes that where uploaded.

### downloaded

    public void downloaded(Peer peer,
                           int size)

  Called when a peer has downloaded some bytes of a piece.

  Specified by:
    `downloaded` in interface `PeerListener`
  Parameters:
    `peer` - the Peer from which size bytes where downloaded.
    `size` - the number of bytes that where downloaded.

### gotPiece

    public boolean gotPiece(Peer peer,
                            int piece,
                            byte[] bs)

  Returns false if the piece is no good (according to the hash). In that case the peer that supplied the piece should probably be blacklisted.

  Specified by:
    `gotPiece` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the piece.
    `piece` - the piece number received.
    `bs` - the byte array containing the piece.
  Returns:
    true when the bytes represent the piece, false otherwise.
  Throws:
    `RuntimeException` - on IOE saving the piece

### gotChoke

    public void gotChoke(Peer peer,
                         boolean choke)

  this does nothing but logging

  Specified by:
    `gotChoke` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `choke` - true when the peer got a choke message, false when the peer got an unchoke message.

### gotInterest

    public void gotInterest(Peer peer,
                            boolean interest)

  Description copied from interface: `PeerListener`
  Called when an interested message is received.

  Specified by:
    `gotInterest` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `interest` - true when the peer got a interested message, false when the peer got an uninterested message.

### disconnected

    public void disconnected(Peer peer)

  Description copied from interface: `PeerListener`
  Called when the connection to the peer was terminated or the connection handshake failed.

  Specified by:
    `disconnected` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that just got disconnected.

### removePeerFromPieces

    public void removePeerFromPieces(Peer peer)

  Called when a peer is removed, to prevent it from being used in rarest-first calculations.

### savePartialPieces

    public void savePartialPieces(Peer peer,
                                  List<PartialPiece> partials)

  Save partial pieces on peer disconnection and hopefully restart it later. Replace a partial piece in the List if the new one is bigger. Storage method is private so we can expand to save multiple partials if we wish. Also mark the piece unrequested if this peer was the only one.

  Specified by:
    `savePartialPieces` in interface `PeerListener`
  Parameters:
    `peer` - partials, must include the zero-offset (empty) ones too
  Since:
    0.8.2

### getPartialPiece

    public PartialPiece getPartialPiece(Peer peer,
                                        BitField havePieces)

  Return partial piece to the PeerState if it's still wanted and peer has it.

  Specified by:
    `getPartialPiece` in interface `PeerListener`
  Parameters:
    `havePieces` - pieces the peer has, the rv will be one of these
  Returns:
    PartialPiece or null
  Since:
    0.8.2

### needPiece

    public boolean needPiece(Peer peer,
                             BitField havePieces)

  Called when we are downloading from the peer and may need to ask for a new piece. Returns true if wantPiece() or getPartialPiece() would return a piece.

  Specified by:
    `needPiece` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that will be asked to provide the piece.
    `havePieces` - a BitField containing the pieces that the other side has.
  Returns:
    if we want any of what the peer has
  Since:
    0.8.2

### gotExtension

    public void gotExtension(Peer peer,
                             int id,
                             byte[] bs)

  PeerListener callback

  Specified by:
    `gotExtension` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `id` - the message ID
    `bs` - the message payload
  Since:
    0.8.4

### sendPeers

    void sendPeers(Peer peer)

  Send a PEX message to the peer, if he supports PEX. This just sends everybody we are connected to, we don't track new vs. old peers yet.

  Since:
    0.8.4

### setStorage

    public void setStorage(Storage stg)

  Sets the storage after transition out of magnet mode Snark calls this after we call gotMetaInfo()

  Since:
    0.8.4

### gotPort

    public void gotPort(Peer peer,
                        int port)

  PeerListener callback Tell the DHT to ping it, this will get back the node info

  Specified by:
    `gotPort` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `port` - the port
  Since:
    0.8.4

### gotPeers

    public void gotPeers(Peer peer,
                         List<PeerID> peers)

  PeerListener callback

  Specified by:
    `gotPeers` in interface `PeerListener`
  Parameters:
    `peer` - the Peer that got the message.
    `peers` - the peer IDs (dest hashes)
  Since:
    0.8.4

### getPEXPeers

    Set<PeerID> getPEXPeers()

  Called by TrackerClient

  Since:
    0.8.4

### allowedUploaders

    public int allowedUploaders()

  Return number of allowed uploaders for this torrent. Check with Snark to see if we are over the total upload limit.

### getUploaders

    public int getUploaders()

  Returns:
    current
  Since:
    0.8.4

### overUpBWLimit

    public boolean overUpBWLimit()

### overUpBWLimit

    public boolean overUpBWLimit(long total)