org.klomp.snark.web
Class FetchAndAdd

java.lang.Object
  extended by org.klomp.snark.Snark
      extended by org.klomp.snark.web.FetchAndAdd
All Implemented Interfaces:
Runnable, EepGet.StatusListener, CoordinatorListener, ShutdownListener, StorageListener

public class FetchAndAdd
extends Snark
implements EepGet.StatusListener, Runnable

A cancellable torrent file downloader. We extend Snark so its status may be easily listed in the web table without adding a lot of code there. Upon successful download, this Snark will be deleted and a "real" Snark created. The methods return values similar to a Snark in magnet mode. A fake info hash, which is the SHA1 of the URL, is returned to prevent duplicates. This Snark may be stopped and restarted, although a partially downloaded file is discarded.

Since:
0.9.1 Moved from I2PSnarkUtil

Field Summary
 
Fields inherited from class org.klomp.snark.Snark
_util, PROP_MAX_CONNECTIONS
 
Constructor Summary
FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url, File dataDir)
          Caller should call _mgr.addDownloader(this), which will start things off.
 
Method Summary
 void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause)
           
 void attempting(String url)
           
 void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url)
          alreadyTransferred - total of all attempts, not including currentWrite If nonzero on the first call, a partial file of that length was found, _and_ the server supports resume.
 String getBaseName()
           
 long getDownloaded()
           
 long getDownloadRate()
           
 byte[] getInfoHash()
           
 String getName()
           
 long getNeededLength()
          Bytes still wanted.
 int getPeerCount()
           
 long getRemainingLength()
          Bytes not yet in storage.
 long getTotalLength()
           
 int getTrackerSeenPeers()
           
 void headerReceived(String url, int attemptNum, String key, String val)
          Note: Headers are not processed, and this is not called, for most error response codes, unless setWriteErrorToOutput() is called before fetch().
 boolean isStopped()
           
 void run()
          Set off by startTorrent()
 void startTorrent()
          Start up contacting peers and querying the tracker.
 void stopTorrent()
          Stop contacting the tracker and talking with peers
 void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified)
           
 void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt)
           
 
Methods inherited from class org.klomp.snark.Snark
addMessage, getID, getMetaInfo, getNeeded, getPeerList, getPieceLength, getPieces, getStorage, getTrackerProblems, getTrackerURL, getUploaded, getUploadRate, gotMetaInfo, isAllocating, isAutoStoppable, isChecking, isStarting, overUpBWLimit, overUpBWLimit, overUploadLimit, peerChange, restartAcceptor, setAutoStoppable, setStarting, setTrackerProblems, setTrackerSeenPeers, setWantedPieces, shutdown, stopTorrent, storageAllChecked, storageAllocated, storageChecked, storageCompleted, storageCreateFile, updatePiecePriorities
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

FetchAndAdd

public FetchAndAdd(I2PAppContext ctx,
                   SnarkManager mgr,
                   String url,
                   File dataDir)
Caller should call _mgr.addDownloader(this), which will start things off.

Parameters:
dataDir - null to default to snark data directory
Method Detail

run

public void run()
Set off by startTorrent()

Specified by:
run in interface Runnable

startTorrent

public void startTorrent()
Description copied from class: Snark
Start up contacting peers and querying the tracker. Blocks if tunnel is not yet open.

Overrides:
startTorrent in class Snark

stopTorrent

public void stopTorrent()
Description copied from class: Snark
Stop contacting the tracker and talking with peers

Overrides:
stopTorrent in class Snark

isStopped

public boolean isStopped()
Overrides:
isStopped in class Snark

getName

public String getName()
Overrides:
getName in class Snark
Returns:
file name of .torrent file (should be full absolute path), or a fake name if in magnet mode.

getBaseName

public String getBaseName()
Overrides:
getBaseName in class Snark
Returns:
base name of torrent [filtered version of getMetaInfo.getName()], or a fake name if in magnet mode

getInfoHash

public byte[] getInfoHash()
Overrides:
getInfoHash in class Snark
Returns:
always will be valid even in magnet mode

getTotalLength

public long getTotalLength()
Overrides:
getTotalLength in class Snark
Returns:
torrent file size or -1

getRemainingLength

public long getRemainingLength()
Description copied from class: Snark
Bytes not yet in storage. Does NOT account for skipped files.

Overrides:
getRemainingLength in class Snark
Returns:
-1 when done so the web will list us as "complete" instead of "seeding"

getNeededLength

public long getNeededLength()
Description copied from class: Snark
Bytes still wanted. DOES account for (i.e. does not include) skipped files. FIXME -1 when not running.

Overrides:
getNeededLength in class Snark
Returns:
torrent file bytes remaining or -1

getDownloadRate

public long getDownloadRate()
Overrides:
getDownloadRate in class Snark

getDownloaded

public long getDownloaded()
Overrides:
getDownloaded in class Snark

getPeerCount

public int getPeerCount()
Overrides:
getPeerCount in class Snark

getTrackerSeenPeers

public int getTrackerSeenPeers()
Overrides:
getTrackerSeenPeers in class Snark
Returns:
count returned from tracker

attemptFailed

public void attemptFailed(String url,
                          long bytesTransferred,
                          long bytesRemaining,
                          int currentAttempt,
                          int numRetries,
                          Exception cause)
Specified by:
attemptFailed in interface EepGet.StatusListener

bytesTransferred

public void bytesTransferred(long alreadyTransferred,
                             int currentWrite,
                             long bytesTransferred,
                             long bytesRemaining,
                             String url)
Description copied from interface: EepGet.StatusListener
alreadyTransferred - total of all attempts, not including currentWrite If nonzero on the first call, a partial file of that length was found, _and_ the server supports resume. If zero on a subsequent call after some bytes are transferred (and presumably after an attemptFailed), the server does _not_ support resume and we had to start over. To track _actual_ transfer if the output file could already exist, the listener should keep its own counter, or subtract the initial alreadyTransferred value. And watch out for alreadyTransferred resetting if a resume failed... currentWrite - since last call to the listener bytesTransferred - includes headers, retries, redirects, discarded partial downloads, ... bytesRemaining - on this attempt only, currentWrite already subtracted - or -1 if chunked encoding or server does not return a length Total length should be == alreadyTransferred + currentWrite + bytesRemaining for all calls

Specified by:
bytesTransferred in interface EepGet.StatusListener

transferComplete

public void transferComplete(long alreadyTransferred,
                             long bytesTransferred,
                             long bytesRemaining,
                             String url,
                             String outputFile,
                             boolean notModified)
Specified by:
transferComplete in interface EepGet.StatusListener

transferFailed

public void transferFailed(String url,
                           long bytesTransferred,
                           long bytesRemaining,
                           int currentAttempt)
Specified by:
transferFailed in interface EepGet.StatusListener

headerReceived

public void headerReceived(String url,
                           int attemptNum,
                           String key,
                           String val)
Description copied from interface: EepGet.StatusListener
Note: Headers are not processed, and this is not called, for most error response codes, unless setWriteErrorToOutput() is called before fetch(). To be changed?

Specified by:
headerReceived in interface EepGet.StatusListener

attempting

public void attempting(String url)
Specified by:
attempting in interface EepGet.StatusListener