diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java index c59b3f20bf..93a1f1505d 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.ingest; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -37,6 +38,9 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.NetworkUtils; +import org.sleuthkit.autopsy.ingest.DataSourceIngestPipeline.PipelineModule; +import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason; +import org.sleuthkit.autopsy.ingest.IngestTasksScheduler.IngestJobTasksSnapshot; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.IngestJobInfo; @@ -51,7 +55,7 @@ import org.sleuthkit.autopsy.modules.interestingitems.FilesSet; * Encapsulates a data source and the ingest module pipelines used to process * it. */ -final class DataSourceIngestJob { +public final class DataSourceIngestJob { private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName()); @@ -1079,71 +1083,90 @@ final class DataSourceIngestJob { * @return An ingest job statistics object. */ Snapshot getSnapshot(boolean getIngestTasksSnapshot) { - return new Snapshot(getIngestTasksSnapshot); + /** + * Determine whether file ingest is running at the time of this snapshot + * and determine the earliest file ingest level pipeline start time, if + * file ingest was started at all. + */ + boolean fileIngestRunning = false; + Date fileIngestStartTime = null; + + for (FileIngestPipeline pipeline : this.fileIngestPipelines) { + if (pipeline.isRunning()) { + fileIngestRunning = true; + } + Date pipelineStartTime = pipeline.getStartTime(); + if (null != pipelineStartTime && (null == fileIngestStartTime || pipelineStartTime.before(fileIngestStartTime))) { + fileIngestStartTime = pipelineStartTime; + } + } + + long processedFilesCount = 0; + long estimatedFilesToProcessCount = 0; + long snapShotTime = new Date().getTime(); + IngestJobTasksSnapshot tasksSnapshot = null; + + if (getIngestTasksSnapshot) { + synchronized (fileIngestProgressLock) { + processedFilesCount = this.processedFiles; + estimatedFilesToProcessCount = this.estimatedFilesToProcess; + snapShotTime = new Date().getTime(); + } + tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(id); + + } + + return new Snapshot(this.dataSource.getName(), id, createTime, + getCurrentDataSourceIngestModule(), fileIngestRunning, fileIngestStartTime, + cancelled, cancellationReason, cancelledDataSourceIngestModules, + processedFilesCount, estimatedFilesToProcessCount, snapShotTime, tasksSnapshot); } /** * Stores basic diagnostic statistics for a data source ingest job. */ - final class Snapshot { + public static final class Snapshot implements Serializable { + + private static final long serialVersionUID = 1L; private final String dataSource; private final long jobId; private final long jobStartTime; private final long snapShotTime; - private final DataSourceIngestPipeline.PipelineModule dataSourceLevelIngestModule; - private boolean fileIngestRunning; - private Date fileIngestStartTime; + transient private final PipelineModule dataSourceLevelIngestModule; + private final boolean fileIngestRunning; + private final Date fileIngestStartTime; private final long processedFiles; private final long estimatedFilesToProcess; - private final IngestTasksScheduler.IngestJobTasksSnapshot tasksSnapshot; - private final boolean jobCancelled; - private final IngestJob.CancellationReason jobCancellationReason; - private final List cancelledDataSourceModules; + private final IngestJobTasksSnapshot tasksSnapshot; + transient private final boolean jobCancelled; + transient private final CancellationReason jobCancellationReason; + transient private final List cancelledDataSourceModules; /** * Constructs an object to store basic diagnostic statistics for a data * source ingest job. */ - Snapshot(boolean getIngestTasksSnapshot) { - this.dataSource = DataSourceIngestJob.this.dataSource.getName(); - this.jobId = DataSourceIngestJob.this.id; - this.jobStartTime = DataSourceIngestJob.this.createTime; - this.dataSourceLevelIngestModule = DataSourceIngestJob.this.getCurrentDataSourceIngestModule(); + Snapshot(String dataSourceName, long jobId, long jobStartTime, PipelineModule dataSourceIngestModule, + boolean fileIngestRunning, Date fileIngestStartTime, + boolean jobCancelled, CancellationReason cancellationReason, List cancelledModules, + long processedFiles, long estimatedFilesToProcess, + long snapshotTime, IngestJobTasksSnapshot tasksSnapshot) { + this.dataSource = dataSourceName; + this.jobId = jobId; + this.jobStartTime = jobStartTime; + this.dataSourceLevelIngestModule = dataSourceIngestModule; - /** - * Determine whether file ingest is running at the time of this - * snapshot and determine the earliest file ingest level pipeline - * start time, if file ingest was started at all. - */ - for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) { - if (pipeline.isRunning()) { - this.fileIngestRunning = true; - } - Date pipelineStartTime = pipeline.getStartTime(); - if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(this.fileIngestStartTime))) { - this.fileIngestStartTime = pipelineStartTime; - } - } - - this.jobCancelled = cancelled; + this.fileIngestRunning = fileIngestRunning; + this.fileIngestStartTime = fileIngestStartTime; + this.jobCancelled = jobCancelled; this.jobCancellationReason = cancellationReason; - this.cancelledDataSourceModules = new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules); + this.cancelledDataSourceModules = cancelledModules; - if (getIngestTasksSnapshot) { - synchronized (DataSourceIngestJob.this.fileIngestProgressLock) { - this.processedFiles = DataSourceIngestJob.this.processedFiles; - this.estimatedFilesToProcess = DataSourceIngestJob.this.estimatedFilesToProcess; - this.snapShotTime = new Date().getTime(); - } - this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId); - - } else { - this.processedFiles = 0; - this.estimatedFilesToProcess = 0; - this.snapShotTime = new Date().getTime(); - this.tasksSnapshot = null; - } + this.processedFiles = processedFiles; + this.estimatedFilesToProcess = estimatedFilesToProcess; + this.snapShotTime = snapshotTime; + this.tasksSnapshot = tasksSnapshot; } /** @@ -1190,11 +1213,11 @@ final class DataSourceIngestJob { return this.dataSourceLevelIngestModule; } - boolean fileIngestIsRunning() { + boolean getFileIngestIsRunning() { return this.fileIngestRunning; } - Date fileIngestStartTime() { + Date getFileIngestStartTime() { return this.fileIngestStartTime; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java index 33d767fb00..720313ba15 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java @@ -355,10 +355,10 @@ public final class IngestJob { dataSourceModule = new DataSourceIngestModuleHandle(dataSourceJobs.get(snapshot.getJobId()), module); } } - if (snapshot.fileIngestIsRunning()) { + if (snapshot.getFileIngestIsRunning()) { fileIngestRunning = true; } - Date childFileIngestStartTime = snapshot.fileIngestStartTime(); + Date childFileIngestStartTime = snapshot.getFileIngestStartTime(); if (null != childFileIngestStartTime && (null == fileIngestStartTime || childFileIngestStartTime.before(fileIngestStartTime))) { fileIngestStartTime = childFileIngestStartTime; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 28a7c44474..fabf317187 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.awt.EventQueue; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -107,7 +108,7 @@ import org.sleuthkit.datamodel.Content; * job progress, and ingest module run times. */ @ThreadSafe -public class IngestManager { +public class IngestManager implements IngestProgressSnapshotProvider { private final static Logger logger = Logger.getLogger(IngestManager.class.getName()); private final static String INGEST_JOB_EVENT_CHANNEL_NAME = "%s-Ingest-Job-Events"; //NON-NLS @@ -756,7 +757,8 @@ public class IngestManager { * * @return Map of module name to run time (in milliseconds) */ - Map getModuleRunTimes() { + @Override + public Map getModuleRunTimes() { synchronized (ingestModuleRunTimes) { Map times = new HashMap<>(ingestModuleRunTimes); return times; @@ -769,7 +771,8 @@ public class IngestManager { * * @return A collection of ingest manager ingest task snapshots. */ - List getIngestThreadActivitySnapshots() { + @Override + public List getIngestThreadActivitySnapshots() { return new ArrayList<>(ingestThreadActivitySnapshots.values()); } @@ -778,7 +781,8 @@ public class IngestManager { * * @return A list of ingest job state snapshots. */ - List getIngestJobSnapshots() { + @Override + public List getIngestJobSnapshots() { List snapShots = new ArrayList<>(); synchronized (ingestJobsById) { ingestJobsById.values().forEach((job) -> { @@ -916,7 +920,9 @@ public class IngestManager { * running in an ingest thread. */ @Immutable - static final class IngestThreadActivitySnapshot { + public static final class IngestThreadActivitySnapshot implements Serializable { + + private static final long serialVersionUID = 1L; private final long threadId; private final Date startTime; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotDialog.java index bf28a611a4..eddebd59c4 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotDialog.java @@ -50,12 +50,14 @@ public final class IngestProgressSnapshotDialog extends JDialog { /** * Constructs an instance of the dialog with its own frame. Could be modal. + * Uses the given provider as the source of data for the dialog. * * @param owner - the owner of this dialog. If this dialog should be * modal, the owner gets set to non modal. * @param shouldBeModal - true if this should be modal, false otherwise. + * @param provider - the provider to use as the source of data. */ - public IngestProgressSnapshotDialog(Container owner, Boolean shouldBeModal) { + public IngestProgressSnapshotDialog(Container owner, Boolean shouldBeModal, IngestProgressSnapshotProvider provider) { super((Window) owner, TITLE, ModalityType.MODELESS); if (shouldBeModal && owner instanceof JDialog) { // if called from a modal dialog, manipulate the parent be just under this in z order, and not modal. final JDialog pseudoOwner = (JDialog) owner; @@ -82,7 +84,7 @@ public final class IngestProgressSnapshotDialog extends JDialog { this.getRootPane().registerKeyboardAction(e -> { this.dispose(); }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - add(new IngestProgressSnapshotPanel(this)); + add(new IngestProgressSnapshotPanel(this, provider)); pack(); setResizable(false); if (shouldBeModal) { // if called from a modal dialog, become modal, otherwise don't. @@ -90,4 +92,17 @@ public final class IngestProgressSnapshotDialog extends JDialog { } setVisible(true); } + + /** + * Constructs an instance of the dialog with its own frame. Could be modal. + * Uses the internal IngestManager instance as the source of data for the + * dialog + * + * @param owner - the owner of this dialog. If this dialog should be + * modal, the owner gets set to non modal. + * @param shouldBeModal - true if this should be modal, false otherwise. + */ + public IngestProgressSnapshotDialog(Container owner, Boolean shouldBeModal) { + this(owner, shouldBeModal, IngestManager.getInstance()); + } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java index 65cd40a9b2..be4661ce5b 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java @@ -33,15 +33,17 @@ import org.openide.util.NbBundle; /** * A panel that displays ingest task progress snapshots. */ -public class IngestProgressSnapshotPanel extends javax.swing.JPanel { +class IngestProgressSnapshotPanel extends javax.swing.JPanel { private final JDialog parent; + private final IngestProgressSnapshotProvider snapshotProvider; private final IngestThreadActivitySnapshotsTableModel threadActivityTableModel; private final IngestJobTableModel jobTableModel; private final ModuleTableModel moduleTableModel; - IngestProgressSnapshotPanel(JDialog parent) { + IngestProgressSnapshotPanel(JDialog parent, IngestProgressSnapshotProvider snapshotProvider) { this.parent = parent; + this.snapshotProvider = snapshotProvider; threadActivityTableModel = new IngestThreadActivitySnapshotsTableModel(); jobTableModel = new IngestJobTableModel(); moduleTableModel = new ModuleTableModel(); @@ -105,7 +107,7 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } private void refresh() { - snapshots = IngestManager.getInstance().getIngestThreadActivitySnapshots(); + snapshots = snapshotProvider.getIngestThreadActivitySnapshots(); fireTableDataChanged(); } @@ -187,7 +189,7 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } private void refresh() { - jobSnapshots = IngestManager.getInstance().getIngestJobSnapshots(); + jobSnapshots = snapshotProvider.getIngestJobSnapshots(); fireTableDataChanged(); } @@ -299,7 +301,7 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } private void refresh() { - Map moduleStatMap = IngestManager.getInstance().getModuleRunTimes(); + Map moduleStatMap = snapshotProvider.getModuleRunTimes(); moduleStats.clear(); totalTime = 0; for (String k : moduleStatMap.keySet()) { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotProvider.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotProvider.java new file mode 100644 index 0000000000..511939e1f9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotProvider.java @@ -0,0 +1,49 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.ingest; + +import java.util.List; +import java.util.Map; + +/** + * Interface that provides a snapshot of ingest progress. + */ +public interface IngestProgressSnapshotProvider { + + /** + * Get a snapshot of the state of ingest threads. + * + * @return A list of IngestThreadActivitySnapshot + */ + List getIngestThreadActivitySnapshots(); + + /** + * Get a snapshot of the state of ingest jobs. + * + * @return A list of ingest job snapshots. + */ + List getIngestJobSnapshots(); + + /** + * Gets the cumulative run times for the ingest module. + * + * @return Map of module name to run time (in milliseconds) + */ + Map getModuleRunTimes(); +} diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java index 26e603e55b..f63ed1b885 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestTasksScheduler.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.ingest; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -555,7 +556,11 @@ final class IngestTasksScheduler { * @return */ synchronized IngestJobTasksSnapshot getTasksSnapshotForJob(long jobId) { - return new IngestJobTasksSnapshot(jobId); + return new IngestJobTasksSnapshot(jobId, this.dataSourceIngestThreadQueue.countQueuedTasksForJob(jobId), + countTasksForJob(this.rootFileTaskQueue, jobId), + countTasksForJob(this.pendingFileTaskQueue, jobId), + this.fileIngestThreadsQueue.countQueuedTasksForJob(jobId), + this.dataSourceIngestThreadQueue.countRunningTasksForJob(jobId) + this.fileIngestThreadsQueue.countRunningTasksForJob(jobId)); } /** @@ -825,8 +830,9 @@ final class IngestTasksScheduler { /** * A snapshot of ingest tasks data for an ingest job. */ - class IngestJobTasksSnapshot { + public static final class IngestJobTasksSnapshot implements Serializable { + private static final long serialVersionUID = 1L; private final long jobId; private final long dsQueueSize; private final long rootQueueSize; @@ -839,13 +845,13 @@ final class IngestTasksScheduler { * * @param jobId The identifier associated with the job. */ - IngestJobTasksSnapshot(long jobId) { + IngestJobTasksSnapshot(long jobId, long dsQueueSize, long rootQueueSize, long dirQueueSize, long fileQueueSize, long runningListSize) { this.jobId = jobId; - this.dsQueueSize = IngestTasksScheduler.this.dataSourceIngestThreadQueue.countQueuedTasksForJob(jobId); - this.rootQueueSize = countTasksForJob(IngestTasksScheduler.this.rootFileTaskQueue, jobId); - this.dirQueueSize = countTasksForJob(IngestTasksScheduler.this.pendingFileTaskQueue, jobId); - this.fileQueueSize = IngestTasksScheduler.this.fileIngestThreadsQueue.countQueuedTasksForJob(jobId);; - this.runningListSize = IngestTasksScheduler.this.dataSourceIngestThreadQueue.countRunningTasksForJob(jobId) + IngestTasksScheduler.this.fileIngestThreadsQueue.countRunningTasksForJob(jobId); + this.dsQueueSize = dsQueueSize; + this.rootQueueSize = rootQueueSize; + this.dirQueueSize = dirQueueSize; + this.fileQueueSize = fileQueueSize; + this.runningListSize = runningListSize; } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index 5d8768c25c..f17372f055 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -143,19 +143,20 @@ final class AutoIngestAdminActions { static final class ProgressDialogAction extends AbstractAction { private static final long serialVersionUID = 1L; + private final AutoIngestJob job; - ProgressDialogAction() { + ProgressDialogAction(AutoIngestJob job) { super(Bundle.AutoIngestAdminActions_progressDialogAction_title()); + this.job = job; } @Override public void actionPerformed(ActionEvent e) { - //TODO JIRA-3734 final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); if (tc != null) { AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); if (dashboard != null) { - new IngestProgressSnapshotDialog(dashboard.getTopLevelAncestor(), true); + new IngestProgressSnapshotDialog(dashboard.getTopLevelAncestor(), true, job); } } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index 40537d3b83..25a3b3d495 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,23 +25,28 @@ import java.time.Instant; import java.util.Collections; import java.util.Comparator; import java.util.Date; +import java.util.List; +import java.util.Map; import java.util.Objects; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.NetworkUtils; +import org.sleuthkit.autopsy.ingest.DataSourceIngestJob.Snapshot; import org.sleuthkit.autopsy.ingest.IngestJob; +import org.sleuthkit.autopsy.ingest.IngestManager.IngestThreadActivitySnapshot; +import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotProvider; /** * An automated ingest job, which is an ingest job performed by the automated * ingest service. */ @ThreadSafe -final class AutoIngestJob implements Comparable, Serializable { +final class AutoIngestJob implements Comparable, IngestProgressSnapshotProvider, Serializable { private static final long serialVersionUID = 1L; - private static final int CURRENT_VERSION = 2; + private static final int CURRENT_VERSION = 3; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); @@ -89,6 +94,13 @@ final class AutoIngestJob implements Comparable, Serializable { @GuardedBy("this") private long dataSourceSize; + /* + * Version 3 fields. + */ + private List ingestThreadsSnapshot; + private List ingestJobsSnapshot; + private Map moduleRunTimesSnapshot; + /** * Constructs a new automated ingest job. All job state not specified in the * job manifest is set to the default state for a new job. @@ -125,6 +137,13 @@ final class AutoIngestJob implements Comparable, Serializable { * Version 2 fields. */ this.dataSourceSize = 0; + + /* + * Version 3 fields. + */ + this.ingestThreadsSnapshot = Collections.emptyList(); + this.ingestJobsSnapshot = Collections.emptyList(); + this.moduleRunTimesSnapshot = Collections.emptyMap(); } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -167,6 +186,13 @@ final class AutoIngestJob implements Comparable, Serializable { * Version 2 fields. */ this.dataSourceSize = nodeData.getDataSourceSize(); + + /* + * Version 3 fields + */ + this.ingestThreadsSnapshot = Collections.emptyList(); + this.ingestJobsSnapshot = Collections.emptyList(); + this.moduleRunTimesSnapshot = Collections.emptyMap(); } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -340,6 +366,31 @@ final class AutoIngestJob implements Comparable, Serializable { return this.ingestJob; } + /** + * Sets the ingest thread snapshot for the auto ingest job. + * + * @param snapshot + */ + synchronized void setIngestThreadSnapshot(List snapshot) { + this.ingestThreadsSnapshot = snapshot; + } + + /** + * Sets the ingest job snapshot for the auto ingest job. + * @param snapshot + */ + synchronized void setIngestJobsSnapshot(List snapshot) { + this.ingestJobsSnapshot = snapshot; + } + + /** + * Sets the module run times snapshot for the auto ingest job. + * @param snapshot + */ + synchronized void setModuleRuntimesSnapshot(Map snapshot) { + this.moduleRunTimesSnapshot = snapshot; + } + /** * Cancels the job. */ @@ -541,6 +592,21 @@ final class AutoIngestJob implements Comparable, Serializable { return -this.getManifest().getDateFileCreated().compareTo(otherJob.getManifest().getDateFileCreated()); } + @Override + public List getIngestThreadActivitySnapshots() { + return this.ingestThreadsSnapshot; + } + + @Override + public List getIngestJobSnapshots() { + return this.ingestJobsSnapshot; + } + + @Override + public Map getModuleRunTimes() { + return this.moduleRunTimesSnapshot; + } + /** * Comparator that supports doing a descending sort of jobs based on job * completion date. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index 916245d412..55837299ae 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -260,9 +260,9 @@ final class AutoIngestJobsNode extends AbstractNode { actions.add(deprioritizeCaseAction); break; case RUNNING_JOB: - actions.add(new AutoIngestAdminActions.ProgressDialogAction()); + actions.add(new AutoIngestAdminActions.ProgressDialogAction(autoIngestJob)); actions.add(new AutoIngestAdminActions.CancelJobAction(autoIngestJob)); - actions.add(new AutoIngestAdminActions.CancelModuleAction()); +// actions.add(new AutoIngestAdminActions.CancelModuleAction()); break; case COMPLETED_JOB: actions.add(new AutoIngestAdminActions.ReprocessJobAction(autoIngestJob)); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 987ee36c15..d43db389fd 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -3052,6 +3052,9 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen synchronized (jobsLock) { if (currentJob != null) { currentJob.getProcessingStageDetails(); + currentJob.setIngestThreadSnapshot(IngestManager.getInstance().getIngestThreadActivitySnapshots()); + currentJob.setIngestJobsSnapshot(IngestManager.getInstance().getIngestJobSnapshots()); + currentJob.setModuleRuntimesSnapshot(IngestManager.getInstance().getModuleRunTimes()); setChanged(); notifyObservers(Event.JOB_STATUS_UPDATED); updateCoordinationServiceManifestNode(currentJob); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index 08272a27fb..09e6d1a861 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -188,7 +188,17 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen */ AutoIngestJob job = event.getJob(); jobsSnapshot.removePendingJob(job); - jobsSnapshot.addOrReplaceRunningJob(job); + + // Update the state of the existing job in the running jobs table + for (AutoIngestJob runningJob : jobsSnapshot.getRunningJobs()) { + if (runningJob.equals(job)) { + runningJob.setIngestJobsSnapshot(job.getIngestJobSnapshots()); + runningJob.setIngestThreadSnapshot(job.getIngestThreadActivitySnapshots()); + runningJob.setModuleRuntimesSnapshot(job.getModuleRunTimes()); + runningJob.setProcessingStage(job.getProcessingStage(), job.getProcessingStageStartDate()); + runningJob.setProcessingStatus(job.getProcessingStatus()); + } + } setChanged(); notifyObservers(jobsSnapshot); }