19package org.sleuthkit.autopsy.modules.embeddedfileextractor;
21import com.google.common.util.concurrent.ThreadFactoryBuilder;
23import java.io.IOException;
24import java.util.ArrayList;
26import java.util.concurrent.Callable;
27import java.util.concurrent.ScheduledThreadPoolExecutor;
28import java.util.concurrent.TimeUnit;
29import org.sleuthkit.autopsy.apputils.ApplicationLoggers;
30import java.util.logging.Logger;
31import org.sleuthkit.autopsy.ingest.IngestJobContext;
32import org.sleuthkit.autopsy.threadutils.TaskRetryUtil;
52class 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;
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) {
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();
222 return context.fileIngestIsCancelled();
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);