diff --git a/Core/src/org/sleuthkit/autopsy/actions/TagAction.java b/Core/src/org/sleuthkit/autopsy/actions/TagAction.java index 8db091b54b..6b5615a812 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/TagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/TagAction.java @@ -54,6 +54,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact; * that the directory tree would refresh. But, we haven't had a chance to add * that so, we fire these events and the tree refreshes based on them. */ - IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent("TagAction", BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)); + IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent("TagAction", BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)); //NON-NLS } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 463ef55096..a8393e42bf 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -107,7 +107,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabel4.text")); // NOI18N - restartRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N + restartRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N NON-NLS org.openide.awt.Mnemonics.setLocalizedText(restartRequiredLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java index ae2bd50bc1..616059a28d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java @@ -46,8 +46,8 @@ final class IngestJob { private long estimatedFilesToProcess = 0L; // Guarded by this private long processedFiles = 0L; // Guarded by this private DataSourceIngestPipeline dataSourceIngestPipeline; - private ProgressHandle dataSourceTasksProgress; - private ProgressHandle fileTasksProgress; + private ProgressHandle dataSourceIngestProgress; + private ProgressHandle fileIngestProgress; private volatile boolean cancelled = false; /** @@ -140,11 +140,11 @@ final class IngestJob { final String displayName = NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.initialDisplayName", dataSource.getName()); - dataSourceTasksProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { + dataSourceIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { - if (dataSourceTasksProgress != null) { - dataSourceTasksProgress.setDisplayName( + if (dataSourceIngestProgress != null) { + dataSourceIngestProgress.setDisplayName( NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling", displayName)); @@ -153,19 +153,19 @@ final class IngestJob { return true; } }); - dataSourceTasksProgress.start(); - dataSourceTasksProgress.switchToIndeterminate(); + dataSourceIngestProgress.start(); + dataSourceIngestProgress.switchToIndeterminate(); } private void startFileIngestProgressBar() { final String displayName = NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", dataSource.getName()); - fileTasksProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { + fileIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { - if (fileTasksProgress != null) { - fileTasksProgress.setDisplayName( + if (fileIngestProgress != null) { + fileIngestProgress.setDisplayName( NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling", displayName)); } @@ -174,29 +174,28 @@ final class IngestJob { } }); estimatedFilesToProcess = dataSource.accept(new GetFilesCountVisitor()); - fileTasksProgress.start(); - fileTasksProgress.switchToDeterminate((int) estimatedFilesToProcess); + fileIngestProgress.start(); + fileIngestProgress.switchToDeterminate((int) estimatedFilesToProcess); } void process(DataSourceIngestTask task) throws InterruptedException { if (!isCancelled()) { List errors = new ArrayList<>(); - errors.addAll(dataSourceIngestPipeline.process(task.getDataSource(), dataSourceTasksProgress)); + errors.addAll(dataSourceIngestPipeline.process(task.getDataSource(), dataSourceIngestProgress)); if (!errors.isEmpty()) { logIngestModuleErrors(errors); } } else { taskScheduler.removeTasksForIngestJob(id); } + taskScheduler.notifyDataSourceIngestTaskCompleted(task); - // Because there is only one data source task per job, it is o.k. to - // call ProgressHandle.finish() now that the data source ingest modules - // are through using the progress bar via the DataSourceIngestModuleProgress wrapper. - // Calling ProgressHandle.finish() again in finish() will be harmless. - dataSourceTasksProgress.finish(); - - if (taskScheduler.isLastTaskForIngestJob(task)) { - finish(); + if (!taskScheduler.hasDataSourceIngestTaskForIngestJob(this)) { + finishProgressBar(dataSourceIngestProgress); + if (!taskScheduler.hasFileIngestTaskForIngestJob(this)) { + finishProgressBar(fileIngestProgress); + finish(); + } } } @@ -206,9 +205,9 @@ final class IngestJob { synchronized (this) { ++processedFiles; if (processedFiles <= estimatedFilesToProcess) { - fileTasksProgress.progress(file.getName(), (int) processedFiles); + fileIngestProgress.progress(file.getName(), (int) processedFiles); } else { - fileTasksProgress.progress(file.getName(), (int) estimatedFilesToProcess); + fileIngestProgress.progress(file.getName(), (int) estimatedFilesToProcess); } } FileIngestPipeline pipeline = fileIngestPipelines.take(); @@ -221,9 +220,21 @@ final class IngestJob { } else { taskScheduler.removeTasksForIngestJob(id); } + taskScheduler.notifyFileIngestTaskCompleted(task); - if (taskScheduler.isLastTaskForIngestJob(task)) { - finish(); + if (!taskScheduler.hasFileIngestTaskForIngestJob(this)) { + finishProgressBar(fileIngestProgress); + if (!taskScheduler.hasDataSourceIngestTaskForIngestJob(this)) { + finishProgressBar(dataSourceIngestProgress); + finish(); + } + } + } + + private synchronized void finishProgressBar(ProgressHandle progress) { + if (progress != null) { + progress.finish(); + progress = null; } } @@ -236,8 +247,6 @@ final class IngestJob { if (!errors.isEmpty()) { logIngestModuleErrors(errors); } - dataSourceTasksProgress.finish(); - fileTasksProgress.finish(); ingestJobsById.remove(id); if (!isCancelled()) { IngestManager.getInstance().fireIngestJobCompleted(id); @@ -256,6 +265,8 @@ final class IngestJob { private void cancel() { cancelled = true; + finishProgressBar(dataSourceIngestProgress); + finishProgressBar(fileIngestProgress); IngestManager.getInstance().fireIngestJobCancelled(id); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java index 9c003895d4..2225efc617 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java @@ -45,7 +45,8 @@ final class IngestScheduler { private final TreeSet rootDirectoryTasks = new TreeSet<>(new RootDirectoryTaskComparator()); // Guarded by this private final List directoryTasks = new ArrayList<>(); // Guarded by this private final LinkedBlockingQueue fileTasks = new LinkedBlockingQueue<>(); // Guarded by this - private final List tasksInProgress = new ArrayList<>(); // Guarded by this + private final List dataSourceTasksInProgress = new ArrayList<>(); // Guarded by this + private final List fileTasksInProgress = new ArrayList<>(); // Guarded by this private final DataSourceIngestTaskQueue dataSourceTaskDispenser = new DataSourceIngestTaskQueue(); private final FileIngestTaskQueue fileTaskDispenser = new FileIngestTaskQueue(); @@ -105,7 +106,7 @@ final class IngestScheduler { } } - updateFileTaskQueues(null); + updateFileTaskQueues(); } void addFileTaskToIngestJob(IngestJob job, AbstractFile file) { @@ -120,7 +121,7 @@ final class IngestScheduler { } } - synchronized void removeTasksForIngestJob(long ingestJobId) { + synchronized void removeTasksForIngestJob(long ingestJobId) { // Remove all tasks for this ingest job that are not in progress. Iterator fileTasksIterator = fileTasks.iterator(); while (fileTasksIterator.hasNext()) { @@ -148,11 +149,7 @@ final class IngestScheduler { } } - private synchronized void updateFileTaskQueues(FileIngestTask taskInProgress) throws InterruptedException { - if (taskInProgress != null) { - tasksInProgress.add(taskInProgress); - } - + private synchronized void updateFileTaskQueues() throws InterruptedException { // we loop because we could have a directory that has all files // that do not get enqueued while (true) { @@ -262,36 +259,52 @@ final class IngestScheduler { return fileTaskDispenser; } - synchronized boolean isLastTaskForIngestJob(IngestTask completedTask) { - tasksInProgress.remove(completedTask); - IngestJob job = completedTask.getIngestJob(); + synchronized void notifyDataSourceIngestTaskCompleted(DataSourceIngestTask task) { + dataSourceTasksInProgress.remove(task); + } + + synchronized void notifyFileIngestTaskCompleted(FileIngestTask task) { + fileTasksInProgress.remove(task); + } + + synchronized boolean hasDataSourceIngestTaskForIngestJob(IngestJob job) { long jobId = job.getId(); - for (IngestTask task : tasksInProgress) { + for (IngestTask task : dataSourceTasksInProgress) { if (task.getIngestJob().getId() == jobId) { - return false; - } - } - for (FileIngestTask task : fileTasks) { - if (task.getIngestJob().getId() == jobId) { - return false; - } - } - for (FileIngestTask task : directoryTasks) { - if (task.getIngestJob().getId() == jobId) { - return false; - } - } - for (FileIngestTask task : rootDirectoryTasks) { - if (task.getIngestJob().getId() == jobId) { - return false; + return true; } } for (DataSourceIngestTask task : dataSourceTasks) { if (task.getIngestJob().getId() == jobId) { - return false; + return true; } } - return true; + return false; + } + + synchronized boolean hasFileIngestTaskForIngestJob(IngestJob job) { + long jobId = job.getId(); + for (IngestTask task : fileTasksInProgress) { + if (task.getIngestJob().getId() == jobId) { + return true; + } + } + for (FileIngestTask task : fileTasks) { + if (task.getIngestJob().getId() == jobId) { + return true; + } + } + for (FileIngestTask task : directoryTasks) { + if (task.getIngestJob().getId() == jobId) { + return true; + } + } + for (FileIngestTask task : rootDirectoryTasks) { + if (task.getIngestJob().getId() == jobId) { + return true; + } + } + return false; } private static class RootDirectoryTaskComparator implements Comparator { @@ -394,7 +407,11 @@ final class IngestScheduler { @Override public IngestTask getNextTask() throws InterruptedException { - return dataSourceTasks.take(); + DataSourceIngestTask task = dataSourceTasks.take(); + synchronized (this) { + dataSourceTasksInProgress.add(task); + } + return task; } } @@ -403,7 +420,10 @@ final class IngestScheduler { @Override public IngestTask getNextTask() throws InterruptedException { FileIngestTask task = fileTasks.take(); - updateFileTaskQueues(task); + synchronized (this) { + fileTasksInProgress.add(task); + } + updateFileTaskQueues(); return task; } }