/**
  * 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);
 }
 public static SPMAsyncTask construct(
     CommandCoordinator coco, AsyncTaskCreationInfo creationInfo, AsyncTask asyncTask) {
   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());
  }