threading bugfixes and improvements
This commit is contained in:
parent
a94e60312c
commit
ecf7674c95
@ -16,6 +16,7 @@ import javax.swing.DefaultListModel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.Timer;
|
import javax.swing.Timer;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
@ -90,6 +91,9 @@ public class FileBotPanelSelectionList extends JList {
|
|||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
selectEnabled = true;
|
selectEnabled = true;
|
||||||
|
|
||||||
|
// bring window to front when on dnd
|
||||||
|
SwingUtilities.getWindowAncestor(FileBotPanelSelectionList.this).toFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ public class ChecksumComputationExecutor {
|
|||||||
|
|
||||||
private static final int MINIMUM_POOL_SIZE = 1;
|
private static final int MINIMUM_POOL_SIZE = 1;
|
||||||
|
|
||||||
private boolean active = false;
|
private Boolean active = false;
|
||||||
private long lastTaskCount = 0;
|
private long lastTaskCount = 0;
|
||||||
|
|
||||||
private static ChecksumComputationExecutor instance = null;
|
private static ChecksumComputationExecutor instance = new ChecksumComputationExecutor();
|
||||||
|
|
||||||
private LinkedBlockingQueue<ChecksumComputationTask> workQueue = new LinkedBlockingQueue<ChecksumComputationTask>();
|
private LinkedBlockingQueue<ChecksumComputationTask> workQueue = new LinkedBlockingQueue<ChecksumComputationTask>();
|
||||||
|
|
||||||
@ -48,25 +48,20 @@ public class ChecksumComputationExecutor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private ChecksumComputationExecutor() {
|
public static ChecksumComputationExecutor getInstance() {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static synchronized ChecksumComputationExecutor getInstance() {
|
|
||||||
if (instance == null)
|
|
||||||
instance = new ChecksumComputationExecutor();
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void execute(ChecksumComputationTask task) {
|
public void execute(ChecksumComputationTask task) {
|
||||||
setActive(true);
|
synchronized (workQueue) {
|
||||||
|
setActive(true);
|
||||||
|
|
||||||
adjustPoolSize();
|
adjustPoolSize();
|
||||||
|
|
||||||
|
executor.execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
executor.execute(task);
|
|
||||||
fireActiveSessionTaskCountChange();
|
fireActiveSessionTaskCountChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +73,7 @@ public class ChecksumComputationExecutor {
|
|||||||
// for only a few files, use only one thread
|
// for only a few files, use only one thread
|
||||||
// for lots of files, use multiple threads
|
// for lots of files, use multiple threads
|
||||||
// e.g 200 files ~ 1 thread, 1000 files ~ 2 threads, 40000 files ~ 4 threads
|
// e.g 200 files ~ 1 thread, 1000 files ~ 2 threads, 40000 files ~ 4 threads
|
||||||
int recommendedPoolSize = (int) Math.max(Math.log10(Math.max(workQueue.size(), 1)), MINIMUM_POOL_SIZE);
|
int recommendedPoolSize = (int) Math.log10(Math.max(workQueue.size(), 1) + MINIMUM_POOL_SIZE);
|
||||||
|
|
||||||
if (executor.getCorePoolSize() != recommendedPoolSize)
|
if (executor.getCorePoolSize() != recommendedPoolSize)
|
||||||
executor.setCorePoolSize(recommendedPoolSize);
|
executor.setCorePoolSize(recommendedPoolSize);
|
||||||
@ -107,22 +102,24 @@ public class ChecksumComputationExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private synchronized void setActive(boolean b) {
|
private void setActive(boolean b) {
|
||||||
if (this.active == b)
|
synchronized (active) {
|
||||||
return;
|
if (this.active == b)
|
||||||
|
return;
|
||||||
|
|
||||||
this.active = b;
|
this.active = b;
|
||||||
|
|
||||||
if (!this.active) {
|
if (!this.active) {
|
||||||
// end of active computing session
|
// end of active computing session
|
||||||
lastTaskCount = executor.getTaskCount();
|
lastTaskCount = executor.getTaskCount();
|
||||||
|
|
||||||
// reset pool size
|
// reset pool size
|
||||||
adjustPoolSize();
|
adjustPoolSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke property change events on EDT
|
||||||
|
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, null, active));
|
||||||
}
|
}
|
||||||
|
|
||||||
// invoke property change events on EDT
|
|
||||||
SwingUtilities.invokeLater(new FirePropertyChangeRunnable(ACTIVE_PROPERTY, null, active));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,6 +157,20 @@ public class ChecksumComputationExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
synchronized (workQueue) {
|
||||||
|
executor.purge();
|
||||||
|
workQueue.clear();
|
||||||
|
|
||||||
|
adjustPoolSize();
|
||||||
|
|
||||||
|
if (executor.getActiveCount() == 0) {
|
||||||
|
setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
propertyChangeSupport.addPropertyChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.sfv;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -77,6 +78,11 @@ public class ChecksumRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Collection<Checksum> getChecksums() {
|
||||||
|
return checksumMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void putChecksum(File columnRoot, Checksum checksum) {
|
public void putChecksum(File columnRoot, Checksum checksum) {
|
||||||
checksumMap.put(columnRoot, checksum);
|
checksumMap.put(columnRoot, checksum);
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,6 @@ public class SfvTableModel extends AbstractTableModel {
|
|||||||
private int checksumColumnsOffset = 2;
|
private int checksumColumnsOffset = 2;
|
||||||
|
|
||||||
|
|
||||||
public SfvTableModel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getColumnName(int columnIndex) {
|
public String getColumnName(int columnIndex) {
|
||||||
if (columnIndex == 0)
|
if (columnIndex == 0)
|
||||||
@ -152,16 +147,16 @@ public class SfvTableModel extends AbstractTableModel {
|
|||||||
|
|
||||||
|
|
||||||
public synchronized void clear() {
|
public synchronized void clear() {
|
||||||
|
|
||||||
// stop any running computations
|
// stop any running computations
|
||||||
for (ChecksumRow row : rows) {
|
for (ChecksumRow row : rows) {
|
||||||
for (File columnRoot : checksumColumnRoots) {
|
for (Checksum checksum : row.getChecksums()) {
|
||||||
Checksum c = row.getChecksum(columnRoot);
|
checksum.cancelComputationTask();
|
||||||
|
|
||||||
if (c != null)
|
|
||||||
c.cancelComputationTask();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChecksumComputationExecutor.getInstance().clear();
|
||||||
|
|
||||||
checksumColumnRoots.clear();
|
checksumColumnRoots.clear();
|
||||||
rows.clear();
|
rows.clear();
|
||||||
rowMap.clear();
|
rowMap.clear();
|
||||||
|
@ -6,14 +6,12 @@ import java.io.BufferedReader;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.sourceforge.filebot.ui.FileFormat;
|
import net.sourceforge.filebot.ui.FileFormat;
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
|
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.FileTransferablePolicy;
|
|
||||||
import net.sourceforge.filebot.ui.transferablepolicies.MultiTransferablePolicy;
|
import net.sourceforge.filebot.ui.transferablepolicies.MultiTransferablePolicy;
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class SfvFilePolicy extends FileTransferablePolicy {
|
private class SfvFilePolicy extends BackgroundFileTransferablePolicy<SfvTableModel.Entry> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean accept(File file) {
|
protected boolean accept(File file) {
|
||||||
@ -45,6 +43,28 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void process(List<SfvTableModel.Entry> chunks) {
|
||||||
|
tableModel.addAll(chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean load(List<File> files) {
|
||||||
|
synchronized (ChecksumComputationExecutor.getInstance()) {
|
||||||
|
ChecksumComputationExecutor.getInstance().pause();
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
load(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChecksumComputationExecutor.getInstance().resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean load(File sfvFile) {
|
protected boolean load(File sfvFile) {
|
||||||
|
|
||||||
@ -54,8 +74,6 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
String line = null;
|
String line = null;
|
||||||
Pattern pattern = Pattern.compile("(.*)\\s+(\\p{XDigit}{8})");
|
Pattern pattern = Pattern.compile("(.*)\\s+(\\p{XDigit}{8})");
|
||||||
|
|
||||||
ArrayList<SfvTableModel.Entry> entries = new ArrayList<SfvTableModel.Entry>(50);
|
|
||||||
|
|
||||||
while ((line = in.readLine()) != null) {
|
while ((line = in.readLine()) != null) {
|
||||||
if (line.startsWith(";"))
|
if (line.startsWith(";"))
|
||||||
continue;
|
continue;
|
||||||
@ -68,21 +86,17 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
String filename = matcher.group(1);
|
String filename = matcher.group(1);
|
||||||
String checksumString = matcher.group(2);
|
String checksumString = matcher.group(2);
|
||||||
|
|
||||||
entries.add(new SfvTableModel.Entry(filename, new Checksum(checksumString), sfvFile));
|
publish(new SfvTableModel.Entry(filename, new Checksum(checksumString), sfvFile));
|
||||||
|
|
||||||
File compareColumnRoot = sfvFile.getParentFile();
|
File compareColumnRoot = sfvFile.getParentFile();
|
||||||
File compareFile = new File(compareColumnRoot, filename);
|
File compareFile = new File(compareColumnRoot, filename);
|
||||||
|
|
||||||
if (compareFile.exists()) {
|
if (compareFile.exists()) {
|
||||||
entries.add(new SfvTableModel.Entry(filename, new Checksum(compareFile), compareColumnRoot));
|
publish(new SfvTableModel.Entry(filename, new Checksum(compareFile), compareColumnRoot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
if (!entries.isEmpty()) {
|
|
||||||
tableModel.addAll(entries);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
@ -124,22 +138,26 @@ public class SfvTransferablePolicy extends MultiTransferablePolicy {
|
|||||||
if (files.isEmpty())
|
if (files.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ChecksumComputationExecutor.getInstance().pause();
|
synchronized (ChecksumComputationExecutor.getInstance()) {
|
||||||
|
ChecksumComputationExecutor.getInstance().pause();
|
||||||
|
|
||||||
File firstFile = files.get(0);
|
File firstFile = files.get(0);
|
||||||
|
|
||||||
if ((files.size() == 1 && firstFile.isDirectory())) {
|
if ((files.size() == 1 && firstFile.isDirectory())) {
|
||||||
for (File f : firstFile.listFiles())
|
for (File f : firstFile.listFiles()) {
|
||||||
load(f, firstFile, "");
|
load(f, firstFile, "");
|
||||||
} else {
|
}
|
||||||
File columnRoot = firstFile.getParentFile();
|
} else {
|
||||||
|
File columnRoot = firstFile.getParentFile();
|
||||||
|
|
||||||
for (File f : files)
|
for (File f : files) {
|
||||||
load(f, columnRoot, "");
|
load(f, columnRoot, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChecksumComputationExecutor.getInstance().resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
ChecksumComputationExecutor.getInstance().resume();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user