Merge pull request #795 from rcordovano/snapshots_improvements

Snapshots improvements
This commit is contained in:
Richard Cordovano 2014-06-19 13:29:05 -04:00
commit b3d1f71a65
12 changed files with 231 additions and 189 deletions

View File

@ -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();

View File

@ -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

View File

@ -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<DataSourceIngestModuleDecorator> 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;
}

View File

@ -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);
}
}

View File

@ -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<FileIngestModuleDecorator> modules = new ArrayList<>();
private final List<FileIngestModuleDecorator> modules = new ArrayList<>();
FileIngestPipeline(IngestJobContext context, List<IngestModuleTemplate> 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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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<Long, Future<Void>> startIngestJobThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles.
private final ConcurrentHashMap<Long, Future<?>> dataSourceIngestThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles.
private final ConcurrentHashMap<Long, Future<?>> fileIngestThreads = new ConcurrentHashMap<>(); // Maps thread ids to cancellation handles.
private final ConcurrentHashMap<Long, IngestThreadActivitySnapshot> 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<IngestTask.ProgressSnapshot> 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<IngestThreadActivitySnapshot> 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<Void> 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;
}
}
}

View File

@ -19,9 +19,10 @@
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="snapshotsScrollPane" max="32767" attributes="0"/>
<Component id="snapshotsScrollPane" pref="881" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="0" pref="733" max="32767" attributes="0"/>
<Component id="fileProcessedPerSecondLabel" min="-2" pref="173" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="refreshButton" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="closeButton" linkSize="1" min="-2" max="-2" attributes="0"/>
@ -40,6 +41,7 @@
<Group type="103" groupAlignment="3" attributes="0">
<Component id="refreshButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="closeButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="fileProcessedPerSecondLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -54,7 +56,7 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="snapshotsTable">
<Component class="javax.swing.JTable" name="threadActivitySnapshotsTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="0" rowCount="0"/>
@ -89,5 +91,12 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="fileProcessedPerSecondLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestProgressSnapshotPanel.fileProcessedPerSecondLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -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<IngestTask.ProgressSnapshot> 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<IngestManager.IngestThreadActivitySnapshot> 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
}

View File

@ -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<AbstractFile> 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<IngestTask.ProgressSnapshot> getIngestTaskProgressSnapshots() {
return taskProgressSnapShots.getSnapshots();
}
synchronized void cancelIngestJob(IngestJob job) {
long jobId = job.getId();
removeAllPendingTasksForJob(pendingRootDirectoryTasks, jobId);

View File

@ -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<Long, IngestTask.ProgressSnapshot> snapshots = new ConcurrentHashMap<>(); // Maps ingest thread ids to progress snapshots.
void update(ProgressSnapshot snapshot) {
snapshots.put(snapshot.getThreadId(), snapshot);
}
List<ProgressSnapshot> getSnapshots() {
return new ArrayList(snapshots.values());
}
}
}
abstract void execute(long threadId) throws InterruptedException;
}