private static CommandEntity getCommandEntity(CommandCoordinator coco, Guid cmdId) {
   CommandEntity cmdEntity = coco.getCommandEntity(cmdId);
   if (cmdEntity == null) {
     cmdEntity =
         coco.createCommandEntity(cmdId, VdcActionType.Unknown, new VdcActionParametersBase());
   }
   return cmdEntity;
 }
  /**
   * Call VDSCommand for each pool id fetched from poolsOfActiveTasks , and Initialize a map with
   * each storage pool Id task statuses.
   *
   * @param poolsOfActiveTasks - Set of all the active tasks fetched from _tasks.
   * @return poolsAsyncTaskMap - Map which contains tasks for each storage pool id.
   */
  private Map<Guid, Map<Guid, AsyncTaskStatus>> getSPMsTasksStatuses(Set<Guid> poolsOfActiveTasks) {
    Map<Guid, Map<Guid, AsyncTaskStatus>> poolsAsyncTaskMap = new HashMap<>();

    // For each pool Id (SPM) ,add its tasks to the map.
    for (Guid storagePoolID : poolsOfActiveTasks) {
      try {
        Map<Guid, AsyncTaskStatus> map = coco.getAllTasksStatuses(storagePoolID);
        if (map != null) {
          poolsAsyncTaskMap.put(storagePoolID, map);
        }
      } catch (RuntimeException e) {
        if ((e instanceof EngineException)
            && (((EngineException) e).getErrorCode() == EngineError.VDS_NETWORK_ERROR)) {
          log.debug(
              "Get SPM task statuses: Calling Command {}VDSCommand, "
                  + "with storagePoolId '{}') threw an exception.",
              VDSCommandType.SPMGetAllTasksStatuses,
              storagePoolID);
        } else {
          log.debug(
              "Get SPM task statuses: Calling Command {}VDSCommand, "
                  + "with storagePoolId '{}') threw an exception: {}",
              VDSCommandType.SPMGetAllTasksStatuses,
              storagePoolID,
              e.getMessage());
        }
        log.debug("Exception", e);
      }
    }

    return poolsAsyncTaskMap;
  }
 public void logAndFailPartiallySubmittedTaskOfCommand(final AsyncTask task, String message) {
   log.info(
       "Failing partially submitted task AsyncTaskType '{}': Task '{}' Parent Command '{}'",
       task.getTaskType(),
       task.getTaskId(),
       task.getActionType());
   task.getTaskParameters().setTaskGroupSuccess(false);
   if (task.getActionType() == VdcActionType.Unknown) {
     removeTaskFromDbByTaskId(task.getTaskId());
     log.info(
         "Not calling endAction for partially submitted task and AsyncTaskType '{}': Task '{}' Parent Command '{}'",
         task.getTaskType(),
         task.getTaskId(),
         task.getActionType());
     return;
   }
   log.info(
       "Calling updateTask for partially submitted task and AsyncTaskType '{}': Task '{}' Parent Command"
           + " '{}' Parameters class '{}'",
       task.getTaskType(),
       task.getTaskId(),
       task.getActionType());
   AsyncTaskCreationInfo creationInfo =
       new AsyncTaskCreationInfo(Guid.Empty, task.getTaskType(), task.getStoragePoolId());
   SPMTask spmTask = coco.construct(creationInfo, task);
   AsyncTaskStatus failureStatus = new AsyncTaskStatus();
   failureStatus.setStatus(AsyncTaskStatusEnum.finished);
   failureStatus.setResult(AsyncTaskResultEnum.failure);
   failureStatus.setMessage(message);
   spmTask.setState(AsyncTaskState.Ended);
   spmTask.setLastTaskStatus(failureStatus);
   spmTask.updateTask(failureStatus);
 }
 // NOTE - any change to the logic here and in the async tasks managed command requires inspection
 // of
 // CommandExecutor.handleUnmanagedCommands()
 public void initAsyncTaskManager() {
   tasksInDbAfterRestart = new ConcurrentHashMap<>();
   Map<Guid, List<AsyncTask>> rootCommandIdToTasksMap =
       groupTasksByRootCommandId(coco.getAllAsyncTasksFromDb());
   int numberOfCommandsPartiallyExecuted = 0;
   for (Entry<Guid, List<AsyncTask>> entry : rootCommandIdToTasksMap.entrySet()) {
     if (isPartiallyExecutedCommand(rootCommandIdToTasksMap.get(entry.getKey()))) {
       log.info("Root Command '{}' has partially executed task.", entry.getKey());
       numberOfCommandsPartiallyExecuted++;
     }
   }
   irsBrokerLatch = new CountDownLatch(numberOfCommandsPartiallyExecuted);
   for (Entry<Guid, List<AsyncTask>> entry : rootCommandIdToTasksMap.entrySet()) {
     if (isPartiallyExecutedCommand(rootCommandIdToTasksMap.get(entry.getKey()))) {
       log.info("Root Command '{}' has partially executed tasks.", entry.getKey());
       handlePartiallyExecuteTasksOfCommand(rootCommandIdToTasksMap.get(entry.getKey()));
     }
     for (AsyncTask task : entry.getValue()) {
       if (!isPartiallyExecutedTask(task)) {
         tasksInDbAfterRestart.putIfAbsent(task.getStoragePoolId(), new ArrayList<>());
         tasksInDbAfterRestart.get(task.getStoragePoolId()).add(task);
       }
     }
   }
   try {
     irsBrokerLatch.await();
     log.info("Initialization of AsyncTaskManager completed successfully.");
   } catch (InterruptedException e) {
   }
 }
 /**
  * Constructs a task based on creation info (task type and task parameters as retrieved from the
  * vdsm). Use in order to construct tasks when service is initializing.
  *
  * @param coco Handle to command coordinator
  * @param creationInfo The Asyc Task Creation info
  */
 public static SPMAsyncTask construct(
     CommandCoordinator coco, AsyncTaskCreationInfo creationInfo) {
   AsyncTask asyncTask = coco.getByVdsmTaskId(creationInfo.getVdsmTaskId());
   if (asyncTask == null || asyncTask.getActionParameters() == null) {
     asyncTask =
         new AsyncTask(
             AsyncTaskResultEnum.success,
             AsyncTaskStatusEnum.running,
             Guid.Empty,
             creationInfo.getVdsmTaskId(),
             creationInfo.getStepId(),
             creationInfo.getStoragePoolID(),
             creationInfo.getTaskType(),
             getCommandEntity(
                 coco, asyncTask == null ? Guid.newGuid() : asyncTask.getRootCommandId()),
             getCommandEntity(
                 coco, asyncTask == null ? Guid.newGuid() : asyncTask.getCommandId()));
     creationInfo.setTaskType(AsyncTaskType.unknown);
   }
   AsyncTaskParameters asyncTaskParams = new AsyncTaskParameters(creationInfo, asyncTask);
   return construct(coco, creationInfo.getTaskType(), asyncTaskParams, true);
 }
  /**
   * Retrieves from the specified storage pool the tasks that exist on it and adds them to the
   * manager.
   *
   * @param sp the storage pool to retrieve running tasks from
   */
  public void addStoragePoolExistingTasks(StoragePool sp) {
    List<AsyncTaskCreationInfo> currPoolTasks = null;
    try {
      currPoolTasks = coco.getAllTasksInfo(sp.getId());
    } catch (RuntimeException e) {
      log.error(
          "Getting existing tasks on Storage Pool '{}' failed: {}", sp.getName(), e.getMessage());
      log.debug("Exception", e);
    }

    if (currPoolTasks != null && currPoolTasks.size() > 0) {
      synchronized (this) {
        final List<SPMTask> newlyAddedTasks = new ArrayList<>();

        for (AsyncTaskCreationInfo creationInfo : currPoolTasks) {
          creationInfo.setStoragePoolID(sp.getId());
          if (!_tasks.containsKey(creationInfo.getVdsmTaskId())) {
            try {
              SPMTask task;
              if (partiallyCompletedCommandTasks.containsKey(creationInfo.getVdsmTaskId())) {
                AsyncTask asyncTaskInDb =
                    partiallyCompletedCommandTasks.get(creationInfo.getVdsmTaskId());
                task = coco.construct(creationInfo, asyncTaskInDb);
                if (task.getEntitiesMap() == null) {
                  task.setEntitiesMap(new HashMap<>());
                }
                partiallyCompletedCommandTasks.remove(task.getVdsmTaskId());
                // mark it as a task of a partially completed command
                // Will result in failure of the command
                task.setPartiallyCompletedCommandTask(true);
              } else {
                task = coco.construct(creationInfo);
              }
              addTaskToManager(task);
              newlyAddedTasks.add(task);
            } catch (Exception e) {
              log.error(
                  "Failed to load task of type '{}' with id '{}': {}.",
                  creationInfo.getTaskType(),
                  creationInfo.getVdsmTaskId(),
                  ExceptionUtils.getRootCauseMessage(e));
              log.debug("Exception", e);
            }
          }
        }

        TransactionSupport.executeInNewTransaction(
            () -> {
              for (SPMTask task : newlyAddedTasks) {
                AsyncTaskUtils.addOrUpdateTaskInDB(task);
              }
              return null;
            });

        for (SPMTask task : newlyAddedTasks) {
          startPollingTask(task.getVdsmTaskId());
        }

        log.info(
            "Discovered {} tasks on Storage Pool '{}', {} added to manager.",
            currPoolTasks.size(),
            sp.getName(),
            newlyAddedTasks.size());
      }
    } else {
      log.info("Discovered no tasks on Storage Pool '{}'", sp.getName());
    }

    List<AsyncTask> tasksInDForStoragePool = tasksInDbAfterRestart.get(sp.getId());
    if (tasksInDForStoragePool != null) {
      for (AsyncTask task : tasksInDForStoragePool) {
        if (!_tasks.containsKey(task.getVdsmTaskId())) {
          coco.removeByVdsmTaskId(task.getVdsmTaskId());
        }
      }
    }

    // Either the tasks were only in DB - so they were removed from db, or they are polled -
    // in any case no need to hold them in the map that represents the tasksInDbAfterRestart
    tasksInDbAfterRestart.remove(sp.getId());
  }
 public SPMTask createTask(AsyncTaskType taskType, AsyncTaskParameters taskParameters) {
   return coco.construct(taskType, taskParameters, false);
 }
 public void logAndFailTaskOfCommandWithEmptyVdsmId(Guid asyncTaskId, String message) {
   AsyncTask task = coco.getAsyncTaskFromDb(asyncTaskId);
   if (task != null) {
     logAndFailPartiallySubmittedTaskOfCommand(task, message);
   }
 }