Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataSourceIngestJob.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.ingest;
20 
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.CopyOnWriteArrayList;
29 import java.util.concurrent.LinkedBlockingQueue;
30 import java.util.concurrent.atomic.AtomicLong;
31 import java.util.logging.Level;
32 import javax.swing.JOptionPane;
33 import org.netbeans.api.progress.ProgressHandle;
34 import org.openide.util.Cancellable;
35 import org.openide.util.NbBundle;
36 import org.openide.windows.WindowManager;
44 import org.sleuthkit.datamodel.AbstractFile;
45 import org.sleuthkit.datamodel.Content;
46 import org.sleuthkit.datamodel.IngestJobInfo;
47 import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
48 import org.sleuthkit.datamodel.IngestModuleInfo;
49 import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
50 import org.sleuthkit.datamodel.SleuthkitCase;
51 import org.sleuthkit.datamodel.TskCoreException;
54 
59 public final class DataSourceIngestJob {
60 
61  private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName());
62 
69  private final IngestJob parentJob;
70  private static final AtomicLong nextJobId = new AtomicLong(0L);
71  private final long id;
72  private final IngestJobSettings settings;
73  private final Content dataSource;
74  private final List<AbstractFile> files = new ArrayList<>();
75 
79  private static enum Stages {
80 
98  FINALIZATION
99  };
101  private final Object stageCompletionCheckLock = new Object();
102 
111  private final Object dataSourceIngestPipelineLock = new Object();
112  private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
113  private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
114  private DataSourceIngestPipeline currentDataSourceIngestPipeline;
115 
123  private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue = new LinkedBlockingQueue<>();
124  private final List<FileIngestPipeline> fileIngestPipelines = new ArrayList<>();
125 
137  private volatile boolean currentDataSourceIngestModuleCancelled;
138  private final List<String> cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>();
139  private volatile boolean cancelled;
141 
146  private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
147 
152  private final boolean doUI;
153 
158  private final Object dataSourceIngestProgressLock = new Object();
159  private ProgressHandle dataSourceIngestProgress;
160 
165  private final Object fileIngestProgressLock = new Object();
166  private final List<String> filesInProgress = new ArrayList<>();
168  private long processedFiles;
169  private ProgressHandle fileIngestProgress;
170  private String currentFileIngestModule = "";
171  private String currentFileIngestTask = "";
172  private final List<IngestModuleInfo> ingestModules = new ArrayList<>();
173  private volatile IngestJobInfo ingestJob;
174 
178  private final long createTime;
179 
191  DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
192  this(parentJob, dataSource, Collections.emptyList(), settings, runInteractively);
193  }
194 
208  DataSourceIngestJob(IngestJob parentJob, Content dataSource, List<AbstractFile> files, IngestJobSettings settings, boolean runInteractively) {
209  this.parentJob = parentJob;
210  this.id = DataSourceIngestJob.nextJobId.getAndIncrement();
211  this.dataSource = dataSource;
212  this.files.addAll(files);
213  this.settings = settings;
214  this.doUI = runInteractively;
215  this.createTime = new Date().getTime();
216  this.createIngestPipelines();
217  }
218 
222  private void createIngestPipelines() {
223  List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
224 
228  Map<String, IngestModuleTemplate> dataSourceModuleTemplates = new LinkedHashMap<>();
229  Map<String, IngestModuleTemplate> fileModuleTemplates = new LinkedHashMap<>();
230  for (IngestModuleTemplate template : ingestModuleTemplates) {
231  if (template.isDataSourceIngestModuleTemplate()) {
232  dataSourceModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
233  }
234  if (template.isFileIngestModuleTemplate()) {
235  fileModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
236  }
237  }
238 
243  IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
244  List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
245  List<IngestModuleTemplate> fileIngestModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(fileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
246  List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
247 
253  for (IngestModuleTemplate template : dataSourceModuleTemplates.values()) {
254  firstStageDataSourceModuleTemplates.add(template);
255  }
256  for (IngestModuleTemplate template : fileModuleTemplates.values()) {
257  fileIngestModuleTemplates.add(template);
258  }
259 
263  this.firstStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, firstStageDataSourceModuleTemplates);
264  this.secondStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, secondStageDataSourceModuleTemplates);
265 
269  try {
270  int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
271  for (int i = 0; i < numberOfFileIngestThreads; ++i) {
272  FileIngestPipeline pipeline = new FileIngestPipeline(this, fileIngestModuleTemplates);
273  this.fileIngestPipelinesQueue.put(pipeline);
274  this.fileIngestPipelines.add(pipeline);
275  }
276  } catch (InterruptedException ex) {
282  Thread.currentThread().interrupt();
283  }
284  try {
285  SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
286  this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
287  this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
288  this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
289  } catch (TskCoreException | NoCurrentCaseException ex) {
290  logErrorMessage(Level.WARNING, "Failed to add ingest modules listing to case database", ex);
291  }
292  }
293 
294  private void addIngestModules(List<IngestModuleTemplate> templates, IngestModuleType type, SleuthkitCase skCase) throws TskCoreException {
295  for (IngestModuleTemplate module : templates) {
296  ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
297  }
298  }
299 
315  private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
316  List<IngestModuleTemplate> templates = new ArrayList<>();
317  for (String moduleClassName : pipelineConfig) {
318  if (ingestModuleTemplates.containsKey(moduleClassName)) {
319  templates.add(ingestModuleTemplates.remove(moduleClassName));
320  }
321  }
322  return templates;
323  }
324 
330  long getId() {
331  return this.id;
332  }
333 
339  String getExecutionContext() {
340  return this.settings.getExecutionContext();
341  }
342 
348  Content getDataSource() {
349  return this.dataSource;
350  }
351 
358  boolean shouldProcessUnallocatedSpace() {
359  return this.settings.getProcessUnallocatedSpace();
360  }
361 
367  FilesSet getFileIngestFilter() {
368  return this.settings.getFileFilter();
369  }
370 
376  boolean hasIngestPipeline() {
378  || this.hasFileIngestPipeline()
380  }
381 
389  return (this.firstStageDataSourceIngestPipeline.isEmpty() == false);
390  }
391 
399  return (this.secondStageDataSourceIngestPipeline.isEmpty() == false);
400  }
401 
407  private boolean hasFileIngestPipeline() {
408  if (!this.fileIngestPipelines.isEmpty()) {
409  return !this.fileIngestPipelines.get(0).isEmpty();
410  }
411  return false;
412  }
413 
419  List<IngestModuleError> start() {
420  List<IngestModuleError> errors = startUpIngestPipelines();
421  if (errors.isEmpty()) {
422  try {
423  this.ingestJob = Case.getCurrentCaseThrows().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
424  } catch (TskCoreException | NoCurrentCaseException ex) {
425  logErrorMessage(Level.WARNING, "Failed to add ingest job info to case database", ex); //NON-NLS
426  }
428  logInfoMessage("Starting first stage analysis"); //NON-NLS
429  this.startFirstStage();
430  } else if (this.hasSecondStageDataSourceIngestPipeline()) {
431  logInfoMessage("Starting second stage analysis"); //NON-NLS
432  this.startSecondStage();
433  }
434  }
435  return errors;
436  }
437 
444  private List<IngestModuleError> startUpIngestPipelines() {
445  List<IngestModuleError> errors = new ArrayList<>();
446 
447  /*
448  * Start the data-source-level ingest module pipelines.
449  */
450  errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
451  errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
452 
453  /*
454  * If the data-source-level ingest pipelines were successfully started,
455  * start the Start the file-level ingest pipelines (one per file ingest
456  * thread).
457  */
458  if (errors.isEmpty()) {
459  for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
460  errors.addAll(pipeline.startUp());
461  if (!errors.isEmpty()) {
462  /*
463  * If there are start up errors, the ingest job will not
464  * proceed, so shut down any file ingest pipelines that did
465  * start up.
466  */
467  while (!this.fileIngestPipelinesQueue.isEmpty()) {
468  FileIngestPipeline startedPipeline = this.fileIngestPipelinesQueue.poll();
469  if (startedPipeline.isRunning()) {
470  List<IngestModuleError> shutDownErrors = startedPipeline.shutDown();
471  if (!shutDownErrors.isEmpty()) {
472  /*
473  * The start up errors will ultimately be
474  * reported to the user for possible remedy, but
475  * the shut down errors are logged here.
476  */
477  logIngestModuleErrors(shutDownErrors);
478  }
479  }
480  }
481  break;
482  }
483  }
484  }
485 
486  return errors;
487  }
488 
492  private void startFirstStage() {
493  this.stage = DataSourceIngestJob.Stages.FIRST;
494 
495  if (this.hasFileIngestPipeline()) {
496  synchronized (this.fileIngestProgressLock) {
497  this.estimatedFilesToProcess = this.dataSource.accept(new GetFilesCountVisitor());
498  }
499  }
500 
501  if (this.doUI) {
507  }
508  if (this.hasFileIngestPipeline()) {
510  }
511  }
512 
517  synchronized (this.dataSourceIngestPipelineLock) {
518  this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
519  }
520 
525  logInfoMessage("Scheduling first stage data source and file level analysis tasks"); //NON-NLS
526  DataSourceIngestJob.taskScheduler.scheduleIngestTasks(this);
527  } else if (this.hasFirstStageDataSourceIngestPipeline()) {
528  logInfoMessage("Scheduling first stage data source level analysis tasks"); //NON-NLS
529  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
530  } else {
531  logInfoMessage("Scheduling file level analysis tasks, no first stage data source level analysis configured"); //NON-NLS
532  DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(this, this.files);
533 
542  this.checkForStageCompleted();
543  }
544  }
545 
549  private void startSecondStage() {
550  logInfoMessage("Starting second stage analysis"); //NON-NLS
551  this.stage = DataSourceIngestJob.Stages.SECOND;
552  if (this.doUI) {
554  }
555  synchronized (this.dataSourceIngestPipelineLock) {
556  this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
557  }
558  logInfoMessage("Scheduling second stage data source level analysis tasks"); //NON-NLS
559  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
560  }
561 
566  if (this.doUI) {
567  synchronized (this.dataSourceIngestProgressLock) {
568  String displayName = NbBundle.getMessage(this.getClass(),
569  "IngestJob.progress.dataSourceIngest.initialDisplayName",
570  this.dataSource.getName());
571  this.dataSourceIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
572  @Override
573  public boolean cancel() {
574  // If this method is called, the user has already pressed
575  // the cancel button on the progress bar and the OK button
576  // of a cancelation confirmation dialog supplied by
577  // NetBeans. What remains to be done is to find out whether
578  // the user wants to cancel only the currently executing
579  // data source ingest module or the entire ingest job.
580  DataSourceIngestCancellationPanel panel = new DataSourceIngestCancellationPanel();
581  String dialogTitle = NbBundle.getMessage(DataSourceIngestJob.this.getClass(), "IngestJob.cancellationDialog.title");
582  JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
583  if (panel.cancelAllDataSourceIngestModules()) {
585  } else {
586  DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
587  }
588  return true;
589  }
590  });
591  this.dataSourceIngestProgress.start();
592  this.dataSourceIngestProgress.switchToIndeterminate();
593  }
594  }
595  }
596 
600  private void startFileIngestProgressBar() {
601  if (this.doUI) {
602  synchronized (this.fileIngestProgressLock) {
603  String displayName = NbBundle.getMessage(this.getClass(),
604  "IngestJob.progress.fileIngest.displayName",
605  this.dataSource.getName());
606  this.fileIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
607  @Override
608  public boolean cancel() {
609  // If this method is called, the user has already pressed
610  // the cancel button on the progress bar and the OK button
611  // of a cancelation confirmation dialog supplied by
612  // NetBeans.
614  return true;
615  }
616  });
617  this.fileIngestProgress.start();
618  this.fileIngestProgress.switchToDeterminate((int) this.estimatedFilesToProcess);
619  }
620  }
621  }
622 
627  private void checkForStageCompleted() {
628  synchronized (this.stageCompletionCheckLock) {
629  if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(this)) {
630  switch (this.stage) {
631  case FIRST:
632  this.finishFirstStage();
633  break;
634  case SECOND:
635  this.finish();
636  break;
637  }
638  }
639  }
640  }
641 
646  private void finishFirstStage() {
647  logInfoMessage("Finished first stage analysis"); //NON-NLS
648 
649  // Shut down the file ingest pipelines. Note that no shut down is
650  // required for the data source ingest pipeline because data source
651  // ingest modules do not have a shutdown() method.
652  List<IngestModuleError> errors = new ArrayList<>();
653  while (!this.fileIngestPipelinesQueue.isEmpty()) {
654  FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
655  if (pipeline.isRunning()) {
656  errors.addAll(pipeline.shutDown());
657  }
658  }
659  if (!errors.isEmpty()) {
660  logIngestModuleErrors(errors);
661  }
662 
663  if (this.doUI) {
664  // Finish the first stage data source ingest progress bar, if it hasn't
665  // already been finished.
666  synchronized (this.dataSourceIngestProgressLock) {
667  if (this.dataSourceIngestProgress != null) {
668  this.dataSourceIngestProgress.finish();
669  this.dataSourceIngestProgress = null;
670  }
671  }
672 
673  // Finish the file ingest progress bar, if it hasn't already
674  // been finished.
675  synchronized (this.fileIngestProgressLock) {
676  if (this.fileIngestProgress != null) {
677  this.fileIngestProgress.finish();
678  this.fileIngestProgress = null;
679  }
680  }
681  }
682 
686  if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
687  this.startSecondStage();
688  } else {
689  this.finish();
690  }
691  }
692 
696  private void finish() {
697  logInfoMessage("Finished analysis"); //NON-NLS
699 
700  if (this.doUI) {
701  // Finish the second stage data source ingest progress bar, if it hasn't
702  // already been finished.
703  synchronized (this.dataSourceIngestProgressLock) {
704  if (this.dataSourceIngestProgress != null) {
705  this.dataSourceIngestProgress.finish();
706  this.dataSourceIngestProgress = null;
707  }
708  }
709  }
710  if (ingestJob != null) {
711  if (this.cancelled) {
712  try {
713  ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
714  } catch (TskCoreException ex) {
715  logErrorMessage(Level.WARNING, "Failed to update ingest job status in case database", ex);
716  }
717  } else {
718  try {
719  ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
720  } catch (TskCoreException ex) {
721  logErrorMessage(Level.WARNING, "Failed to update ingest job status in case database", ex);
722  }
723  }
724  try {
725  this.ingestJob.setEndDateTime(new Date());
726  } catch (TskCoreException ex) {
727  logErrorMessage(Level.WARNING, "Failed to set job end date in case database", ex);
728  }
729  }
730  this.parentJob.dataSourceJobFinished(this);
731  }
732 
739  void process(DataSourceIngestTask task) {
740  try {
741  synchronized (this.dataSourceIngestPipelineLock) {
742  if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
743  List<IngestModuleError> errors = new ArrayList<>();
744  errors.addAll(this.currentDataSourceIngestPipeline.process(task));
745  if (!errors.isEmpty()) {
746  logIngestModuleErrors(errors);
747  }
748  }
749  }
750 
751  if (this.doUI) {
756  synchronized (this.dataSourceIngestProgressLock) {
757  if (null != this.dataSourceIngestProgress) {
758  this.dataSourceIngestProgress.finish();
759  this.dataSourceIngestProgress = null;
760  }
761  }
762  }
763 
764  } finally {
765  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
766  this.checkForStageCompleted();
767  }
768  }
769 
781  void process(FileIngestTask task) throws InterruptedException {
782  try {
783  if (!this.isCancelled()) {
784  FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
785  if (!pipeline.isEmpty()) {
786  AbstractFile file = task.getFile();
787 
788  synchronized (this.fileIngestProgressLock) {
789  ++this.processedFiles;
790  if (this.doUI) {
794  if (this.processedFiles <= this.estimatedFilesToProcess) {
795  this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
796  } else {
797  this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
798  }
799  this.filesInProgress.add(file.getName());
800  }
801  }
802 
806  List<IngestModuleError> errors = new ArrayList<>();
807  errors.addAll(pipeline.process(task));
808  if (!errors.isEmpty()) {
809  logIngestModuleErrors(errors);
810  }
811 
812  if (this.doUI && !this.cancelled) {
813  synchronized (this.fileIngestProgressLock) {
818  this.filesInProgress.remove(file.getName());
819  if (this.filesInProgress.size() > 0) {
820  this.fileIngestProgress.progress(this.filesInProgress.get(0));
821  } else {
822  this.fileIngestProgress.progress("");
823  }
824  }
825  }
826  }
827  this.fileIngestPipelinesQueue.put(pipeline);
828  }
829  } finally {
830  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
831  this.checkForStageCompleted();
832  }
833  }
834 
842  void addFiles(List<AbstractFile> files) {
843  if (DataSourceIngestJob.Stages.FIRST == this.stage) {
844  DataSourceIngestJob.taskScheduler.fastTrackFileIngestTasks(this, files);
845  } else {
846  logErrorMessage(Level.SEVERE, "Adding files to job during second stage analysis not supported");
847  }
848 
855  this.checkForStageCompleted();
856  }
857 
864  void updateDataSourceIngestProgressBarDisplayName(String displayName) {
865  if (this.doUI && !this.cancelled) {
866  synchronized (this.dataSourceIngestProgressLock) {
867  this.dataSourceIngestProgress.setDisplayName(displayName);
868  }
869  }
870  }
871 
880  void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
881  if (this.doUI && !this.cancelled) {
882  synchronized (this.dataSourceIngestProgressLock) {
883  if (null != this.dataSourceIngestProgress) {
884  this.dataSourceIngestProgress.switchToDeterminate(workUnits);
885  }
886  }
887  }
888  }
889 
895  void switchDataSourceIngestProgressBarToIndeterminate() {
896  if (this.doUI && !this.cancelled) {
897  synchronized (this.dataSourceIngestProgressLock) {
898  if (null != this.dataSourceIngestProgress) {
899  this.dataSourceIngestProgress.switchToIndeterminate();
900  }
901  }
902  }
903  }
904 
911  void advanceDataSourceIngestProgressBar(int workUnits) {
912  if (this.doUI && !this.cancelled) {
913  synchronized (this.dataSourceIngestProgressLock) {
914  if (null != this.dataSourceIngestProgress) {
915  this.dataSourceIngestProgress.progress("", workUnits);
916  }
917  }
918  }
919  }
920 
927  void advanceDataSourceIngestProgressBar(String currentTask) {
928  if (this.doUI && !this.cancelled) {
929  synchronized (this.dataSourceIngestProgressLock) {
930  if (null != this.dataSourceIngestProgress) {
931  this.dataSourceIngestProgress.progress(currentTask);
932  }
933  }
934  }
935  }
936 
945  void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
946  if (this.doUI && !this.cancelled) {
947  synchronized (this.fileIngestProgressLock) {
948  this.dataSourceIngestProgress.progress(currentTask, workUnits);
949  }
950  }
951  }
952 
960  boolean currentDataSourceIngestModuleIsCancelled() {
962  }
963 
970  void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
971  this.currentDataSourceIngestModuleCancelled = false;
972  this.cancelledDataSourceIngestModules.add(moduleDisplayName);
973 
974  if (this.doUI) {
982  synchronized (this.dataSourceIngestProgressLock) {
983  this.dataSourceIngestProgress.finish();
984  this.dataSourceIngestProgress = null;
986  }
987  }
988  }
989 
995  DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
996  if (null != this.currentDataSourceIngestPipeline) {
997  return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
998  } else {
999  return null;
1000  }
1001  }
1002 
1007  void cancelCurrentDataSourceIngestModule() {
1008  this.currentDataSourceIngestModuleCancelled = true;
1009  }
1010 
1017  void cancel(IngestJob.CancellationReason reason) {
1018  this.cancelled = true;
1019  this.cancellationReason = reason;
1020  DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this);
1021 
1022  if (this.doUI) {
1023  synchronized (this.dataSourceIngestProgressLock) {
1024  if (null != dataSourceIngestProgress) {
1025  dataSourceIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.initialDisplayName", dataSource.getName()));
1026  dataSourceIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1027  }
1028  }
1029 
1030  synchronized (this.fileIngestProgressLock) {
1031  if (null != this.fileIngestProgress) {
1032  this.fileIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", this.dataSource.getName()));
1033  this.fileIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1034  }
1035  }
1036  }
1037  }
1038 
1046  void setCurrentFileIngestModule(String moduleName, String taskName) {
1047  this.currentFileIngestModule = moduleName;
1048  this.currentFileIngestTask = taskName;
1049  }
1050 
1057  boolean isCancelled() {
1058  return this.cancelled;
1059  }
1060 
1066  IngestJob.CancellationReason getCancellationReason() {
1067  return this.cancellationReason;
1068  }
1069 
1076  private void logInfoMessage(String message) {
1077  logger.log(Level.INFO, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id)); //NON-NLS
1078  }
1079 
1088  private void logErrorMessage(Level level, String message, Throwable throwable) {
1089  logger.log(level, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id), throwable); //NON-NLS
1090  }
1091 
1099  private void logErrorMessage(Level level, String message) {
1100  logger.log(level, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id)); //NON-NLS
1101  }
1102 
1108  private void logIngestModuleErrors(List<IngestModuleError> errors) {
1109  for (IngestModuleError error : errors) {
1110  logErrorMessage(Level.SEVERE, String.format("%s experienced an error during analysis", error.getModuleDisplayName()), error.getThrowable()); //NON-NLS
1111  }
1112  }
1113 
1119  Snapshot getSnapshot(boolean getIngestTasksSnapshot) {
1125  boolean fileIngestRunning = false;
1126  Date fileIngestStartTime = null;
1127 
1128  for (FileIngestPipeline pipeline : this.fileIngestPipelines) {
1129  if (pipeline.isRunning()) {
1130  fileIngestRunning = true;
1131  }
1132  Date pipelineStartTime = pipeline.getStartTime();
1133  if (null != pipelineStartTime && (null == fileIngestStartTime || pipelineStartTime.before(fileIngestStartTime))) {
1134  fileIngestStartTime = pipelineStartTime;
1135  }
1136  }
1137 
1138  long processedFilesCount = 0;
1139  long estimatedFilesToProcessCount = 0;
1140  long snapShotTime = new Date().getTime();
1141  IngestJobTasksSnapshot tasksSnapshot = null;
1142 
1143  if (getIngestTasksSnapshot) {
1144  synchronized (fileIngestProgressLock) {
1145  processedFilesCount = this.processedFiles;
1146  estimatedFilesToProcessCount = this.estimatedFilesToProcess;
1147  snapShotTime = new Date().getTime();
1148  }
1149  tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(id);
1150 
1151  }
1152 
1153  return new Snapshot(this.dataSource.getName(), id, createTime,
1154  getCurrentDataSourceIngestModule(), fileIngestRunning, fileIngestStartTime,
1156  processedFilesCount, estimatedFilesToProcessCount, snapShotTime, tasksSnapshot);
1157  }
1158 
1162  public static final class Snapshot implements Serializable {
1163 
1164  private static final long serialVersionUID = 1L;
1165 
1166  private final String dataSource;
1167  private final long jobId;
1168  private final long jobStartTime;
1169  private final long snapShotTime;
1170  transient private final PipelineModule dataSourceLevelIngestModule;
1171  private final boolean fileIngestRunning;
1172  private final Date fileIngestStartTime;
1173  private final long processedFiles;
1174  private final long estimatedFilesToProcess;
1175  private final IngestJobTasksSnapshot tasksSnapshot;
1176  transient private final boolean jobCancelled;
1178  transient private final List<String> cancelledDataSourceModules;
1179 
1184  Snapshot(String dataSourceName, long jobId, long jobStartTime, PipelineModule dataSourceIngestModule,
1185  boolean fileIngestRunning, Date fileIngestStartTime,
1186  boolean jobCancelled, CancellationReason cancellationReason, List<String> cancelledModules,
1187  long processedFiles, long estimatedFilesToProcess,
1188  long snapshotTime, IngestJobTasksSnapshot tasksSnapshot) {
1189  this.dataSource = dataSourceName;
1190  this.jobId = jobId;
1191  this.jobStartTime = jobStartTime;
1192  this.dataSourceLevelIngestModule = dataSourceIngestModule;
1193 
1194  this.fileIngestRunning = fileIngestRunning;
1195  this.fileIngestStartTime = fileIngestStartTime;
1196  this.jobCancelled = jobCancelled;
1197  this.jobCancellationReason = cancellationReason;
1198  this.cancelledDataSourceModules = cancelledModules;
1199 
1200  this.processedFiles = processedFiles;
1201  this.estimatedFilesToProcess = estimatedFilesToProcess;
1202  this.snapShotTime = snapshotTime;
1203  this.tasksSnapshot = tasksSnapshot;
1204  }
1205 
1212  long getSnapshotTime() {
1213  return snapShotTime;
1214  }
1215 
1222  String getDataSource() {
1223  return dataSource;
1224  }
1225 
1232  long getJobId() {
1233  return this.jobId;
1234  }
1235 
1242  long getJobStartTime() {
1243  return jobStartTime;
1244  }
1245 
1246  DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
1247  return this.dataSourceLevelIngestModule;
1248  }
1249 
1250  boolean getFileIngestIsRunning() {
1251  return this.fileIngestRunning;
1252  }
1253 
1254  Date getFileIngestStartTime() {
1255  return this.fileIngestStartTime;
1256  }
1257 
1264  double getSpeed() {
1265  return (double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
1266  }
1267 
1273  long getFilesProcessed() {
1274  return processedFiles;
1275  }
1276 
1283  long getFilesEstimated() {
1284  return estimatedFilesToProcess;
1285  }
1286 
1287  long getRootQueueSize() {
1288  if (null == this.tasksSnapshot) {
1289  return 0;
1290  }
1291  return this.tasksSnapshot.getRootQueueSize();
1292  }
1293 
1294  long getDirQueueSize() {
1295  if (null == this.tasksSnapshot) {
1296  return 0;
1297  }
1298  return this.tasksSnapshot.getDirectoryTasksQueueSize();
1299  }
1300 
1301  long getFileQueueSize() {
1302  if (null == this.tasksSnapshot) {
1303  return 0;
1304  }
1305  return this.tasksSnapshot.getFileQueueSize();
1306  }
1307 
1308  long getDsQueueSize() {
1309  if (null == this.tasksSnapshot) {
1310  return 0;
1311  }
1312  return this.tasksSnapshot.getDsQueueSize();
1313  }
1314 
1315  long getRunningListSize() {
1316  if (null == this.tasksSnapshot) {
1317  return 0;
1318  }
1319  return this.tasksSnapshot.getRunningListSize();
1320  }
1321 
1322  boolean isCancelled() {
1323  return this.jobCancelled;
1324  }
1325 
1331  IngestJob.CancellationReason getCancellationReason() {
1332  return this.jobCancellationReason;
1333  }
1334 
1342  List<String> getCancelledDataSourceIngestModules() {
1343  return Collections.unmodifiableList(this.cancelledDataSourceModules);
1344  }
1345 
1346  }
1347 
1348 }
static synchronized IngestManager getInstance()
void logErrorMessage(Level level, String message, Throwable throwable)
void logIngestModuleErrors(List< IngestModuleError > errors)
List< IngestModuleTemplate > getEnabledIngestModuleTemplates()
static List< IngestModuleTemplate > getConfiguredIngestModuleTemplates(Map< String, IngestModuleTemplate > ingestModuleTemplates, List< String > pipelineConfig)
void addIngestModules(List< IngestModuleTemplate > templates, IngestModuleType type, SleuthkitCase skCase)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
final LinkedBlockingQueue< FileIngestPipeline > fileIngestPipelinesQueue
final List< FileIngestPipeline > fileIngestPipelines
volatile IngestJob.CancellationReason cancellationReason

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.