19 package org.sleuthkit.autopsy.modules.embeddedfileextractor;
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
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;
52 class FileTaskExecutor {
54 private static final int MIN_THREADS_IN_POOL = 4;
55 private static final int MAX_THREADS_IN_POOL = Integer.MAX_VALUE;
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;
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);
111 boolean exists(
final File file)
throws FileTaskFailedException, InterruptedException {
112 Callable<Boolean> task = () -> {
113 return file.exists();
115 return attemptTask(task, String.format(FILE_EXISTS_TASK_DESC_FMT_STR, file.getPath()));
131 boolean mkdirs(
final File file)
throws FileTaskFailedException, InterruptedException {
132 Callable<Boolean> task = () -> {
133 return file.mkdirs();
135 return attemptTask(task, String.format(MKDIRS_TASK_DESC_FMT_STR, file.getPath()));
150 boolean createNewFile(
final File file)
throws FileTaskFailedException, InterruptedException {
151 Callable<Boolean> task = () -> {
152 return file.createNewFile();
154 return attemptTask(task, String.format(NEW_FILE_TASK_DESC_FMT_STR, file.getPath()));
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");
193 executor.shutdownNow();
229 static final class FileTaskFailedException
extends Exception {
231 private static final long serialVersionUID = 1L;
238 private FileTaskFailedException(String message) {
248 private FileTaskFailedException(String message, Throwable cause) {
249 super(message, cause);
boolean fileIngestIsCancelled()