Пример #1
0
  /**
   * Return recall tasks for being taken over. The status of the tasks that are returned is set to
   * in progress.
   *
   * @param input a key value pair in which the value is the number of results to be returned in the
   * @return the tasks ready to takeover
   * @throws TapeRecallException
   */
  @PUT
  @Consumes("text/plain")
  @Produces("text/plain")
  public Response putTakeoverTasks(InputStream input) throws TapeRecallException {

    // retrieve the Input String
    String inputStr = buildInputString(input);

    log.debug("@PUT (input string) = '{}'", inputStr);

    // retrieve the number of tasks to takeover (default = 1)
    int numbOfTask = 1;

    // retrieve value from Body param
    String keyTakeover = config.getTaskoverKey();

    int eqIndex = inputStr.indexOf('=');

    if (eqIndex > 0) {

      String value = inputStr.substring(eqIndex);
      String key = inputStr.substring(0, eqIndex);

      if (key.equals(keyTakeover)) {

        try {

          // trim out the '\n' end.
          numbOfTask = Integer.valueOf(value.substring(1, value.length() - 1));

        } catch (NumberFormatException e) {

          throw new TapeRecallException(
              "Unable to understand " + "the number value = '" + value + "'");
        }
      }
    }

    // retrieve the tasks
    ArrayList<TapeRecallTO> tasks = new TapeRecallCatalog().takeoverNTasksWithDoubles(numbOfTask);

    HashMap<UUID, ArrayList<TapeRecallTO>> groupTaskMap = buildGroupTaskMap(tasks);

    ArrayList<TapeRecallTO> groupTasks = new ArrayList<TapeRecallTO>();

    for (ArrayList<TapeRecallTO> groupTaskList : groupTaskMap.values()) {

      try {

        groupTasks.add(makeOne(groupTaskList));

      } catch (IllegalArgumentException e) {

        log.error(
            "Unable to makeOne the task list . IllegalArgumentException : {}", e.getMessage(), e);
        log.error("Erroneous task list (long output): {}", groupTaskList.toString());
        log.error("Skip the erroneous task list and go on...Please contact StoRM support");
      }
    }

    if (tasks.size() > groupTasks.size()) {

      log.debug("Taking over some multy-group tasks");
    }

    log.debug(
        "Number of tasks recalled : <{}> over <{}> tasks requested",
        groupTasks.size(),
        tasks.size());

    // need a generic entity
    GenericEntity<List<TapeRecallTO>> entity = new GenericEntity<List<TapeRecallTO>>(tasks) {};

    return Response.ok(entity).build();
  }
Пример #2
0
/** @author zappi */
@Path("/recalltable/tasks")
public class TasksResource {

  private static final Logger log = LoggerFactory.getLogger(TasksResource.class);

  private static Configuration config = Configuration.getInstance();

  /**
   * Return recall tasks for being taken over. The status of the tasks that are returned is set to
   * in progress.
   *
   * @param input a key value pair in which the value is the number of results to be returned in the
   * @return the tasks ready to takeover
   * @throws TapeRecallException
   */
  @PUT
  @Consumes("text/plain")
  @Produces("text/plain")
  public Response putTakeoverTasks(InputStream input) throws TapeRecallException {

    // retrieve the Input String
    String inputStr = buildInputString(input);

    log.debug("@PUT (input string) = '{}'", inputStr);

    // retrieve the number of tasks to takeover (default = 1)
    int numbOfTask = 1;

    // retrieve value from Body param
    String keyTakeover = config.getTaskoverKey();

    int eqIndex = inputStr.indexOf('=');

    if (eqIndex > 0) {

      String value = inputStr.substring(eqIndex);
      String key = inputStr.substring(0, eqIndex);

      if (key.equals(keyTakeover)) {

        try {

          // trim out the '\n' end.
          numbOfTask = Integer.valueOf(value.substring(1, value.length() - 1));

        } catch (NumberFormatException e) {

          throw new TapeRecallException(
              "Unable to understand " + "the number value = '" + value + "'");
        }
      }
    }

    // retrieve the tasks
    ArrayList<TapeRecallTO> tasks = new TapeRecallCatalog().takeoverNTasksWithDoubles(numbOfTask);

    HashMap<UUID, ArrayList<TapeRecallTO>> groupTaskMap = buildGroupTaskMap(tasks);

    ArrayList<TapeRecallTO> groupTasks = new ArrayList<TapeRecallTO>();

    for (ArrayList<TapeRecallTO> groupTaskList : groupTaskMap.values()) {

      try {

        groupTasks.add(makeOne(groupTaskList));

      } catch (IllegalArgumentException e) {

        log.error(
            "Unable to makeOne the task list . IllegalArgumentException : {}", e.getMessage(), e);
        log.error("Erroneous task list (long output): {}", groupTaskList.toString());
        log.error("Skip the erroneous task list and go on...Please contact StoRM support");
      }
    }

    if (tasks.size() > groupTasks.size()) {

      log.debug("Taking over some multy-group tasks");
    }

    log.debug(
        "Number of tasks recalled : <{}> over <{}> tasks requested",
        groupTasks.size(),
        tasks.size());

    // need a generic entity
    GenericEntity<List<TapeRecallTO>> entity = new GenericEntity<List<TapeRecallTO>>(tasks) {};

    return Response.ok(entity).build();
  }

