* rewrote the checksum computation stuff to support multiple parallel computation queues
* refactoring * svn properties
This commit is contained in:
parent
6d2ff4dfe4
commit
2b9c8e840a
|
@ -5,7 +5,6 @@ package net.sourceforge.filebot.ui.panel.sfv;
|
|||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -26,7 +25,10 @@ public class Checksum {
|
|||
|
||||
|
||||
public static enum State {
|
||||
PENDING, INPROGRESS, READY, ERROR;
|
||||
PENDING,
|
||||
INPROGRESS,
|
||||
READY,
|
||||
ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,11 +43,10 @@ public class Checksum {
|
|||
}
|
||||
|
||||
|
||||
public Checksum(File file) {
|
||||
computationTask = new ChecksumComputationTask(file);
|
||||
computationTask.addPropertyChangeListener(new ComputationTaskPropertyChangeListener());
|
||||
public Checksum(ChecksumComputationTask computationTask) {
|
||||
this.computationTask = computationTask;
|
||||
|
||||
ChecksumComputationExecutor.getInstance().execute(computationTask);
|
||||
this.computationTask.addPropertyChangeListener(new ComputationTaskPropertyChangeListener());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,224 +0,0 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.sfv;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.sourceforge.tuned.PausableThreadPoolExecutor;
|
||||
|
||||
|
||||
public class ChecksumComputationExecutor {
|
||||
|
||||
public static final String PAUSED_PROPERTY = "PAUSED_PROPERTY";
|
||||
public static final String ACTIVE_PROPERTY = "ACTIVE_PROPERTY";
|
||||
public static final String REMAINING_TASK_COUNT_PROPERTY = "REMAINING_TASK_COUNT_PROPERTY";
|
||||
public static final String ACTIVE_SESSION_TASK_COUNT_PROPERTY = "ACTIVE_SESSION_TASK_COUNT_PROPERTY";
|
||||
|
||||
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||
|
||||
private static final int MINIMUM_POOL_SIZE = 1;
|
||||
|
||||
private Boolean active = false;
|
||||
private long lastTaskCount = 0;
|
||||
|
||||
private static ChecksumComputationExecutor instance = new ChecksumComputationExecutor();
|
||||
|
||||
private LinkedBlockingQueue<ChecksumComputationTask> workQueue = new LinkedBlockingQueue<ChecksumComputationTask>();
|
||||
|
||||
private PausableThreadPoolExecutor executor = new PausableThreadPoolExecutor(MINIMUM_POOL_SIZE, workQueue) {
|
||||
|
||||
@Override
|
||||
protected void beforeExecute(Thread t, Runnable r) {
|
||||
super.beforeExecute(t, r);
|
||||
fireRemainingTaskCountChange();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
// afterExecute is called from the same thread, the runnable is called,
|
||||
// so there is at least one active thread
|
||||
if (workQueue.isEmpty() && getActiveCount() <= 1)
|
||||
setActive(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static ChecksumComputationExecutor getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public void execute(ChecksumComputationTask task) {
|
||||
synchronized (workQueue) {
|
||||
setActive(true);
|
||||
|
||||
adjustPoolSize();
|
||||
|
||||
executor.execute(task);
|
||||
}
|
||||
|
||||
fireActiveSessionTaskCountChange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* increase/decrease the core pool size depending on number of queued tasks
|
||||
*/
|
||||
private void adjustPoolSize() {
|
||||
// for only a few files, use only one thread
|
||||
// for lots of files, use multiple threads
|
||||
// e.g 200 files ~ 1 thread, 1000 files ~ 2 threads, 40000 files ~ 4 threads
|
||||
int recommendedPoolSize = (int) Math.log10(Math.max(workQueue.size(), 1) + MINIMUM_POOL_SIZE);
|
||||
|
||||
if (executor.getCorePoolSize() != recommendedPoolSize)
|
||||
executor.setCorePoolSize(recommendedPoolSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only use in block that is synchronized to {@link ChecksumComputationExecutor#getInstance()} after {@link ChecksumComputationExecutor#pause()} has been called.
|
||||
*/
|
||||
public synchronized void resume() {
|
||||
if (!isPaused())
|
||||
return;
|
||||
|
||||
executor.resume();
|
||||
|
||||
// invoke property change events on EDT
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(PAUSED_PROPERTY, null, executor.isPaused()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synchronize to {@link ChecksumComputationExecutor#getInstance()} before using {@link ChecksumComputationExecutor#pause()}.
|
||||
*
|
||||
* <pre>
|
||||
* synchronized (ChecksumComputationExecutor.getInstance()) {
|
||||
* ChecksumComputationExecutor.getInstance().pause();
|
||||
*
|
||||
* // some code
|
||||
*
|
||||
* ChecksumComputationExecutor.getInstance().resume();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public synchronized void pause() {
|
||||
if (isPaused())
|
||||
return;
|
||||
|
||||
executor.pause();
|
||||
|
||||
// invoke property change events on EDT
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(PAUSED_PROPERTY, null, executor.isPaused()));
|
||||
}
|
||||
|
||||
|
||||
private void setActive(boolean b) {
|
||||
synchronized (active) {
|
||||
if (this.active == b)
|
||||
return;
|
||||
|
||||
this.active = b;
|
||||
|
||||
if (!this.active) {
|
||||
// end of active computing session
|
||||
lastTaskCount = executor.getTaskCount();
|
||||
|
||||
// reset pool size
|
||||
adjustPoolSize();
|
||||
}
|
||||
|
||||
// invoke property change events on EDT
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, null, active));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void fireRemainingTaskCountChange() {
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(REMAINING_TASK_COUNT_PROPERTY, null, getRemainingTaskCount()));
|
||||
}
|
||||
|
||||
|
||||
private void fireActiveSessionTaskCountChange() {
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_SESSION_TASK_COUNT_PROPERTY, null, getActiveSessionTaskCount()));
|
||||
}
|
||||
|
||||
|
||||
public boolean isPaused() {
|
||||
return executor.isPaused();
|
||||
}
|
||||
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Number of remaining tasks
|
||||
*/
|
||||
public int getRemainingTaskCount() {
|
||||
return workQueue.size() + executor.getActiveCount();
|
||||
}
|
||||
|
||||
|
||||
public int getActiveSessionTaskCount() {
|
||||
return (int) (executor.getTaskCount() - lastTaskCount);
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
synchronized (workQueue) {
|
||||
executor.purge();
|
||||
workQueue.clear();
|
||||
|
||||
adjustPoolSize();
|
||||
|
||||
fireRemainingTaskCountChange();
|
||||
fireActiveSessionTaskCountChange();
|
||||
|
||||
if (executor.getActiveCount() == 0) {
|
||||
setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void purge() {
|
||||
executor.purge();
|
||||
fireActiveSessionTaskCountChange();
|
||||
}
|
||||
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
private class FirePropertyChangeRunnable implements Runnable {
|
||||
|
||||
private String property;
|
||||
private Object oldValue;
|
||||
private Object newValue;
|
||||
|
||||
|
||||
public FirePropertyChangeRunnable(String property, Object oldValue, Object newValue) {
|
||||
this.property = property;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
propertyChangeSupport.firePropertyChange(property, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.sfv;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
|
||||
public class ChecksumComputationService {
|
||||
|
||||
public static final String ACTIVE_PROPERTY = "ACTIVE_PROPERTY";
|
||||
public static final String REMAINING_TASK_COUNT_PROPERTY = "REMAINING_TASK_COUNT_PROPERTY";
|
||||
|
||||
private static final ChecksumComputationService service = new ChecksumComputationService();
|
||||
|
||||
|
||||
public static ChecksumComputationService getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
private final Map<File, ChecksumComputationExecutor> executors = new HashMap<File, ChecksumComputationExecutor>();
|
||||
|
||||
private final AtomicInteger activeSessionTaskCount = new AtomicInteger(0);
|
||||
private final AtomicInteger remainingTaskCount = new AtomicInteger(0);
|
||||
|
||||
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||
|
||||
|
||||
private ChecksumComputationService() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ChecksumComputationTask submit(File file, File workerQueueKey) {
|
||||
ChecksumComputationTask task = new ChecksumComputationTask(file);
|
||||
|
||||
getExecutor(workerQueueKey).execute(task);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
public void cancelAll() {
|
||||
synchronized (executors) {
|
||||
for (ChecksumComputationExecutor executor : executors.values()) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isActive() {
|
||||
return activeSessionTaskCount.get() > 0;
|
||||
}
|
||||
|
||||
|
||||
public int getRemainingTaskCount() {
|
||||
return remainingTaskCount.get();
|
||||
}
|
||||
|
||||
|
||||
public int getActiveSessionTaskCount() {
|
||||
return activeSessionTaskCount.get();
|
||||
}
|
||||
|
||||
|
||||
public void purge() {
|
||||
synchronized (executors) {
|
||||
for (ChecksumComputationExecutor executor : executors.values()) {
|
||||
executor.purge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ChecksumComputationExecutor getExecutor(File workerQueueKey) {
|
||||
synchronized (executors) {
|
||||
ChecksumComputationExecutor executor = executors.get(workerQueueKey);
|
||||
|
||||
if (executor == null) {
|
||||
executor = new ChecksumComputationExecutor();
|
||||
executors.put(workerQueueKey, executor);
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ChecksumComputationExecutor extends ThreadPoolExecutor {
|
||||
|
||||
private static final int MINIMUM_POOL_SIZE = 1;
|
||||
|
||||
|
||||
public ChecksumComputationExecutor() {
|
||||
super(MINIMUM_POOL_SIZE, MINIMUM_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new ChecksumComputationThreadFactory());
|
||||
}
|
||||
|
||||
|
||||
private void adjustPoolSize() {
|
||||
// for only a few files, use one thread
|
||||
// for lots of files, use multiple threads
|
||||
// e.g 50 files ~ 1 thread, 1000 files ~ 3 threads, 40000 files ~ 5 threads
|
||||
|
||||
int preferredPoolSize = MINIMUM_POOL_SIZE;
|
||||
|
||||
int queueSize = getQueue().size();
|
||||
|
||||
if (queueSize > 0) {
|
||||
preferredPoolSize += Math.log10(Math.max(queueSize / 10, 1));
|
||||
}
|
||||
|
||||
if (getCorePoolSize() != preferredPoolSize) {
|
||||
setCorePoolSize(preferredPoolSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
if (activeSessionTaskCount.getAndIncrement() <= 0) {
|
||||
setActive(true);
|
||||
}
|
||||
|
||||
super.execute(command);
|
||||
|
||||
adjustPoolSize();
|
||||
|
||||
remainingTaskCount.incrementAndGet();
|
||||
fireRemainingTaskCountChange();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void purge() {
|
||||
try {
|
||||
List<ChecksumComputationTask> cancelledTasks = new ArrayList<ChecksumComputationTask>();
|
||||
|
||||
for (Runnable entry : getQueue()) {
|
||||
ChecksumComputationTask task = (ChecksumComputationTask) entry;
|
||||
|
||||
if (task.isCancelled()) {
|
||||
cancelledTasks.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
for (ChecksumComputationTask task : cancelledTasks) {
|
||||
remove(task);
|
||||
}
|
||||
} catch (ConcurrentModificationException ex) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean remove(Runnable task) {
|
||||
boolean success = super.remove(task);
|
||||
|
||||
if (success) {
|
||||
activeSessionTaskCount.decrementAndGet();
|
||||
|
||||
if (remainingTaskCount.decrementAndGet() <= 0) {
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
fireRemainingTaskCountChange();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
super.afterExecute(r, t);
|
||||
|
||||
if (remainingTaskCount.decrementAndGet() <= 0) {
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
fireRemainingTaskCountChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setActive(boolean active) {
|
||||
if (!active) {
|
||||
activeSessionTaskCount.set(0);
|
||||
remainingTaskCount.set(0);
|
||||
|
||||
synchronized (executors) {
|
||||
executors.clear();
|
||||
}
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, active));
|
||||
}
|
||||
|
||||
|
||||
private void fireRemainingTaskCountChange() {
|
||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(REMAINING_TASK_COUNT_PROPERTY, getRemainingTaskCount()));
|
||||
}
|
||||
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
propertyChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
private class FirePropertyChangeRunnable implements Runnable {
|
||||
|
||||
private final String property;
|
||||
private final Object oldValue;
|
||||
private final Object newValue;
|
||||
|
||||
|
||||
public FirePropertyChangeRunnable(String property, Object oldValue, Object newValue) {
|
||||
this.property = property;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
|
||||
public FirePropertyChangeRunnable(String property, Object newValue) {
|
||||
this(property, null, newValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
propertyChangeSupport.firePropertyChange(property, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ChecksumComputationThreadFactory implements ThreadFactory {
|
||||
|
||||
private static final AtomicInteger poolNumber = new AtomicInteger(0);
|
||||
|
||||
private final ThreadGroup group = new ThreadGroup("ChecksumComputationPool");
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(0);
|
||||
|
||||
private final String namePrefix = String.format("%s-%d-thread-", group.getName(), poolNumber.incrementAndGet());
|
||||
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(group, r, namePrefix + threadNumber.incrementAndGet(), 0);
|
||||
|
||||
t.setDaemon(false);
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@ public class ChecksumComputationTask extends SwingWorker<Long, Object> {
|
|||
|
||||
private static final int BUFFER_SIZE = 32 * 1024;
|
||||
|
||||
private File file;
|
||||
private final File file;
|
||||
|
||||
|
||||
public ChecksumComputationTask(File file) {
|
||||
|
@ -36,7 +36,7 @@ public class ChecksumComputationTask extends SwingWorker<Long, Object> {
|
|||
int bytesRead = 0;
|
||||
|
||||
while ((bytesRead = cis.read(buffer)) >= 0) {
|
||||
if (isCancelled())
|
||||
if (isCancelled() || Thread.currentThread().isInterrupted())
|
||||
break;
|
||||
|
||||
done += bytesRead;
|
||||
|
@ -54,7 +54,6 @@ public class ChecksumComputationTask extends SwingWorker<Long, Object> {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + " (" + file.getName() + ")";
|
||||
return String.format("%s (%s)", getClass().getSimpleName(), file.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,13 +17,9 @@ import javax.swing.table.AbstractTableModel;
|
|||
import net.sourceforge.filebot.FileFormat;
|
||||
|
||||
|
||||
class SfvTableModel extends AbstractTableModel {
|
||||
class ChecksumTableModel extends AbstractTableModel {
|
||||
|
||||
private List<ChecksumRow> rows = new ArrayList<ChecksumRow>();
|
||||
|
||||
/**
|
||||
* Used for Name->Checksum mapping (for performance reasons)
|
||||
*/
|
||||
private Map<String, ChecksumRow> rowMap = new HashMap<String, ChecksumRow>();
|
||||
|
||||
private List<File> checksumColumnRoots = new ArrayList<File>();
|
||||
|
@ -145,7 +141,7 @@ class SfvTableModel extends AbstractTableModel {
|
|||
rows.removeAll(rowsToRemove);
|
||||
fireTableRowsDeleted(rowIndices[0], rowIndices[rowIndices.length - 1]);
|
||||
|
||||
ChecksumComputationExecutor.getInstance().purge();
|
||||
ChecksumComputationService.getService().purge();
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,7 +154,7 @@ class SfvTableModel extends AbstractTableModel {
|
|||
}
|
||||
}
|
||||
|
||||
ChecksumComputationExecutor.getInstance().clear();
|
||||
ChecksumComputationService.getService().cancelAll();
|
||||
|
||||
checksumColumnRoots.clear();
|
||||
rows.clear();
|
||||
|
@ -174,7 +170,7 @@ class SfvTableModel extends AbstractTableModel {
|
|||
}
|
||||
|
||||
|
||||
public LinkedHashMap<String, Checksum> getChecksumColumn(File columnRoot) {
|
||||
public Map<String, Checksum> getChecksumColumn(File columnRoot) {
|
||||
LinkedHashMap<String, Checksum> checksumMap = new LinkedHashMap<String, Checksum>();
|
||||
|
||||
for (ChecksumRow row : rows) {
|
|
@ -94,7 +94,7 @@ public class SfvPanel extends FileBotPanel {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SfvTableModel model = (SfvTableModel) sfvTable.getModel();
|
||||
ChecksumTableModel model = (ChecksumTableModel) sfvTable.getModel();
|
||||
|
||||
ArrayList<File> options = new ArrayList<File>();
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
|
||||
|
||||
public SfvTable() {
|
||||
final SfvTableModel model = (SfvTableModel) getModel();
|
||||
final ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||
model.addPropertyChangeListener(repaintListener);
|
||||
|
||||
setFillsViewportHeight(true);
|
||||
|
@ -69,7 +69,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
|
||||
@Override
|
||||
protected TableModel createDefaultDataModel() {
|
||||
return new SfvTableModel();
|
||||
return new ChecksumTableModel();
|
||||
}
|
||||
|
||||
|
||||
|
@ -93,7 +93,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
public void clear() {
|
||||
((BackgroundFileTransferablePolicy<?>) getTransferablePolicy()).cancelAll();
|
||||
|
||||
((SfvTableModel) getModel()).clear();
|
||||
((ChecksumTableModel) getModel()).clear();
|
||||
}
|
||||
|
||||
private PropertyChangeListener repaintListener = new PropertyChangeListener() {
|
||||
|
@ -115,7 +115,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
|
||||
|
||||
public String getDefaultFileName() {
|
||||
SfvTableModel model = (SfvTableModel) getModel();
|
||||
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||
File columnRoot = model.getChecksumColumnRoot(0);
|
||||
|
||||
String name = "";
|
||||
|
@ -136,7 +136,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
|
||||
|
||||
public void removeRows(int... rowIndices) {
|
||||
SfvTableModel model = (SfvTableModel) getModel();
|
||||
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||
model.removeRows(rowIndices);
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
|
|||
try {
|
||||
PrintStream out = new PrintStream(file);
|
||||
|
||||
SfvTableModel model = (SfvTableModel) getModel();
|
||||
ChecksumTableModel model = (ChecksumTableModel) getModel();
|
||||
File columnRoot = model.getChecksumColumnRoot(checksumColumnIndex);
|
||||
|
||||
if (columnRoot != null) {
|
||||
|
|
|
@ -17,12 +17,12 @@ import net.sourceforge.filebot.FileBotUtil;
|
|||
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
|
||||
|
||||
|
||||
class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<SfvTableModel.Entry> {
|
||||
class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumTableModel.Entry> {
|
||||
|
||||
private SfvTableModel tableModel;
|
||||
private ChecksumTableModel tableModel;
|
||||
|
||||
|
||||
public SfvTransferablePolicy(SfvTableModel tableModel) {
|
||||
public SfvTransferablePolicy(ChecksumTableModel tableModel) {
|
||||
this.tableModel = tableModel;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<SfvTableMod
|
|||
|
||||
|
||||
@Override
|
||||
protected void process(List<SfvTableModel.Entry> chunks) {
|
||||
protected void process(List<ChecksumTableModel.Entry> chunks) {
|
||||
tableModel.addAll(chunks);
|
||||
}
|
||||
|
||||
|
@ -65,13 +65,13 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<SfvTableMod
|
|||
String filename = matcher.group(1);
|
||||
String checksumString = matcher.group(2);
|
||||
|
||||
publish(new SfvTableModel.Entry(filename, new Checksum(checksumString), sfvFile));
|
||||
publish(new ChecksumTableModel.Entry(filename, new Checksum(checksumString), sfvFile));
|
||||
|
||||
File compareColumnRoot = sfvFile.getParentFile();
|
||||
File compareFile = new File(compareColumnRoot, filename);
|
||||
|
||||
if (compareFile.exists()) {
|
||||
publish(new SfvTableModel.Entry(filename, new Checksum(compareFile), compareColumnRoot));
|
||||
publish(new ChecksumTableModel.Entry(filename, new Checksum(ChecksumComputationService.getService().submit(compareFile, compareColumnRoot)), compareColumnRoot));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,29 +91,23 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<SfvTableMod
|
|||
|
||||
@Override
|
||||
protected void load(List<File> files) {
|
||||
synchronized (ChecksumComputationExecutor.getInstance()) {
|
||||
ChecksumComputationExecutor.getInstance().pause();
|
||||
|
||||
if (FileBotUtil.containsOnlySfvFiles(files)) {
|
||||
// one or more sfv files
|
||||
for (File file : files) {
|
||||
loadSfvFile(file);
|
||||
}
|
||||
} else if ((files.size() == 1) && files.get(0).isDirectory()) {
|
||||
// one single folder
|
||||
File file = files.get(0);
|
||||
|
||||
for (File f : file.listFiles()) {
|
||||
load(f, file, "");
|
||||
}
|
||||
} else {
|
||||
// bunch of files
|
||||
for (File f : files) {
|
||||
load(f, f.getParentFile(), "");
|
||||
}
|
||||
if (FileBotUtil.containsOnlySfvFiles(files)) {
|
||||
// one or more sfv files
|
||||
for (File file : files) {
|
||||
loadSfvFile(file);
|
||||
}
|
||||
} else if ((files.size() == 1) && files.get(0).isDirectory()) {
|
||||
// one single folder
|
||||
File file = files.get(0);
|
||||
|
||||
ChecksumComputationExecutor.getInstance().resume();
|
||||
for (File f : file.listFiles()) {
|
||||
load(f, file, "");
|
||||
}
|
||||
} else {
|
||||
// bunch of files
|
||||
for (File f : files) {
|
||||
load(f, f.getParentFile(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +123,7 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<SfvTableMod
|
|||
load(f, columnRoot, newPrefix);
|
||||
}
|
||||
} else if (file.isFile()) {
|
||||
publish(new SfvTableModel.Entry(prefix + file.getName(), new Checksum(file), columnRoot));
|
||||
publish(new ChecksumTableModel.Entry(prefix + file.getName(), new Checksum(ChecksumComputationService.getService().submit(file, columnRoot)), columnRoot));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,59 +36,44 @@ class TotalProgressPanel extends Box {
|
|||
setBorder(BorderFactory.createCompoundBorder(margin, title));
|
||||
|
||||
add(progressBar);
|
||||
ChecksumComputationExecutor.getInstance().addPropertyChangeListener(executorListener);
|
||||
ChecksumComputationService.getService().addPropertyChangeListener(executorListener);
|
||||
}
|
||||
|
||||
private PropertyChangeListener executorListener = new PropertyChangeListener() {
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
ChecksumComputationExecutor executor = ChecksumComputationExecutor.getInstance();
|
||||
|
||||
String property = evt.getPropertyName();
|
||||
|
||||
if (property == ChecksumComputationExecutor.ACTIVE_PROPERTY) {
|
||||
if (property == ChecksumComputationService.ACTIVE_PROPERTY) {
|
||||
Boolean active = (Boolean) evt.getNewValue();
|
||||
setVisible(active);
|
||||
return;
|
||||
}
|
||||
|
||||
if (property == ChecksumComputationExecutor.PAUSED_PROPERTY) {
|
||||
Boolean paused = (Boolean) evt.getNewValue();
|
||||
|
||||
if (paused) {
|
||||
progressBar.setString("Updating ...");
|
||||
if (active) {
|
||||
new SetVisibleTimer().start();
|
||||
}
|
||||
} else if (property == ChecksumComputationService.REMAINING_TASK_COUNT_PROPERTY) {
|
||||
|
||||
int taskCount = ChecksumComputationService.getService().getActiveSessionTaskCount();
|
||||
int progress = taskCount - ChecksumComputationService.getService().getRemainingTaskCount();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (property == ChecksumComputationExecutor.ACTIVE_SESSION_TASK_COUNT_PROPERTY) {
|
||||
progressBar.setMaximum(executor.getActiveSessionTaskCount());
|
||||
}
|
||||
|
||||
if (property == ChecksumComputationExecutor.REMAINING_TASK_COUNT_PROPERTY) {
|
||||
int progress = executor.getActiveSessionTaskCount() - executor.getRemainingTaskCount();
|
||||
progressBar.setValue(progress);
|
||||
progressBar.setMaximum(taskCount);
|
||||
|
||||
progressBar.setString(progressBar.getValue() + " / " + progressBar.getMaximum());
|
||||
}
|
||||
|
||||
progressBar.setString(progressBar.getValue() + " / " + progressBar.getMaximum());
|
||||
if (!ChecksumComputationService.getService().isActive()) {
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean flag) {
|
||||
if (flag) {
|
||||
new SetVisibleTimer().start();
|
||||
} else {
|
||||
super.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private int millisToSetVisible = 200;
|
||||
|
||||
|
||||
private class SetVisibleTimer extends Timer implements ActionListener {
|
||||
|
||||
private static final int millisToSetVisible = 200;
|
||||
|
||||
|
||||
public SetVisibleTimer() {
|
||||
super(millisToSetVisible, null);
|
||||
addActionListener(this);
|
||||
|
@ -97,8 +82,7 @@ class TotalProgressPanel extends Box {
|
|||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (ChecksumComputationExecutor.getInstance().isActive())
|
||||
TotalProgressPanel.super.setVisible(true);
|
||||
setVisible(ChecksumComputationService.getService().isActive());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,9 @@ package net.sourceforge.filebot.ui.transfer;
|
|||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.TransferHandler;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
|
||||
|
||||
public class DefaultTransferHandler extends TransferHandler {
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
firePropertyChange(LOADING_PROPERTY, false, true);
|
||||
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, false, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
firePropertyChange(LOADING_PROPERTY, true, false);
|
||||
propertyChangeSupport.firePropertyChange(LOADING_PROPERTY, true, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -184,17 +184,8 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
|
|||
}
|
||||
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
propertyChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
|
||||
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
|
||||
propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ package net.sourceforge.filebot.web;
|
|||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.tuned.DownloadTask;
|
||||
|
||||
|
||||
public class SubsceneSubtitleDescriptor {
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
package net.sourceforge.filebot.web;
|
||||
package net.sourceforge.tuned;
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -55,8 +55,7 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
|
|||
|
||||
|
||||
public DownloadTask(URL url, Map<String, String> postdata) {
|
||||
this.url = url;
|
||||
this.postdata = encodeParameters(postdata);
|
||||
this(url, encodeParameters(postdata));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue