package com.limegroup.gnutella.downloader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.auth.Credentials; import org.limewire.collection.IntervalSet; import org.limewire.io.Address; import org.limewire.util.Objects; import com.limegroup.gnutella.RemoteFileDesc; import com.limegroup.gnutella.URN; public class RemoteFileDescContext { private static final Log LOG = LogFactory.getLog(RemoteFileDescContext.class); private final RemoteFileDesc remoteFileDesc; /** * The number of times this download has failed while attempting * to transfer data. */ private int failedCount; /** * The list of available ranges. * This is NOT SERIALIZED. */ private IntervalSet availableRanges; /** * Whether or not THEX retrieval has failed with this host. */ private boolean thexFailed; /** * The last known queue status of the remote host * negative values mean free slots. */ private int queueStatus = Integer.MAX_VALUE; /** * The earliest time to retry this host in milliseconds since 01-01-1970. */ private volatile long earliestRetryTime; /** * The time at which this host was head pinged, or 0 if not applicable. */ private volatile long pingTime = 0; /** * The time at which this host returned a head pong, or 0 if not applicable. */ private volatile long pongTime = 0; public RemoteFileDescContext(RemoteFileDesc remoteFileDesc) { this.remoteFileDesc = Objects.nonNull(remoteFileDesc, "remoteFileDesc"); } public RemoteFileDesc getRemoteFileDesc() { return remoteFileDesc; } /** * Returns the current failed count. */ public int getFailedCount() { return failedCount; } /** * Increments the failed count by one. */ public void incrementFailedCount() { ++failedCount; } /** * Resets the failed count back to zero. */ public void resetFailedCount() { this.failedCount = 0; } /** * Accessor for the available ranges. */ public IntervalSet getAvailableRanges() { try { return availableRanges.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } /** * Mutator for the available ranges. */ public void setAvailableRanges(IntervalSet availableRanges) { this.availableRanges = availableRanges; } /** * Returns true if this is a partial source. */ public boolean isPartialSource() { return availableRanges != null; } /** * @return true if this host is still busy and should not be retried */ public boolean isBusy() { return isBusy(System.currentTimeMillis()); } public boolean isBusy(long now) { return now < earliestRetryTime; } /** * @return time to wait until this host will be ready to be retried * in seconds */ public int getWaitTime(long now) { return isBusy(now) ? (int) (earliestRetryTime - now)/1000 + 1 : 0; } /** * Mutator for _earliestRetryTime. * @param seconds number of seconds to wait before retrying */ public void setRetryAfter(int seconds) { if(LOG.isDebugEnabled()) LOG.debug("setting retry after to be [" + seconds + "] seconds for " + this); earliestRetryTime = System.currentTimeMillis() + seconds*1000; } /** * Records the time at which the most recent head ping was sent. */ public void recordPingTime(long now) { pingTime = now; } /** * Records the time at which the most recent head pong was received. */ public void recordPongTime(long now) { pongTime = now; } /** * Returns the round-trip time if a pong has been received for the * most recent head ping, otherwise returns Long.MAX_VALUE. */ public long getRoundTripTime() { if(pongTime > pingTime) return pongTime - pingTime; else return Long.MAX_VALUE; } /** * @return Returns the _THEXFailed. */ public boolean hasTHEXFailed() { return thexFailed; } /** * Having THEX with this host is no good. We can get our THEX from anybody, * so we won't bother again. */ public void setTHEXFailed() { thexFailed = true; } public URN getSHA1Urn() { return remoteFileDesc.getSHA1Urn(); } public boolean isReplyToMulticast() { return remoteFileDesc.isReplyToMulticast(); } public int getQueueStatus() { return queueStatus; } public void setQueueStatus(int queueStatus) { this.queueStatus = queueStatus; } public Address getAddress() { return remoteFileDesc.getAddress(); } public Credentials getCredentials() { return remoteFileDesc.getCredentials(); } public boolean isFromAlternateLocation() { return remoteFileDesc.isFromAlternateLocation(); } @Override public String toString() { return remoteFileDesc.toString(); } }