store done pieces on disk to enable resume

pull/4/head
Zlatin Balevsky 2019-06-01 18:09:14 +01:00
parent 82377aa9df
commit 98ea8154a5
4 changed files with 43 additions and 6 deletions

View File

@ -54,7 +54,8 @@ public class Core {
final EventBus eventBus
final Persona me
final File home
private final TrustService trustService
private final PersisterService persisterService
private final HostCache hostCache
@ -64,7 +65,8 @@ public class Core {
private final ConnectionEstablisher connectionEstablisher
private final HasherService hasherService
public Core(MuWireSettings props, File home) {
public Core(MuWireSettings props, File home) {
this.home = home
log.info "Initializing I2P context"
I2PAppContext.getGlobalContext().logManager()
I2PAppContext.getGlobalContext()._logManager = new MuWireLogManager()
@ -164,7 +166,7 @@ public class Core {
eventBus.register(ResultsEvent.class, searchManager)
log.info("initializing download manager")
DownloadManager downloadManager = new DownloadManager(eventBus, i2pConnector)
DownloadManager downloadManager = new DownloadManager(eventBus, i2pConnector, new File(home, "incompletes"))
eventBus.register(UIDownloadEvent.class, downloadManager)
log.info("initializing upload manager")

View File

@ -11,10 +11,13 @@ public class DownloadManager {
private final EventBus eventBus
private final I2PConnector connector
private final Executor executor
private final File incompletes
public DownloadManager(EventBus eventBus, I2PConnector connector) {
public DownloadManager(EventBus eventBus, I2PConnector connector, File incompletes) {
this.eventBus = eventBus
this.connector = connector
this.incompletes = incompletes
incompletes.mkdir()
this.executor = Executors.newCachedThreadPool({ r ->
Thread rv = new Thread(r)
rv.setName("download-worker")
@ -26,7 +29,8 @@ public class DownloadManager {
public void onUIDownloadEvent(UIDownloadEvent e) {
def downloader = new Downloader(e.target, e.result.size,
e.result.infohash, e.result.pieceSize, connector, e.result.sender.destination)
e.result.infohash, e.result.pieceSize, connector, e.result.sender.destination,
incompletes)
executor.execute({downloader.download()} as Runnable)
eventBus.publish(new DownloadStartedEvent(downloader : downloader))
}

View File

@ -23,6 +23,7 @@ public class Downloader {
private final I2PConnector connector
private final Destination destination
private final int nPieces
private final File piecesFile
private Endpoint endpoint
private volatile DownloadSession currentSession
@ -30,12 +31,14 @@ public class Downloader {
private volatile boolean cancelled
private volatile Thread downloadThread
public Downloader(File file, long length, InfoHash infoHash, int pieceSizePow2, I2PConnector connector, Destination destination) {
public Downloader(File file, long length, InfoHash infoHash, int pieceSizePow2, I2PConnector connector, Destination destination,
File incompletes) {
this.file = file
this.infoHash = infoHash
this.length = length
this.connector = connector
this.destination = destination
this.piecesFile = new File(incompletes, file.getName()+".pieces")
this.pieceSize = 1 << pieceSizePow2
int nPieces
@ -50,6 +53,7 @@ public class Downloader {
}
void download() {
readPieces()
downloadThread = Thread.currentThread()
Endpoint endpoint = null
try {
@ -58,8 +62,10 @@ public class Downloader {
while(!pieces.isComplete()) {
currentSession = new DownloadSession(pieces, infoHash, endpoint, file, pieceSize, length)
currentSession.request()
writePieces()
}
currentState = DownloadState.FINISHED
piecesFile.delete()
} catch (Exception bad) {
log.log(Level.WARNING,"Exception while downloading",bad)
if (cancelled)
@ -71,6 +77,23 @@ public class Downloader {
}
}
void readPieces() {
if (!piecesFile.exists())
return
piecesFile.withReader {
int piece = Integer.parseInt(it.readLine())
pieces.markDownloaded(piece)
}
}
void writePieces() {
piecesFile.withPrintWriter { writer ->
pieces.getDownloaded().each { piece ->
writer.println(piece)
}
}
}
public long donePieces() {
pieces.donePieces()
}

View File

@ -33,6 +33,14 @@ class Pieces {
}
}
def getDownloaded() {
def rv = []
for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i+1)) {
rv << i
}
rv
}
synchronized void markDownloaded(int piece) {
bitSet.set(piece)
}