summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/filetransfer/util/AbstractTransfer.java
blob: 636f880c7486dc439645977c5699426fa50e78c0 (plain) (tree)
1
2
3
4


                                      
                                                 









































                                                                                                   

                                                                   

































                                                                                                         




                                           





















































                                                                                   
package org.openslx.filetransfer.util;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.openslx.bwlp.thrift.iface.TransferInformation;

public abstract class AbstractTransfer
{

	/**
	 * How long to keep this transfer information when the transfer is
	 * (potentially) done
	 */
	private static final long FINISH_TIMEOUT = TimeUnit.MINUTES.toMillis( 3 );

	/**
	 * How long to keep this transfer information when there are no active
	 * connections and the transfer seems unfinished
	 */
	private static final long IDLE_TIMEOUT = TimeUnit.HOURS.toMillis( 6 );

	/**
	 * How long to count this transfer towards active transfers when it has
	 * no active connection.
	 */
	private static final long HOT_IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis( 10 );
	/**
	 * Time stamp of when (we think) the transfer finished. Clients can/might
	 * not tell us they're done, and simply taking "no active connection" as a
	 * sign the download is done might have unwanted effects if the user's
	 * connection drops for a minute. If this time stamp (plus a FINISH_TIMEOUT)
	 * passed,
	 * we consider the download done and flag it for removal.
	 * If set to zero, the transfer is not finished, or not assumed to have
	 * finished.
	 */
	protected final AtomicLong potentialFinishTime = new AtomicLong( 0 );

	/**
	 * Time of last activity on this transfer.
	 */
	protected final AtomicLong lastActivityTime = new AtomicLong( System.currentTimeMillis() );

	private final String transferId;
	
	protected AtomicInteger connectFails = new AtomicInteger();

	public AbstractTransfer( String transferId )
	{
		this.transferId = transferId;
	}

	/**
	 * Returns true if the transfer is considered completed.
	 * 
	 * @param now pass System.currentTimeMillis()
	 * @return true if the transfer is considered completed
	 */
	public boolean isComplete( long now )
	{
		long val = potentialFinishTime.get();
		return val != 0 && val + FINISH_TIMEOUT < now;
	}

	/**
	 * Returns true if there has been no activity on this transfer for a certain
	 * amount of time.
	 * 
	 * @param now pass System.currentTimeMillis()
	 * @return true if the transfer reached its idle timeout
	 */
	public final boolean hasReachedIdleTimeout( long now )
	{
		return getActiveConnectionCount() == 0 && lastActivityTime.get() + IDLE_TIMEOUT < now;
	}

	public final boolean countsTowardsConnectionLimit( long now )
	{
		return getActiveConnectionCount() > 0 || lastActivityTime.get() + HOT_IDLE_TIMEOUT > now;
	}
	
	public final int connectFailCount()
	{
		return connectFails.get();
	}

	public final String getId()
	{
		return transferId;
	}

	public abstract TransferInformation getTransferInfo();

	/**
	 * Returns true if this transfer would potentially accept new connections.
	 * This should NOT return false if there are too many concurrent
	 * connections, as this is used to signal the client whether to keep trying
	 * to connect.
	 * 
	 * @return true if this transfer would potentially accept new connections
	 */
	public abstract boolean isActive();

	/**
	 * Cancel this transfer, aborting all active connections and rejecting
	 * further incoming ones.
	 */
	public abstract void cancel();

	/**
	 * Returns number of active transfer connections.
	 * 
	 * @return number of active transfer connections
	 */
	public abstract int getActiveConnectionCount();

	public abstract String getRelativePath();

	/**
	 * Try to close everything passed to this method. Never throw an exception
	 * if it fails, just silently continue.
	 * 
	 * @param item One or more objects that are AutoCloseable
	 */
	static void safeClose( AutoCloseable... item )
	{
		if ( item == null )
			return;
		for ( AutoCloseable c : item ) {
			if ( c == null )
				continue;
			try {
				c.close();
			} catch ( Exception e ) {
			}
		}
	}

}