pause/resume downloads
This commit is contained in:
@@ -25,7 +25,7 @@ import net.i2p.util.ConcurrentHashSet
|
|||||||
|
|
||||||
@Log
|
@Log
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
public enum DownloadState { CONNECTING, HASHLIST, DOWNLOADING, FAILED, CANCELLED, FINISHED }
|
public enum DownloadState { CONNECTING, HASHLIST, DOWNLOADING, FAILED, CANCELLED, PAUSED, FINISHED }
|
||||||
private enum WorkerState { CONNECTING, HASHLIST, DOWNLOADING, FINISHED}
|
private enum WorkerState { CONNECTING, HASHLIST, DOWNLOADING, FINISHED}
|
||||||
|
|
||||||
private static final ExecutorService executorService = Executors.newCachedThreadPool({r ->
|
private static final ExecutorService executorService = Executors.newCachedThreadPool({r ->
|
||||||
@@ -53,7 +53,7 @@ public class Downloader {
|
|||||||
private final Set<Destination> successfulDestinations = new ConcurrentHashSet<>()
|
private final Set<Destination> successfulDestinations = new ConcurrentHashSet<>()
|
||||||
|
|
||||||
|
|
||||||
private volatile boolean cancelled
|
private volatile boolean cancelled, paused
|
||||||
private final AtomicBoolean eventFired = new AtomicBoolean()
|
private final AtomicBoolean eventFired = new AtomicBoolean()
|
||||||
private boolean piecesFileClosed
|
private boolean piecesFileClosed
|
||||||
|
|
||||||
@@ -136,6 +136,9 @@ public class Downloader {
|
|||||||
public DownloadState getCurrentState() {
|
public DownloadState getCurrentState() {
|
||||||
if (cancelled)
|
if (cancelled)
|
||||||
return DownloadState.CANCELLED
|
return DownloadState.CANCELLED
|
||||||
|
if (paused)
|
||||||
|
return DownloadState.PAUSED
|
||||||
|
|
||||||
boolean allFinished = true
|
boolean allFinished = true
|
||||||
activeWorkers.values().each {
|
activeWorkers.values().each {
|
||||||
allFinished &= it.currentState == WorkerState.FINISHED
|
allFinished &= it.currentState == WorkerState.FINISHED
|
||||||
@@ -183,6 +186,11 @@ public class Downloader {
|
|||||||
pieces.clearAll()
|
pieces.clearAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pause() {
|
||||||
|
paused = true
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
activeWorkers.values().each {
|
activeWorkers.values().each {
|
||||||
it.cancel()
|
it.cancel()
|
||||||
@@ -203,6 +211,7 @@ public class Downloader {
|
|||||||
def worker = activeWorkers.get(destination)
|
def worker = activeWorkers.get(destination)
|
||||||
if (worker != null) {
|
if (worker != null) {
|
||||||
if (worker.currentState == WorkerState.FINISHED) {
|
if (worker.currentState == WorkerState.FINISHED) {
|
||||||
|
paused = false
|
||||||
def newWorker = new DownloadWorker(destination)
|
def newWorker = new DownloadWorker(destination)
|
||||||
activeWorkers.put(destination, newWorker)
|
activeWorkers.put(destination, newWorker)
|
||||||
executorService.submit(newWorker)
|
executorService.submit(newWorker)
|
||||||
|
|||||||
@@ -166,6 +166,12 @@ class MainFrameController {
|
|||||||
downloader.resume()
|
downloader.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ControllerAction
|
||||||
|
void pause() {
|
||||||
|
def downloader = model.downloads[selectedDownload()].downloader
|
||||||
|
downloader.pause()
|
||||||
|
}
|
||||||
|
|
||||||
private void markTrust(String tableName, TrustLevel level, def list) {
|
private void markTrust(String tableName, TrustLevel level, def list) {
|
||||||
int row = builder.getVariable(tableName).getSelectedRow()
|
int row = builder.getVariable(tableName).getSelectedRow()
|
||||||
if (row < 0)
|
if (row < 0)
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ class MainFrameModel {
|
|||||||
@Observable boolean trustButtonsEnabled
|
@Observable boolean trustButtonsEnabled
|
||||||
@Observable boolean cancelButtonEnabled
|
@Observable boolean cancelButtonEnabled
|
||||||
@Observable boolean retryButtonEnabled
|
@Observable boolean retryButtonEnabled
|
||||||
|
@Observable boolean pauseButtonEnabled
|
||||||
|
@Observable String resumeButtonText
|
||||||
|
|
||||||
private final Set<InfoHash> infoHashes = new HashSet<>()
|
private final Set<InfoHash> infoHashes = new HashSet<>()
|
||||||
|
|
||||||
@@ -168,6 +170,8 @@ class MainFrameModel {
|
|||||||
watched.addAll(core.muOptions.watchedDirectories)
|
watched.addAll(core.muOptions.watchedDirectories)
|
||||||
builder.getVariable("watched-directories-table").model.fireTableDataChanged()
|
builder.getVariable("watched-directories-table").model.fireTableDataChanged()
|
||||||
watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) }
|
watched.each { core.eventBus.publish(new FileSharedEvent(file : new File(it))) }
|
||||||
|
|
||||||
|
resumeButtonText = "Retry"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -135,8 +135,9 @@ class MainFrameView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
panel (constraints : BorderLayout.SOUTH) {
|
panel (constraints : BorderLayout.SOUTH) {
|
||||||
|
button(text: "Pause", enabled : bind {model.pauseButtonEnabled}, pauseAction)
|
||||||
button(text: "Cancel", enabled : bind {model.cancelButtonEnabled }, cancelAction )
|
button(text: "Cancel", enabled : bind {model.cancelButtonEnabled }, cancelAction )
|
||||||
button(text: "Retry", enabled : bind {model.retryButtonEnabled}, resumeAction)
|
button(text: bind { model.resumeButtonText }, enabled : bind {model.retryButtonEnabled}, resumeAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,6 +296,7 @@ class MainFrameView {
|
|||||||
if (selectedRow < 0) {
|
if (selectedRow < 0) {
|
||||||
model.cancelButtonEnabled = false
|
model.cancelButtonEnabled = false
|
||||||
model.retryButtonEnabled = false
|
model.retryButtonEnabled = false
|
||||||
|
model.pauseButtonEnabled = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
def downloader = model.downloads[selectedRow]?.downloader
|
def downloader = model.downloads[selectedRow]?.downloader
|
||||||
@@ -305,15 +307,25 @@ class MainFrameView {
|
|||||||
case Downloader.DownloadState.DOWNLOADING :
|
case Downloader.DownloadState.DOWNLOADING :
|
||||||
case Downloader.DownloadState.HASHLIST:
|
case Downloader.DownloadState.HASHLIST:
|
||||||
model.cancelButtonEnabled = true
|
model.cancelButtonEnabled = true
|
||||||
|
model.pauseButtonEnabled = true
|
||||||
model.retryButtonEnabled = false
|
model.retryButtonEnabled = false
|
||||||
break
|
break
|
||||||
case Downloader.DownloadState.FAILED:
|
case Downloader.DownloadState.FAILED:
|
||||||
model.cancelButtonEnabled = true
|
model.cancelButtonEnabled = true
|
||||||
model.retryButtonEnabled = true
|
model.retryButtonEnabled = true
|
||||||
|
model.resumeButtonText = "Retry"
|
||||||
|
model.pauseButtonEnabled = false
|
||||||
|
break
|
||||||
|
case Downloader.DownloadState.PAUSED:
|
||||||
|
model.cancelButtonEnabled = true
|
||||||
|
model.retryButtonEnabled = true
|
||||||
|
model.resumeButtonText = "Resume"
|
||||||
|
model.pauseButtonEnabled = false
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
model.cancelButtonEnabled = false
|
model.cancelButtonEnabled = false
|
||||||
model.retryButtonEnabled = false
|
model.retryButtonEnabled = false
|
||||||
|
model.pauseButtonEnabled = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -421,21 +433,32 @@ class MainFrameView {
|
|||||||
int selected = selectedDownloaderRow()
|
int selected = selectedDownloaderRow()
|
||||||
if (selected < 0)
|
if (selected < 0)
|
||||||
return
|
return
|
||||||
|
boolean pauseEnabled = false
|
||||||
boolean cancelEnabled = false
|
boolean cancelEnabled = false
|
||||||
boolean retryEnabled = false
|
boolean retryEnabled = false
|
||||||
|
String resumeText = "Retry"
|
||||||
Downloader downloader = model.downloads[selected].downloader
|
Downloader downloader = model.downloads[selected].downloader
|
||||||
switch(downloader.currentState) {
|
switch(downloader.currentState) {
|
||||||
case Downloader.DownloadState.DOWNLOADING:
|
case Downloader.DownloadState.DOWNLOADING:
|
||||||
case Downloader.DownloadState.HASHLIST:
|
case Downloader.DownloadState.HASHLIST:
|
||||||
case Downloader.DownloadState.CONNECTING:
|
case Downloader.DownloadState.CONNECTING:
|
||||||
|
pauseEnabled = true
|
||||||
cancelEnabled = true
|
cancelEnabled = true
|
||||||
retryEnabled = false
|
retryEnabled = false
|
||||||
break
|
break
|
||||||
case Downloader.DownloadState.FAILED:
|
case Downloader.DownloadState.FAILED:
|
||||||
|
pauseEnabled = false
|
||||||
cancelEnabled = true
|
cancelEnabled = true
|
||||||
retryEnabled = true
|
retryEnabled = true
|
||||||
break
|
break
|
||||||
|
case Downloader.DownloadState.PAUSED:
|
||||||
|
pauseEnabled = false
|
||||||
|
cancelEnabled = true
|
||||||
|
retryEnabled = true
|
||||||
|
resumeText = "Resume"
|
||||||
|
break
|
||||||
default :
|
default :
|
||||||
|
pauseEnabled = false
|
||||||
cancelEnabled = false
|
cancelEnabled = false
|
||||||
retryEnabled = false
|
retryEnabled = false
|
||||||
}
|
}
|
||||||
@@ -450,6 +473,12 @@ class MainFrameView {
|
|||||||
})
|
})
|
||||||
menu.add(copyHashToClipboard)
|
menu.add(copyHashToClipboard)
|
||||||
|
|
||||||
|
if (pauseEnabled) {
|
||||||
|
JMenuItem pause = new JMenuItem("Pause")
|
||||||
|
pause.addActionListener({mvcGroup.controller.pause()})
|
||||||
|
menu.add(pause)
|
||||||
|
}
|
||||||
|
|
||||||
if (cancelEnabled) {
|
if (cancelEnabled) {
|
||||||
JMenuItem cancel = new JMenuItem("Cancel")
|
JMenuItem cancel = new JMenuItem("Cancel")
|
||||||
cancel.addActionListener({mvcGroup.controller.cancel()})
|
cancel.addActionListener({mvcGroup.controller.cancel()})
|
||||||
@@ -457,7 +486,7 @@ class MainFrameView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (retryEnabled) {
|
if (retryEnabled) {
|
||||||
JMenuItem retry = new JMenuItem("Retry")
|
JMenuItem retry = new JMenuItem(resumeText)
|
||||||
retry.addActionListener({mvcGroup.controller.resume()})
|
retry.addActionListener({mvcGroup.controller.resume()})
|
||||||
menu.add(retry)
|
menu.add(retry)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user