diff --git a/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java b/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java index 4a8ab2309d..82f2b3bfc4 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/ShowIngestProgressSnapshotAction.java @@ -20,8 +20,6 @@ package org.sleuthkit.autopsy.actions; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionRegistration; @@ -29,7 +27,6 @@ import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.actions.SystemAction; -import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog; @ActionID( @@ -46,16 +43,6 @@ public final class ShowIngestProgressSnapshotAction extends SystemAction impleme private static final String ACTION_NAME = NbBundle.getMessage(ShowIngestProgressSnapshotAction.class, "ShowIngestProgressSnapshotAction.actionName.text"); - public ShowIngestProgressSnapshotAction() { - setEnabled(false); - IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - setEnabled(IngestManager.getInstance().isIngestRunning()); - } - }); - } - @Override public void actionPerformed(ActionEvent e) { IngestProgressSnapshotDialog dialog = new IngestProgressSnapshotDialog(); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index bc7c8f2783..8e1cdf51fb 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -68,12 +68,14 @@ IngestJobConfigurator.createModuleSettingsFolderForContext.exception.title=Inges IngestJobConfigurator.saveJobSettings.usermsg=Failed to save ingest job settings for {0} module. IngestJobConfigurator.saveJobSettings.usermsg.title=Ingest Job Settings IngestJobConfigurationPanel.descriptionLabel.text= -IngestProgressSnapshotDialog.title.text=Ingest Task Progress Snapshots +IngestProgressSnapshotDialog.title.text=Ingest Progress Snapshot IngestProgressSnapshotPanel.refreshButton.text=Refresh IngestProgressSnapshotPanel.closeButton.text=Close IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=Thread ID IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=Data Source -IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.ingestModule=Ingest Module +IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=Activity IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=File IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=Start Time IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=Elapsed Time (H\:M\:S) +IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text=Files/Sec: {0} +IngestManager.IngestThreadActivitySnapshot.idleThread=IDLE diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java index 13dc301040..2752646947 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestPipeline.java @@ -32,6 +32,7 @@ import org.sleuthkit.datamodel.Content; */ final class DataSourceIngestPipeline { + private static final IngestManager ingestManager = IngestManager.getInstance(); private final IngestJobContext context; private List modules = new ArrayList<>(); @@ -90,7 +91,7 @@ final class DataSourceIngestPipeline { progress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.displayName", module.getDisplayName(), dataSource.getName())); - task.updateProgressStatus(module.getDisplayName(), null); + ingestManager.setIngestTaskProgress(task, module.getDisplayName()); module.process(dataSource, new DataSourceIngestModuleProgress(progress)); } catch (Exception ex) { // Catch-all exception firewall errors.add(new IngestModuleError(module.getDisplayName(), ex)); @@ -99,6 +100,7 @@ final class DataSourceIngestPipeline { break; } } + ingestManager.setIngestTaskProgressCompleted(task); return errors; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestTask.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestTask.java index ae3652c4af..4fecebbe84 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestTask.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestTask.java @@ -18,21 +18,15 @@ */ package org.sleuthkit.autopsy.ingest; -import org.sleuthkit.datamodel.Content; - final class DataSourceIngestTask extends IngestTask { - DataSourceIngestTask(IngestJob job, ProgressSnapshots snapshots) { - super(job, snapshots); + DataSourceIngestTask(IngestJob job) { + super(job); } - Content getDataSource() { - return getIngestJob().getDataSource(); - } - @Override void execute(long threadId) throws InterruptedException { - super.execute(threadId); + super.setThreadId(threadId); getIngestJob().process(this); } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java index 3416c9d3f7..6d53ad12bc 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestPipeline.java @@ -30,8 +30,9 @@ import org.sleuthkit.datamodel.AbstractFile; */ final class FileIngestPipeline { + private static final IngestManager ingestManager = IngestManager.getInstance(); private final IngestJobContext context; - private List modules = new ArrayList<>(); + private final List modules = new ArrayList<>(); FileIngestPipeline(IngestJobContext context, List moduleTemplates) { this.context = context; @@ -96,7 +97,7 @@ final class FileIngestPipeline { AbstractFile file = task.getFile(); for (FileIngestModuleDecorator module : modules) { try { - task.updateProgressStatus(module.getDisplayName(), file); + ingestManager.setIngestTaskProgress(task, module.getDisplayName()); module.process(file); } catch (Exception ex) { // Catch-all exception firewall errors.add(new IngestModuleError(module.getDisplayName(), ex)); @@ -109,6 +110,7 @@ final class FileIngestPipeline { if (!context.isJobCancelled()) { IngestManager.getInstance().fireFileIngestDone(file.getId()); } + ingestManager.setIngestTaskProgressCompleted(task); return errors; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestTask.java b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestTask.java index 8c02d063f2..6fa02cf4fc 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/FileIngestTask.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/FileIngestTask.java @@ -29,8 +29,8 @@ final class FileIngestTask extends IngestTask { private final AbstractFile file; - FileIngestTask(IngestJob job, AbstractFile file, ProgressSnapshots snapshots) { - super(job, snapshots); + FileIngestTask(IngestJob job, AbstractFile file) { + super(job); this.file = file; } @@ -40,7 +40,7 @@ final class FileIngestTask extends IngestTask { @Override void execute(long threadId) throws InterruptedException { - super.execute(threadId); + super.setThreadId(threadId); getIngestJob().process(this); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java index 92e2359b6a..0cdcdbeb24 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java @@ -180,10 +180,7 @@ final class IngestJob { * @return True or false. */ boolean hasDataSourceIngestPipeline() { - if (dataSourceIngestPipeline.isEmpty()) { - return false; - } - return true; + return (dataSourceIngestPipeline.isEmpty() == false); } /** @@ -192,10 +189,7 @@ final class IngestJob { * @return True or false. */ boolean hasFileIngestPipeline() { - if (fileIngestPipelines.peek().isEmpty()) { - return false; - } - return true; + return (fileIngestPipelines.peek().isEmpty() == false); } void process(DataSourceIngestTask task) throws InterruptedException { @@ -206,7 +200,7 @@ final class IngestJob { logIngestModuleErrors(errors); } } - if (dataSourceIngestProgress != null) { + if (null != dataSourceIngestProgress) { dataSourceIngestProgress.finish(); // This is safe because this method will be called at most once per // ingest job and finish() will not be called while that single diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index 4de62c14b2..57a33db0f8 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.ingest; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -40,6 +42,7 @@ import org.sleuthkit.datamodel.Content; import javax.swing.JOptionPane; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.datamodel.AbstractFile; /** * Manages the execution of ingest jobs. @@ -63,13 +66,16 @@ public class IngestManager { private final ConcurrentHashMap> startIngestJobThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. private final ConcurrentHashMap> dataSourceIngestThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. private final ConcurrentHashMap> fileIngestThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles. + private final ConcurrentHashMap ingestThreadActivitySnapshots = new ConcurrentHashMap<>(); // Maps ingest thread ids to progress ingestThreadActivitySnapshots. + private final Object processedFilesSnapshotLock = new Object(); + private ProcessedFilesSnapshot processedFilesSnapshot = new ProcessedFilesSnapshot(); private volatile IngestMessageTopComponent ingestMessageBox; private int numberOfFileIngestThreads = DEFAULT_NUMBER_OF_FILE_INGEST_THREADS; /** * Gets the ingest manager. * - * @returns A singleton IngestManager object. + * @return A singleton IngestManager object. */ public synchronized static IngestManager getInstance() { if (instance == null) { @@ -113,14 +119,17 @@ public class IngestManager { /** * Gets the number of data source ingest threads the ingest manager will * use. + * + * @return The number of data source ingest threads. */ public int getNumberOfDataSourceIngestThreads() { return DEFAULT_NUMBER_OF_DATA_SOURCE_INGEST_THREADS; } /** - * Gets the maximum number of file ingest threads the ingest manager will - * use. + * Gets the number of file ingest threads the ingest manager will use. + * + * @return The number of file ingest threads. */ public int getNumberOfFileIngestThreads() { return numberOfFileIngestThreads; @@ -134,6 +143,7 @@ public class IngestManager { long threadId = nextThreadId.incrementAndGet(); Future handle = dataSourceIngestThreadPool.submit(new ExecuteIngestTasksThread(threadId, IngestScheduler.getInstance().getDataSourceIngestTaskQueue())); dataSourceIngestThreads.put(threadId, handle); + ingestThreadActivitySnapshots.put(threadId, new IngestThreadActivitySnapshot(threadId)); } /** @@ -144,6 +154,7 @@ public class IngestManager { long threadId = nextThreadId.incrementAndGet(); Future handle = fileIngestThreadPool.submit(new ExecuteIngestTasksThread(threadId, IngestScheduler.getInstance().getFileIngestTaskQueue())); fileIngestThreads.put(threadId, handle); + ingestThreadActivitySnapshots.put(threadId, new IngestThreadActivitySnapshot(threadId)); } /** @@ -203,10 +214,38 @@ public class IngestManager { return IngestScheduler.getInstance().ingestJobsAreRunning(); } - List getIngestTaskProgressSnapshots() { - return IngestScheduler.getInstance().getIngestTaskProgressSnapshots(); + void setIngestTaskProgress(DataSourceIngestTask task, String ingestModuleDisplayName) { + ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId(), ingestModuleDisplayName, task.getDataSource())); + } + + void setIngestTaskProgress(FileIngestTask task, String ingestModuleDisplayName) { + ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId(), ingestModuleDisplayName, task.getDataSource(), task.getFile())); } + void setIngestTaskProgressCompleted(DataSourceIngestTask task) { + ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId())); + } + + void setIngestTaskProgressCompleted(FileIngestTask task) { + ingestThreadActivitySnapshots.put(task.getThreadId(), new IngestThreadActivitySnapshot(task.getThreadId())); + synchronized (processedFilesSnapshotLock) { + processedFilesSnapshot.incrementProcessedFilesCount(); + } + } + + List getIngestThreadActivitySnapshots() { + return new ArrayList(ingestThreadActivitySnapshots.values()); + } + + ProcessedFilesSnapshot getProcessedFilesSnapshot() { + ProcessedFilesSnapshot snapshot; + synchronized (processedFilesSnapshotLock) { + snapshot = processedFilesSnapshot; + processedFilesSnapshot = new ProcessedFilesSnapshot(); + } + return snapshot; + } + public void cancelAllIngestJobs() { // Stop creating new ingest jobs. for (Future handle : startIngestJobThreads.values()) { @@ -421,7 +460,7 @@ public class IngestManager { return -1; } } - + /** * Creates ingest jobs. */ @@ -494,7 +533,7 @@ public class IngestManager { notifyMessage.append("\n\n"); JOptionPane.showMessageDialog(null, notifyMessage.toString(), NbBundle.getMessage(this.getClass(), - "IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle"), JOptionPane.ERROR_MESSAGE); + "IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle"), JOptionPane.ERROR_MESSAGE); } progress.progress(++dataSourceProcessed); @@ -502,11 +541,14 @@ public class IngestManager { break; } } + } catch (InterruptedException ex) { + // Reset interrupted status. + Thread.currentThread().interrupt(); } finally { progress.finish(); startIngestJobThreads.remove(threadId); - return null; } + return null; } } @@ -578,4 +620,80 @@ public class IngestManager { } } } + + static final class IngestThreadActivitySnapshot { + + private final long threadId; + private final Date startTime; + private final String activity; + private final String dataSourceName; + private final String fileName; + + IngestThreadActivitySnapshot(long threadId) { + this.threadId = threadId; + startTime = new Date(); + this.activity = NbBundle.getMessage(this.getClass(), "IngestManager.IngestThreadActivitySnapshot.idleThread"); + this.dataSourceName = ""; + this.fileName = ""; + } + + IngestThreadActivitySnapshot(long threadId, String activity, Content dataSource) { + this.threadId = threadId; + startTime = new Date(); + this.activity = activity; + this.dataSourceName = dataSource.getName(); + this.fileName = ""; + } + + IngestThreadActivitySnapshot(long threadId, String activity, Content dataSource, AbstractFile file) { + this.threadId = threadId; + startTime = new Date(); + this.activity = activity; + this.dataSourceName = dataSource.getName(); + this.fileName = file.getName(); + } + + long getThreadId() { + return threadId; + } + + Date getStartTime() { + return startTime; + } + + String getActivity() { + return activity; + } + + String getDataSourceName() { + return dataSourceName; + } + + String getFileName() { + return fileName; + } + } + + static final class ProcessedFilesSnapshot { + + private final Date startTime; + private long processedFilesCount; + + ProcessedFilesSnapshot() { + this.startTime = new Date(); + this.processedFilesCount = 0; + } + + void incrementProcessedFilesCount() { + ++processedFilesCount; + } + + Date getStartTime() { + return startTime; + } + + long getProcessedFilesCount() { + return processedFilesCount; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form index a18c047dc4..bef05de400 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.form @@ -19,9 +19,10 @@ - + - + + @@ -40,6 +41,7 @@ + @@ -54,7 +56,7 @@ - + @@ -89,5 +91,12 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java index 0ea37f4679..601e95f887 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestProgressSnapshotPanel.java @@ -18,8 +18,6 @@ */ package org.sleuthkit.autopsy.ingest; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.util.Date; import java.util.List; import javax.swing.JDialog; @@ -27,79 +25,75 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import org.apache.commons.lang3.time.DurationFormatUtils; import org.openide.util.NbBundle; -import org.sleuthkit.datamodel.AbstractFile; public class IngestProgressSnapshotPanel extends javax.swing.JPanel { private final JDialog parent; - private final SnapshotsTableModel tableModel; + private final IngestThreadActivitySnapshotsTableModel threadActivityTableModel; IngestProgressSnapshotPanel(JDialog parent) { this.parent = parent; - tableModel = new SnapshotsTableModel(); + threadActivityTableModel = new IngestThreadActivitySnapshotsTableModel(); initComponents(); customizeComponents(); - IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent event) { - refreshButton.setEnabled(IngestManager.getInstance().isIngestRunning() == true); - } - }); } private void customizeComponents() { - snapshotsTable.setModel(tableModel); + threadActivitySnapshotsTable.setModel(threadActivityTableModel); int width = snapshotsScrollPane.getPreferredSize().width; - for (int i = 0; i < snapshotsTable.getColumnCount(); ++i) { - TableColumn column = snapshotsTable.getColumnModel().getColumn(i); + for (int i = 0; i < threadActivitySnapshotsTable.getColumnCount(); ++i) { + TableColumn column = threadActivitySnapshotsTable.getColumnModel().getColumn(i); switch (i) { case 0: - column.setPreferredWidth(((int) (width * 0.05))); + column.setPreferredWidth(((int) (width * 0.02))); break; case 1: - column.setPreferredWidth(((int) (width * 0.15))); + column.setPreferredWidth(((int) (width * 0.20))); break; case 2: - column.setPreferredWidth(((int) (width * 0.25))); + column.setPreferredWidth(((int) (width * 0.15))); break; case 3: column.setPreferredWidth(((int) (width * 0.35))); break; case 4: - column.setPreferredWidth(((int) (width * 0.10))); + column.setPreferredWidth(((int) (width * 0.18))); break; case 5: column.setPreferredWidth(((int) (width * 0.10))); break; } } - - snapshotsTable.setFillsViewportHeight(true); + + threadActivitySnapshotsTable.setFillsViewportHeight(true); + + fileProcessedPerSecondLabel.setText(NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text", 0)); } - private class SnapshotsTableModel extends AbstractTableModel { + private class IngestThreadActivitySnapshotsTableModel extends AbstractTableModel { private final String[] columnNames = {NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID"), - NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource"), - NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.ingestModule"), - NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file"), - NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime"), - NbBundle.getMessage(this.getClass(), - "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime")}; - private List snapshots; + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID"), + NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity"), + NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource"), + NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file"), + NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime"), + NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime")}; + private List snapshots; - private SnapshotsTableModel() { + private IngestThreadActivitySnapshotsTableModel() { refresh(); } private void refresh() { - snapshots = IngestManager.getInstance().getIngestTaskProgressSnapshots(); + snapshots = IngestManager.getInstance().getIngestThreadActivitySnapshots(); fireTableDataChanged(); } @@ -120,25 +114,20 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { @Override public Object getValueAt(int rowIndex, int columnIndex) { - IngestTask.ProgressSnapshot snapshot = snapshots.get(rowIndex); + IngestManager.IngestThreadActivitySnapshot snapshot = snapshots.get(rowIndex); Object cellValue; switch (columnIndex) { case 0: cellValue = snapshot.getThreadId(); break; case 1: - cellValue = snapshot.getDataSource().getName(); + cellValue = snapshot.getActivity(); break; case 2: - cellValue = snapshot.getModuleDisplayName(); + cellValue = snapshot.getDataSourceName(); break; case 3: - AbstractFile file = snapshot.getFile(); - if (file != null) { - cellValue = file.getName(); - } else { - cellValue = ""; - } + cellValue = snapshot.getFileName(); break; case 4: cellValue = snapshot.getStartTime(); @@ -146,10 +135,7 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { case 5: Date now = new Date(); long elapsedTime = now.getTime() - snapshot.getStartTime().getTime(); - cellValue = DurationFormatUtils.formatDurationHMS(elapsedTime); - // TODO: Restore when we go to Java 8 -// long elapsedTime = Duration.between(snapshot.getStartTime(), LocalTime.now()).toMillis(); -// cellValue = DurationFormatUtils.formatDurationHMS(elapsedTime); + cellValue = DurationFormatUtils.formatDurationHMS(elapsedTime); break; default: cellValue = null; @@ -169,11 +155,12 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { private void initComponents() { snapshotsScrollPane = new javax.swing.JScrollPane(); - snapshotsTable = new javax.swing.JTable(); + threadActivitySnapshotsTable = new javax.swing.JTable(); refreshButton = new javax.swing.JButton(); closeButton = new javax.swing.JButton(); + fileProcessedPerSecondLabel = new javax.swing.JLabel(); - snapshotsTable.setModel(new javax.swing.table.DefaultTableModel( + threadActivitySnapshotsTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { }, @@ -181,7 +168,7 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } )); - snapshotsScrollPane.setViewportView(snapshotsTable); + snapshotsScrollPane.setViewportView(threadActivitySnapshotsTable); org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(IngestProgressSnapshotPanel.class, "IngestProgressSnapshotPanel.refreshButton.text")); // NOI18N refreshButton.addActionListener(new java.awt.event.ActionListener() { @@ -197,6 +184,8 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { } }); + org.openide.awt.Mnemonics.setLocalizedText(fileProcessedPerSecondLabel, org.openide.util.NbBundle.getMessage(IngestProgressSnapshotPanel.class, "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -204,9 +193,10 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(snapshotsScrollPane) + .addComponent(snapshotsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 881, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addGap(0, 733, Short.MAX_VALUE) + .addComponent(fileProcessedPerSecondLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(refreshButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(closeButton))) @@ -223,7 +213,8 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(refreshButton) - .addComponent(closeButton)) + .addComponent(closeButton) + .addComponent(fileProcessedPerSecondLabel)) .addContainerGap()) ); @@ -236,14 +227,19 @@ public class IngestProgressSnapshotPanel extends javax.swing.JPanel { }//GEN-LAST:event_closeButtonActionPerformed private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed - if (IngestManager.getInstance().isIngestRunning() == true) { - tableModel.refresh(); - } + threadActivityTableModel.refresh(); + IngestManager.ProcessedFilesSnapshot snapshot = IngestManager.getInstance().getProcessedFilesSnapshot(); + Date now = new Date(); + long elapsedTime = now.getTime() - snapshot.getStartTime().getTime(); + double filesPerSecond = (double) snapshot.getProcessedFilesCount() / (double) elapsedTime * 1000.0; + fileProcessedPerSecondLabel.setText(NbBundle.getMessage(this.getClass(), + "IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text", filesPerSecond)); }//GEN-LAST:event_refreshButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton closeButton; + private javax.swing.JLabel fileProcessedPerSecondLabel; private javax.swing.JButton refreshButton; private javax.swing.JScrollPane snapshotsScrollPane; - private javax.swing.JTable snapshotsTable; + private javax.swing.JTable threadActivitySnapshotsTable; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java index 5a762b9d12..8c688a97c5 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestScheduler.java @@ -55,7 +55,6 @@ final class IngestScheduler { // private volatile boolean cancellingAllTasks = false; TODO: Uncomment this with related code, if desired private final DataSourceIngestTaskQueue dataSourceTaskDispenser = new DataSourceIngestTaskQueue(); private final FileIngestTaskQueue fileTaskDispenser = new FileIngestTaskQueue(); - private final IngestTask.ProgressSnapshots taskProgressSnapShots = new IngestTask.ProgressSnapshots(); // The following five collections lie at the heart of the scheduler. // // The pending tasks queues are used to schedule tasks for an ingest job. If @@ -132,7 +131,7 @@ final class IngestScheduler { } synchronized private void scheduleDataSourceIngestTask(IngestJob job) throws InterruptedException { - DataSourceIngestTask task = new DataSourceIngestTask(job, taskProgressSnapShots); + DataSourceIngestTask task = new DataSourceIngestTask(job); tasksInProgress.add(task); try { // Should not block, queue is (theoretically) unbounded. @@ -147,7 +146,7 @@ final class IngestScheduler { synchronized private void scheduleFileIngestTasks(IngestJob job) throws InterruptedException { List topLevelFiles = getTopLevelFiles(job.getDataSource()); for (AbstractFile firstLevelFile : topLevelFiles) { - FileIngestTask task = new FileIngestTask(job, firstLevelFile, taskProgressSnapShots); + FileIngestTask task = new FileIngestTask(job, firstLevelFile); if (shouldEnqueueFileTask(task)) { tasksInProgress.add(task); pendingRootDirectoryTasks.add(task); @@ -223,7 +222,7 @@ final class IngestScheduler { for (Content child : directory.getChildren()) { if (child instanceof AbstractFile) { AbstractFile file = (AbstractFile) child; - FileIngestTask childTask = new FileIngestTask(directoryTask.getIngestJob(), file, taskProgressSnapShots); + FileIngestTask childTask = new FileIngestTask(directoryTask.getIngestJob(), file); if (file.hasChildren()) { // Found a subdirectory, put the task in the // pending directory tasks queue. @@ -321,7 +320,7 @@ final class IngestScheduler { void scheduleAdditionalFileIngestTask(IngestJob job, AbstractFile file) throws InterruptedException { if (enabled) { - FileIngestTask task = new FileIngestTask(job, file, taskProgressSnapShots); + FileIngestTask task = new FileIngestTask(job, file); if (shouldEnqueueFileTask(task)) { // Send the file task directly to file tasks queue, no need to // update the pending root directory or pending directory tasks @@ -365,10 +364,6 @@ final class IngestScheduler { return !ingestJobsById.isEmpty(); } - List getIngestTaskProgressSnapshots() { - return taskProgressSnapShots.getSnapshots(); - } - synchronized void cancelIngestJob(IngestJob job) { long jobId = job.getId(); removeAllPendingTasksForJob(pendingRootDirectoryTasks, jobId); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestTask.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestTask.java index 389e3d6bb8..7ff6634f64 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestTask.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestTask.java @@ -18,91 +18,34 @@ */ package org.sleuthkit.autopsy.ingest; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -class IngestTask { +abstract class IngestTask { + private final static long NOT_SET = Long.MIN_VALUE; private final IngestJob job; - private final ProgressSnapshots snapshots; private long threadId; - IngestTask(IngestJob job, ProgressSnapshots snapshots) { + IngestTask(IngestJob job) { this.job = job; - this.snapshots = snapshots; + threadId = NOT_SET; } IngestJob getIngestJob() { return job; } - void updateProgressStatus(String ingestModuleDisplayName, AbstractFile file) { - snapshots.update(new ProgressSnapshot(threadId, job.getDataSource(), ingestModuleDisplayName, file)); + Content getDataSource() { + return getIngestJob().getDataSource(); + } + + long getThreadId() { + return threadId; } - - void execute(long threadId) throws InterruptedException { + + void setThreadId(long threadId) { this.threadId = threadId; - } - - public static final class ProgressSnapshot { - - private final long threadId; - private final Content dataSource; - private final String ingestModuleDisplayName; - private final AbstractFile file; - private final Date startTime; - // TODO: Restore when we go to Java 8 -// private final LocalTime startTime; - - private ProgressSnapshot(long threadId, Content dataSource, String ingestModuleDisplayName, AbstractFile file) { - this.threadId = threadId; - this.dataSource = dataSource; - this.ingestModuleDisplayName = ingestModuleDisplayName; - this.file = file; - startTime = new Date(); - // TODO: Restore when we go to Java 8 -// startTime = LocalTime.now(); - } - - long getThreadId() { - return threadId; - } - - Content getDataSource() { - return dataSource; - } - - String getModuleDisplayName() { - return ingestModuleDisplayName; - } - - AbstractFile getFile() { - return file; - } - - Date getStartTime() { - return startTime; - } - // TODO: Restore when we go to Java 8 -// LocalTime getStartTime() { -// return startTime; -// } - } - - static final class ProgressSnapshots { - - private final ConcurrentHashMap snapshots = new ConcurrentHashMap<>(); // Maps ingest thread ids to progress snapshots. - - void update(ProgressSnapshot snapshot) { - snapshots.put(snapshot.getThreadId(), snapshot); - } - - List getSnapshots() { - return new ArrayList(snapshots.values()); - } - } + } + + abstract void execute(long threadId) throws InterruptedException; }