Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
IngestJob.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.ingest;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.atomic.AtomicInteger;
29 import java.util.concurrent.atomic.AtomicLong;
30 
31 import org.openide.util.NbBundle;
32 import org.sleuthkit.datamodel.AbstractFile;
33 import org.sleuthkit.datamodel.Content;
34 
39 public final class IngestJob {
40 
41  /*
42  * An ingest job can be cancelled for various reasons.
43  */
44  public enum CancellationReason {
45 
46  NOT_CANCELLED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.notCancelled.text")),
47  USER_CANCELLED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.cancelledByUser.text")),
48  INGEST_MODULES_STARTUP_FAILED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.ingestModStartFail.text")),
49  OUT_OF_DISK_SPACE(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.outOfDiskSpace.text")),
50  SERVICES_DOWN(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.servicesDown.text")),
51  CASE_CLOSED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.caseClosed.text"));
52 
53  private final String displayName;
54 
55  private CancellationReason(String displayName) {
56  this.displayName = displayName;
57  }
58 
59  public String getDisplayName() {
60  return displayName;
61  }
62  }
63 
64  private final static AtomicLong nextId = new AtomicLong(0L);
65  private final long id;
66  private final Map<Long, DataSourceIngestJob> dataSourceJobs;
67  private final AtomicInteger incompleteJobsCount;
69 
79  IngestJob(Collection<Content> dataSources, IngestJobSettings settings, boolean doUI) {
80  this.id = IngestJob.nextId.getAndIncrement();
81  this.dataSourceJobs = new ConcurrentHashMap<>();
82  for (Content dataSource : dataSources) {
83  DataSourceIngestJob dataSourceIngestJob = new DataSourceIngestJob(this, dataSource, settings, doUI);
84  this.dataSourceJobs.put(dataSourceIngestJob.getId(), dataSourceIngestJob);
85  }
86  incompleteJobsCount = new AtomicInteger(dataSourceJobs.size());
87  cancellationReason = CancellationReason.NOT_CANCELLED;
88  }
89 
101  IngestJob(Content dataSource, List<AbstractFile> files, IngestJobSettings settings, boolean doUI) {
102  this.id = IngestJob.nextId.getAndIncrement();
103  this.dataSourceJobs = new ConcurrentHashMap<>();
104  DataSourceIngestJob dataSourceIngestJob = new DataSourceIngestJob(this, dataSource, files, settings, doUI);
105  this.dataSourceJobs.put(dataSourceIngestJob.getId(), dataSourceIngestJob);
106  incompleteJobsCount = new AtomicInteger(dataSourceJobs.size());
107  cancellationReason = CancellationReason.NOT_CANCELLED;
108  }
109 
115  public long getId() {
116  return this.id;
117  }
118 
126  boolean hasIngestPipeline() {
133  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
134  if (dataSourceJob.hasIngestPipeline()) {
135  return true;
136  }
137  }
138  return false;
139  }
140 
147  List<IngestModuleError> start() {
148  /*
149  * Try to start each data source ingest job. Note that there is a not
150  * unwarranted assumption here that if there is going to be a module
151  * startup failure, it will be for the first data source ingest job.
152  *
153  * TODO (RC): Consider separating module start up from pipeline startup
154  * so that no processing is done if this assumption is false.
155  */
156  List<IngestModuleError> errors = new ArrayList<>();
157  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
158  errors.addAll(dataSourceJob.start());
159  if (errors.isEmpty() == false) {
160  break;
161  }
162  }
163 
164  /*
165  * Handle start up success or failure.
166  */
167  if (errors.isEmpty()) {
168  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
169  IngestManager.getInstance().fireDataSourceAnalysisStarted(id, dataSourceJob.getId(), dataSourceJob.getDataSource());
170  }
171  } else {
172  cancel(CancellationReason.INGEST_MODULES_STARTUP_FAILED);
173  }
174 
175  return errors;
176  }
177 
184  return new ProgressSnapshot(true);
185  }
186 
192  public ProgressSnapshot getSnapshot(boolean getIngestTasksSnapshot) {
193  return new ProgressSnapshot(getIngestTasksSnapshot);
194  }
195 
202  List<DataSourceIngestJob.Snapshot> getDataSourceIngestJobSnapshots() {
203  List<DataSourceIngestJob.Snapshot> snapshots = new ArrayList<>();
204  this.dataSourceJobs.values().stream().forEach((dataSourceJob) -> {
205  snapshots.add(dataSourceJob.getSnapshot(true));
206  });
207  return snapshots;
208  }
209 
218  @Deprecated
219  public void cancel() {
221  }
222 
231  public void cancel(CancellationReason reason) {
232  this.cancellationReason = reason;
233  this.dataSourceJobs.values().stream().forEach((job) -> {
234  job.cancel(reason);
235  });
236  }
237 
244  return this.cancellationReason;
245  }
246 
253  public boolean isCancelled() {
254  return (CancellationReason.NOT_CANCELLED != this.cancellationReason);
255  }
256 
263  void dataSourceJobFinished(DataSourceIngestJob job) {
264  IngestManager ingestManager = IngestManager.getInstance();
265  if (!job.isCancelled()) {
266  ingestManager.fireDataSourceAnalysisCompleted(id, job.getId(), job.getDataSource());
267  } else {
268  IngestManager.getInstance().fireDataSourceAnalysisCancelled(id, job.getId(), job.getDataSource());
269  }
270  if (incompleteJobsCount.decrementAndGet() == 0) {
271  ingestManager.finishIngestJob(this);
272  }
273  }
274 
278  public final class ProgressSnapshot {
279 
280  private final List<DataSourceProcessingSnapshot> dataSourceProcessingSnapshots;
282  private boolean fileIngestRunning;
283  private Date fileIngestStartTime;
284  private final boolean jobCancelled;
286 
291  public final class DataSourceProcessingSnapshot {
292 
294 
296  this.snapshot = snapshot;
297  }
298 
305  public String getDataSource() {
306  return snapshot.getDataSource();
307  }
308 
315  public boolean isCancelled() {
316  return snapshot.isCancelled();
317  }
318 
325  return snapshot.getCancellationReason();
326  }
327 
335  public List<String> getCancelledDataSourceIngestModules() {
336  return snapshot.getCancelledDataSourceIngestModules();
337  }
338 
339  }
340 
344  private ProgressSnapshot(boolean getIngestTasksSnapshot) {
345  dataSourceModule = null;
346  fileIngestRunning = false;
347  fileIngestStartTime = null;
348  dataSourceProcessingSnapshots = new ArrayList<>();
349  for (DataSourceIngestJob dataSourceJob : dataSourceJobs.values()) {
350  DataSourceIngestJob.Snapshot snapshot = dataSourceJob.getSnapshot(getIngestTasksSnapshot);
351  dataSourceProcessingSnapshots.add(new DataSourceProcessingSnapshot(snapshot));
352  if (null == dataSourceModule) {
353  DataSourceIngestPipeline.PipelineModule module = snapshot.getDataSourceLevelIngestModule();
354  if (null != module) {
355  dataSourceModule = new DataSourceIngestModuleHandle(dataSourceJobs.get(snapshot.getJobId()), module);
356  }
357  }
358  if (snapshot.getFileIngestIsRunning()) {
359  fileIngestRunning = true;
360  }
361  Date childFileIngestStartTime = snapshot.getFileIngestStartTime();
362  if (null != childFileIngestStartTime && (null == fileIngestStartTime || childFileIngestStartTime.before(fileIngestStartTime))) {
363  fileIngestStartTime = childFileIngestStartTime;
364  }
365  }
366  this.jobCancelled = isCancelled();
368  }
369 
377  return this.dataSourceModule;
378  }
379 
386  public boolean fileIngestIsRunning() {
387  return this.fileIngestRunning;
388  }
389 
395  public Date fileIngestStartTime() {
396  return new Date(this.fileIngestStartTime.getTime());
397  }
398 
405  public boolean isCancelled() {
406  return this.jobCancelled;
407  }
408 
415  return this.jobCancellationReason;
416  }
417 
423  public List<DataSourceProcessingSnapshot> getDataSourceSnapshots() {
424  return Collections.unmodifiableList(this.dataSourceProcessingSnapshots);
425  }
426 
427  }
428 
434  public static class DataSourceIngestModuleHandle {
435 
436  private final DataSourceIngestJob job;
437  private final DataSourceIngestPipeline.PipelineModule module;
438  private final boolean cancelled;
439 
449  private DataSourceIngestModuleHandle(DataSourceIngestJob job, DataSourceIngestPipeline.PipelineModule module) {
450  this.job = job;
451  this.module = module;
452  this.cancelled = job.currentDataSourceIngestModuleIsCancelled();
453  }
454 
461  public String displayName() {
462  return this.module.getDisplayName();
463  }
464 
471  public Date startTime() {
472  return this.module.getProcessingStartTime();
473  }
474 
481  public boolean isCancelled() {
482  return this.cancelled;
483  }
484 
490  public void cancel() {
502  if (this.job.getCurrentDataSourceIngestModule() == this.module) {
503  this.job.cancelCurrentDataSourceIngestModule();
504  }
505  }
506 
507  }
508 
509 }
DataSourceIngestModuleHandle(DataSourceIngestJob job, DataSourceIngestPipeline.PipelineModule module)
Definition: IngestJob.java:449
static synchronized IngestManager getInstance()
final DataSourceIngestPipeline.PipelineModule module
Definition: IngestJob.java:437
final AtomicInteger incompleteJobsCount
Definition: IngestJob.java:67
void cancel(CancellationReason reason)
Definition: IngestJob.java:231
final Map< Long, DataSourceIngestJob > dataSourceJobs
Definition: IngestJob.java:66
DataSourceIngestModuleHandle runningDataSourceIngestModule()
Definition: IngestJob.java:376
List< DataSourceProcessingSnapshot > getDataSourceSnapshots()
Definition: IngestJob.java:423
final IngestJob.CancellationReason jobCancellationReason
Definition: IngestJob.java:285
CancellationReason getCancellationReason()
Definition: IngestJob.java:243
static final AtomicLong nextId
Definition: IngestJob.java:64
ProgressSnapshot(boolean getIngestTasksSnapshot)
Definition: IngestJob.java:344
volatile CancellationReason cancellationReason
Definition: IngestJob.java:68
ProgressSnapshot getSnapshot(boolean getIngestTasksSnapshot)
Definition: IngestJob.java:192
final List< DataSourceProcessingSnapshot > dataSourceProcessingSnapshots
Definition: IngestJob.java:280

Copyright © 2012-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.