Autopsy  4.5.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-2017 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;
38 import org.sleuthkit.datamodel.AbstractFile;
39 import org.sleuthkit.datamodel.Content;
40 import org.sleuthkit.datamodel.IngestJobInfo;
41 import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
42 import org.sleuthkit.datamodel.IngestModuleInfo;
43 import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
44 import org.sleuthkit.datamodel.SleuthkitCase;
45 import org.sleuthkit.datamodel.TskCoreException;
47 
52 final class DataSourceIngestJob {
53 
54  private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName());
55 
60  private final IngestJob parentJob;
61  private static final AtomicLong nextJobId = new AtomicLong(0L);
62  private final long id;
63  private final IngestJobSettings settings;
64  private final Content dataSource;
65 
69  private static enum Stages {
70 
88  FINALIZATION
89  };
90  private volatile Stages stage = DataSourceIngestJob.Stages.INITIALIZATION;
91  private final Object stageCompletionCheckLock = new Object();
92 
101  private final Object dataSourceIngestPipelineLock = new Object();
102  private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
103  private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
104  private DataSourceIngestPipeline currentDataSourceIngestPipeline;
105 
113  private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue = new LinkedBlockingQueue<>();
114  private final List<FileIngestPipeline> fileIngestPipelines = new ArrayList<>();
115 
127  private volatile boolean currentDataSourceIngestModuleCancelled;
128  private final List<String> cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>();
129  private volatile boolean cancelled;
130  private volatile IngestJob.CancellationReason cancellationReason = IngestJob.CancellationReason.NOT_CANCELLED;
131 
136  private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
137 
142  private final boolean doUI;
143 
148  private final Object dataSourceIngestProgressLock = new Object();
149  private ProgressHandle dataSourceIngestProgress;
150 
155  private final Object fileIngestProgressLock = new Object();
156  private final List<String> filesInProgress = new ArrayList<>();
157  private long estimatedFilesToProcess;
158  private long processedFiles;
159  private ProgressHandle fileIngestProgress;
160  private String currentFileIngestModule = "";
161  private String currentFileIngestTask = "";
162  private final List<IngestModuleInfo> ingestModules = new ArrayList<>();
163  private IngestJobInfo ingestJob;
164 
168  private final long createTime;
169 
181  DataSourceIngestJob(IngestJob parentJob, Content dataSource, IngestJobSettings settings, boolean runInteractively) {
182  this.parentJob = parentJob;
183  this.id = DataSourceIngestJob.nextJobId.getAndIncrement();
184  this.dataSource = dataSource;
185  this.settings = settings;
186  this.doUI = runInteractively;
187  this.createTime = new Date().getTime();
188  this.createIngestPipelines();
189  }
190 
194  private void createIngestPipelines() {
195  List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
196 
200  Map<String, IngestModuleTemplate> dataSourceModuleTemplates = new HashMap<>();
201  Map<String, IngestModuleTemplate> fileModuleTemplates = new HashMap<>();
202  for (IngestModuleTemplate template : ingestModuleTemplates) {
203  if (template.isDataSourceIngestModuleTemplate()) {
204  dataSourceModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
205  }
206  if (template.isFileIngestModuleTemplate()) {
207  fileModuleTemplates.put(template.getModuleFactory().getClass().getCanonicalName(), template);
208  }
209  }
210 
215  IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
216  List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
217  List<IngestModuleTemplate> fileIngestModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(fileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
218  List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
219 
225  for (IngestModuleTemplate template : dataSourceModuleTemplates.values()) {
226  firstStageDataSourceModuleTemplates.add(template);
227  }
228  for (IngestModuleTemplate template : fileModuleTemplates.values()) {
229  fileIngestModuleTemplates.add(template);
230  }
231 
235  this.firstStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, firstStageDataSourceModuleTemplates);
236  this.secondStageDataSourceIngestPipeline = new DataSourceIngestPipeline(this, secondStageDataSourceModuleTemplates);
237 
241  try {
242  int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
243  for (int i = 0; i < numberOfFileIngestThreads; ++i) {
244  FileIngestPipeline pipeline = new FileIngestPipeline(this, fileIngestModuleTemplates);
245  this.fileIngestPipelinesQueue.put(pipeline);
246  this.fileIngestPipelines.add(pipeline);
247  }
248  } catch (InterruptedException ex) {
254  Thread.currentThread().interrupt();
255  }
256  SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
257  try {
258  this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
259  this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
260  this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
261  } catch (TskCoreException ex) {
262  logger.log(Level.SEVERE, "Failed to add ingest modules to database.", ex);
263  }
264  }
265 
266  private void addIngestModules(List<IngestModuleTemplate> templates, IngestModuleType type, SleuthkitCase skCase) throws TskCoreException {
267  for (IngestModuleTemplate module : templates) {
268  ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
269  }
270  }
271 
287  private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
288  List<IngestModuleTemplate> templates = new ArrayList<>();
289  for (String moduleClassName : pipelineConfig) {
290  if (ingestModuleTemplates.containsKey(moduleClassName)) {
291  templates.add(ingestModuleTemplates.remove(moduleClassName));
292  }
293  }
294  return templates;
295  }
296 
302  long getId() {
303  return this.id;
304  }
305 
311  String getExecutionContext() {
312  return this.settings.getExecutionContext();
313  }
314 
320  Content getDataSource() {
321  return this.dataSource;
322  }
323 
330  boolean shouldProcessUnallocatedSpace() {
331  return this.settings.getProcessUnallocatedSpace();
332  }
333 
339  FilesSet getFileIngestFilter() {
340  return this.settings.getFileIngestFilter();
341  }
342 
348  boolean hasIngestPipeline() {
349  return this.hasFirstStageDataSourceIngestPipeline()
350  || this.hasFileIngestPipeline()
351  || this.hasSecondStageDataSourceIngestPipeline();
352  }
353 
360  private boolean hasFirstStageDataSourceIngestPipeline() {
361  return (this.firstStageDataSourceIngestPipeline.isEmpty() == false);
362  }
363 
370  private boolean hasSecondStageDataSourceIngestPipeline() {
371  return (this.secondStageDataSourceIngestPipeline.isEmpty() == false);
372  }
373 
379  private boolean hasFileIngestPipeline() {
380  if (!this.fileIngestPipelines.isEmpty()) {
381  return !this.fileIngestPipelines.get(0).isEmpty();
382  }
383  return false;
384  }
385 
391  List<IngestModuleError> start() {
392  List<IngestModuleError> errors = startUpIngestPipelines();
393  if (errors.isEmpty()) {
394  if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
395  logger.log(Level.INFO, "Starting first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
396  this.startFirstStage();
397  } else if (this.hasSecondStageDataSourceIngestPipeline()) {
398  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
399  this.startSecondStage();
400  }
401  try {
402  this.ingestJob = Case.getCurrentCase().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
403  } catch (TskCoreException ex) {
404  logger.log(Level.SEVERE, "Failed to add ingest job to database.", ex);
405  }
406  }
407  return errors;
408  }
409 
416  private List<IngestModuleError> startUpIngestPipelines() {
417  List<IngestModuleError> errors = new ArrayList<>();
418 
419  /*
420  * Start the data-source-level ingest module pipelines.
421  */
422  errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
423  errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
424 
425  /*
426  * If the data-source-level ingest pipelines were successfully started,
427  * start the Start the file-level ingest pipelines (one per file ingest
428  * thread).
429  */
430  if (errors.isEmpty()) {
431  for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
432  errors.addAll(pipeline.startUp());
433  if (!errors.isEmpty()) {
434  /*
435  * If there are start up errors, the ingest job will not
436  * proceed, so shut down any file ingest pipelines that did
437  * start up.
438  */
439  while (!this.fileIngestPipelinesQueue.isEmpty()) {
440  FileIngestPipeline startedPipeline = this.fileIngestPipelinesQueue.poll();
441  if (startedPipeline.isRunning()) {
442  List<IngestModuleError> shutDownErrors = startedPipeline.shutDown();
443  if (!shutDownErrors.isEmpty()) {
444  /*
445  * The start up errors will ultimately be
446  * reported to the user for possible remedy, but
447  * the shut down errors are logged here.
448  */
449  logIngestModuleErrors(shutDownErrors);
450  }
451  }
452  }
453  break;
454  }
455  }
456  }
457 
458  return errors;
459  }
460 
464  private void startFirstStage() {
465  this.stage = DataSourceIngestJob.Stages.FIRST;
466 
467  if (this.hasFileIngestPipeline()) {
468  synchronized (this.fileIngestProgressLock) {
469  this.estimatedFilesToProcess = this.dataSource.accept(new GetFilesCountVisitor());
470  }
471  }
472 
473  if (this.doUI) {
477  if (this.hasFirstStageDataSourceIngestPipeline()) {
478  this.startDataSourceIngestProgressBar();
479  }
480  if (this.hasFileIngestPipeline()) {
481  this.startFileIngestProgressBar();
482  }
483  }
484 
489  synchronized (this.dataSourceIngestPipelineLock) {
490  this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
491  }
492 
496  if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
497  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
498  DataSourceIngestJob.taskScheduler.scheduleIngestTasks(this);
499  } else if (this.hasFirstStageDataSourceIngestPipeline()) {
500  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
501  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
502  } else {
503  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
504  DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(this);
505 
514  this.checkForStageCompleted();
515  }
516  }
517 
521  private void startSecondStage() {
522  logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
523  this.stage = DataSourceIngestJob.Stages.SECOND;
524  if (this.doUI) {
525  this.startDataSourceIngestProgressBar();
526  }
527  synchronized (this.dataSourceIngestPipelineLock) {
528  this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
529  }
530  logger.log(Level.INFO, "Scheduling second stage data source level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
531  DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
532  }
533 
537  private void startDataSourceIngestProgressBar() {
538  if (this.doUI) {
539  synchronized (this.dataSourceIngestProgressLock) {
540  String displayName = NbBundle.getMessage(this.getClass(),
541  "IngestJob.progress.dataSourceIngest.initialDisplayName",
542  this.dataSource.getName());
543  this.dataSourceIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
544  @Override
545  public boolean cancel() {
546  // If this method is called, the user has already pressed
547  // the cancel button on the progress bar and the OK button
548  // of a cancelation confirmation dialog supplied by
549  // NetBeans. What remains to be done is to find out whether
550  // the user wants to cancel only the currently executing
551  // data source ingest module or the entire ingest job.
552  DataSourceIngestCancellationPanel panel = new DataSourceIngestCancellationPanel();
553  String dialogTitle = NbBundle.getMessage(DataSourceIngestJob.this.getClass(), "IngestJob.cancellationDialog.title");
554  JOptionPane.showConfirmDialog(null, panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
555  if (panel.cancelAllDataSourceIngestModules()) {
556  DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
557  } else {
558  DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
559  }
560  return true;
561  }
562  });
563  this.dataSourceIngestProgress.start();
564  this.dataSourceIngestProgress.switchToIndeterminate();
565  }
566  }
567  }
568 
572  private void startFileIngestProgressBar() {
573  if (this.doUI) {
574  synchronized (this.fileIngestProgressLock) {
575  String displayName = NbBundle.getMessage(this.getClass(),
576  "IngestJob.progress.fileIngest.displayName",
577  this.dataSource.getName());
578  this.fileIngestProgress = ProgressHandle.createHandle(displayName, new Cancellable() {
579  @Override
580  public boolean cancel() {
581  // If this method is called, the user has already pressed
582  // the cancel button on the progress bar and the OK button
583  // of a cancelation confirmation dialog supplied by
584  // NetBeans.
585  DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
586  return true;
587  }
588  });
589  this.fileIngestProgress.start();
590  this.fileIngestProgress.switchToDeterminate((int) this.estimatedFilesToProcess);
591  }
592  }
593  }
594 
599  private void checkForStageCompleted() {
600  synchronized (this.stageCompletionCheckLock) {
601  if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(this)) {
602  switch (this.stage) {
603  case FIRST:
604  this.finishFirstStage();
605  break;
606  case SECOND:
607  this.finish();
608  break;
609  }
610  }
611  }
612  }
613 
618  private void finishFirstStage() {
619  logger.log(Level.INFO, "Finished first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
620 
621  // Shut down the file ingest pipelines. Note that no shut down is
622  // required for the data source ingest pipeline because data source
623  // ingest modules do not have a shutdown() method.
624  List<IngestModuleError> errors = new ArrayList<>();
625  while (!this.fileIngestPipelinesQueue.isEmpty()) {
626  FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
627  if (pipeline.isRunning()) {
628  errors.addAll(pipeline.shutDown());
629  }
630  }
631  if (!errors.isEmpty()) {
632  logIngestModuleErrors(errors);
633  }
634 
635  if (this.doUI) {
636  // Finish the first stage data source ingest progress bar, if it hasn't
637  // already been finished.
638  synchronized (this.dataSourceIngestProgressLock) {
639  if (this.dataSourceIngestProgress != null) {
640  this.dataSourceIngestProgress.finish();
641  this.dataSourceIngestProgress = null;
642  }
643  }
644 
645  // Finish the file ingest progress bar, if it hasn't already
646  // been finished.
647  synchronized (this.fileIngestProgressLock) {
648  if (this.fileIngestProgress != null) {
649  this.fileIngestProgress.finish();
650  this.fileIngestProgress = null;
651  }
652  }
653  }
654 
658  if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
659  this.startSecondStage();
660  } else {
661  this.finish();
662  }
663  }
664 
668  private void finish() {
669  logger.log(Level.INFO, "Finished analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
670  this.stage = DataSourceIngestJob.Stages.FINALIZATION;
671 
672  if (this.doUI) {
673  // Finish the second stage data source ingest progress bar, if it hasn't
674  // already been finished.
675  synchronized (this.dataSourceIngestProgressLock) {
676  if (this.dataSourceIngestProgress != null) {
677  this.dataSourceIngestProgress.finish();
678  this.dataSourceIngestProgress = null;
679  }
680  }
681  }
682  if (this.cancelled) {
683  try {
684  ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
685  } catch (TskCoreException ex) {
686  logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
687  }
688  } else {
689  try {
690  ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
691  } catch (TskCoreException ex) {
692  logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
693  }
694  }
695  try {
696  this.ingestJob.setEndDateTime(new Date());
697  } catch (TskCoreException ex) {
698  logger.log(Level.SEVERE, "Failed to set end date for ingest job in database.", ex);
699  }
700  this.parentJob.dataSourceJobFinished(this);
701 
702  }
703 
710  void process(DataSourceIngestTask task) {
711  try {
712  synchronized (this.dataSourceIngestPipelineLock) {
713  if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
714  List<IngestModuleError> errors = new ArrayList<>();
715  errors.addAll(this.currentDataSourceIngestPipeline.process(task));
716  if (!errors.isEmpty()) {
717  logIngestModuleErrors(errors);
718  }
719  }
720  }
721 
722  if (this.doUI) {
727  synchronized (this.dataSourceIngestProgressLock) {
728  if (null != this.dataSourceIngestProgress) {
729  this.dataSourceIngestProgress.finish();
730  this.dataSourceIngestProgress = null;
731  }
732  }
733  }
734 
735  } finally {
736  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
737  this.checkForStageCompleted();
738  }
739  }
740 
752  void process(FileIngestTask task) throws InterruptedException {
753  try {
754  if (!this.isCancelled()) {
755  FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
756  if (!pipeline.isEmpty()) {
757  AbstractFile file = task.getFile();
758 
759  synchronized (this.fileIngestProgressLock) {
760  ++this.processedFiles;
761  if (this.doUI) {
765  if (this.processedFiles <= this.estimatedFilesToProcess) {
766  this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
767  } else {
768  this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
769  }
770  this.filesInProgress.add(file.getName());
771  }
772  }
773 
777  List<IngestModuleError> errors = new ArrayList<>();
778  errors.addAll(pipeline.process(task));
779  if (!errors.isEmpty()) {
780  logIngestModuleErrors(errors);
781  }
782 
783  if (this.doUI && !this.cancelled) {
784  synchronized (this.fileIngestProgressLock) {
789  this.filesInProgress.remove(file.getName());
790  if (this.filesInProgress.size() > 0) {
791  this.fileIngestProgress.progress(this.filesInProgress.get(0));
792  } else {
793  this.fileIngestProgress.progress("");
794  }
795  }
796  }
797  }
798  this.fileIngestPipelinesQueue.put(pipeline);
799  }
800  } finally {
801  DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
802  this.checkForStageCompleted();
803  }
804  }
805 
813  void addFiles(List<AbstractFile> files) {
814  if (DataSourceIngestJob.Stages.FIRST == this.stage) {
815  for (AbstractFile file : files) {
816  DataSourceIngestJob.taskScheduler.scheduleFileIngestTask(this, file);
817  }
818  } else {
819  DataSourceIngestJob.logger.log(Level.SEVERE, "Adding files during second stage not supported"); //NON-NLS
820  }
821 
828  this.checkForStageCompleted();
829  }
830 
837  void updateDataSourceIngestProgressBarDisplayName(String displayName) {
838  if (this.doUI && !this.cancelled) {
839  synchronized (this.dataSourceIngestProgressLock) {
840  this.dataSourceIngestProgress.setDisplayName(displayName);
841  }
842  }
843  }
844 
853  void switchDataSourceIngestProgressBarToDeterminate(int workUnits) {
854  if (this.doUI && !this.cancelled) {
855  synchronized (this.dataSourceIngestProgressLock) {
856  if (null != this.dataSourceIngestProgress) {
857  this.dataSourceIngestProgress.switchToDeterminate(workUnits);
858  }
859  }
860  }
861  }
862 
868  void switchDataSourceIngestProgressBarToIndeterminate() {
869  if (this.doUI && !this.cancelled) {
870  synchronized (this.dataSourceIngestProgressLock) {
871  if (null != this.dataSourceIngestProgress) {
872  this.dataSourceIngestProgress.switchToIndeterminate();
873  }
874  }
875  }
876  }
877 
884  void advanceDataSourceIngestProgressBar(int workUnits) {
885  if (this.doUI && !this.cancelled) {
886  synchronized (this.dataSourceIngestProgressLock) {
887  if (null != this.dataSourceIngestProgress) {
888  this.dataSourceIngestProgress.progress("", workUnits);
889  }
890  }
891  }
892  }
893 
900  void advanceDataSourceIngestProgressBar(String currentTask) {
901  if (this.doUI && !this.cancelled) {
902  synchronized (this.dataSourceIngestProgressLock) {
903  if (null != this.dataSourceIngestProgress) {
904  this.dataSourceIngestProgress.progress(currentTask);
905  }
906  }
907  }
908  }
909 
918  void advanceDataSourceIngestProgressBar(String currentTask, int workUnits) {
919  if (this.doUI && !this.cancelled) {
920  synchronized (this.fileIngestProgressLock) {
921  this.dataSourceIngestProgress.progress(currentTask, workUnits);
922  }
923  }
924  }
925 
933  boolean currentDataSourceIngestModuleIsCancelled() {
934  return this.currentDataSourceIngestModuleCancelled;
935  }
936 
943  void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
944  this.currentDataSourceIngestModuleCancelled = false;
945  this.cancelledDataSourceIngestModules.add(moduleDisplayName);
946 
947  if (this.doUI) {
955  synchronized (this.dataSourceIngestProgressLock) {
956  this.dataSourceIngestProgress.finish();
957  this.dataSourceIngestProgress = null;
958  this.startDataSourceIngestProgressBar();
959  }
960  }
961  }
962 
968  DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
969  if (null != this.currentDataSourceIngestPipeline) {
970  return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
971  } else {
972  return null;
973  }
974  }
975 
980  void cancelCurrentDataSourceIngestModule() {
981  this.currentDataSourceIngestModuleCancelled = true;
982  }
983 
990  void cancel(IngestJob.CancellationReason reason) {
991  this.cancelled = true;
992  this.cancellationReason = reason;
993  DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this);
994 
995  if (this.doUI) {
996  synchronized (this.dataSourceIngestProgressLock) {
997  if (null != dataSourceIngestProgress) {
998  dataSourceIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.initialDisplayName", dataSource.getName()));
999  dataSourceIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1000  }
1001  }
1002 
1003  synchronized (this.fileIngestProgressLock) {
1004  if (null != this.fileIngestProgress) {
1005  this.fileIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", this.dataSource.getName()));
1006  this.fileIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling"));
1007  }
1008  }
1009  }
1010  }
1011 
1019  void setCurrentFileIngestModule(String moduleName, String taskName) {
1020  this.currentFileIngestModule = moduleName;
1021  this.currentFileIngestTask = taskName;
1022  }
1023 
1030  boolean isCancelled() {
1031  return this.cancelled;
1032  }
1033 
1039  IngestJob.CancellationReason getCancellationReason() {
1040  return this.cancellationReason;
1041  }
1042 
1048  private void logIngestModuleErrors(List<IngestModuleError> errors) {
1049  for (IngestModuleError error : errors) {
1050  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
1051  }
1052  }
1053 
1059  Snapshot getSnapshot(boolean getIngestTasksSnapshot) {
1060  return new Snapshot(getIngestTasksSnapshot);
1061  }
1062 
1066  final class Snapshot {
1067 
1068  private final String dataSource;
1069  private final long jobId;
1070  private final long jobStartTime;
1071  private final long snapShotTime;
1072  private final DataSourceIngestPipeline.PipelineModule dataSourceLevelIngestModule;
1073  private boolean fileIngestRunning;
1074  private Date fileIngestStartTime;
1075  private final long processedFiles;
1076  private final long estimatedFilesToProcess;
1077  private final IngestTasksScheduler.IngestJobTasksSnapshot tasksSnapshot;
1078  private final boolean jobCancelled;
1079  private final IngestJob.CancellationReason jobCancellationReason;
1080  private final List<String> cancelledDataSourceModules;
1081 
1086  Snapshot(boolean getIngestTasksSnapshot) {
1087  this.dataSource = DataSourceIngestJob.this.dataSource.getName();
1088  this.jobId = DataSourceIngestJob.this.id;
1089  this.jobStartTime = DataSourceIngestJob.this.createTime;
1090  this.dataSourceLevelIngestModule = DataSourceIngestJob.this.getCurrentDataSourceIngestModule();
1091 
1097  for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) {
1098  if (pipeline.isRunning()) {
1099  this.fileIngestRunning = true;
1100  }
1101  Date pipelineStartTime = pipeline.getStartTime();
1102  if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(this.fileIngestStartTime))) {
1103  this.fileIngestStartTime = pipelineStartTime;
1104  }
1105  }
1106 
1107  this.jobCancelled = cancelled;
1108  this.jobCancellationReason = cancellationReason;
1109  this.cancelledDataSourceModules = new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules);
1110 
1111  if (getIngestTasksSnapshot) {
1112  synchronized (DataSourceIngestJob.this.fileIngestProgressLock) {
1113  this.processedFiles = DataSourceIngestJob.this.processedFiles;
1114  this.estimatedFilesToProcess = DataSourceIngestJob.this.estimatedFilesToProcess;
1115  this.snapShotTime = new Date().getTime();
1116  }
1117  this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId);
1118 
1119  } else {
1120  this.processedFiles = 0;
1121  this.estimatedFilesToProcess = 0;
1122  this.snapShotTime = new Date().getTime();
1123  this.tasksSnapshot = null;
1124  }
1125  }
1126 
1133  long getSnapshotTime() {
1134  return snapShotTime;
1135  }
1136 
1143  String getDataSource() {
1144  return dataSource;
1145  }
1146 
1153  long getJobId() {
1154  return this.jobId;
1155  }
1156 
1163  long getJobStartTime() {
1164  return jobStartTime;
1165  }
1166 
1167  DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
1168  return this.dataSourceLevelIngestModule;
1169  }
1170 
1171  boolean fileIngestIsRunning() {
1172  return this.fileIngestRunning;
1173  }
1174 
1175  Date fileIngestStartTime() {
1176  return this.fileIngestStartTime;
1177  }
1178 
1185  double getSpeed() {
1186  return (double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
1187  }
1188 
1194  long getFilesProcessed() {
1195  return processedFiles;
1196  }
1197 
1204  long getFilesEstimated() {
1205  return estimatedFilesToProcess;
1206  }
1207 
1208  long getRootQueueSize() {
1209  if (null == this.tasksSnapshot) {
1210  return 0;
1211  }
1212  return this.tasksSnapshot.getRootQueueSize();
1213  }
1214 
1215  long getDirQueueSize() {
1216  if (null == this.tasksSnapshot) {
1217  return 0;
1218  }
1219  return this.tasksSnapshot.getDirectoryTasksQueueSize();
1220  }
1221 
1222  long getFileQueueSize() {
1223  if (null == this.tasksSnapshot) {
1224  return 0;
1225  }
1226  return this.tasksSnapshot.getFileQueueSize();
1227  }
1228 
1229  long getDsQueueSize() {
1230  if (null == this.tasksSnapshot) {
1231  return 0;
1232  }
1233  return this.tasksSnapshot.getDsQueueSize();
1234  }
1235 
1236  long getRunningListSize() {
1237  if (null == this.tasksSnapshot) {
1238  return 0;
1239  }
1240  return this.tasksSnapshot.getRunningListSize();
1241  }
1242 
1243  boolean isCancelled() {
1244  return this.jobCancelled;
1245  }
1246 
1252  IngestJob.CancellationReason getCancellationReason() {
1253  return this.jobCancellationReason;
1254  }
1255 
1263  List<String> getCancelledDataSourceIngestModules() {
1264  return Collections.unmodifiableList(this.cancelledDataSourceModules);
1265  }
1266 
1267  }
1268 
1269 }

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