Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
TaskRetryUtil.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020-2021 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.threadutils;
20 
21 import java.util.List;
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.ScheduledFuture;
25 import java.util.concurrent.ScheduledThreadPoolExecutor;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.TimeoutException;
28 import java.util.concurrent.atomic.AtomicLong;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31 
38 public class TaskRetryUtil {
39 
40  private static final AtomicLong totalTasks = new AtomicLong();
41  private static final AtomicLong totalTaskRetries = new AtomicLong();
42  private static final AtomicLong totalTaskAttemptTimeOuts = new AtomicLong();
43  private static final AtomicLong totalFailedTasks = new AtomicLong();
44 
49  public static class TaskAttempt {
50 
51  private final Long delay;
52  private final Long timeOut;
53  private final TimeUnit timeUnit;
54 
60  public TaskAttempt() {
61  this.delay = 0L;
62  this.timeOut = 0L;
63  this.timeUnit = TimeUnit.SECONDS;
64  }
65 
75  public TaskAttempt(Long delay, TimeUnit timeUnit) {
76  if (delay == null || delay < 0) {
77  throw new IllegalArgumentException(String.format("Argument for delay parameter = %d, must be zero or any positive integer", delay));
78  }
79  if (timeUnit == null) {
80  throw new IllegalArgumentException("Argument for timeUnit parameter is null");
81  }
82  this.delay = delay;
83  this.timeOut = 0L;
84  this.timeUnit = timeUnit;
85  }
86 
98  public TaskAttempt(Long delay, Long timeOut, TimeUnit timeUnit) {
99  if (delay == null || delay < 0) {
100  throw new IllegalArgumentException(String.format("Argument for delay parameter = %d, must be zero or any positive integer", delay));
101  }
102  if (timeOut == null || timeOut < 0) {
103  throw new IllegalArgumentException(String.format("Argument for timeOut parameter = %d, must be zero or any positive integer", delay));
104  }
105  if (timeUnit == null) {
106  throw new IllegalArgumentException("Argument for timeUnit parameter is null");
107  }
108  this.delay = delay;
109  this.timeOut = timeOut;
110  this.timeUnit = timeUnit;
111  }
112 
119  public Long getDelay() {
120  return delay;
121  }
122 
129  public Long getTimeout() {
130  return timeOut;
131  }
132 
139  public TimeUnit getTimeUnit() {
140  return timeUnit;
141  }
142 
143  }
144 
149  public interface Terminator {
150 
157  boolean stopTaskAttempts();
158 
159  }
160 
183  public static <T> T attemptTask(Callable<T> task, List<TaskAttempt> attempts, ScheduledThreadPoolExecutor executor, Terminator terminator, Logger logger, String taskDesc) throws InterruptedException {
184  /*
185  * Attempt the task.
186  */
187  T result = null;
188  String taskDescForLog = taskDesc != null ? taskDesc : "Task";
189  int attemptCounter = 0;
190  if (attempts.size() > 0) {
191  totalTasks.incrementAndGet();
192  }
193  while (result == null && attemptCounter < attempts.size()) {
194  if (terminator != null && terminator.stopTaskAttempts()) {
195  if (logger != null) {
196  logger.log(Level.WARNING, String.format("Attempts to execute '%s' terminated ", taskDescForLog));
197  }
198  break;
199  }
200  TaskAttempt attempt = attempts.get(attemptCounter);
201  if (attemptCounter > 0) {
202  totalTaskRetries.incrementAndGet();
203  }
204  ScheduledFuture<T> future = executor.schedule(task, attempt.getDelay(), attempt.getTimeUnit());
205  try {
206  result = future.get(attempt.getDelay() + attempt.getTimeout(), attempt.getTimeUnit());
207  } catch (InterruptedException ex) {
208  if (logger != null) {
209  logger.log(Level.SEVERE, String.format("Interrupted executing '%s'", taskDescForLog), ex);
210  }
211  throw ex;
212  } catch (ExecutionException ex) {
213  if (logger != null) {
214  logger.log(Level.SEVERE, String.format("Error executing '%s'", taskDescForLog), ex);
215  }
216  } catch (TimeoutException ex) {
217  if (logger != null) {
218  logger.log(Level.SEVERE, String.format("Time out executing '%s'", taskDescForLog), ex);
219  }
220  totalTaskAttemptTimeOuts.incrementAndGet();
221  future.cancel(true);
222  }
223  ++attemptCounter;
224  }
225 
226  /*
227  * If the task required more than one attempt, log it.
228  */
229  if (logger != null && attemptCounter > 1) {
230  if (result != null) {
231  logger.log(Level.WARNING, String.format("'%s' succeeded after %d attempts", taskDescForLog, attemptCounter));
232  } else {
233  logger.log(Level.SEVERE, String.format("'%s' failed after %d attempts", taskDescForLog, attemptCounter));
234  }
235  }
236 
237  /*
238  * If the task failed, count it as a failed task.
239  */
240  if (result == null) {
241  if (terminator == null || !terminator.stopTaskAttempts()) {
242  totalFailedTasks.incrementAndGet();
243  }
244  }
245 
246  return result;
247  }
248 
254  public static long getTotalTasksCount() {
255  return totalTasks.get();
256  }
257 
263  public static long getTotalTaskRetriesCount() {
264  return totalTaskRetries.get();
265  }
266 
272  public static long getTotalTaskAttemptTimeOutsCount() {
273  return totalTaskAttemptTimeOuts.get();
274  }
275 
282  public static long getTotalFailedTasksCount() {
283  return totalFailedTasks.get();
284  }
285 
289  private TaskRetryUtil() {
290  }
291 
292 }
static< T > T attemptTask(Callable< T > task, List< TaskAttempt > attempts, ScheduledThreadPoolExecutor executor, Terminator terminator, Logger logger, String taskDesc)
TaskAttempt(Long delay, Long timeOut, TimeUnit timeUnit)

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.