  /**
   * Creates a map with the taskIds as keys and the list of tasks related to each taskId (key) as
   * value
   *
   * @param tasks
   * @return
   */
  private HashMap<UUID, ArrayList<TapeRecallTO>> buildGroupTaskMap(ArrayList<TapeRecallTO> tasks) {

    HashMap<UUID, ArrayList<TapeRecallTO>> groupTaskMap =
        new HashMap<UUID, ArrayList<TapeRecallTO>>();

    for (TapeRecallTO task : tasks) {

      ArrayList<TapeRecallTO> taskList = groupTaskMap.get(task.getGroupTaskId());

      if (taskList == null) {

        taskList = new ArrayList<TapeRecallTO>();
        groupTaskMap.put(task.getGroupTaskId(), taskList);
      }

      taskList.add(task);
    }

    return groupTaskMap;
  }

  /**
   * Given a list of tasks with the same taskId oproduces a single task merging the list members
   *
   * @param recallTasks
   * @return
   */
  private TapeRecallTO makeOne(ArrayList<TapeRecallTO> recallTasks)
      throws IllegalArgumentException {

    TapeRecallTO taskTO = new TapeRecallTO();

    UUID taskId = recallTasks.get(0).getTaskId();

    // verify that all have the same task id
    for (TapeRecallTO recallTask : recallTasks) {

      if (!recallTask.getTaskId().equals(taskId)) {

        log.error(
            "Received a list of not omogeneous tasks, the taskid '{}' is not matched by : {}",
            taskId,
            recallTask.toString());

        throw new IllegalArgumentException("Received a list of not omogeneous tasks");
      }
    }

    for (TapeRecallTO recallTask : recallTasks) {

      // set common fields from any of the tasks
      taskTO.setTaskId(recallTask.getTaskId());
      taskTO.setGroupTaskId(recallTask.getGroupTaskId());
      taskTO.setRequestToken(recallTask.getRequestToken());
      taskTO.setRequestType(recallTask.getRequestType());
      taskTO.setFileName(recallTask.getFileName());
      taskTO.setUserID(recallTask.getUserID());
      taskTO.setVoName(recallTask.getVoName());
      taskTO.setStatus(TapeRecallStatus.QUEUED);

      break;
    }

    /*
     * merge task on recall related fields to have a pin that starts as soon as
     * requested and last as long as needed
     */

    int maxRetryAttempt = 0;

    Date minInsertionInstant = null;
    Date minDeferredRecallInstant = null;
    Date maxPinExpirationInstant = null;

    for (TapeRecallTO recallTask : recallTasks) {

      if (recallTask.getRetryAttempt() > maxRetryAttempt) {
        maxRetryAttempt = recallTask.getRetryAttempt();
      }

      if (minInsertionInstant == null
          || recallTask.getInsertionInstant().before(minInsertionInstant)) {

        minInsertionInstant = recallTask.getInsertionInstant();
      }

      if (minDeferredRecallInstant == null
          || recallTask.getDeferredRecallInstant().before(minDeferredRecallInstant)) {

        minDeferredRecallInstant = recallTask.getDeferredRecallInstant();
      }

      Date currentPinExpirationInstant =
          new Date(
              recallTask.getDeferredRecallInstant().getTime()
                  + (recallTask.getPinLifetime() * 1000));

      if (maxPinExpirationInstant == null
          || currentPinExpirationInstant.after(maxPinExpirationInstant)) {

        maxPinExpirationInstant = currentPinExpirationInstant;
      }
    }

    taskTO.setRetryAttempt(maxRetryAttempt);
    taskTO.setInsertionInstant(minInsertionInstant);
    taskTO.setDeferredRecallInstant(minDeferredRecallInstant);

    int pinLifeTime =
        (int) (maxPinExpirationInstant.getTime() - minDeferredRecallInstant.getTime()) / 1000;

    taskTO.setPinLifetime(pinLifeTime);

    return taskTO;
  }

  /** Utility method. */
  private String buildInputString(InputStream input) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(input));

    StringBuilder sb = new StringBuilder();

    String line = null;

    try {

      while ((line = reader.readLine()) != null) {

        sb.append(line + "\n");
      }

    } catch (IOException e) {

      e.printStackTrace();

    } finally {

      try {

        input.close();

      } catch (IOException e) {

        e.printStackTrace();
      }
    }

    String inputStr = sb.toString();

    return inputStr;
  }
}