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;
122 private final Object cancellationStateMonitor =
new Object();
123 private final List<String> cancelledDataSourceIngestModules =
new CopyOnWriteArrayList<>();
129 private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
135 private final boolean doUI;
141 private final Object dataSourceIngestProgressLock =
new Object();
142 private ProgressHandle dataSourceIngestProgress;
148 private final Object fileIngestProgressLock =
new Object();
149 private final List<String> filesInProgress =
new ArrayList<>();
150 private long estimatedFilesToProcess;
151 private long processedFiles;
152 private ProgressHandle fileIngestProgress;
153 private String currentFileIngestModule =
"";
154 private String currentFileIngestTask =
"";
159 private final long createTime;
173 this.parentJob = parentJob;
174 this.
id = DataSourceIngestJob.nextJobId.getAndIncrement();
175 this.dataSource = dataSource;
176 this.settings = settings;
177 this.doUI = runInteractively;
178 this.createTime =
new Date().getTime();
179 this.createIngestPipelines();
185 private void createIngestPipelines() {
186 List<IngestModuleTemplate> ingestModuleTemplates = this.settings.getEnabledIngestModuleTemplates();
191 Map<String, IngestModuleTemplate> dataSourceModuleTemplates =
new HashMap<>();
192 Map<String, IngestModuleTemplate> fileModuleTemplates =
new HashMap<>();
193 for (IngestModuleTemplate
template : ingestModuleTemplates) {
194 if (
template.isDataSourceIngestModuleTemplate()) {
195 dataSourceModuleTemplates.put(
template.getModuleFactory().getClass().getCanonicalName(),
template);
197 if (
template.isFileIngestModuleTemplate()) {
198 fileModuleTemplates.put(
template.getModuleFactory().getClass().getCanonicalName(),
template);
206 IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
207 List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
208 List<IngestModuleTemplate> fileIngestModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(fileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
209 List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = DataSourceIngestJob.getConfiguredIngestModuleTemplates(dataSourceModuleTemplates, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
216 for (IngestModuleTemplate
template : dataSourceModuleTemplates.values()) {
217 firstStageDataSourceModuleTemplates.add(
template);
219 for (IngestModuleTemplate
template : fileModuleTemplates.values()) {
220 fileIngestModuleTemplates.add(
template);
226 this.firstStageDataSourceIngestPipeline =
new DataSourceIngestPipeline(
this, firstStageDataSourceModuleTemplates);
227 this.secondStageDataSourceIngestPipeline =
new DataSourceIngestPipeline(
this, secondStageDataSourceModuleTemplates);
233 int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
234 for (
int i = 0; i < numberOfFileIngestThreads; ++i) {
235 FileIngestPipeline pipeline =
new FileIngestPipeline(
this, fileIngestModuleTemplates);
236 this.fileIngestPipelinesQueue.put(pipeline);
237 this.fileIngestPipelines.add(pipeline);
239 }
catch (InterruptedException ex) {
245 Thread.currentThread().interrupt();
264 private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(Map<String, IngestModuleTemplate> ingestModuleTemplates, List<String> pipelineConfig) {
265 List<IngestModuleTemplate> templates =
new ArrayList<>();
266 for (String moduleClassName : pipelineConfig) {
267 if (ingestModuleTemplates.containsKey(moduleClassName)) {
268 templates.add(ingestModuleTemplates.remove(moduleClassName));
288 String getExecutionContext() {
289 return this.settings.getExecutionContext();
297 Content getDataSource() {
298 return this.dataSource;
307 boolean shouldProcessUnallocatedSpace() {
308 return this.settings.getProcessUnallocatedSpace();
316 boolean hasIngestPipeline() {
317 return this.hasFirstStageDataSourceIngestPipeline()
318 || this.hasFileIngestPipeline()
319 || this.hasSecondStageDataSourceIngestPipeline();
328 private boolean hasFirstStageDataSourceIngestPipeline() {
329 return (this.firstStageDataSourceIngestPipeline.isEmpty() ==
false);
338 private boolean hasSecondStageDataSourceIngestPipeline() {
339 return (this.secondStageDataSourceIngestPipeline.isEmpty() ==
false);
347 private boolean hasFileIngestPipeline() {
348 if (!this.fileIngestPipelines.isEmpty()) {
349 return !this.fileIngestPipelines.get(0).isEmpty();
359 List<IngestModuleError> start() {
360 List<IngestModuleError> errors = startUpIngestPipelines();
361 if (errors.isEmpty()) {
362 if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
363 logger.log(Level.INFO,
"Starting first stage analysis for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
364 this.startFirstStage();
365 }
else if (this.hasSecondStageDataSourceIngestPipeline()) {
366 logger.log(Level.INFO,
"Starting second stage analysis for {0} (jobId={1}), no first stage configured",
new Object[]{dataSource.getName(), this.id});
367 this.startSecondStage();
379 private List<IngestModuleError> startUpIngestPipelines() {
380 List<IngestModuleError> errors =
new ArrayList<>();
383 errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
386 errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
389 for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
390 errors.addAll(pipeline.startUp());
391 if (!errors.isEmpty()) {
400 while (!this.fileIngestPipelinesQueue.isEmpty()) {
401 pipeline = this.fileIngestPipelinesQueue.poll();
402 if (pipeline.isRunning()) {
403 List<IngestModuleError> shutDownErrors = pipeline.shutDown();
404 if (!shutDownErrors.isEmpty()) {
405 logIngestModuleErrors(shutDownErrors);
413 logIngestModuleErrors(errors);
420 private void startFirstStage() {
421 this.stage = DataSourceIngestJob.Stages.
FIRST;
423 if (this.hasFileIngestPipeline()) {
424 synchronized (this.fileIngestProgressLock) {
425 this.estimatedFilesToProcess = this.dataSource.accept(
new GetFilesCountVisitor());
433 if (this.hasFirstStageDataSourceIngestPipeline()) {
434 this.startDataSourceIngestProgressBar();
436 if (this.hasFileIngestPipeline()) {
437 this.startFileIngestProgressBar();
445 synchronized (this.dataSourceIngestPipelineLock) {
446 this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
452 if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
453 logger.log(Level.INFO,
"Scheduling first stage data source and file level analysis tasks for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
454 DataSourceIngestJob.taskScheduler.scheduleIngestTasks(
this);
455 }
else if (this.hasFirstStageDataSourceIngestPipeline()) {
456 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});
457 DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(
this);
459 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});
460 DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(
this);
470 this.checkForStageCompleted();
477 private void startSecondStage() {
478 logger.log(Level.INFO,
"Starting second stage analysis for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
479 this.stage = DataSourceIngestJob.Stages.
SECOND;
481 this.startDataSourceIngestProgressBar();
483 synchronized (this.dataSourceIngestPipelineLock) {
484 this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
486 logger.log(Level.INFO,
"Scheduling second stage data source level analysis tasks for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
487 DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(
this);
493 private void startDataSourceIngestProgressBar() {
495 synchronized (this.dataSourceIngestProgressLock) {
496 String displayName = NbBundle.getMessage(this.getClass(),
497 "IngestJob.progress.dataSourceIngest.initialDisplayName",
498 this.dataSource.getName());
499 this.dataSourceIngestProgress = ProgressHandleFactory.createHandle(displayName,
new Cancellable() {
501 public boolean cancel() {
508 DataSourceIngestCancellationPanel panel =
new DataSourceIngestCancellationPanel();
509 String dialogTitle = NbBundle.getMessage(DataSourceIngestJob.this.getClass(),
"IngestJob.cancellationDialog.title");
510 JOptionPane.showConfirmDialog(null, panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
511 if (panel.cancelAllDataSourceIngestModules()) {
512 DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
514 DataSourceIngestJob.this.cancelCurrentDataSourceIngestModule();
519 this.dataSourceIngestProgress.start();
520 this.dataSourceIngestProgress.switchToIndeterminate();
528 private void startFileIngestProgressBar() {
530 synchronized (this.fileIngestProgressLock) {
531 String displayName = NbBundle.getMessage(this.getClass(),
532 "IngestJob.progress.fileIngest.displayName",
533 this.dataSource.getName());
534 this.fileIngestProgress = ProgressHandleFactory.createHandle(displayName,
new Cancellable() {
536 public boolean cancel() {
541 DataSourceIngestJob.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
545 this.fileIngestProgress.start();
546 this.fileIngestProgress.switchToDeterminate((
int) this.estimatedFilesToProcess);
555 private void checkForStageCompleted() {
556 synchronized (this.stageCompletionCheckLock) {
557 if (DataSourceIngestJob.taskScheduler.tasksForJobAreCompleted(
this)) {
558 switch (this.stage) {
560 this.finishFirstStage();
574 private void finishFirstStage() {
575 logger.log(Level.INFO,
"Finished first stage analysis for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
580 List<IngestModuleError> errors =
new ArrayList<>();
581 while (!this.fileIngestPipelinesQueue.isEmpty()) {
582 FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
583 if (pipeline.isRunning()) {
584 errors.addAll(pipeline.shutDown());
587 if (!errors.isEmpty()) {
588 logIngestModuleErrors(errors);
594 synchronized (this.dataSourceIngestProgressLock) {
595 if (this.dataSourceIngestProgress != null) {
596 this.dataSourceIngestProgress.finish();
597 this.dataSourceIngestProgress = null;
603 synchronized (this.fileIngestProgressLock) {
604 if (this.fileIngestProgress != null) {
605 this.fileIngestProgress.finish();
606 this.fileIngestProgress = null;
614 if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
615 this.startSecondStage();
624 private void finish() {
625 logger.log(Level.INFO,
"Finished analysis for {0} (jobId={1})",
new Object[]{dataSource.getName(), this.id});
631 synchronized (this.dataSourceIngestProgressLock) {
632 if (this.dataSourceIngestProgress != null) {
633 this.dataSourceIngestProgress.finish();
634 this.dataSourceIngestProgress = null;
639 this.parentJob.dataSourceJobFinished(
this);
648 void process(DataSourceIngestTask task) {
650 synchronized (this.dataSourceIngestPipelineLock) {
651 if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
652 List<IngestModuleError> errors =
new ArrayList<>();
653 errors.addAll(this.currentDataSourceIngestPipeline.process(task));
654 if (!errors.isEmpty()) {
655 logIngestModuleErrors(errors);
665 synchronized (this.dataSourceIngestProgressLock) {
666 if (null != this.dataSourceIngestProgress) {
667 this.dataSourceIngestProgress.finish();
668 this.dataSourceIngestProgress = null;
674 DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
675 this.checkForStageCompleted();
690 void process(FileIngestTask task)
throws InterruptedException {
692 if (!this.isCancelled()) {
693 FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
694 if (!pipeline.isEmpty()) {
695 AbstractFile file = task.getFile();
697 synchronized (this.fileIngestProgressLock) {
698 ++this.processedFiles;
703 if (this.processedFiles <= this.estimatedFilesToProcess) {
704 this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
706 this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
708 this.filesInProgress.add(file.getName());
715 List<IngestModuleError> errors =
new ArrayList<>();
716 errors.addAll(pipeline.process(task));
717 if (!errors.isEmpty()) {
718 logIngestModuleErrors(errors);
721 if (this.doUI && !this.cancelled) {
722 synchronized (this.fileIngestProgressLock) {
727 this.filesInProgress.remove(file.getName());
728 if (this.filesInProgress.size() > 0) {
729 this.fileIngestProgress.progress(this.filesInProgress.get(0));
731 this.fileIngestProgress.progress(
"");
736 this.fileIngestPipelinesQueue.put(pipeline);
739 DataSourceIngestJob.taskScheduler.notifyTaskCompleted(task);
740 this.checkForStageCompleted();
751 void addFiles(List<AbstractFile> files) {
752 if (DataSourceIngestJob.Stages.FIRST ==
this.stage) {
753 for (AbstractFile file : files) {
754 DataSourceIngestJob.taskScheduler.scheduleFileIngestTask(
this, file);
757 DataSourceIngestJob.logger.log(Level.SEVERE,
"Adding files during second stage not supported");
766 this.checkForStageCompleted();
775 void updateDataSourceIngestProgressBarDisplayName(String displayName) {
776 if (this.doUI && !this.cancelled) {
777 synchronized (this.dataSourceIngestProgressLock) {
778 this.dataSourceIngestProgress.setDisplayName(displayName);
791 void switchDataSourceIngestProgressBarToDeterminate(
int workUnits) {
792 if (this.doUI && !this.cancelled) {
793 synchronized (this.dataSourceIngestProgressLock) {
794 if (null != this.dataSourceIngestProgress) {
795 this.dataSourceIngestProgress.switchToDeterminate(workUnits);
806 void switchDataSourceIngestProgressBarToIndeterminate() {
807 if (this.doUI && !this.cancelled) {
808 synchronized (this.dataSourceIngestProgressLock) {
809 if (null != this.dataSourceIngestProgress) {
810 this.dataSourceIngestProgress.switchToIndeterminate();
822 void advanceDataSourceIngestProgressBar(
int workUnits) {
823 if (this.doUI && !this.cancelled) {
824 synchronized (this.dataSourceIngestProgressLock) {
825 if (null != this.dataSourceIngestProgress) {
826 this.dataSourceIngestProgress.progress(
"", workUnits);
838 void advanceDataSourceIngestProgressBar(String currentTask) {
839 if (this.doUI && !this.cancelled) {
840 synchronized (this.dataSourceIngestProgressLock) {
841 if (null != this.dataSourceIngestProgress) {
842 this.dataSourceIngestProgress.progress(currentTask);
856 void advanceDataSourceIngestProgressBar(String currentTask,
int workUnits) {
857 if (this.doUI && !this.cancelled) {
858 synchronized (this.fileIngestProgressLock) {
859 this.dataSourceIngestProgress.progress(currentTask, workUnits);
871 boolean currentDataSourceIngestModuleIsCancelled() {
872 return this.currentDataSourceIngestModuleCancelled;
881 void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
882 this.currentDataSourceIngestModuleCancelled =
false;
883 this.cancelledDataSourceIngestModules.add(moduleDisplayName);
893 synchronized (this.dataSourceIngestProgressLock) {
894 this.dataSourceIngestProgress.finish();
895 this.dataSourceIngestProgress = null;
896 this.startDataSourceIngestProgressBar();
906 DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
907 if (null != this.currentDataSourceIngestPipeline) {
908 return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
918 void cancelCurrentDataSourceIngestModule() {
919 this.currentDataSourceIngestModuleCancelled =
true;
928 void cancel(IngestJob.CancellationReason reason) {
934 synchronized (this.dataSourceIngestProgressLock) {
935 if (dataSourceIngestProgress != null) {
936 final String displayName = NbBundle.getMessage(this.getClass(),
937 "IngestJob.progress.dataSourceIngest.initialDisplayName",
938 dataSource.getName());
939 dataSourceIngestProgress.setDisplayName(
940 NbBundle.getMessage(
this.getClass(),
941 "IngestJob.progress.cancelling",
950 synchronized (this.fileIngestProgressLock) {
951 if (this.fileIngestProgress != null) {
952 final String displayName = NbBundle.getMessage(this.getClass(),
953 "IngestJob.progress.fileIngest.displayName",
954 this.dataSource.getName());
955 this.fileIngestProgress.setDisplayName(
956 NbBundle.getMessage(
this.getClass(),
"IngestJob.progress.cancelling",
958 if (!this.currentFileIngestModule.isEmpty() && !this.currentFileIngestTask.isEmpty()) {
959 this.fileIngestProgress.progress(NbBundle.getMessage(
this.getClass(),
960 "IngestJob.progress.fileIngest.cancelMessage",
961 this.currentFileIngestModule, this.currentFileIngestTask));
972 if (Stages.FINALIZATION != stage) {
973 synchronized (cancellationStateMonitor) {
978 this.cancelled =
true;
979 this.cancellationReason = reason;
987 DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(
this);
988 this.checkForStageCompleted();
998 void setCurrentFileIngestModule(String moduleName, String taskName) {
999 this.currentFileIngestModule = moduleName;
1000 this.currentFileIngestTask = taskName;
1009 boolean isCancelled() {
1010 return this.cancelled;
1018 IngestJob.CancellationReason getCancellationReason() {
1019 return this.cancellationReason;
1027 private void logIngestModuleErrors(List<IngestModuleError> errors) {
1028 for (IngestModuleError error : errors) {
1029 DataSourceIngestJob.logger.log(Level.SEVERE, String.format(
"%s experienced an error analyzing %s (jobId=%d)", error.getModuleDisplayName(), dataSource.getName(), this.id), error.getModuleError());
1038 Snapshot getSnapshot(
boolean getIngestTasksSnapshot) {
1039 return new Snapshot(getIngestTasksSnapshot);
1045 final class Snapshot {
1047 private final String dataSource;
1048 private final long jobId;
1049 private final long jobStartTime;
1050 private final long snapShotTime;
1051 private final DataSourceIngestPipeline.PipelineModule dataSourceLevelIngestModule;
1052 private boolean fileIngestRunning;
1053 private Date fileIngestStartTime;
1054 private final long processedFiles;
1055 private final long estimatedFilesToProcess;
1056 private final IngestTasksScheduler.IngestJobTasksSnapshot tasksSnapshot;
1057 private final boolean jobCancelled;
1058 private final IngestJob.CancellationReason jobCancellationReason;
1059 private final List<String> cancelledDataSourceModules;
1065 Snapshot(
boolean getIngestTasksSnapshot) {
1066 this.dataSource = DataSourceIngestJob.this.dataSource.getName();
1067 this.jobId = DataSourceIngestJob.this.id;
1068 this.jobStartTime = DataSourceIngestJob.this.createTime;
1069 this.dataSourceLevelIngestModule = DataSourceIngestJob.this.getCurrentDataSourceIngestModule();
1076 for (FileIngestPipeline pipeline : DataSourceIngestJob.this.fileIngestPipelines) {
1077 if (pipeline.isRunning()) {
1078 this.fileIngestRunning =
true;
1080 Date pipelineStartTime = pipeline.getStartTime();
1081 if (null != pipelineStartTime && (null == this.fileIngestStartTime || pipelineStartTime.before(
this.fileIngestStartTime))) {
1082 this.fileIngestStartTime = pipelineStartTime;
1086 this.jobCancelled = cancelled;
1087 this.jobCancellationReason = cancellationReason;
1088 this.cancelledDataSourceModules =
new ArrayList<>(DataSourceIngestJob.this.cancelledDataSourceIngestModules);
1090 if (getIngestTasksSnapshot) {
1091 synchronized (DataSourceIngestJob.this.fileIngestProgressLock) {
1092 this.processedFiles = DataSourceIngestJob.this.processedFiles;
1093 this.estimatedFilesToProcess = DataSourceIngestJob.this.estimatedFilesToProcess;
1094 this.snapShotTime =
new Date().getTime();
1096 this.tasksSnapshot = DataSourceIngestJob.taskScheduler.getTasksSnapshotForJob(this.jobId);
1099 this.processedFiles = 0;
1100 this.estimatedFilesToProcess = 0;
1101 this.snapShotTime =
new Date().getTime();
1102 this.tasksSnapshot = null;
1112 long getSnapshotTime() {
1113 return snapShotTime;
1122 String getDataSource() {
1142 long getJobStartTime() {
1143 return jobStartTime;
1146 DataSourceIngestPipeline.PipelineModule getDataSourceLevelIngestModule() {
1147 return this.dataSourceLevelIngestModule;
1150 boolean fileIngestIsRunning() {
1151 return this.fileIngestRunning;
1154 Date fileIngestStartTime() {
1155 return this.fileIngestStartTime;
1165 return (
double) processedFiles / ((snapShotTime - jobStartTime) / 1000);
1173 long getFilesProcessed() {
1174 return processedFiles;
1183 long getFilesEstimated() {
1184 return estimatedFilesToProcess;
1187 long getRootQueueSize() {
1188 if (null == this.tasksSnapshot) {
1191 return this.tasksSnapshot.getRootQueueSize();
1194 long getDirQueueSize() {
1195 if (null == this.tasksSnapshot) {
1198 return this.tasksSnapshot.getDirectoryTasksQueueSize();
1201 long getFileQueueSize() {
1202 if (null == this.tasksSnapshot) {
1205 return this.tasksSnapshot.getFileQueueSize();
1208 long getDsQueueSize() {
1209 if (null == this.tasksSnapshot) {
1212 return this.tasksSnapshot.getDsQueueSize();
1215 long getRunningListSize() {
1216 if (null == this.tasksSnapshot) {
1219 return this.tasksSnapshot.getRunningListSize();
1222 boolean isCancelled() {
1223 return this.jobCancelled;
1231 IngestJob.CancellationReason getCancellationReason() {
1232 return this.jobCancellationReason;
1242 List<String> getCancelledDataSourceIngestModules() {
1243 return Collections.unmodifiableList(this.cancelledDataSourceModules);