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.LinkedHashMap;
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 java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import java.util.stream.Stream;
34 import javax.swing.JOptionPane;
35 import org.netbeans.api.progress.ProgressHandle;
36 import org.openide.util.Cancellable;
37 import org.openide.util.NbBundle;
38 import org.openide.windows.WindowManager;
48 import org.
sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
50 import org.
sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
60 final class IngestJobPipeline {
62 private static String AUTOPSY_MODULE_PREFIX =
"org.sleuthkit.autopsy";
64 private static final Logger logger = Logger.getLogger(IngestJobPipeline.class.getName());
67 private static final Pattern JYTHON_REGEX = Pattern.compile(
"org\\.python\\.proxies\\.(.+?)\\$(.+?)(\\$[0-9]*)?$");
75 private final IngestJob parentJob;
76 private static final AtomicLong nextJobId =
new AtomicLong(0L);
77 private final long id;
78 private final IngestJobSettings settings;
79 private Content dataSource = null;
80 private final IngestJob.Mode ingestMode;
81 private final List<AbstractFile> files =
new ArrayList<>();
112 private final Object stageCompletionCheckLock =
new Object();
122 private final Object dataSourceIngestPipelineLock =
new Object();
123 private DataSourceIngestPipeline firstStageDataSourceIngestPipeline;
124 private DataSourceIngestPipeline secondStageDataSourceIngestPipeline;
125 private DataSourceIngestPipeline currentDataSourceIngestPipeline;
134 private final LinkedBlockingQueue<FileIngestPipeline> fileIngestPipelinesQueue =
new LinkedBlockingQueue<>();
135 private final List<FileIngestPipeline> fileIngestPipelines =
new ArrayList<>();
148 private volatile boolean currentDataSourceIngestModuleCancelled;
149 private final List<String> cancelledDataSourceIngestModules =
new CopyOnWriteArrayList<>();
150 private volatile boolean cancelled;
157 private static final IngestTasksScheduler taskScheduler = IngestTasksScheduler.getInstance();
163 private final boolean doUI;
169 private final Object dataSourceIngestProgressLock =
new Object();
170 private ProgressHandle dataSourceIngestProgress;
176 private final Object fileIngestProgressLock =
new Object();
177 private final List<String> filesInProgress =
new ArrayList<>();
178 private long estimatedFilesToProcess;
179 private long processedFiles;
180 private ProgressHandle fileIngestProgress;
181 private String currentFileIngestModule =
"";
182 private String currentFileIngestTask =
"";
183 private final List<IngestModuleInfo> ingestModules =
new ArrayList<>();
184 private volatile IngestJobInfo ingestJob;
189 private final long createTime;
201 this(parentJob, dataSource, Collections.emptyList(), settings);
216 this.parentJob = parentJob;
217 this.
id = IngestJobPipeline.nextJobId.getAndIncrement();
218 this.dataSource = dataSource;
219 this.files.addAll(files);
220 this.ingestMode = parentJob.getIngestMode();
221 this.settings = settings;
223 this.createTime =
new Date().getTime();
225 this.createIngestPipelines();
238 private static void addOrdered(
final List<IngestModuleTemplate> dest,
239 final Map<String, IngestModuleTemplate> src,
final Map<String, IngestModuleTemplate> jythonSrc) {
241 final List<IngestModuleTemplate> autopsyModules =
new ArrayList<>();
242 final List<IngestModuleTemplate> thirdPartyModules =
new ArrayList<>();
244 Stream.concat(src.entrySet().stream(), jythonSrc.entrySet().stream()).forEach((templateEntry) -> {
245 if (templateEntry.getKey().startsWith(AUTOPSY_MODULE_PREFIX)) {
246 autopsyModules.add(templateEntry.getValue());
248 thirdPartyModules.add(templateEntry.getValue());
252 dest.addAll(autopsyModules);
253 dest.addAll(thirdPartyModules);
266 private static String getJythonName(String canonicalName) {
267 Matcher m = JYTHON_REGEX.matcher(canonicalName);
269 return String.format(
"%s.%s", m.group(1), m.group(2));
284 private static void addModule(Map<String, IngestModuleTemplate> mapping,
285 Map<String, IngestModuleTemplate> jythonMapping, IngestModuleTemplate
template) {
287 String className =
template.getModuleFactory().getClass().getCanonicalName();
288 String jythonName = getJythonName(className);
289 if (jythonName != null) {
290 jythonMapping.put(jythonName,
template);
292 mapping.put(className,
template);
299 private void createIngestPipelines() {
305 Map<String, IngestModuleTemplate> dataSourceModuleTemplates =
new LinkedHashMap<>();
306 Map<String, IngestModuleTemplate> fileModuleTemplates =
new LinkedHashMap<>();
309 Map<String, IngestModuleTemplate> jythonDataSourceModuleTemplates =
new LinkedHashMap<>();
310 Map<String, IngestModuleTemplate> jythonFileModuleTemplates =
new LinkedHashMap<>();
312 for (IngestModuleTemplate
template : ingestModuleTemplates) {
313 if (
template.isDataSourceIngestModuleTemplate()) {
314 addModule(dataSourceModuleTemplates, jythonDataSourceModuleTemplates,
template);
316 if (
template.isFileIngestModuleTemplate()) {
317 addModule(fileModuleTemplates, jythonFileModuleTemplates,
template);
325 IngestPipelinesConfiguration pipelineConfigs = IngestPipelinesConfiguration.getInstance();
326 List<IngestModuleTemplate> firstStageDataSourceModuleTemplates = IngestJobPipeline.getConfiguredIngestModuleTemplates(
327 dataSourceModuleTemplates, jythonDataSourceModuleTemplates, pipelineConfigs.getStageOneDataSourceIngestPipelineConfig());
329 List<IngestModuleTemplate> fileIngestModuleTemplates = IngestJobPipeline.getConfiguredIngestModuleTemplates(
330 fileModuleTemplates, jythonFileModuleTemplates, pipelineConfigs.getFileIngestPipelineConfig());
332 List<IngestModuleTemplate> secondStageDataSourceModuleTemplates = IngestJobPipeline.getConfiguredIngestModuleTemplates(
333 dataSourceModuleTemplates, null, pipelineConfigs.getStageTwoDataSourceIngestPipelineConfig());
340 addOrdered(firstStageDataSourceModuleTemplates, dataSourceModuleTemplates, jythonDataSourceModuleTemplates);
341 addOrdered(fileIngestModuleTemplates, fileModuleTemplates, jythonFileModuleTemplates);
346 this.firstStageDataSourceIngestPipeline =
new DataSourceIngestPipeline(
this, firstStageDataSourceModuleTemplates);
347 this.secondStageDataSourceIngestPipeline =
new DataSourceIngestPipeline(
this, secondStageDataSourceModuleTemplates);
353 int numberOfFileIngestThreads = IngestManager.getInstance().getNumberOfFileIngestThreads();
354 for (
int i = 0; i < numberOfFileIngestThreads; ++i) {
355 FileIngestPipeline pipeline =
new FileIngestPipeline(
this, fileIngestModuleTemplates);
356 this.fileIngestPipelinesQueue.put(pipeline);
357 this.fileIngestPipelines.add(pipeline);
359 }
catch (InterruptedException ex) {
365 Thread.currentThread().interrupt();
368 SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
369 this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
370 this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
371 this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
372 }
catch (TskCoreException | NoCurrentCaseException ex) {
373 logErrorMessage(Level.WARNING,
"Failed to add ingest modules listing to case database", ex);
377 private void addIngestModules(List<IngestModuleTemplate> templates, IngestModuleType type, SleuthkitCase skCase)
throws TskCoreException {
378 for (IngestModuleTemplate module : templates) {
379 ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
403 private static List<IngestModuleTemplate> getConfiguredIngestModuleTemplates(
404 Map<String, IngestModuleTemplate> ingestModuleTemplates, Map<String, IngestModuleTemplate> jythonIngestModuleTemplates, List<String> pipelineConfig) {
405 List<IngestModuleTemplate> templates =
new ArrayList<>();
406 for (String moduleClassName : pipelineConfig) {
407 if (ingestModuleTemplates != null && ingestModuleTemplates.containsKey(moduleClassName)) {
408 templates.add(ingestModuleTemplates.remove(moduleClassName));
409 }
else if (jythonIngestModuleTemplates != null && jythonIngestModuleTemplates.containsKey(moduleClassName)) {
410 templates.add(jythonIngestModuleTemplates.remove(moduleClassName));
430 String getExecutionContext() {
439 Content getDataSource() {
440 return this.dataSource;
449 boolean shouldProcessUnallocatedSpace() {
458 FilesSet getFileIngestFilter() {
467 boolean hasIngestPipeline() {
468 return this.hasFirstStageDataSourceIngestPipeline()
469 || this.hasFileIngestPipeline()
470 || this.hasSecondStageDataSourceIngestPipeline();
479 private boolean hasFirstStageDataSourceIngestPipeline() {
480 return (this.firstStageDataSourceIngestPipeline.isEmpty() ==
false);
489 private boolean hasSecondStageDataSourceIngestPipeline() {
490 return (this.secondStageDataSourceIngestPipeline.isEmpty() ==
false);
498 private boolean hasFileIngestPipeline() {
499 if (!this.fileIngestPipelines.isEmpty()) {
500 return !this.fileIngestPipelines.get(0).isEmpty();
510 List<IngestModuleError> start() {
511 if (dataSource == null) {
513 throw new IllegalStateException(
"Ingest started before setting data source");
515 List<IngestModuleError> errors = startUpIngestPipelines();
516 if (errors.isEmpty()) {
518 this.ingestJob = Case.getCurrentCaseThrows().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules,
new Date(this.createTime),
new Date(0), IngestJobStatusType.STARTED,
"");
519 }
catch (TskCoreException | NoCurrentCaseException ex) {
520 logErrorMessage(Level.WARNING,
"Failed to add ingest job info to case database", ex);
523 if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
524 if (ingestMode == IngestJob.Mode.BATCH) {
525 logInfoMessage(
"Starting first stage analysis");
526 this.startFirstStage();
528 logInfoMessage(
"Preparing for first stage analysis");
529 this.startFileIngestStreaming();
531 }
else if (this.hasSecondStageDataSourceIngestPipeline()) {
532 logInfoMessage(
"Starting second stage analysis");
533 this.startSecondStage();
545 private List<IngestModuleError> startUpIngestPipelines() {
546 List<IngestModuleError> errors =
new ArrayList<>();
551 errors.addAll(this.firstStageDataSourceIngestPipeline.startUp());
552 errors.addAll(this.secondStageDataSourceIngestPipeline.startUp());
559 if (errors.isEmpty()) {
560 for (FileIngestPipeline pipeline : this.fileIngestPipelinesQueue) {
561 errors.addAll(pipeline.startUp());
562 if (!errors.isEmpty()) {
568 while (!this.fileIngestPipelinesQueue.isEmpty()) {
569 FileIngestPipeline startedPipeline = this.fileIngestPipelinesQueue.poll();
570 if (startedPipeline.isRunning()) {
571 List<IngestModuleError> shutDownErrors = startedPipeline.shutDown();
572 if (!shutDownErrors.isEmpty()) {
578 logIngestModuleErrors(shutDownErrors);
593 private void startFirstStage() {
596 if (this.hasFileIngestPipeline()) {
597 synchronized (this.fileIngestProgressLock) {
598 this.estimatedFilesToProcess = this.dataSource.accept(
new GetFilesCountVisitor());
606 if (this.hasFirstStageDataSourceIngestPipeline()) {
607 this.startDataSourceIngestProgressBar();
609 if (this.hasFileIngestPipeline()) {
610 this.startFileIngestProgressBar();
618 synchronized (this.dataSourceIngestPipelineLock) {
619 this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
625 if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
626 logInfoMessage(
"Scheduling first stage data source and file level analysis tasks");
627 IngestJobPipeline.taskScheduler.scheduleIngestTasks(
this);
628 }
else if (this.hasFirstStageDataSourceIngestPipeline()) {
629 logInfoMessage(
"Scheduling first stage data source level analysis tasks");
630 IngestJobPipeline.taskScheduler.scheduleDataSourceIngestTask(
this);
632 logInfoMessage(
"Scheduling file level analysis tasks, no first stage data source level analysis configured");
633 IngestJobPipeline.taskScheduler.scheduleFileIngestTasks(
this, this.files);
643 this.checkForStageCompleted();
651 private void startFileIngestStreaming() {
652 synchronized (this.stageCompletionCheckLock) {
656 if (this.hasFileIngestPipeline()) {
657 synchronized (this.fileIngestProgressLock) {
658 this.estimatedFilesToProcess = 0;
663 if (this.hasFileIngestPipeline()) {
664 this.startFileIngestProgressBar();
668 logInfoMessage(
"Waiting for streaming files");
675 private void startDataSourceIngestStreaming() {
679 synchronized (fileIngestProgressLock) {
680 if (null != this.fileIngestProgress) {
681 estimatedFilesToProcess = dataSource.accept(
new GetFilesCountVisitor());
682 fileIngestProgress.switchToDeterminate((
int) estimatedFilesToProcess);
690 if (this.hasFirstStageDataSourceIngestPipeline()) {
691 this.startDataSourceIngestProgressBar();
699 synchronized (this.dataSourceIngestPipelineLock) {
700 this.currentDataSourceIngestPipeline = this.firstStageDataSourceIngestPipeline;
703 logInfoMessage(
"Scheduling first stage data source level analysis tasks");
704 synchronized (this.stageCompletionCheckLock) {
706 IngestJobPipeline.taskScheduler.scheduleDataSourceIngestTask(
this);
713 private void startSecondStage() {
714 logInfoMessage(
"Starting second stage analysis");
717 this.startDataSourceIngestProgressBar();
719 synchronized (this.dataSourceIngestPipelineLock) {
720 this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
722 logInfoMessage(
"Scheduling second stage data source level analysis tasks");
723 IngestJobPipeline.taskScheduler.scheduleDataSourceIngestTask(
this);
729 private void startDataSourceIngestProgressBar() {
731 synchronized (this.dataSourceIngestProgressLock) {
732 String displayName = NbBundle.getMessage(this.getClass(),
733 "IngestJob.progress.dataSourceIngest.initialDisplayName",
734 this.dataSource.getName());
735 this.dataSourceIngestProgress = ProgressHandle.createHandle(displayName,
new Cancellable() {
737 public boolean cancel() {
744 DataSourceIngestCancellationPanel panel =
new DataSourceIngestCancellationPanel();
745 String dialogTitle = NbBundle.getMessage(IngestJobPipeline.this.getClass(),
"IngestJob.cancellationDialog.title");
746 JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), panel, dialogTitle, JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE);
747 if (panel.cancelAllDataSourceIngestModules()) {
748 IngestJobPipeline.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
750 IngestJobPipeline.this.cancelCurrentDataSourceIngestModule();
755 this.dataSourceIngestProgress.start();
756 this.dataSourceIngestProgress.switchToIndeterminate();
764 private void startFileIngestProgressBar() {
766 synchronized (this.fileIngestProgressLock) {
767 String displayName = NbBundle.getMessage(this.getClass(),
768 "IngestJob.progress.fileIngest.displayName",
769 this.dataSource.getName());
770 this.fileIngestProgress = ProgressHandle.createHandle(displayName,
new Cancellable() {
772 public boolean cancel() {
777 IngestJobPipeline.this.cancel(IngestJob.CancellationReason.USER_CANCELLED);
781 this.fileIngestProgress.start();
782 this.fileIngestProgress.switchToDeterminate((
int) this.estimatedFilesToProcess);
791 private void checkForStageCompleted() {
792 if (ingestMode == IngestJob.Mode.BATCH) {
793 checkForStageCompletedBatch();
795 checkForStageCompletedStreaming();
803 private void checkForStageCompletedBatch() {
804 synchronized (this.stageCompletionCheckLock) {
805 if (IngestJobPipeline.taskScheduler.currentTasksAreCompleted(
this)) {
806 switch (this.stage) {
807 case FIRST_STAGE_FILES_AND_DATASOURCE:
808 this.finishFirstStage();
822 private void checkForStageCompletedStreaming() {
823 synchronized (this.stageCompletionCheckLock) {
824 if (IngestJobPipeline.taskScheduler.currentTasksAreCompleted(
this)) {
825 switch (this.stage) {
826 case FIRST_STAGE_FILES_ONLY:
829 case FIRST_STAGE_FILES_AND_DATASOURCE:
831 this.finishFirstStage();
845 private void finishFirstStage() {
846 logInfoMessage(
"Finished first stage analysis");
851 List<IngestModuleError> errors =
new ArrayList<>();
852 while (!this.fileIngestPipelinesQueue.isEmpty()) {
853 FileIngestPipeline pipeline = fileIngestPipelinesQueue.poll();
854 if (pipeline.isRunning()) {
855 errors.addAll(pipeline.shutDown());
858 if (!errors.isEmpty()) {
859 logIngestModuleErrors(errors);
865 synchronized (this.dataSourceIngestProgressLock) {
866 if (this.dataSourceIngestProgress != null) {
867 this.dataSourceIngestProgress.finish();
868 this.dataSourceIngestProgress = null;
874 synchronized (this.fileIngestProgressLock) {
875 if (this.fileIngestProgress != null) {
876 this.fileIngestProgress.finish();
877 this.fileIngestProgress = null;
885 if (!this.cancelled && this.hasSecondStageDataSourceIngestPipeline()) {
886 this.startSecondStage();
895 private void finish() {
896 logInfoMessage(
"Finished analysis");
902 synchronized (this.dataSourceIngestProgressLock) {
903 if (this.dataSourceIngestProgress != null) {
904 this.dataSourceIngestProgress.finish();
905 this.dataSourceIngestProgress = null;
909 if (ingestJob != null) {
910 if (this.cancelled) {
912 ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
913 }
catch (TskCoreException ex) {
914 logErrorMessage(Level.WARNING,
"Failed to update ingest job status in case database", ex);
918 ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
919 }
catch (TskCoreException ex) {
920 logErrorMessage(Level.WARNING,
"Failed to update ingest job status in case database", ex);
924 this.ingestJob.setEndDateTime(
new Date());
925 }
catch (TskCoreException ex) {
926 logErrorMessage(Level.WARNING,
"Failed to set job end date in case database", ex);
929 this.parentJob.ingestJobPipelineFinished(
this);
938 void process(DataSourceIngestTask task) {
940 synchronized (this.dataSourceIngestPipelineLock) {
941 if (!this.isCancelled() && !this.currentDataSourceIngestPipeline.isEmpty()) {
942 List<IngestModuleError> errors =
new ArrayList<>();
943 errors.addAll(this.currentDataSourceIngestPipeline.process(task));
944 if (!errors.isEmpty()) {
945 logIngestModuleErrors(errors);
955 synchronized (this.dataSourceIngestProgressLock) {
956 if (null != this.dataSourceIngestProgress) {
957 this.dataSourceIngestProgress.finish();
958 this.dataSourceIngestProgress = null;
964 IngestJobPipeline.taskScheduler.notifyTaskCompleted(task);
965 this.checkForStageCompleted();
980 void process(FileIngestTask task)
throws InterruptedException {
982 if (!this.isCancelled()) {
983 FileIngestPipeline pipeline = this.fileIngestPipelinesQueue.take();
984 if (!pipeline.isEmpty()) {
987 file = task.getFile();
988 }
catch (TskCoreException ex) {
991 List<IngestModuleError> errors =
new ArrayList<>();
992 errors.add(
new IngestModuleError(
"Ingest Job Pipeline", ex));
993 logIngestModuleErrors(errors);
994 this.fileIngestPipelinesQueue.put(pipeline);
998 synchronized (this.fileIngestProgressLock) {
999 ++this.processedFiles;
1004 if (this.processedFiles <= this.estimatedFilesToProcess) {
1005 this.fileIngestProgress.progress(file.getName(), (int) this.processedFiles);
1007 this.fileIngestProgress.progress(file.getName(), (int) this.estimatedFilesToProcess);
1009 this.filesInProgress.add(file.getName());
1016 List<IngestModuleError> errors =
new ArrayList<>();
1017 errors.addAll(pipeline.process(task));
1018 if (!errors.isEmpty()) {
1019 logIngestModuleErrors(errors);
1022 if (this.doUI && !this.cancelled) {
1023 synchronized (this.fileIngestProgressLock) {
1028 this.filesInProgress.remove(file.getName());
1029 if (this.filesInProgress.size() > 0) {
1030 this.fileIngestProgress.progress(this.filesInProgress.get(0));
1032 this.fileIngestProgress.progress(
"");
1037 this.fileIngestPipelinesQueue.put(pipeline);
1040 IngestJobPipeline.taskScheduler.notifyTaskCompleted(task);
1041 this.checkForStageCompleted();
1051 void addStreamingIngestFiles(List<Long> fileObjIds) {
1054 if (!hasFileIngestPipeline()) {
1058 if (stage.equals(Stages.FIRST_STAGE_FILES_ONLY)) {
1059 IngestJobPipeline.taskScheduler.scheduleStreamedFileIngestTasks(
this, fileObjIds);
1061 logErrorMessage(Level.SEVERE,
"Adding streaming files to job during stage " + stage.toString() +
" not supported");
1069 void processStreamingIngestDataSource() {
1070 startDataSourceIngestStreaming();
1071 checkForStageCompleted();
1081 void addFiles(List<AbstractFile> files) {
1082 if (stage.equals(Stages.FIRST_STAGE_FILES_ONLY)
1083 || stage.equals(Stages.FIRST_STAGE_FILES_AND_DATASOURCE)) {
1084 IngestJobPipeline.taskScheduler.fastTrackFileIngestTasks(
this, files);
1086 logErrorMessage(Level.SEVERE,
"Adding files to job during second stage analysis not supported");
1095 this.checkForStageCompleted();
1104 void updateDataSourceIngestProgressBarDisplayName(String displayName) {
1105 if (this.doUI && !this.cancelled) {
1106 synchronized (this.dataSourceIngestProgressLock) {
1107 this.dataSourceIngestProgress.setDisplayName(displayName);
1120 void switchDataSourceIngestProgressBarToDeterminate(
int workUnits) {
1121 if (this.doUI && !this.cancelled) {
1122 synchronized (this.dataSourceIngestProgressLock) {
1123 if (null != this.dataSourceIngestProgress) {
1124 this.dataSourceIngestProgress.switchToDeterminate(workUnits);
1135 void switchDataSourceIngestProgressBarToIndeterminate() {
1136 if (this.doUI && !this.cancelled) {
1137 synchronized (this.dataSourceIngestProgressLock) {
1138 if (null != this.dataSourceIngestProgress) {
1139 this.dataSourceIngestProgress.switchToIndeterminate();
1151 void advanceDataSourceIngestProgressBar(
int workUnits) {
1152 if (this.doUI && !this.cancelled) {
1153 synchronized (this.dataSourceIngestProgressLock) {
1154 if (null != this.dataSourceIngestProgress) {
1155 this.dataSourceIngestProgress.progress(
"", workUnits);
1167 void advanceDataSourceIngestProgressBar(String currentTask) {
1168 if (this.doUI && !this.cancelled) {
1169 synchronized (this.dataSourceIngestProgressLock) {
1170 if (null != this.dataSourceIngestProgress) {
1171 this.dataSourceIngestProgress.progress(currentTask);
1185 void advanceDataSourceIngestProgressBar(String currentTask,
int workUnits) {
1186 if (this.doUI && !this.cancelled) {
1187 synchronized (this.fileIngestProgressLock) {
1188 this.dataSourceIngestProgress.progress(currentTask, workUnits);
1200 boolean currentDataSourceIngestModuleIsCancelled() {
1201 return this.currentDataSourceIngestModuleCancelled;
1210 void currentDataSourceIngestModuleCancellationCompleted(String moduleDisplayName) {
1211 this.currentDataSourceIngestModuleCancelled =
false;
1212 this.cancelledDataSourceIngestModules.add(moduleDisplayName);
1222 synchronized (this.dataSourceIngestProgressLock) {
1223 this.dataSourceIngestProgress.finish();
1224 this.dataSourceIngestProgress = null;
1225 this.startDataSourceIngestProgressBar();
1235 DataSourceIngestPipeline.PipelineModule getCurrentDataSourceIngestModule() {
1236 if (null != this.currentDataSourceIngestPipeline) {
1237 return this.currentDataSourceIngestPipeline.getCurrentlyRunningModule();
1247 void cancelCurrentDataSourceIngestModule() {
1248 this.currentDataSourceIngestModuleCancelled =
true;
1257 void cancel(IngestJob.CancellationReason reason) {
1258 this.cancelled =
true;
1259 this.cancellationReason = reason;
1260 IngestJobPipeline.taskScheduler.cancelPendingTasksForIngestJob(
this);
1263 synchronized (this.dataSourceIngestProgressLock) {
1264 if (null != dataSourceIngestProgress) {
1265 dataSourceIngestProgress.setDisplayName(NbBundle.getMessage(
this.getClass(),
"IngestJob.progress.dataSourceIngest.initialDisplayName", this.dataSource.getName()));
1266 dataSourceIngestProgress.progress(NbBundle.getMessage(
this.getClass(),
"IngestJob.progress.cancelling"));
1270 synchronized (this.fileIngestProgressLock) {
1271 if (null != this.fileIngestProgress) {
1272 this.fileIngestProgress.setDisplayName(NbBundle.getMessage(
this.getClass(),
"IngestJob.progress.fileIngest.displayName", this.dataSource.getName()));
1273 this.fileIngestProgress.progress(NbBundle.getMessage(
this.getClass(),
"IngestJob.progress.cancelling"));
1279 checkForStageCompleted();
1289 void setCurrentFileIngestModule(String moduleName, String taskName) {
1290 this.currentFileIngestModule = moduleName;
1291 this.currentFileIngestTask = taskName;
1300 boolean isCancelled() {
1301 return this.cancelled;
1309 IngestJob.CancellationReason getCancellationReason() {
1310 return this.cancellationReason;
1319 private void logInfoMessage(String message) {
1320 logger.log(Level.INFO, String.format(
"%s (data source = %s, objId = %d, pipeline id = %d, ingest job id = %d)", message,
this.dataSource.getName(), this.dataSource.getId(), id, ingestJob.getIngestJobId()));
1331 private void logErrorMessage(Level level, String message, Throwable throwable) {
1332 logger.log(level, String.format(
"%s (data source = %s, objId = %d, pipeline id = %d, ingest job id = %d)", message,
this.dataSource.getName(), this.dataSource.getId(), id, ingestJob.getIngestJobId()), throwable);
1342 private void logErrorMessage(Level level, String message) {
1343 logger.log(level, String.format(
"%s (data source = %s, objId = %d, pipeline id = %d, ingest job id %d)", message,
this.dataSource.getName(), this.dataSource.getId(), id, ingestJob.getIngestJobId()));
1351 private void logIngestModuleErrors(List<IngestModuleError> errors) {
1352 for (IngestModuleError error : errors) {
1353 logErrorMessage(Level.SEVERE, String.format(
"%s experienced an error during analysis", error.getModuleDisplayName()), error.getThrowable());
1362 Snapshot getSnapshot(
boolean getIngestTasksSnapshot) {
1368 boolean fileIngestRunning =
false;
1369 Date fileIngestStartTime = null;
1371 for (FileIngestPipeline pipeline : this.fileIngestPipelines) {
1372 if (pipeline.isRunning()) {
1373 fileIngestRunning =
true;
1375 Date pipelineStartTime = pipeline.getStartTime();
1376 if (null != pipelineStartTime && (null == fileIngestStartTime || pipelineStartTime.before(fileIngestStartTime))) {
1377 fileIngestStartTime = pipelineStartTime;
1381 long processedFilesCount = 0;
1382 long estimatedFilesToProcessCount = 0;
1383 long snapShotTime =
new Date().getTime();
1384 IngestJobTasksSnapshot tasksSnapshot = null;
1386 if (getIngestTasksSnapshot) {
1387 synchronized (fileIngestProgressLock) {
1388 processedFilesCount = this.processedFiles;
1389 estimatedFilesToProcessCount = this.estimatedFilesToProcess;
1390 snapShotTime =
new Date().getTime();
1392 tasksSnapshot = IngestJobPipeline.taskScheduler.getTasksSnapshotForJob(
id);
1396 return new Snapshot(this.dataSource.getName(), id, createTime,
1397 getCurrentDataSourceIngestModule(), fileIngestRunning, fileIngestStartTime,
1398 cancelled, cancellationReason, cancelledDataSourceIngestModules,
1399 processedFilesCount, estimatedFilesToProcessCount, snapShotTime, tasksSnapshot);
static boolean runningWithGUI
List< IngestModuleTemplate > getEnabledIngestModuleTemplates()
String getExecutionContext()
FIRST_STAGE_FILES_AND_DATASOURCE
boolean getProcessUnallocatedSpace()