19 package org.sleuthkit.autopsy.ingest;
 
   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;
 
   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;
 
   44 final class DataSourceIngestJob {
 
   46     private static final Logger logger = Logger.getLogger(DataSourceIngestJob.class.getName());
 
   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;
 
   83     private final Object stageCompletionCheckLock = 
new Object();
 
   93     private final Object dataSourceIngestPipelineLock = 
new Object();
 
   94     private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
 
   95     private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
 
   96     private DataSourceIngestPipeline currentDataSourceIngestPipeline;
 
  105     private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue = 
new LinkedBlockingQueue<>();
 
  106     private final List<FileIngestPipeline> fileIngestPipelines = 
new ArrayList<>();
 
  119     private volatile boolean currentDataSourceIngestModuleCancelled;
 
  120     private volatile boolean cancelled;
 
  121     private final List<String> cancelledDataSourceIngestModules = 
new CopyOnWriteArrayList<>();
 
  127     private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
 
  133     private final boolean runInteractively;
 
  139     private final Object dataSourceIngestProgressLock = 
new Object();
 
  140     private ProgressHandle dataSourceIngestProgress;
 
  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;
 
  155     private final long createTime;
 
  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();
 
  181     private void createIngestPipelines() {
 
  182         List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
 
  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);
 
  193             if (
template.isFileIngestModuleTemplate()) {
 
  194                 fileModuleTemplates.put(
template.getModuleFactory().getClass().getCanonicalName(), 
template);
 
  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());
 
  212         for (IngestModuleTemplate 
template : dataSourceModuleTemplates.values()) {
 
  213             firstStageDataSourceModuleTemplates.add(
template);
 
  215         for (IngestModuleTemplate 
template : fileModuleTemplates.values()) {
 
  216             fileIngestModuleTemplates.add(
template);
 
  222         this.firstStageDataSourceIngestPipeline = 
new DataSourceIngestPipeline(
this, firstStageDataSourceModuleTemplates);
 
  223         this.secondStageDataSourceIngestPipeline = 
new DataSourceIngestPipeline(
this, secondStageDataSourceModuleTemplates);
 
  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);
 
  235         } 
catch (InterruptedException ex) {
 
  241             Thread.currentThread().interrupt();
 
  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));
 
  283     Content getDataSource() {
 
  284         return this.dataSource;
 
  293     boolean shouldProcessUnallocatedSpace() {
 
  294         return this.settings.getProcessUnallocatedSpace();
 
  302     boolean hasIngestPipeline() {
 
  303         return this.hasFirstStageDataSourceIngestPipeline()
 
  304                 || this.hasFileIngestPipeline()
 
  305                 || this.hasSecondStageDataSourceIngestPipeline();
 
  314     private boolean hasFirstStageDataSourceIngestPipeline() {
 
  315         return (this.firstStageDataSourceIngestPipeline.isEmpty() == 
false);
 
  324     private boolean hasSecondStageDataSourceIngestPipeline() {
 
  325         return (this.secondStageDataSourceIngestPipeline.isEmpty() == 
false);
 
  333     private boolean hasFileIngestPipeline() {
 
  334         if (!this.fileIngestPipelines.isEmpty()) {
 
  335             return !this.fileIngestPipelines.get(0).isEmpty();
 
  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();
 
  365     private List<IngestModuleError> startUpIngestPipelines() {
 
  366         List<IngestModuleError> errors = 
new ArrayList<>();
 
  369         errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
 
  372         errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
 
  375         for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
 
  376             errors.addAll(pipeline.startUp());
 
  377             if (!errors.isEmpty()) {
 
  386                 while (!this.fileIngestPipelinesQueue.isEmpty()) {
 
  387                     pipeline = this.fileIngestPipelinesQueue.poll();
 
  388                     List<IngestModuleError> shutDownErrors = pipeline.shutDown();
 
  389                     if (!shutDownErrors.isEmpty()) {
 
  390                         logIngestModuleErrors(shutDownErrors);
 
  397         logIngestModuleErrors(errors);
 
  404     private void startFirstStage() {
 
  405         this.stage = DataSourceIngestJob.Stages.
FIRST;
 
  407         if (this.hasFileIngestPipeline()) {
 
  408             synchronized (this.fileIngestProgressLock) {
 
  409                 this.estimatedFilesToProcess = this.dataSource.
accept(
new GetFilesCountVisitor());
 
  413         if (this.runInteractively) {
 
  417             if (this.hasFirstStageDataSourceIngestPipeline()) {
 
  418                 this.startDataSourceIngestProgressBar();
 
  420             if (this.hasFileIngestPipeline()) {
 
  421                 this.startFileIngestProgressBar();
 
  429         synchronized (this.dataSourceIngestPipelineLock) {
 
  430             this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
 
  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);
 
  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);
 
  454             this.checkForStageCompleted();
 
  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();
 
  467         synchronized (this.dataSourceIngestPipelineLock) {
 
  468             this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
 
  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);
 
  477     private void startDataSourceIngestProgressBar() {
 
  478         if (this.runInteractively) {
 
  479             synchronized (this.dataSourceIngestProgressLock) {
 
  480                 String displayName = NbBundle.getMessage(this.getClass(),
 
  481                         "IngestJob.progress.dataSourceIngest.initialDisplayName",
 
  483                 this.dataSourceIngestProgress = ProgressHandleFactory.createHandle(displayName, 
new Cancellable() {
 
  485                     public boolean cancel() {
 
  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();
 
  498                             DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
 
  503                 this.dataSourceIngestProgress.start();
 
  504                 this.dataSourceIngestProgress.switchToIndeterminate();
 
  512     private void startFileIngestProgressBar() {
 
  513         if (this.runInteractively) {
 
  514             synchronized (this.fileIngestProgressLock) {
 
  515                 String displayName = NbBundle.getMessage(this.getClass(),
 
  516                         "IngestJob.progress.fileIngest.displayName",
 
  518                 this.fileIngestProgress = ProgressHandleFactory.createHandle(displayName, 
new Cancellable() {
 
  520                     public boolean cancel() {
 
  525                         DataSourceIngestJob.this.cancel();
 
  529                 this.fileIngestProgress.start();
 
  530                 this.fileIngestProgress.switchToDeterminate((
int) this.estimatedFilesToProcess);
 
  539     private void checkForStageCompleted() {
 
  540         synchronized (this.stageCompletionCheckLock) {
 
  541             if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(
this)) {
 
  542                 switch (this.stage) {
 
  544                         this.finishFirstStage();
 
  558     private void finishFirstStage() {
 
  559         logger.log(Level.INFO, 
"Finished first stage analysis for {0} (jobId={1})", 
new Object[]{dataSource.getName(), this.id});
 
  564         List<IngestModuleError> errors = 
new ArrayList<>();
 
  565         while (!this.fileIngestPipelinesQueue.isEmpty()) {
 
  566             FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
 
  567             errors.addAll(pipeline.shutDown());
 
  569         if (!errors.isEmpty()) {
 
  570             logIngestModuleErrors(errors);
 
  573         if (this.runInteractively) {
 
  576             synchronized (this.dataSourceIngestProgressLock) {
 
  577                 if (this.dataSourceIngestProgress != null) {
 
  578                     this.dataSourceIngestProgress.finish();
 
  579                     this.dataSourceIngestProgress = null;
 
  585             synchronized (this.fileIngestProgressLock) {
 
  586                 if (this.fileIngestProgress != null) {
 
  587                     this.fileIngestProgress.finish();
 
  588                     this.fileIngestProgress = null;
 
  596         if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
 
  597             this.startSecondStage();
 
  606     private void finish() {
 
  607         logger.log(Level.INFO, 
"Finished analysis for {0} (jobId={1})", 
new Object[]{dataSource.getName(), this.id});
 
  610         if (this.runInteractively) {
 
  613             synchronized (this.dataSourceIngestProgressLock) {
 
  614                 if (this.dataSourceIngestProgress != null) {
 
  615                     this.dataSourceIngestProgress.finish();
 
  616                     this.dataSourceIngestProgress = null;
 
  621         this.parentJob.dataSourceJobFinished(
this);
 
  630     void process(DataSourceIngestTask task) {
 
  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);
 
  642             if (this.runInteractively) {
 
  647                 synchronized (this.dataSourceIngestProgressLock) {
 
  648                     if (null != this.dataSourceIngestProgress) {
 
  649                         this.dataSourceIngestProgress.finish();
 
  650                         this.dataSourceIngestProgress = null;
 
  656             DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
 
  657             this.checkForStageCompleted();
 
  670     void process(FileIngestTask task) 
throws InterruptedException {
 
  672             if (!this.isCancelled()) {
 
  673                 FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
 
  674                 if (!pipeline.isEmpty()) {
 
  675                     AbstractFile file = task.getFile();
 
  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);
 
  686                                 this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
 
  688                             this.filesInProgress.add(file.getName());
 
  695                     List<IngestModuleError> errors = 
new ArrayList<>();
 
  696                     errors.addAll(pipeline.process(task));
 
  697                     if (!errors.isEmpty()) {
 
  698                         logIngestModuleErrors(errors);
 
  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));
 
  711                                 this.fileIngestProgress.progress(
"");
 
  716                 this.fileIngestPipelinesQueue.put(pipeline);
 
  719             DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
 
  720             this.checkForStageCompleted();
 
  731     void addFiles(List<AbstractFile> files) {
 
  732         if (DataSourceIngestJob.Stages.FIRST == 
this.stage) {
 
  733             for (AbstractFile file : files) {
 
  734                 DataSourceIngestJob.taskScheduler.scheduleFileIngestTask(
this, file);
 
  737             DataSourceIngestJob.logger.log(Level.SEVERE, 
"Adding files during second stage not supported"); 
 
  746         this.checkForStageCompleted();
 
  755     void updateDataSourceIngestProgressBarDisplayName(String displayName) {
 
  756         if (this.runInteractively && !this.cancelled) {
 
  757             synchronized (this.dataSourceIngestProgressLock) {
 
  758                 this.dataSourceIngestProgress.setDisplayName(displayName);
 
  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);
 
  786     void switchDataSourceIngestProgressBarToIndeterminate() {
 
  787         if (this.runInteractively && !this.cancelled) {
 
  788             synchronized (this.dataSourceIngestProgressLock) {
 
  789                 if (null != this.dataSourceIngestProgress) {
 
  790                     this.dataSourceIngestProgress.switchToIndeterminate();
 
  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);
 
  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);
 
  836     void advanceDataSourceIngestProgressBar(String currentTask, 
int workUnits) {
 
  837         if (this.runInteractively && !this.cancelled) {
 
  838             synchronized (this.fileIngestProgressLock) {
 
  839                 this.dataSourceIngestProgress.progress(currentTask, workUnits);
 
  851     boolean currentDataSourceIngestModuleIsCancelled() {
 
  852         return this.currentDataSourceIngestModuleCancelled;
 
  861     void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
 
  862         this.currentDataSourceIngestModuleCancelled = 
false;
 
  863         this.cancelledDataSourceIngestModules.add(moduleDisplayName);
 
  865         if (this.runInteractively) {
 
  873             synchronized (this.dataSourceIngestProgressLock) {
 
  874                 this.dataSourceIngestProgress.finish();
 
  875                 this.dataSourceIngestProgress = null;
 
  876                 this.startDataSourceIngestProgressBar();
 
  886     DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
 
  887         if (null != this.currentDataSourceIngestPipeline) {
 
  888             return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
 
  898     void cancelCurrentDataSourceIngestModule() {
 
  899         this.currentDataSourceIngestModuleCancelled = 
true;
 
  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",
 
  917                     dataSourceIngestProgress.setDisplayName(
 
  918                             NbBundle.getMessage(
this.getClass(),
 
  919                                     "IngestJob.progress.cancelling",
 
  928             synchronized (this.fileIngestProgressLock) {
 
  929                 if (this.fileIngestProgress != null) {
 
  930                     final String displayName = NbBundle.getMessage(this.getClass(),
 
  931                             "IngestJob.progress.fileIngest.displayName",
 
  933                     this.fileIngestProgress.setDisplayName(
 
  934                             NbBundle.getMessage(
this.getClass(), 
"IngestJob.progress.cancelling",
 
  940         this.cancelled = 
true;
 
  946         DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(
this);
 
  947         this.checkForStageCompleted();
 
  956     boolean isCancelled() {
 
  957         return this.cancelled;
 
  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()); 
 
  976     Snapshot getSnapshot(
boolean getIngestTasksSnapshot) {
 
  977         return new Snapshot(getIngestTasksSnapshot);
 
  983     final class Snapshot {
 
  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;
 
 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();
 
 1013             for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) {
 
 1014                 if (pipeline.isRunning()) {
 
 1015                     this.fileIngestRunning = 
true;
 
 1017                 Date pipelineStartTime = pipeline.getStartTime();
 
 1018                 if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(
this.fileIngestStartTime))) {
 
 1019                     this.fileIngestStartTime = pipelineStartTime;
 
 1023             this.jobCancelled = cancelled;
 
 1024             this.cancelledDataSourceModules = 
new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules);
 
 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();
 
 1032                 this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId);
 
 1035                 this.processedFiles = 0;
 
 1036                 this.estimatedFilesToProcess = 0;
 
 1037                 this.snapShotTime = 
new Date().getTime();
 
 1038                 this.tasksSnapshot = null;
 
 1048         long getSnapshotTime() {
 
 1049             return snapShotTime;
 
 1058         String getDataSource() {
 
 1078         long getJobStartTime() {
 
 1079             return jobStartTime;
 
 1082         DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
 
 1083             return this.dataSourceLevelIngestModule;
 
 1086         boolean fileIngestIsRunning() {
 
 1087             return this.fileIngestRunning;
 
 1090         Date fileIngestStartTime() {
 
 1091             return this.fileIngestStartTime;
 
 1101             return (
double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
 
 1109         long getFilesProcessed() {
 
 1110             return processedFiles;
 
 1119         long getFilesEstimated() {
 
 1120             return estimatedFilesToProcess;
 
 1123         long getRootQueueSize() {
 
 1124             if (null == this.tasksSnapshot) {
 
 1127             return this.tasksSnapshot.getRootQueueSize();
 
 1130         long getDirQueueSize() {
 
 1131             if (null == this.tasksSnapshot) {
 
 1134             return this.tasksSnapshot.getDirectoryTasksQueueSize();
 
 1137         long getFileQueueSize() {
 
 1138             if (null == this.tasksSnapshot) {
 
 1141             return this.tasksSnapshot.getFileQueueSize();
 
 1144         long getDsQueueSize() {
 
 1145             if (null == this.tasksSnapshot) {
 
 1148             return this.tasksSnapshot.getDsQueueSize();
 
 1151         long getRunningListSize() {
 
 1152             if (null == this.tasksSnapshot) {
 
 1155             return this.tasksSnapshot.getRunningListSize();
 
 1158         boolean isCancelled() {
 
 1159             return this.jobCancelled;
 
 1169         List<String> getCancelledDataSourceIngestModules() {
 
 1170             return Collections.unmodifiableList(this.cancelledDataSourceModules);
 
public< T > T accept(ContentVisitor< T > v)