Autopsy  4.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-2015 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.Content;
33 
40 public final class IngestJob {
41 
42  /*
43  * An ingest job can be cancelled for various reasons.
44  */
45  public enum CancellationReason {
46 
47  NOT_CANCELLED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.notCancelled.text")),
48  USER_CANCELLED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.cancelledByUser.text")),
49  INGEST_MODULES_STARTUP_FAILED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.ingestModStartFail.text")),
50  OUT_OF_DISK_SPACE(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.outOfDiskSpace.text")),
51  SERVICES_DOWN(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.servicesDown.text")),
52  CASE_CLOSED(NbBundle.getMessage(IngestJob.class, "IngestJob.cancelReason.caseClosed.text"));
53 
54  private final String displayName;
55 
56  private CancellationReason(String displayName) {
57  this.displayName = displayName;
58  }
59 
60  public String getDisplayName() {
61  return displayName;
62  }
63  }
64 
65  private static final AtomicLong nextId = new AtomicLong(0L);
66  private final long id;
67  private final Map<Long, DataSourceIngestJob> dataSourceJobs;
68  private final AtomicInteger incompleteJobsCount;
69  private boolean started;
70  private boolean cancelled;
72 
82  IngestJob(Collection<Content> dataSources, IngestJobSettings settings, boolean doUI) {
83  this.id = IngestJob.nextId.getAndIncrement();
84  this.dataSourceJobs = new ConcurrentHashMap<>();
85  for (Content dataSource : dataSources) {
86  DataSourceIngestJob dataSourceIngestJob = new DataSourceIngestJob(this, dataSource, settings, doUI);
87  this.dataSourceJobs.put(dataSourceIngestJob.getId(), dataSourceIngestJob);
88  }
89  incompleteJobsCount = new AtomicInteger(dataSourceJobs.size());
90  cancellationReason = CancellationReason.NOT_CANCELLED;
91  }
92 
98  public long getId() {
99  return this.id;
100  }
101 
109  boolean hasIngestPipeline() {
116  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
117  if (dataSourceJob.hasIngestPipeline()) {
118  return true;
119  }
120  }
121  return false;
122  }
123 
130  synchronized List<IngestModuleError> start() {
131  List<IngestModuleError> errors = new ArrayList<>();
132  if (started) {
133  errors.add(new IngestModuleError("IngestJob", new IllegalStateException("Job already started"))); //NON-NLS
134  return errors;
135  }
136  started = true;
137 
138  /*
139  * Try to start each data source ingest job. Note that there is a not
140  * unwarranted assumption here that if there is going to be a module
141  * startup failure, it will be for the first data source ingest job.
142  *
143  * TODO (RC): Consider separating module start up from pipeline startup
144  * so that no processing is done if this assumption is false.
145  */
146  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
147  errors.addAll(dataSourceJob.start());
148  if (errors.isEmpty() == false) {
149  break;
150  }
151  }
152 
153  /*
154  * Handle start up success or failure.
155  */
156  if (errors.isEmpty()) {
157  for (DataSourceIngestJob dataSourceJob : this.dataSourceJobs.values()) {
158  IngestManager.getInstance().fireDataSourceAnalysisStarted(id, dataSourceJob.getId(), dataSourceJob.getDataSource());
159  }
160  } else {
161  cancel(CancellationReason.INGEST_MODULES_STARTUP_FAILED);
162  }
163 
164  return errors;
165  }
166 
173  return new ProgressSnapshot(true);
174  }
175 
181  public ProgressSnapshot getSnapshot(boolean getIngestTasksSnapshot) {
182  return new ProgressSnapshot(getIngestTasksSnapshot);
183  }
184 
191  List<DataSourceIngestJob.Snapshot> getDataSourceIngestJobSnapshots() {
192  List<DataSourceIngestJob.Snapshot> snapshots = new ArrayList<>();
193  this.dataSourceJobs.values().stream().forEach((dataSourceJob) -> {
194  snapshots.add(dataSourceJob.getSnapshot(true));
195  });
196  return snapshots;
197  }
198 
207  @Deprecated
208  synchronized public void cancel() {
210  }
211 
220  synchronized public void cancel(CancellationReason reason) {
221  this.dataSourceJobs.values().stream().forEach((job) -> {
222  job.cancel(reason);
223  });
224  this.cancelled = true;
225  this.cancellationReason = reason;
226  }
227 
234  return this.cancellationReason;
235  }
236 
243  synchronized public boolean isCancelled() {
244  return this.cancelled;
245  }
246 
253  void dataSourceJobFinished(DataSourceIngestJob job) {
254  IngestManager ingestManager = IngestManager.getInstance();
255  if (!job.isCancelled()) {
256  ingestManager.fireDataSourceAnalysisCompleted(id, job.getId(), job.getDataSource());
257  } else {
258  IngestManager.getInstance().fireDataSourceAnalysisCancelled(id, job.getId(), job.getDataSource());
259  }
260  if (incompleteJobsCount.decrementAndGet() == 0) {
261  ingestManager.finishIngestJob(this);
262  }
263  }
264 
268  public final class ProgressSnapshot {
269 
270  private final List<DataSourceProcessingSnapshot> dataSourceProcessingSnapshots;
272  private boolean fileIngestRunning;
273  private Date fileIngestStartTime;
274  private final boolean jobCancelled;
276 
281  public final class DataSourceProcessingSnapshot {
282 
283  private final DataSourceIngestJob.Snapshot snapshot;
284 
285  private DataSourceProcessingSnapshot(DataSourceIngestJob.Snapshot snapshot) {
286  this.snapshot = snapshot;
287  }
288 
295  public String getDataSource() {
296  return snapshot.getDataSource();
297  }
298 
305  public boolean isCancelled() {
306  return snapshot.isCancelled();
307  }
308 
315  return snapshot.getCancellationReason();
316  }
317 
325  public List<String> getCancelledDataSourceIngestModules() {
326  return snapshot.getCancelledDataSourceIngestModules();
327  }
328 
329  }
330 
334  private ProgressSnapshot(boolean getIngestTasksSnapshot) {
335  dataSourceModule = null;
336  fileIngestRunning = false;
337  fileIngestStartTime = null;
338  dataSourceProcessingSnapshots = new ArrayList<>();
339  for (DataSourceIngestJob dataSourceJob : dataSourceJobs.values()) {
340  DataSourceIngestJob.Snapshot snapshot = dataSourceJob.getSnapshot(getIngestTasksSnapshot);
341  dataSourceProcessingSnapshots.add(new DataSourceProcessingSnapshot(snapshot));
342  if (null == dataSourceModule) {
343  DataSourceIngestPipeline.PipelineModule module = snapshot.getDataSourceLevelIngestModule();
344  if (null != module) {
345  dataSourceModule = new DataSourceIngestModuleHandle(dataSourceJobs.get(snapshot.getJobId()), module);
346  }
347  }
348  if (snapshot.fileIngestIsRunning()) {
349  fileIngestRunning = true;
350  }
351  Date childFileIngestStartTime = snapshot.fileIngestStartTime();
352  if (null != childFileIngestStartTime && (null == fileIngestStartTime || childFileIngestStartTime.before(fileIngestStartTime))) {
353  fileIngestStartTime = childFileIngestStartTime;
354  }
355  }
356  this.jobCancelled = cancelled;
358  }
359 
367  return this.dataSourceModule;
368  }
369 
376  public boolean fileIngestIsRunning() {
377  return this.fileIngestRunning;
378  }
379 
385  public Date fileIngestStartTime() {
386  return new Date(this.fileIngestStartTime.getTime());
387  }
388 
395  public boolean isCancelled() {
396  return this.jobCancelled;
397  }
398 
405  return this.jobCancellationReason;
406  }
407 
413  public List<DataSourceProcessingSnapshot> getDataSourceSnapshots() {
414  return Collections.unmodifiableList(this.dataSourceProcessingSnapshots);
415  }
416 
417  }
418 
424  public static class DataSourceIngestModuleHandle {
425 
426  private final DataSourceIngestJob job;
427  private final DataSourceIngestPipeline.PipelineModule module;
428  private final boolean cancelled;
429 
439  private DataSourceIngestModuleHandle(DataSourceIngestJob job, DataSourceIngestPipeline.PipelineModule module) {
440  this.job = job;
441  this.module = module;
442  this.cancelled = job.currentDataSourceIngestModuleIsCancelled();
443  }
444 
451  public String displayName() {
452  return this.module.getDisplayName();
453  }
454 
461  public Date startTime() {
462  return this.module.getProcessingStartTime();
463  }
464 
471  public boolean isCancelled() {
472  return this.cancelled;
473  }
474 
480  public void cancel() {
492  if (this.job.getCurrentDataSourceIngestModule() == this.module) {
493  this.job.cancelCurrentDataSourceIngestModule();
494  }
495  }
496 
497  }
498 
499 }
DataSourceIngestModuleHandle(DataSourceIngestJob job, DataSourceIngestPipeline.PipelineModule module)
Definition: IngestJob.java:439
static synchronized IngestManager getInstance()
final DataSourceIngestPipeline.PipelineModule module
Definition: IngestJob.java:427
final AtomicInteger incompleteJobsCount
Definition: IngestJob.java:68
final Map< Long, DataSourceIngestJob > dataSourceJobs
Definition: IngestJob.java:67
DataSourceIngestModuleHandle runningDataSourceIngestModule()
Definition: IngestJob.java:366
List< DataSourceProcessingSnapshot > getDataSourceSnapshots()
Definition: IngestJob.java:413
final IngestJob.CancellationReason jobCancellationReason
Definition: IngestJob.java:275
synchronized boolean isCancelled()
Definition: IngestJob.java:243
synchronized CancellationReason getCancellationReason()
Definition: IngestJob.java:404
static final AtomicLong nextId
Definition: IngestJob.java:65
synchronized void cancel(CancellationReason reason)
Definition: IngestJob.java:220
ProgressSnapshot(boolean getIngestTasksSnapshot)
Definition: IngestJob.java:334
synchronized CancellationReason getCancellationReason()
Definition: IngestJob.java:233
ProgressSnapshot getSnapshot(boolean getIngestTasksSnapshot)
Definition: IngestJob.java:181
final List< DataSourceProcessingSnapshot > dataSourceProcessingSnapshots
Definition: IngestJob.java:270

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.