Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileTaskExecutor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 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.modules.embeddedfileextractor;
20 
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.ScheduledThreadPoolExecutor;
28 import java.util.concurrent.TimeUnit;
30 import java.util.logging.Logger;
33 
52 class FileTaskExecutor {
53 
54  private static final int MIN_THREADS_IN_POOL = 4;
55  private static final int MAX_THREADS_IN_POOL = Integer.MAX_VALUE; // Effectively no limit
56  private static final String FILE_IO_TASK_THREAD_NAME = "file-io-executor-task-%d";
57  private static final String FILE_EXISTS_TASK_DESC_FMT_STR = "Checking if %s already exists";
58  private static final String MKDIRS_TASK_DESC_FMT_STR = "Making directory %s";
59  private static final String NEW_FILE_TASK_DESC_FMT_STR = "Creating new file %s";
60  private static final String FILE_OPS_LOG_NAME = "efe_file_ops";
61  private static final Logger logger = ApplicationLoggers.getLogger(FILE_OPS_LOG_NAME);
62  private final ScheduledThreadPoolExecutor executor;
63  private final TaskTerminator terminator;
64 
88  FileTaskExecutor(IngestJobContext context) {
89  executor = new ScheduledThreadPoolExecutor(MIN_THREADS_IN_POOL, new ThreadFactoryBuilder().setNameFormat(FILE_IO_TASK_THREAD_NAME).build());
90  executor.setMaximumPoolSize(MAX_THREADS_IN_POOL);
91  if (context != null) {
92  terminator = new TaskTerminator(context);
93  } else {
94  terminator = null;
95  }
96  }
97 
111  boolean exists(final File file) throws FileTaskFailedException, InterruptedException {
112  Callable<Boolean> task = () -> {
113  return file.exists();
114  };
115  return attemptTask(task, String.format(FILE_EXISTS_TASK_DESC_FMT_STR, file.getPath()));
116  }
117 
131  boolean mkdirs(final File file) throws FileTaskFailedException, InterruptedException {
132  Callable<Boolean> task = () -> {
133  return file.mkdirs();
134  };
135  return attemptTask(task, String.format(MKDIRS_TASK_DESC_FMT_STR, file.getPath()));
136  }
137 
150  boolean createNewFile(final File file) throws FileTaskFailedException, InterruptedException {
151  Callable<Boolean> task = () -> {
152  return file.createNewFile();
153  };
154  return attemptTask(task, String.format(NEW_FILE_TASK_DESC_FMT_STR, file.getPath()));
155  }
156 
169  private boolean attemptTask(Callable<Boolean> task, String taskDesc) throws FileTaskFailedException, InterruptedException {
170  List<TaskRetryUtil.TaskAttempt> attempts = new ArrayList<>();
171  attempts.add(new TaskRetryUtil.TaskAttempt(0L, 10L, TimeUnit.MINUTES));
172  attempts.add(new TaskRetryUtil.TaskAttempt(5L, 10L, TimeUnit.MINUTES));
173  attempts.add(new TaskRetryUtil.TaskAttempt(10L, 10L, TimeUnit.MINUTES));
174  attempts.add(new TaskRetryUtil.TaskAttempt(15L, 10L, TimeUnit.MINUTES));
175  Boolean success = TaskRetryUtil.attemptTask(task, attempts, executor, terminator, logger, taskDesc);
176  if (success == null) {
177  throw new FileTaskFailedException(taskDesc + " failed");
178  }
179  return success;
180  }
181 
188  void shutDown() {
189  /*
190  * Not waiting for task terminaton because some tasks may never
191  * terminate. See class doc.
192  */
193  executor.shutdownNow();
194  }
195 
200  private static class TaskTerminator implements TaskRetryUtil.Terminator {
201 
202  private final IngestJobContext context;
203 
212  this.context = context;
213  }
214 
215  @Override
216  public boolean stopTaskAttempts() {
217  /*
218  * This works because IngestJobContext.fileIngestIsCancelled() calls
219  * IngestJobPipeline.isCancelled(), which returns the value of a
220  * volatile variable.
221  */
222  return context.fileIngestIsCancelled();
223  }
224  }
225 
229  static final class FileTaskFailedException extends Exception {
230 
231  private static final long serialVersionUID = 1L;
232 
238  private FileTaskFailedException(String message) {
239  super(message);
240  }
241 
248  private FileTaskFailedException(String message, Throwable cause) {
249  super(message, cause);
250  }
251  }
252 
253 }

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.