Autopsy  3.1
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 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.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.concurrent.CopyOnWriteArrayList;
28 import java.util.concurrent.LinkedBlockingQueue;
29 import java.util.concurrent.atomic.AtomicLong;
30 import java.util.logging.Level;
31 import javax.swing.JOptionPane;
32 import org.netbeans.api.progress.ProgressHandle;
33 import org.netbeans.api.progress.ProgressHandleFactory;
34 import org.openide.util.Cancellable;
35 import org.openide.util.NbBundle;
39 
44 final class DataSourceIngestJob {
45 
46  private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName());
47 
52  private final IngestJob parentJob;
53  private static final AtomicLong nextJobId = new AtomicLong(0L);
54  private final long id;
55  private final IngestJobSettings settings;
56  private final Content dataSource;
57 
61  private static enum Stages {
62 
80  FINALIZATION
81  };
82  private Stages stage = DataSourceIngestJob.Stages.INITIALIZATION;
83  private final Object stageCompletionCheckLock = new Object();
84 
93  private final Object dataSourceIngestPipelineLock = new Object();
94  private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
95  private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
96  private DataSourceIngestPipeline currentDataSourceIngestPipeline;
97 
105  private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue = new LinkedBlockingQueue<>();
106  private final List<FileIngestPipeline> fileIngestPipelines = new ArrayList<>();
107 
119  private volatile boolean currentDataSourceIngestModuleCancelled;
120  private volatile boolean cancelled;
121  private final List<String> cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>();
122 
127  private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
128 
133  private final boolean runInteractively;
134 
139  private final Object dataSourceIngestProgressLock = new Object();
140  private ProgressHandle dataSourceIngestProgress;
141 
146  private final Object fileIngestProgressLock = new Object();
147  private final List<String> filesInProgress = new ArrayList<>();
148  private long estimatedFilesToProcess;
149  private long processedFiles;
150  private ProgressHandle fileIngestProgress;
151 
155  private final long createTime;
156 
168  DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
169  this.parentJob = parentJob;
170  this.id = DataSourceIngestJob.nextJobId.getAndIncrement();
171  this.dataSource = dataSource;
172  this.settings = settings;
173  this.runInteractively = runInteractively;
174  this.createTime = new Date().getTime();
175  this.createIngestPipelines();
176  }
177 
181  private void createIngestPipelines() {
182  List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
183 
187  Map<String, IngestModuleTemplate> dataSourceModuleTemplates = new HashMap<>();
188  Map<String, IngestModuleTemplate> fileModuleTemplates = new HashMap<>();
189  for (IngestModuleTemplate template : ingestModuleTemplates) {
190  if (template.isDataSourceIngestModuleTemplate()) {
191  dataSourceModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
192  }
193  if (template.isFileIngestModuleTemplate()) {
194  fileModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
195  }
196  }
197 
202  IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
203  List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
204  List<IngestModuleTemplate> fileIngestModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(fileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
205  List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
206 
212  for (IngestModuleTemplate template : dataSourceModuleTemplates.values()) {
213  firstStageDataSourceModuleTemplates.add(template);
214  }
215  for (IngestModuleTemplate template : fileModuleTemplates.values()) {
216  fileIngestModuleTemplates.add(template);
217  }
218 
222  this.firstStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, firstStageDataSourceModuleTemplates);
223  this.secondStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, secondStageDataSourceModuleTemplates);
224 
228  try {
229  int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
230  for (int i = 0; i < numberOfFileIngestThreads; ++i) {
231  FileIngestPipeline pipeline = new FileIngestPipeline(this, fileIngestModuleTemplates);
232  this.fileIngestPipelinesQueue.put(pipeline);
233  this.fileIngestPipelines.add(pipeline);
234  }
235  } catch (InterruptedException ex) {
241  Thread.currentThread().interrupt();
242  }
243  }
244 
259  private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
260  List<IngestModuleTemplate> templates = new ArrayList<>();
261  for (String moduleClassName : pipelineConfig) {
262  if (ingestModuleTemplates.containsKey(moduleClassName)) {
263  templates.add(ingestModuleTemplates.remove(moduleClassName));
264  }
265  }
266  return templates;
267  }
268 
274  long getId() {
275  return this.id;
276  }
277 
283  Content getDataSource() {
284  return this.dataSource;
285  }
286 
293  boolean shouldProcessUnallocatedSpace() {
294  return this.settings.getProcessUnallocatedSpace();
295  }
296 
302  boolean hasIngestPipeline() {
303  return this.hasFirstStageDataSourceIngestPipeline()
304  || this.hasFileIngestPipeline()
305  || this.hasSecondStageDataSourceIngestPipeline();
306  }
307 
314  private boolean hasFirstStageDataSourceIngestPipeline() {
315  return (this.firstStageDataSourceIngestPipeline.isEmpty() == false);
316  }
317 
324  private boolean hasSecondStageDataSourceIngestPipeline() {
325  return (this.secondStageDataSourceIngestPipeline.isEmpty() == false);
326  }
327 
333  private boolean hasFileIngestPipeline() {
334  if (!this.fileIngestPipelines.isEmpty()) {
335  return !this.fileIngestPipelines.get(0).isEmpty();
336  }
337  return false;
338  }
339 
345  List<IngestModuleError> start() {
346  List<IngestModuleError> errors = startUpIngestPipelines();
347  if (errors.isEmpty()) {
348  if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
349  logger.log(Level.INFO, "Starting first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
350  this.startFirstStage();
351  } else if (this.hasSecondStageDataSourceIngestPipeline()) {
352  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id});
353  this.startSecondStage();
354  }
355  }
356  return errors;
357  }
358 
365  private List<IngestModuleError> startUpIngestPipelines() {
366  List<IngestModuleError> errors = new ArrayList<>();
367 
368  // Start up the first stage data source ingest pipeline.
369  errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
370 
371  // Start up the second stage data source ingest pipeline.
372  errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
373 
374  // Start up the file ingest pipelines (one per file ingest thread).
375  for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
376  errors.addAll(pipeline.startUp());
377  if (!errors.isEmpty()) {
378  // If there are start up errors, the ingest job will not proceed
379  // and the errors will ultimately be reported to the user for
380  // possible remedy so shut down the pipelines now that an
381  // attempt has been made to start up the data source ingest
382  // pipeline and at least one copy of the file ingest pipeline.
383  // pipeline. There is no need to complete starting up all of the
384  // file ingest pipeline copies since any additional start up
385  // errors are likely redundant.
386  while (!this.fileIngestPipelinesQueue.isEmpty()) {
387  pipeline = this.fileIngestPipelinesQueue.poll();
388  List<IngestModuleError> shutDownErrors = pipeline.shutDown();
389  if (!shutDownErrors.isEmpty()) {
390  logIngestModuleErrors(shutDownErrors);
391  }
392  }
393  break;
394  }
395  }
396 
397  logIngestModuleErrors(errors);
398  return errors;
399  }
400 
404  private void startFirstStage() {
405  this.stage = DataSourceIngestJob.Stages.FIRST;
406 
407  if (this.hasFileIngestPipeline()) {
408  synchronized (this.fileIngestProgressLock) {
409  this.estimatedFilesToProcess = this.dataSource.accept(new GetFilesCountVisitor());
410  }
411  }
412 
413  if (this.runInteractively) {
417  if (this.hasFirstStageDataSourceIngestPipeline()) {
418  this.startDataSourceIngestProgressBar();
419  }
420  if (this.hasFileIngestPipeline()) {
421  this.startFileIngestProgressBar();
422  }
423  }
424 
429  synchronized (this.dataSourceIngestPipelineLock) {
430  this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
431  }
432 
436  if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
437  logger.log(Level.INFO, "Scheduling first stage data source and file level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
438  DataSourceIngestJob.taskScheduler.scheduleIngestTasks(this);
439  } else if (this.hasFirstStageDataSourceIngestPipeline()) {
440  logger.log(Level.INFO, "Scheduling first stage data source level analysis tasks for {0} (jobId={1}), no file level analysis configured", new Object[]{dataSource.getName(), this.id});
441  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
442  } else {
443  logger.log(Level.INFO, "Scheduling file level analysis tasks for {0} (jobId={1}), no first stage data source level analysis configured", new Object[]{dataSource.getName(), this.id});
444  DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(this);
445 
454  this.checkForStageCompleted();
455  }
456  }
457 
461  private void startSecondStage() {
462  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
463  this.stage = DataSourceIngestJob.Stages.SECOND;
464  if (this.runInteractively) {
465  this.startDataSourceIngestProgressBar();
466  }
467  synchronized (this.dataSourceIngestPipelineLock) {
468  this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
469  }
470  logger.log(Level.INFO, "Scheduling second stage data source level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
471  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
472  }
473 
477  private void startDataSourceIngestProgressBar() {
478  if (this.runInteractively) {
479  synchronized (this.dataSourceIngestProgressLock) {
480  String displayName = NbBundle.getMessage(this.getClass(),
481  "IngestJob.progress.dataSourceIngest.initialDisplayName",
482  this.dataSource.getName());
483  this.dataSourceIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
484  @Override
485  public boolean cancel() {
486  // If this method is called, the user has already pressed
487  // the cancel button on the progress bar and the OK button
488  // of a cancelation confirmation dialog supplied by
489  // NetBeans. What remains to be done is to find out whether
490  // the user wants to cancel only the currently executing
491  // data source ingest module or the entire ingest job.
492  DataSourceIngestCancellationPanel panel = new DataSourceIngestCancellationPanel();
493  String dialogTitle = NbBundle.getMessage(DataSourceIngestJob.this.getClass(), "IngestJob.cancellationDialog.title");
494  JOptionPane.showConfirmDialog(null, panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
495  if (panel.cancelAllDataSourceIngestModules()) {
496  DataSourceIngestJob.this.cancel();
497  } else {
498  DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
499  }
500  return true;
501  }
502  });
503  this.dataSourceIngestProgress.start();
504  this.dataSourceIngestProgress.switchToIndeterminate();
505  }
506  }
507  }
508 
512  private void startFileIngestProgressBar() {
513  if (this.runInteractively) {
514  synchronized (this.fileIngestProgressLock) {
515  String displayName = NbBundle.getMessage(this.getClass(),
516  "IngestJob.progress.fileIngest.displayName",
517  this.dataSource.getName());
518  this.fileIngestProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
519  @Override
520  public boolean cancel() {
521  // If this method is called, the user has already pressed
522  // the cancel button on the progress bar and the OK button
523  // of a cancelation confirmation dialog supplied by
524  // NetBeans.
525  DataSourceIngestJob.this.cancel();
526  return true;
527  }
528  });
529  this.fileIngestProgress.start();
530  this.fileIngestProgress.switchToDeterminate((int) this.estimatedFilesToProcess);
531  }
532  }
533  }
534 
539  private void checkForStageCompleted() {
540  synchronized (this.stageCompletionCheckLock) {
541  if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(this)) {
542  switch (this.stage) {
543  case FIRST:
544  this.finishFirstStage();
545  break;
546  case SECOND:
547  this.finish();
548  break;
549  }
550  }
551  }
552  }
553 
558  private void finishFirstStage() {
559  logger.log(Level.INFO, "Finished first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
560 
561  // Shut down the file ingest pipelines. Note that no shut down is
562  // required for the data source ingest pipeline because data source
563  // ingest modules do not have a shutdown() method.
564  List<IngestModuleError> errors = new ArrayList<>();
565  while (!this.fileIngestPipelinesQueue.isEmpty()) {
566  FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
567  errors.addAll(pipeline.shutDown());
568  }
569  if (!errors.isEmpty()) {
570  logIngestModuleErrors(errors);
571  }
572 
573  if (this.runInteractively) {
574  // Finish the first stage data source ingest progress bar, if it hasn't
575  // already been finished.
576  synchronized (this.dataSourceIngestProgressLock) {
577  if (this.dataSourceIngestProgress != null) {
578  this.dataSourceIngestProgress.finish();
579  this.dataSourceIngestProgress = null;
580  }
581  }
582 
583  // Finish the file ingest progress bar, if it hasn't already
584  // been finished.
585  synchronized (this.fileIngestProgressLock) {
586  if (this.fileIngestProgress != null) {
587  this.fileIngestProgress.finish();
588  this.fileIngestProgress = null;
589  }
590  }
591  }
592 
596  if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
597  this.startSecondStage();
598  } else {
599  this.finish();
600  }
601  }
602 
606  private void finish() {
607  logger.log(Level.INFO, "Finished analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id});
608  this.stage = DataSourceIngestJob.Stages.FINALIZATION;
609 
610  if (this.runInteractively) {
611  // Finish the second stage data source ingest progress bar, if it hasn't
612  // already been finished.
613  synchronized (this.dataSourceIngestProgressLock) {
614  if (this.dataSourceIngestProgress != null) {
615  this.dataSourceIngestProgress.finish();
616  this.dataSourceIngestProgress = null;
617  }
618  }
619  }
620 
621  this.parentJob.dataSourceJobFinished(this);
622  }
623 
630  void process(DataSourceIngestTask task) {
631  try {
632  synchronized (this.dataSourceIngestPipelineLock) {
633  if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
634  List<IngestModuleError> errors = new ArrayList<>();
635  errors.addAll(this.currentDataSourceIngestPipeline.process(task));
636  if (!errors.isEmpty()) {
637  logIngestModuleErrors(errors);
638  }
639  }
640  }
641 
642  if (this.runInteractively) {
647  synchronized (this.dataSourceIngestProgressLock) {
648  if (null != this.dataSourceIngestProgress) {
649  this.dataSourceIngestProgress.finish();
650  this.dataSourceIngestProgress = null;
651  }
652  }
653  }
654 
655  } finally {
656  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
657  this.checkForStageCompleted();
658  }
659  }
660 
670  void process(FileIngestTask task) throws InterruptedException {
671  try {
672  if (!this.isCancelled()) {
673  FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
674  if (!pipeline.isEmpty()) {
675  AbstractFile file = task.getFile();
676 
677  synchronized (this.fileIngestProgressLock) {
678  ++this.processedFiles;
679  if (this.runInteractively) {
683  if (this.processedFiles <= this.estimatedFilesToProcess) {
684  this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
685  } else {
686  this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
687  }
688  this.filesInProgress.add(file.getName());
689  }
690  }
691 
695  List<IngestModuleError> errors = new ArrayList<>();
696  errors.addAll(pipeline.process(task));
697  if (!errors.isEmpty()) {
698  logIngestModuleErrors(errors);
699  }
700 
701  if (this.runInteractively && !this.cancelled) {
702  synchronized (this.fileIngestProgressLock) {
707  this.filesInProgress.remove(file.getName());
708  if (this.filesInProgress.size() > 0) {
709  this.fileIngestProgress.progress(this.filesInProgress.get(0));
710  } else {
711  this.fileIngestProgress.progress("");
712  }
713  }
714  }
715  }
716  this.fileIngestPipelinesQueue.put(pipeline);
717  }
718  } finally {
719  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
720  this.checkForStageCompleted();
721  }
722  }
723 
731  void addFiles(List<AbstractFile> files) {
732  if (DataSourceIngestJob.Stages.FIRST == this.stage) {
733  for (AbstractFile file : files) {
734  DataSourceIngestJob.taskScheduler.scheduleFileIngestTask(this, file);
735  }
736  } else {
737  DataSourceIngestJob.logger.log(Level.SEVERE, "Adding files during second stage not supported"); //NON-NLS
738  }
739 
746  this.checkForStageCompleted();
747  }
748 
755  void updateDataSourceIngestProgressBarDisplayName(String displayName) {
756  if (this.runInteractively && !this.cancelled) {
757  synchronized (this.dataSourceIngestProgressLock) {
758  this.dataSourceIngestProgress.setDisplayName(displayName);
759  }
760  }
761  }
762 
771  void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
772  if (this.runInteractively && !this.cancelled) {
773  synchronized (this.dataSourceIngestProgressLock) {
774  if (null != this.dataSourceIngestProgress) {
775  this.dataSourceIngestProgress.switchToDeterminate(workUnits);
776  }
777  }
778  }
779  }
780 
786  void switchDataSourceIngestProgressBarToIndeterminate() {
787  if (this.runInteractively && !this.cancelled) {
788  synchronized (this.dataSourceIngestProgressLock) {
789  if (null != this.dataSourceIngestProgress) {
790  this.dataSourceIngestProgress.switchToIndeterminate();
791  }
792  }
793  }
794  }
795 
802  void advanceDataSourceIngestProgressBar(int workUnits) {
803  if (this.runInteractively && !this.cancelled) {
804  synchronized (this.dataSourceIngestProgressLock) {
805  if (null != this.dataSourceIngestProgress) {
806  this.dataSourceIngestProgress.progress("", workUnits);
807  }
808  }
809  }
810  }
811 
818  void advanceDataSourceIngestProgressBar(String currentTask) {
819  if (this.runInteractively && !this.cancelled) {
820  synchronized (this.dataSourceIngestProgressLock) {
821  if (null != this.dataSourceIngestProgress) {
822  this.dataSourceIngestProgress.progress(currentTask);
823  }
824  }
825  }
826  }
827 
836  void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
837  if (this.runInteractively && !this.cancelled) {
838  synchronized (this.fileIngestProgressLock) {
839  this.dataSourceIngestProgress.progress(currentTask, workUnits);
840  }
841  }
842  }
843 
851  boolean currentDataSourceIngestModuleIsCancelled() {
852  return this.currentDataSourceIngestModuleCancelled;
853  }
854 
861  void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
862  this.currentDataSourceIngestModuleCancelled = false;
863  this.cancelledDataSourceIngestModules.add(moduleDisplayName);
864 
865  if (this.runInteractively) {
873  synchronized (this.dataSourceIngestProgressLock) {
874  this.dataSourceIngestProgress.finish();
875  this.dataSourceIngestProgress = null;
876  this.startDataSourceIngestProgressBar();
877  }
878  }
879  }
880 
886  DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
887  if (null != this.currentDataSourceIngestPipeline) {
888  return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
889  } else {
890  return null;
891  }
892  }
893 
898  void cancelCurrentDataSourceIngestModule() {
899  this.currentDataSourceIngestModuleCancelled = true;
900  }
901 
906  void cancel() {
907  if (this.runInteractively) {
912  synchronized (this.dataSourceIngestProgressLock) {
913  if (dataSourceIngestProgress != null) {
914  final String displayName = NbBundle.getMessage(this.getClass(),
915  "IngestJob.progress.dataSourceIngest.initialDisplayName",
916  dataSource.getName());
917  dataSourceIngestProgress.setDisplayName(
918  NbBundle.getMessage(this.getClass(),
919  "IngestJob.progress.cancelling",
920  displayName));
921  }
922  }
923 
928  synchronized (this.fileIngestProgressLock) {
929  if (this.fileIngestProgress != null) {
930  final String displayName = NbBundle.getMessage(this.getClass(),
931  "IngestJob.progress.fileIngest.displayName",
932  this.dataSource.getName());
933  this.fileIngestProgress.setDisplayName(
934  NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling",
935  displayName));
936  }
937  }
938  }
939 
940  this.cancelled = true;
941 
946  DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this);
947  this.checkForStageCompleted();
948  }
949 
956  boolean isCancelled() {
957  return this.cancelled;
958  }
959 
965  private void logIngestModuleErrors(List<IngestModuleError> errors) {
966  for (IngestModuleError error : errors) {
967  DataSourceIngestJob.logger.log(Level.SEVERE, String.format("%s experienced an error analyzing %s (jobId=%d)", error.getModuleDisplayName(), dataSource.getName(), this.id), error.getModuleError()); //NON-NLS
968  }
969  }
970 
976  Snapshot getSnapshot(boolean getIngestTasksSnapshot) {
977  return new Snapshot(getIngestTasksSnapshot);
978  }
979 
983  final class Snapshot {
984 
985  private final String dataSource;
986  private final long jobId;
987  private final long jobStartTime;
988  private final long snapShotTime;
989  private final DataSourceIngestPipeline.PipelineModule dataSourceLevelIngestModule;
990  private boolean fileIngestRunning;
991  private Date fileIngestStartTime;
992  private final long processedFiles;
993  private final long estimatedFilesToProcess;
994  private final IngestTasksScheduler.IngestJobTasksSnapshot tasksSnapshot;
995  private final boolean jobCancelled;
996  private final List<String> cancelledDataSourceModules;
997 
1002  Snapshot(boolean getIngestTasksSnapshot) {
1003  this.dataSource = DataSourceIngestJob.this.dataSource.getName();
1004  this.jobId = DataSourceIngestJob.this.id;
1005  this.jobStartTime = DataSourceIngestJob.this.createTime;
1006  this.dataSourceLevelIngestModule = DataSourceIngestJob.this.getCurrentDataSourceIngestModule();
1007 
1013  for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) {
1014  if (pipeline.isRunning()) {
1015  this.fileIngestRunning = true;
1016  }
1017  Date pipelineStartTime = pipeline.getStartTime();
1018  if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(this.fileIngestStartTime))) {
1019  this.fileIngestStartTime = pipelineStartTime;
1020  }
1021  }
1022 
1023  this.jobCancelled = cancelled;
1024  this.cancelledDataSourceModules = new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules);
1025 
1026  if (getIngestTasksSnapshot) {
1027  synchronized (DataSourceIngestJob.this.fileIngestProgressLock) {
1028  this.processedFiles = DataSourceIngestJob.this.processedFiles;
1029  this.estimatedFilesToProcess = DataSourceIngestJob.this.estimatedFilesToProcess;
1030  this.snapShotTime = new Date().getTime();
1031  }
1032  this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId);
1033 
1034  } else {
1035  this.processedFiles = 0;
1036  this.estimatedFilesToProcess = 0;
1037  this.snapShotTime = new Date().getTime();
1038  this.tasksSnapshot = null;
1039  }
1040  }
1041 
1048  long getSnapshotTime() {
1049  return snapShotTime;
1050  }
1051 
1058  String getDataSource() {
1059  return dataSource;
1060  }
1061 
1068  long getJobId() {
1069  return this.jobId;
1070  }
1071 
1078  long getJobStartTime() {
1079  return jobStartTime;
1080  }
1081 
1082  DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
1083  return this.dataSourceLevelIngestModule;
1084  }
1085 
1086  boolean fileIngestIsRunning() {
1087  return this.fileIngestRunning;
1088  }
1089 
1090  Date fileIngestStartTime() {
1091  return this.fileIngestStartTime;
1092  }
1093 
1100  double getSpeed() {
1101  return (double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
1102  }
1103 
1109  long getFilesProcessed() {
1110  return processedFiles;
1111  }
1112 
1119  long getFilesEstimated() {
1120  return estimatedFilesToProcess;
1121  }
1122 
1123  long getRootQueueSize() {
1124  if (null == this.tasksSnapshot) {
1125  return 0;
1126  }
1127  return this.tasksSnapshot.getRootQueueSize();
1128  }
1129 
1130  long getDirQueueSize() {
1131  if (null == this.tasksSnapshot) {
1132  return 0;
1133  }
1134  return this.tasksSnapshot.getDirectoryTasksQueueSize();
1135  }
1136 
1137  long getFileQueueSize() {
1138  if (null == this.tasksSnapshot) {
1139  return 0;
1140  }
1141  return this.tasksSnapshot.getFileQueueSize();
1142  }
1143 
1144  long getDsQueueSize() {
1145  if (null == this.tasksSnapshot) {
1146  return 0;
1147  }
1148  return this.tasksSnapshot.getDsQueueSize();
1149  }
1150 
1151  long getRunningListSize() {
1152  if (null == this.tasksSnapshot) {
1153  return 0;
1154  }
1155  return this.tasksSnapshot.getRunningListSize();
1156  }
1157 
1158  boolean isCancelled() {
1159  return this.jobCancelled;
1160  }
1161 
1169  List<String> getCancelledDataSourceIngestModules() {
1170  return Collections.unmodifiableList(this.cancelledDataSourceModules);
1171  }
1172 
1173  }
1174 
1175 }
public< T > T accept(ContentVisitor< T > v)

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.