package yukihane.inqubus.manager;
+import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
import saccubus.worker.WorkerListener;
+import saccubus.worker.impl.MessageReportable;
+import saccubus.worker.impl.PercentageReportable;
import saccubus.worker.impl.convert.Convert;
import saccubus.worker.impl.convert.ConvertProgress;
import saccubus.worker.impl.convert.ConvertResult;
* @author yuki
*/
public class TaskManage {
+
private static final Logger logger = Logger.getLogger(TaskManage.class.getName());
private final ExecutorService downloadExecutorService;
private final ExecutorService convertExecutorService;
private final Map<Integer, ManageTarget<DownloadResult>> downloadTargets = new HashMap<>();
private final Map<Integer, ManageTarget<ConvertResult>> convertTargets = new HashMap<>();
private final TaskManageListener clientListener;
+ private final int waitDownload;
public TaskManage() {
- this(1, 1, null);
+ this(1, 30, 1, null);
}
public TaskManage(int maxDownload, int maxConvert) {
- this(maxDownload, maxConvert, null);
+ this(maxDownload, 30, maxConvert, null);
}
- public TaskManage(int maxDownload, int maxConvert, TaskManageListener listener) {
+ public TaskManage(int maxDownload, int waitDownload, int maxConvert, TaskManageListener listener) {
downloadExecutorService = Executors.newFixedThreadPool(maxDownload);
convertExecutorService = Executors.newFixedThreadPool(maxConvert);
+ this.waitDownload = waitDownload;
this.clientListener = listener;
}
if (dp != null && (dp.getVideoProfile().isDownload() || dp.getCommentProfile().isDownload())) {
// ダウンロードするものがあればまずダウンロード処理
final Download task = new Download(dp, request.getVideoId(),
- new DownloadListener(request.getRowId()));
+ new DownloadListener(request.getRowId()), waitDownload);
final Future<DownloadResult> future = downloadExecutorService.submit(task);
downloadTargets.put(request.getRowId(), new ManageTarget<>(request, future));
return true;
return false;
}
+ public synchronized boolean cancel(int rowId) {
+ // FIXME 実行前にキャンセルした場合にはcancelledイベントが飛ばないのでMapからリクエストを削除できない
+ final ManageTarget<DownloadResult> down = downloadTargets.get(rowId);
+ if (down != null) {
+ return down.getFuture().cancel(true);
+ }
+ final ManageTarget<ConvertResult> conv = convertTargets.get(rowId);
+ if (conv != null) {
+ return conv.getFuture().cancel(true);
+ }
+
+ return false;
+ }
+
private class DownloadListener extends TaskManageInnerListener<DownloadResult, DownloadProgress> {
private DownloadListener(int rowId) {
@Override
public void done(DownloadResult result) {
super.done(result);
- // TODO 変換が必要なら変換キューに入れる
+ synchronized (TaskManage.this) {
+ final ManageTarget<DownloadResult> mt = removeRequest(getRowId());
+ final RequestProcess request = mt.getRequest();
+ if (request.getConvertProfile().isConvert()) {
+ final DownloadProfile dp = request.getDownloadProfile();
+ final File video = (dp.getVideoProfile().isDownload()) ? result.getDownloadVideo() : dp.
+ getVideoProfile().getLocalFile();
+ final File comment = (dp.getCommentProfile().isDownload()) ? result.getDownloadComment() : dp.
+ getCommentProfile().getLocalFile();
+ final ConvertProfile cp = request.getConvertProfile();
+ final Convert task = new Convert(cp, video, comment, new ConvertListener(getRowId()));
+ final Future<ConvertResult> future = convertExecutorService.submit(task);
+ convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
+ }
+ // TODO 変換が必要なら変換キューに入れる
+ }
+
}
@Override
protected TaskKind getKind() {
return TaskKind.DOWNLOAD;
}
+
+ @Override
+ protected ManageTarget<DownloadResult> removeRequest(int rowId) {
+ return downloadTargets.remove(rowId);
+ }
}
private class ConvertListener extends TaskManageInnerListener<ConvertResult, ConvertProgress> {
protected TaskKind getKind() {
return TaskKind.CONVERT;
}
+
+ @Override
+ public void done(ConvertResult result) {
+ super.done(result);
+ synchronized (TaskManage.this) {
+ removeRequest(getRowId());
+ }
+ }
+
+ @Override
+ protected ManageTarget<ConvertResult> removeRequest(int rowId) {
+ return convertTargets.remove(rowId);
+ }
}
- abstract class TaskManageInnerListener<T, V> implements WorkerListener<T, V> {
+ abstract class TaskManageInnerListener<T, V extends PercentageReportable & MessageReportable> implements WorkerListener<T, V> {
private final int rowId;
this.rowId = rowId;
}
+ protected int getRowId() {
+ return rowId;
+ }
+
private void notify(TaskStatus status) {
- notify(status, 0.0, "");
+ notify(status, -1.0, "");
}
private void notify(TaskStatus status, double percentage, String message) {
@Override
public void process(V progress) {
logger.log(Level.FINEST, "process: {0}", progress);
- // TOOD
- notify(TaskStatus.DOING, 0.0, "");
+ notify(TaskStatus.DOING, progress.getPercentage(), progress.getMessage());
}
@Override
- public void cancelled() {
+ public final void cancelled() {
logger.log(Level.FINE, "cancelled: {0}", toString());
+ synchronized (TaskManage.this) {
+ removeRequest(rowId);
+ }
notify(TaskStatus.CANCELLED);
}
+ /**
+ * この処理をオーバライドしてキューからリクエストを削除する必要があります.
+ * @param result 処理結果.
+ */
@Override
public void done(T result) {
logger.log(Level.FINE, "done: {0}", result);
}
@Override
- public void error(Throwable th) {
+ public final void error(Throwable th) {
logger.log(Level.SEVERE, "error", th);
+ synchronized (TaskManage.this) {
+ removeRequest(rowId);
+ }
notify(TaskStatus.ERROR, 0.0, th.getMessage());
}
+
+ protected abstract ManageTarget<T> removeRequest(int rowId);
}
class ManageTarget<T> {