1 package yukihane.inqubus.manager;
4 import java.util.HashMap;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.Executors;
8 import java.util.concurrent.Future;
9 import java.util.logging.Level;
10 import java.util.logging.Logger;
11 import saccubus.worker.WorkerListener;
12 import saccubus.worker.impl.MessageReportable;
13 import saccubus.worker.impl.PercentageReportable;
14 import saccubus.worker.impl.convert.Convert;
15 import saccubus.worker.impl.convert.ConvertProgress;
16 import saccubus.worker.impl.convert.ConvertResult;
17 import saccubus.worker.impl.download.Download;
18 import saccubus.worker.impl.download.DownloadProgress;
19 import saccubus.worker.impl.download.DownloadResult;
20 import saccubus.worker.profile.ConvertProfile;
21 import saccubus.worker.profile.DownloadProfile;
27 public class TaskManage {
29 private static final Logger logger = Logger.getLogger(TaskManage.class.getName());
30 private final ExecutorService downloadExecutorService;
31 private final ExecutorService convertExecutorService;
32 private final Map<Integer, ManageTarget<DownloadResult>> downloadTargets = new HashMap<>();
33 private final Map<Integer, ManageTarget<ConvertResult>> convertTargets = new HashMap<>();
34 private final TaskManageListener clientListener;
35 private final int waitDownload;
41 public TaskManage(int maxDownload, int maxConvert) {
42 this(maxDownload, 30, maxConvert, null);
45 public TaskManage(int maxDownload, int waitDownload, int maxConvert, TaskManageListener listener) {
46 downloadExecutorService = Executors.newFixedThreadPool(maxDownload);
47 convertExecutorService = Executors.newFixedThreadPool(maxConvert);
48 this.waitDownload = waitDownload;
49 this.clientListener = listener;
52 public synchronized boolean add(RequestProcess request) {
53 final DownloadProfile dp = request.getDownloadProfile();
54 final ConvertProfile cp = request.getConvertProfile();
55 if (dp != null && (dp.getVideoProfile().isDownload() || dp.getCommentProfile().isDownload())) {
56 // ダウンロードするものがあればまずダウンロード処理
57 final Download task = new Download(dp, request.getVideoId(),
58 new DownloadListener(request.getRowId()), waitDownload);
59 final Future<DownloadResult> future = downloadExecutorService.submit(task);
60 downloadTargets.put(request.getRowId(), new ManageTarget<>(request, future));
63 } else if (cp != null && cp.isConvert()) {
64 final Convert task = new Convert(cp, dp.getVideoProfile().getLocalFile(), dp.getCommentProfile().
65 getLocalFile(), new ConvertListener(request.getRowId()));
66 final Future<ConvertResult> future = convertExecutorService.submit(task);
67 convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
73 public synchronized boolean cancel(int rowId) {
74 // FIXME 実行前にキャンセルした場合にはcancelledイベントが飛ばないのでMapからリクエストを削除できない
75 final ManageTarget<DownloadResult> down = downloadTargets.get(rowId);
77 return down.getFuture().cancel(true);
79 final ManageTarget<ConvertResult> conv = convertTargets.get(rowId);
81 return conv.getFuture().cancel(true);
87 private class DownloadListener extends TaskManageInnerListener<DownloadResult, DownloadProgress> {
89 private DownloadListener(int rowId) {
94 public void done(DownloadResult result) {
96 synchronized (TaskManage.this) {
97 final ManageTarget<DownloadResult> mt = removeRequest(getRowId());
98 final RequestProcess request = mt.getRequest();
99 if (request.getConvertProfile().isConvert()) {
100 final DownloadProfile dp = request.getDownloadProfile();
101 final File video = (dp.getVideoProfile().isDownload()) ? result.getDownloadVideo() : dp.
102 getVideoProfile().getLocalFile();
103 final File comment = (dp.getCommentProfile().isDownload()) ? result.getDownloadComment() : dp.
104 getCommentProfile().getLocalFile();
105 final ConvertProfile cp = request.getConvertProfile();
106 final Convert task = new Convert(cp, video, comment, new ConvertListener(getRowId()));
107 final Future<ConvertResult> future = convertExecutorService.submit(task);
108 convertTargets.put(request.getRowId(), new ManageTarget<>(request, future));
114 protected TaskKind getKind() {
115 return TaskKind.DOWNLOAD;
119 protected ManageTarget<DownloadResult> removeRequest(int rowId) {
120 return downloadTargets.remove(rowId);
124 private class ConvertListener extends TaskManageInnerListener<ConvertResult, ConvertProgress> {
126 private ConvertListener(int rowId) {
131 protected TaskKind getKind() {
132 return TaskKind.CONVERT;
136 public void done(ConvertResult result) {
138 synchronized (TaskManage.this) {
139 removeRequest(getRowId());
144 protected ManageTarget<ConvertResult> removeRequest(int rowId) {
145 return convertTargets.remove(rowId);
149 abstract class TaskManageInnerListener<T, V extends PercentageReportable & MessageReportable> implements WorkerListener<T, V> {
151 private final int rowId;
153 protected TaskManageInnerListener(int rowId) {
157 protected int getRowId() {
161 private void notify(TaskStatus status) {
162 notify(status, -1.0, "");
165 private void notify(TaskStatus status, double percentage, String message) {
166 if (getListener() == null) {
169 getListener().process(rowId, getKind(), status, percentage, message);
172 private TaskManageListener getListener() {
173 return clientListener;
176 protected abstract TaskKind getKind();
179 public void process(V progress) {
180 logger.log(Level.FINEST, "process: {0}", progress);
181 notify(TaskStatus.DOING, progress.getPercentage(), progress.getMessage());
185 public final void cancelled() {
186 logger.log(Level.FINE, "cancelled: {0}", toString());
187 synchronized (TaskManage.this) {
188 removeRequest(rowId);
190 notify(TaskStatus.CANCELLED);
194 * この処理をオーバライドしてキューからリクエストを削除する必要があります.
195 * @param result 処理結果.
198 public void done(T result) {
199 logger.log(Level.FINE, "done: {0}", result);
200 notify(TaskStatus.DONE);
204 public final void error(Throwable th) {
205 logger.log(Level.SEVERE, "error", th);
206 synchronized (TaskManage.this) {
207 removeRequest(rowId);
209 notify(TaskStatus.ERROR, 0.0, th.getMessage());
212 protected abstract ManageTarget<T> removeRequest(int rowId);
215 class ManageTarget<T> {
217 private final RequestProcess request;
218 private final Future<T> future;
220 ManageTarget(RequestProcess request, Future<T> future) {
221 this.request = request;
222 this.future = future;
225 Future<T> getFuture() {
229 RequestProcess getRequest() {