1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
package tim.prune.function.filesleuth;
import java.util.*;
import tim.prune.function.filesleuth.data.TrackContents;
import tim.prune.function.filesleuth.data.TrackFile;
import tim.prune.function.filesleuth.data.TrackFileList;
import tim.prune.function.filesleuth.data.TrackFileStatus;
/** Responsible for coordinating the various FileScanners working in parallel */
public class ScanController implements TrackListListener, WorkerCoordinator
{
private final TrackFileList _trackList;
private final TimeZone _timezone;
private int _numCurrentWorkers = 0;
private final LinkedList<AbstractFileScanner> _waitingScanners = new LinkedList<>();
private ScannerCreator _scannerCreator = FileScanner::new;
private static final int MAX_PARALLEL_SCANS = 10;
/** Constructor */
public ScanController(TrackFileList inList, TimeZone inTimezone)
{
_trackList = inList;
_trackList.addListener(this);
_timezone = inTimezone;
}
@Override
public void reactToTrackListChange(int inIndex)
{
List<TrackFile> tracks = _trackList.getCurrentContents();
for (int i=inIndex; i<tracks.size(); i++)
{
TrackFile track = tracks.get(i);
if (track.getStatus() == TrackFileStatus.FOUND
&& _trackList.claimTrackFileForScanning(track))
{
_waitingScanners.add(_scannerCreator.createScanner(track, this, _timezone));
}
}
startWaitingScanners();
}
public synchronized void cancel() {
_waitingScanners.clear();
}
public synchronized void startWaitingScanners()
{
while (_numCurrentWorkers < MAX_PARALLEL_SCANS && !_waitingScanners.isEmpty())
{
_waitingScanners.pop().startScan();
_numCurrentWorkers++;
}
}
/** One worker has finished, so pass its results on. Also, we may be able to start another one */
@Override
public void informWorkComplete(TrackFile inFile, TrackContents inContents)
{
_trackList.scanComplete(inFile, inContents);
synchronized (this) {
_numCurrentWorkers--;
}
startWaitingScanners();
}
/** TEST_ONLY: replace the scanner creator to use a different type of worker for testing */
void setScannerCreator(ScannerCreator inCreator) {
_scannerCreator = inCreator;
}
interface ScannerCreator {
AbstractFileScanner createScanner(TrackFile inTrack, WorkerCoordinator inCoordinator, TimeZone inTimezone);
}
}
|