Package org.klomp.snark.web
Class FetchAndAdd
java.lang.Object
org.klomp.snark.Snark
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
-
Constructor Summary
Constructors Constructor Description FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url, File dataDir)
Caller should call _mgr.addDownloader(this), which will start things off. -
Method Summary
Modifier and Type Method Description 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)
Total length should be == alreadyTransferred + currentWrite + bytesRemaining for all callsString
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 peersvoid
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
addComments, addMessage, getCheckingProgress, getComments, getID, getMetaInfo, getNeeded, getPeerList, getPieceLength, getPieces, getRPCID, getSkippedLength, getStartedTime, 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
-
Constructor Details
-
FetchAndAdd
Caller should call _mgr.addDownloader(this), which will start things off.- Parameters:
dataDir
- null to default to snark data directory
-
-
Method Details
-
run
public void run()Set off by startTorrent() -
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 classSnark
-
stopTorrent
public void stopTorrent()Description copied from class:Snark
Stop contacting the tracker and talking with peers- Overrides:
stopTorrent
in classSnark
-
isStopped
public boolean isStopped() -
getName
-
getBaseName
- Overrides:
getBaseName
in classSnark
- 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 classSnark
- Returns:
- always will be valid even in magnet mode
-
getTotalLength
public long getTotalLength()- Overrides:
getTotalLength
in classSnark
- 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 classSnark
- 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 classSnark
- Returns:
- torrent file bytes remaining or -1
-
getDownloadRate
public long getDownloadRate()- Overrides:
getDownloadRate
in classSnark
-
getDownloaded
public long getDownloaded()- Overrides:
getDownloaded
in classSnark
-
getPeerCount
public int getPeerCount()- Overrides:
getPeerCount
in classSnark
-
getTrackerSeenPeers
public int getTrackerSeenPeers()- Overrides:
getTrackerSeenPeers
in classSnark
- 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 interfaceEepGet.StatusListener
- See Also:
EepGet.StatusListener.bytesTransferred(long, int, long, long, java.lang.String)
-
bytesTransferred
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url)Description copied from interface:EepGet.StatusListener
Total length should be == alreadyTransferred + currentWrite + bytesRemaining for all calls- Specified by:
bytesTransferred
in interfaceEepGet.StatusListener
- Parameters:
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 listenerbytesTransferred
- 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
-
transferComplete
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified)- Specified by:
transferComplete
in interfaceEepGet.StatusListener
outputFile
- null if unknown (output stream constructor)- See Also:
EepGet.StatusListener.bytesTransferred(long, int, long, long, java.lang.String)
-
transferFailed
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt)- Specified by:
transferFailed
in interfaceEepGet.StatusListener
- See Also:
EepGet.StatusListener.bytesTransferred(long, int, long, long, java.lang.String)
-
headerReceived
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 interfaceEepGet.StatusListener
-
attempting
- Specified by:
attempting
in interfaceEepGet.StatusListener
-