Autopsy  4.6.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-2018 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.openide.util.Cancellable;
34 import org.openide.util.NbBundle;
35 import org.openide.windows.WindowManager;
40 import org.sleuthkit.datamodel.AbstractFile;
41 import org.sleuthkit.datamodel.Content;
42 import org.sleuthkit.datamodel.IngestJobInfo;
43 import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
44 import org.sleuthkit.datamodel.IngestModuleInfo;
45 import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
46 import org.sleuthkit.datamodel.SleuthkitCase;
47 import org.sleuthkit.datamodel.TskCoreException;
49 
54 final class DataSourceIngestJob {
55 
56  private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName());
57 
64  private final IngestJob parentJob;
65  private static final AtomicLong nextJobId = new AtomicLong(0L);
66  private final long id;
67  private final IngestJobSettings settings;
68  private final Content dataSource;
69  private final List<AbstractFile> files = new ArrayList<>();
70 
74  private static enum Stages {
75 
93  FINALIZATION
94  };
95  private volatile Stages stage = DataSourceIngestJob.Stages.INITIALIZATION;
96  private final Object stageCompletionCheckLock = new Object();
97 
106  private final Object dataSourceIngestPipelineLock = new Object();
107  private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
108  private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
109  private DataSourceIngestPipeline currentDataSourceIngestPipeline;
110 
118  private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue = new LinkedBlockingQueue<>();
119  private final List<FileIngestPipeline> fileIngestPipelines = new ArrayList<>();
120 
132  private volatile boolean currentDataSourceIngestModuleCancelled;
133  private final List<String> cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>();
134  private volatile boolean cancelled;
135  private volatile IngestJob.CancellationReason cancellationReason = IngestJob.CancellationReason.NOT_CANCELLED;
136 
141  private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
142 
147  private final boolean doUI;
148 
153  private final Object dataSourceIngestProgressLock = new Object();
154  private ProgressHandle dataSourceIngestProgress;
155 
160  private final Object fileIngestProgressLock = new Object();
161  private final List<String> filesInProgress = new ArrayList<>();
162  private long estimatedFilesToProcess;
163  private long processedFiles;
164  private ProgressHandle fileIngestProgress;
165  private String currentFileIngestModule = "";
166  private String currentFileIngestTask = "";
167  private final List<IngestModuleInfo> ingestModules = new ArrayList<>();
168  private volatile IngestJobInfo ingestJob;
169 
173  private final long createTime;
174 
186  DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
187  this(parentJob, dataSource, Collections.emptyList(), settings, runInteractively);
188  }
189 
203  DataSourceIngestJob(IngestJob parentJob, Content dataSource, List<AbstractFile> files, IngestJobSettings settings, boolean runInteractively) {
204  this.parentJob = parentJob;
205  this.id = DataSourceIngestJob.nextJobId.getAndIncrement();
206  this.dataSource = dataSource;
207  this.files.addAll(files);
208  this.settings = settings;
209  this.doUI = runInteractively;
210  this.createTime = new Date().getTime();
211  this.createIngestPipelines();
212  }
213 
217  private void createIngestPipelines() {
218  List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
219 
223  Map<String, IngestModuleTemplate> dataSourceModuleTemplates = new HashMap<>();
224  Map<String, IngestModuleTemplate> fileModuleTemplates = new HashMap<>();
225  for (IngestModuleTemplate template : ingestModuleTemplates) {
226  if (template.isDataSourceIngestModuleTemplate()) {
227  dataSourceModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
228  }
229  if (template.isFileIngestModuleTemplate()) {
230  fileModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
231  }
232  }
233 
238  IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
239  List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
240  List<IngestModuleTemplate> fileIngestModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(fileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
241  List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
242 
248  for (IngestModuleTemplate template : dataSourceModuleTemplates.values()) {
249  firstStageDataSourceModuleTemplates.add(template);
250  }
251  for (IngestModuleTemplate template : fileModuleTemplates.values()) {
252  fileIngestModuleTemplates.add(template);
253  }
254 
258  this.firstStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, firstStageDataSourceModuleTemplates);
259  this.secondStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, secondStageDataSourceModuleTemplates);
260 
264  try {
265  int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
266  for (int i = 0; i < numberOfFileIngestThreads; ++i) {
267  FileIngestPipeline pipeline = new FileIngestPipeline(this, fileIngestModuleTemplates);
268  this.fileIngestPipelinesQueue.put(pipeline);
269  this.fileIngestPipelines.add(pipeline);
270  }
271  } catch (InterruptedException ex) {
277  Thread.currentThread().interrupt();
278  }
279  try {
280  SleuthkitCase skCase = Case.getOpenCase().getSleuthkitCase();
281  this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
282  this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
283  this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
284  } catch (TskCoreException | NoCurrentCaseException ex) {
285  logger.log(Level.SEVERE, "Failed to add ingest modules to database.", ex);
286  }
287  }
288 
289  private void addIngestModules(List<IngestModuleTemplate> templates, IngestModuleType type, SleuthkitCase skCase) throws TskCoreException {
290  for (IngestModuleTemplate module : templates) {
291  ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
292  }
293  }
294 
310  private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
311  List<IngestModuleTemplate> templates = new ArrayList<>();
312  for (String moduleClassName : pipelineConfig) {
313  if (ingestModuleTemplates.containsKey(moduleClassName)) {
314  templates.add(ingestModuleTemplates.remove(moduleClassName));
315  }
316  }
317  return templates;
318  }
319 
325  long getId() {
326  return this.id;
327  }
328 
334  String getExecutionContext() {
335  return this.settings.getExecutionContext();
336  }
337 
343  Content getDataSource() {
344  return this.dataSource;
345  }
346 
353  boolean shouldProcessUnallocatedSpace() {
354  return this.settings.getProcessUnallocatedSpace();
355  }
356 
362  FilesSet getFileIngestFilter() {
363  return this.settings.getFileFilter();
364  }
365 
371  boolean hasIngestPipeline() {
372  return this.hasFirstStageDataSourceIngestPipeline()
373  || this.hasFileIngestPipeline()
374  || this.hasSecondStageDataSourceIngestPipeline();
375  }
376 
383  private boolean hasFirstStageDataSourceIngestPipeline() {
384  return (this.firstStageDataSourceIngestPipeline.isEmpty() == false);
385  }
386 
393  private boolean hasSecondStageDataSourceIngestPipeline() {
394  return (this.secondStageDataSourceIngestPipeline.isEmpty() == false);
395  }
396 
402  private boolean hasFileIngestPipeline() {
403  if (!this.fileIngestPipelines.isEmpty()) {
404  return !this.fileIngestPipelines.get(0).isEmpty();
405  }
406  return false;
407  }
408 
414  List<IngestModuleError> start() {
415  List<IngestModuleError> errors = startUpIngestPipelines();
416  if (errors.isEmpty()) {
417  try {
418  this.ingestJob = Case.getOpenCase().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
419  } catch (TskCoreException | NoCurrentCaseException ex) {
420  logger.log(Level.SEVERE, "Failed to add ingest job to database.", ex);
421  }
422  if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
423  logger.log(Level.INFO, "Starting first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
424  this.startFirstStage();
425  } else if (this.hasSecondStageDataSourceIngestPipeline()) {
426  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
427  this.startSecondStage();
428  }
429  }
430  return errors;
431  }
432 
439  private List<IngestModuleError> startUpIngestPipelines() {
440  List<IngestModuleError> errors = new ArrayList<>();
441 
442  /*
443  * Start the data-source-level ingest module pipelines.
444  */
445  errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
446  errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
447 
448  /*
449  * If the data-source-level ingest pipelines were successfully started,
450  * start the Start the file-level ingest pipelines (one per file ingest
451  * thread).
452  */
453  if (errors.isEmpty()) {
454  for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
455  errors.addAll(pipeline.startUp());
456  if (!errors.isEmpty()) {
457  /*
458  * If there are start up errors, the ingest job will not
459  * proceed, so shut down any file ingest pipelines that did
460  * start up.
461  */
462  while (!this.fileIngestPipelinesQueue.isEmpty()) {
463  FileIngestPipeline startedPipeline = this.fileIngestPipelinesQueue.poll();
464  if (startedPipeline.isRunning()) {
465  List<IngestModuleError> shutDownErrors = startedPipeline.shutDown();
466  if (!shutDownErrors.isEmpty()) {
467  /*
468  * The start up errors will ultimately be
469  * reported to the user for possible remedy, but
470  * the shut down errors are logged here.
471  */
472  logIngestModuleErrors(shutDownErrors);
473  }
474  }
475  }
476  break;
477  }
478  }
479  }
480 
481  return errors;
482  }
483 
487  private void startFirstStage() {
488  this.stage = DataSourceIngestJob.Stages.FIRST;
489 
490  if (this.hasFileIngestPipeline()) {
491  synchronized (this.fileIngestProgressLock) {
492  this.estimatedFilesToProcess = this.dataSource.accept(new GetFilesCountVisitor());
493  }
494  }
495 
496  if (this.doUI) {
500  if (this.hasFirstStageDataSourceIngestPipeline()) {
501  this.startDataSourceIngestProgressBar();
502  }
503  if (this.hasFileIngestPipeline()) {
504  this.startFileIngestProgressBar();
505  }
506  }
507 
512  synchronized (this.dataSourceIngestPipelineLock) {
513  this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
514  }
515 
519  if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
520  logger.log(Level.INFO, "Scheduling first stage data source and file level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
521  DataSourceIngestJob.taskScheduler.scheduleIngestTasks(this);
522  } else if (this.hasFirstStageDataSourceIngestPipeline()) {
523  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}); //NON-NLS
524  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
525  } else {
526  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}); //NON-NLS
527  DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(this, this.files);
528 
537  this.checkForStageCompleted();
538  }
539  }
540 
544  private void startSecondStage() {
545  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
546  this.stage = DataSourceIngestJob.Stages.SECOND;
547  if (this.doUI) {
548  this.startDataSourceIngestProgressBar();
549  }
550  synchronized (this.dataSourceIngestPipelineLock) {
551  this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
552  }
553  logger.log(Level.INFO, "Scheduling second stage data source level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
554  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
555  }
556 
560  private void startDataSourceIngestProgressBar() {
561  if (this.doUI) {
562  synchronized (this.dataSourceIngestProgressLock) {
563  String displayName = NbBundle.getMessage(this.getClass(),
564  "IngestJob.progress.dataSourceIngest.initialDisplayName",
565  this.dataSource.getName());
566  this.dataSourceIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
567  @Override
568  public boolean cancel() {
569  // If this method is called, the user has already pressed
570  // the cancel button on the progress bar and the OK button
571  // of a cancelation confirmation dialog supplied by
572  // NetBeans. What remains to be done is to find out whether
573  // the user wants to cancel only the currently executing
574  // data source ingest module or the entire ingest job.
575  DataSourceIngestCancellationPanel panel = new DataSourceIngestCancellationPanel();
576  String dialogTitle = NbBundle.getMessage(DataSourceIngestJob.this.getClass(), "IngestJob.cancellationDialog.title");
577  JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
578  if (panel.cancelAllDataSourceIngestModules()) {
579  DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
580  } else {
581  DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
582  }
583  return true;
584  }
585  });
586  this.dataSourceIngestProgress.start();
587  this.dataSourceIngestProgress.switchToIndeterminate();
588  }
589  }
590  }
591 
595  private void startFileIngestProgressBar() {
596  if (this.doUI) {
597  synchronized (this.fileIngestProgressLock) {
598  String displayName = NbBundle.getMessage(this.getClass(),
599  "IngestJob.progress.fileIngest.displayName",
600  this.dataSource.getName());
601  this.fileIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
602  @Override
603  public boolean cancel() {
604  // If this method is called, the user has already pressed
605  // the cancel button on the progress bar and the OK button
606  // of a cancelation confirmation dialog supplied by
607  // NetBeans.
608  DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
609  return true;
610  }
611  });
612  this.fileIngestProgress.start();
613  this.fileIngestProgress.switchToDeterminate((int) this.estimatedFilesToProcess);
614  }
615  }
616  }
617 
622  private void checkForStageCompleted() {
623  synchronized (this.stageCompletionCheckLock) {
624  if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(this)) {
625  switch (this.stage) {
626  case FIRST:
627  this.finishFirstStage();
628  break;
629  case SECOND:
630  this.finish();
631  break;
632  }
633  }
634  }
635  }
636 
641  private void finishFirstStage() {
642  logger.log(Level.INFO, "Finished first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
643 
644  // Shut down the file ingest pipelines. Note that no shut down is
645  // required for the data source ingest pipeline because data source
646  // ingest modules do not have a shutdown() method.
647  List<IngestModuleError> errors = new ArrayList<>();
648  while (!this.fileIngestPipelinesQueue.isEmpty()) {
649  FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
650  if (pipeline.isRunning()) {
651  errors.addAll(pipeline.shutDown());
652  }
653  }
654  if (!errors.isEmpty()) {
655  logIngestModuleErrors(errors);
656  }
657 
658  if (this.doUI) {
659  // Finish the first stage data source ingest progress bar, if it hasn't
660  // already been finished.
661  synchronized (this.dataSourceIngestProgressLock) {
662  if (this.dataSourceIngestProgress != null) {
663  this.dataSourceIngestProgress.finish();
664  this.dataSourceIngestProgress = null;
665  }
666  }
667 
668  // Finish the file ingest progress bar, if it hasn't already
669  // been finished.
670  synchronized (this.fileIngestProgressLock) {
671  if (this.fileIngestProgress != null) {
672  this.fileIngestProgress.finish();
673  this.fileIngestProgress = null;
674  }
675  }
676  }
677 
681  if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
682  this.startSecondStage();
683  } else {
684  this.finish();
685  }
686  }
687 
691  private void finish() {
692  logger.log(Level.INFO, "Finished analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
693  this.stage = DataSourceIngestJob.Stages.FINALIZATION;
694 
695  if (this.doUI) {
696  // Finish the second stage data source ingest progress bar, if it hasn't
697  // already been finished.
698  synchronized (this.dataSourceIngestProgressLock) {
699  if (this.dataSourceIngestProgress != null) {
700  this.dataSourceIngestProgress.finish();
701  this.dataSourceIngestProgress = null;
702  }
703  }
704  }
705  if (ingestJob != null) {
706  if (this.cancelled) {
707  try {
708  ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
709  } catch (TskCoreException ex) {
710  logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
711  }
712  } else {
713  try {
714  ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
715  } catch (TskCoreException ex) {
716  logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
717  }
718  }
719  try {
720  this.ingestJob.setEndDateTime(new Date());
721  } catch (TskCoreException ex) {
722  logger.log(Level.SEVERE, "Failed to set end date for ingest job in database.", ex);
723  }
724  }
725  this.parentJob.dataSourceJobFinished(this);
726  }
727 
734  void process(DataSourceIngestTask task) {
735  try {
736  synchronized (this.dataSourceIngestPipelineLock) {
737  if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
738  List<IngestModuleError> errors = new ArrayList<>();
739  errors.addAll(this.currentDataSourceIngestPipeline.process(task));
740  if (!errors.isEmpty()) {
741  logIngestModuleErrors(errors);
742  }
743  }
744  }
745 
746  if (this.doUI) {
751  synchronized (this.dataSourceIngestProgressLock) {
752  if (null != this.dataSourceIngestProgress) {
753  this.dataSourceIngestProgress.finish();
754  this.dataSourceIngestProgress = null;
755  }
756  }
757  }
758 
759  } finally {
760  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
761  this.checkForStageCompleted();
762  }
763  }
764 
776  void process(FileIngestTask task) throws InterruptedException {
777  try {
778  if (!this.isCancelled()) {
779  FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
780  if (!pipeline.isEmpty()) {
781  AbstractFile file = task.getFile();
782 
783  synchronized (this.fileIngestProgressLock) {
784  ++this.processedFiles;
785  if (this.doUI) {
789  if (this.processedFiles <= this.estimatedFilesToProcess) {
790  this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
791  } else {
792  this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
793  }
794  this.filesInProgress.add(file.getName());
795  }
796  }
797 
801  List<IngestModuleError> errors = new ArrayList<>();
802  errors.addAll(pipeline.process(task));
803  if (!errors.isEmpty()) {
804  logIngestModuleErrors(errors);
805  }
806 
807  if (this.doUI && !this.cancelled) {
808  synchronized (this.fileIngestProgressLock) {
813  this.filesInProgress.remove(file.getName());
814  if (this.filesInProgress.size() > 0) {
815  this.fileIngestProgress.progress(this.filesInProgress.get(0));
816  } else {
817  this.fileIngestProgress.progress("");
818  }
819  }
820  }
821  }
822  this.fileIngestPipelinesQueue.put(pipeline);
823  }
824  } finally {
825  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
826  this.checkForStageCompleted();
827  }
828  }
829 
837  void addFiles(List<AbstractFile> files) {
838  if (DataSourceIngestJob.Stages.FIRST == this.stage) {
839  DataSourceIngestJob.taskScheduler.fastTrackFileIngestTasks(this, files);
840  } else {
841  DataSourceIngestJob.logger.log(Level.SEVERE, "Adding files during second stage not supported"); //NON-NLS
842  }
843 
850  this.checkForStageCompleted();
851  }
852 
859  void updateDataSourceIngestProgressBarDisplayName(String displayName) {
860  if (this.doUI && !this.cancelled) {
861  synchronized (this.dataSourceIngestProgressLock) {
862  this.dataSourceIngestProgress.setDisplayName(displayName);
863  }
864  }
865  }
866 
875  void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
876  if (this.doUI && !this.cancelled) {
877  synchronized (this.dataSourceIngestProgressLock) {
878  if (null != this.dataSourceIngestProgress) {
879  this.dataSourceIngestProgress.switchToDeterminate(workUnits);
880  }
881  }
882  }
883  }
884 
890  void switchDataSourceIngestProgressBarToIndeterminate() {
891  if (this.doUI && !this.cancelled) {
892  synchronized (this.dataSourceIngestProgressLock) {
893  if (null != this.dataSourceIngestProgress) {
894  this.dataSourceIngestProgress.switchToIndeterminate();
895  }
896  }
897  }
898  }
899 
906  void advanceDataSourceIngestProgressBar(int workUnits) {
907  if (this.doUI && !this.cancelled) {
908  synchronized (this.dataSourceIngestProgressLock) {
909  if (null != this.dataSourceIngestProgress) {
910  this.dataSourceIngestProgress.progress("", workUnits);
911  }
912  }
913  }
914  }
915 
922  void advanceDataSourceIngestProgressBar(String currentTask) {
923  if (this.doUI && !this.cancelled) {
924  synchronized (this.dataSourceIngestProgressLock) {
925  if (null != this.dataSourceIngestProgress) {
926  this.dataSourceIngestProgress.progress(currentTask);
927  }
928  }
929  }
930  }
931 
940  void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
941  if (this.doUI && !this.cancelled) {
942  synchronized (this.fileIngestProgressLock) {
943  this.dataSourceIngestProgress.progress(currentTask, workUnits);
944  }
945  }
946  }
947 
955  boolean currentDataSourceIngestModuleIsCancelled() {
956  return this.currentDataSourceIngestModuleCancelled;
957  }
958 
965  void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
966  this.currentDataSourceIngestModuleCancelled = false;
967  this.cancelledDataSourceIngestModules.add(moduleDisplayName);
968 
969  if (this.doUI) {
977  synchronized (this.dataSourceIngestProgressLock) {
978  this.dataSourceIngestProgress.finish();
979  this.dataSourceIngestProgress = null;
980  this.startDataSourceIngestProgressBar();
981  }
982  }
983  }
984 
990  DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
991  if (null != this.currentDataSourceIngestPipeline) {
992  return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
993  } else {
994  return null;
995  }
996  }
997 
1002  void cancelCurrentDataSourceIngestModule() {
1003  this.currentDataSourceIngestModuleCancelled = true;
1004  }
1005 
1012  void cancel(IngestJob.CancellationReason reason) {
1013  this.cancelled = true;
1014  this.cancellationReason = reason;
1015  DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this);
1016 
1017  if (this.doUI) {
1018  synchronized (this.dataSourceIngestProgressLock) {
1019  if (null != dataSourceIngestProgress) {
1020  dataSourceIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.initialDisplayName", dataSource.getName()));
1021  dataSourceIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1022  }
1023  }
1024 
1025  synchronized (this.fileIngestProgressLock) {
1026  if (null != this.fileIngestProgress) {
1027  this.fileIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", this.dataSource.getName()));
1028  this.fileIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1029  }
1030  }
1031  }
1032  }
1033 
1041  void setCurrentFileIngestModule(String moduleName, String taskName) {
1042  this.currentFileIngestModule = moduleName;
1043  this.currentFileIngestTask = taskName;
1044  }
1045 
1052  boolean isCancelled() {
1053  return this.cancelled;
1054  }
1055 
1061  IngestJob.CancellationReason getCancellationReason() {
1062  return this.cancellationReason;
1063  }
1064 
1070  private void logIngestModuleErrors(List<IngestModuleError> errors) {
1071  for (IngestModuleError error : errors) {
1072  DataSourceIngestJob.logger.log(Level.SEVERE, String.format("%s experienced an error analyzing %s (jobId=%d)", error.getModuleDisplayName(), dataSource.getName(), this.id), error.getThrowable()); //NON-NLS
1073  }
1074  }
1075 
1081  Snapshot getSnapshot(boolean getIngestTasksSnapshot) {
1082  return new Snapshot(getIngestTasksSnapshot);
1083  }
1084 
1088  final class Snapshot {
1089 
1090  private final String dataSource;
1091  private final long jobId;
1092  private final long jobStartTime;
1093  private final long snapShotTime;
1094  private final DataSourceIngestPipeline.PipelineModule dataSourceLevelIngestModule;
1095  private boolean fileIngestRunning;
1096  private Date fileIngestStartTime;
1097  private final long processedFiles;
1098  private final long estimatedFilesToProcess;
1099  private final IngestTasksScheduler.IngestJobTasksSnapshot tasksSnapshot;
1100  private final boolean jobCancelled;
1101  private final IngestJob.CancellationReason jobCancellationReason;
1102  private final List<String> cancelledDataSourceModules;
1103 
1108  Snapshot(boolean getIngestTasksSnapshot) {
1109  this.dataSource = DataSourceIngestJob.this.dataSource.getName();
1110  this.jobId = DataSourceIngestJob.this.id;
1111  this.jobStartTime = DataSourceIngestJob.this.createTime;
1112  this.dataSourceLevelIngestModule = DataSourceIngestJob.this.getCurrentDataSourceIngestModule();
1113 
1119  for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) {
1120  if (pipeline.isRunning()) {
1121  this.fileIngestRunning = true;
1122  }
1123  Date pipelineStartTime = pipeline.getStartTime();
1124  if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(this.fileIngestStartTime))) {
1125  this.fileIngestStartTime = pipelineStartTime;
1126  }
1127  }
1128 
1129  this.jobCancelled = cancelled;
1130  this.jobCancellationReason = cancellationReason;
1131  this.cancelledDataSourceModules = new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules);
1132 
1133  if (getIngestTasksSnapshot) {
1134  synchronized (DataSourceIngestJob.this.fileIngestProgressLock) {
1135  this.processedFiles = DataSourceIngestJob.this.processedFiles;
1136  this.estimatedFilesToProcess = DataSourceIngestJob.this.estimatedFilesToProcess;
1137  this.snapShotTime = new Date().getTime();
1138  }
1139  this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId);
1140 
1141  } else {
1142  this.processedFiles = 0;
1143  this.estimatedFilesToProcess = 0;
1144  this.snapShotTime = new Date().getTime();
1145  this.tasksSnapshot = null;
1146  }
1147  }
1148 
1155  long getSnapshotTime() {
1156  return snapShotTime;
1157  }
1158 
1165  String getDataSource() {
1166  return dataSource;
1167  }
1168 
1175  long getJobId() {
1176  return this.jobId;
1177  }
1178 
1185  long getJobStartTime() {
1186  return jobStartTime;
1187  }
1188 
1189  DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
1190  return this.dataSourceLevelIngestModule;
1191  }
1192 
1193  boolean fileIngestIsRunning() {
1194  return this.fileIngestRunning;
1195  }
1196 
1197  Date fileIngestStartTime() {
1198  return this.fileIngestStartTime;
1199  }
1200 
1207  double getSpeed() {
1208  return (double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
1209  }
1210 
1216  long getFilesProcessed() {
1217  return processedFiles;
1218  }
1219 
1226  long getFilesEstimated() {
1227  return estimatedFilesToProcess;
1228  }
1229 
1230  long getRootQueueSize() {
1231  if (null == this.tasksSnapshot) {
1232  return 0;
1233  }
1234  return this.tasksSnapshot.getRootQueueSize();
1235  }
1236 
1237  long getDirQueueSize() {
1238  if (null == this.tasksSnapshot) {
1239  return 0;
1240  }
1241  return this.tasksSnapshot.getDirectoryTasksQueueSize();
1242  }
1243 
1244  long getFileQueueSize() {
1245  if (null == this.tasksSnapshot) {
1246  return 0;
1247  }
1248  return this.tasksSnapshot.getFileQueueSize();
1249  }
1250 
1251  long getDsQueueSize() {
1252  if (null == this.tasksSnapshot) {
1253  return 0;
1254  }
1255  return this.tasksSnapshot.getDsQueueSize();
1256  }
1257 
1258  long getRunningListSize() {
1259  if (null == this.tasksSnapshot) {
1260  return 0;
1261  }
1262  return this.tasksSnapshot.getRunningListSize();
1263  }
1264 
1265  boolean isCancelled() {
1266  return this.jobCancelled;
1267  }
1268 
1274  IngestJob.CancellationReason getCancellationReason() {
1275  return this.jobCancellationReason;
1276  }
1277 
1285  List<String> getCancelledDataSourceIngestModules() {
1286  return Collections.unmodifiableList(this.cancelledDataSourceModules);
1287  }
1288 
1289  }
1290 
1291 }
List< IngestModuleTemplate > getEnabledIngestModuleTemplates()

Copyright © 2012-2016 Basis Technology. Generated on: Mon May 7 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.