package org.ovirt.engine.core.bll; import java.util.ArrayList; import java.util.HashMap; import org.ovirt.engine.core.bll.tasks.AsyncTaskState; import org.ovirt.engine.core.bll.tasks.CommandAsyncTask; import org.ovirt.engine.core.common.asynctasks.EndedTaskInfo; import org.ovirt.engine.core.common.asynctasks.EndedTasksInfo; import org.ovirt.engine.core.common.businessentities.AsyncTaskStatusEnum; import org.ovirt.engine.core.compat.Guid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CommandMultiAsyncTasks { private static final Logger log = LoggerFactory.getLogger(CommandMultiAsyncTasks.class); private HashMap<Guid, CommandAsyncTask> _listTasks; private Guid commandId; public Guid getCommandId() { return commandId; } private void setCommandId(Guid value) { commandId = value; } public CommandMultiAsyncTasks(Guid commandId) { _listTasks = new HashMap<>(); setCommandId(commandId); } public void attachTask(CommandAsyncTask asyncTask) { synchronized (_listTasks) { if (!_listTasks.containsKey(asyncTask.getVdsmTaskId())) { log.info("CommandMultiAsyncTasks::attachTask: Attaching task '{}' to command '{}'.", asyncTask.getVdsmTaskId(), getCommandId()); _listTasks.put(asyncTask.getVdsmTaskId(), asyncTask); } } } private ArrayList<CommandAsyncTask> getCurrentTasks() { ArrayList<CommandAsyncTask> retValue = new ArrayList<>(); for (CommandAsyncTask task : _listTasks.values()) { if (task.getParameters() != null && task.getParameters().getDbAsyncTask() != null && (task.getState() == AsyncTaskState.Polling || task.getState() == AsyncTaskState.Ended || task .getState() == AsyncTaskState.AttemptingEndAction)) { retValue.add(task); } } return retValue; } public boolean shouldEndAction() { synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); for (CommandAsyncTask task : CurrentActionTypeTasks) { // Check this is a task that is run on VDSM and is not in ENDED state. if (task.getState() != AsyncTaskState.Ended && !Guid.isNullOrEmpty(task.getVdsmTaskId())) { log.info("Task with DB Task ID '{}' and VDSM Task ID '{}' is in state {}. End action for command" + " {} will proceed when all the entity's tasks are completed.", task.getParameters().getDbAsyncTask().getTaskId(), task.getVdsmTaskId(), task.getState(), getCommandId()); return false; } else if (Guid.isNullOrEmpty(task.getVdsmTaskId())) { log.info("Task with DB task ID '{}' has empty vdsm task ID and is about to be cleared", task.getVdsmTaskId()); } } } return true; } public void markAllWithAttemptingEndAction() { synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); for (CommandAsyncTask task : CurrentActionTypeTasks) { task.setState(AsyncTaskState.AttemptingEndAction); } } } public EndedTasksInfo getEndedTasksInfo() { EndedTasksInfo endedTasksInfo = new EndedTasksInfo(); ArrayList<EndedTaskInfo> endedTaskInfoList = new ArrayList<>(); synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); for (CommandAsyncTask task : CurrentActionTypeTasks) { task.setLastStatusAccessTime(); EndedTaskInfo tempVar = new EndedTaskInfo(); tempVar.setTaskStatus(task.getLastTaskStatus()); tempVar.setTaskParameters(task.getParameters()); endedTaskInfoList.add(tempVar); } endedTasksInfo.setTasksInfo(endedTaskInfoList); } return endedTasksInfo; } public int getTasksCountCurrentActionType() { int returnValue = 0; synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); returnValue = CurrentActionTypeTasks.size(); } return returnValue; } public void repoll() { synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); for (CommandAsyncTask task : CurrentActionTypeTasks) { task.setState(AsyncTaskState.Ended); } } } public void clearTasks() { synchronized (_listTasks) { ArrayList<CommandAsyncTask> CurrentActionTypeTasks = getCurrentTasks(); for (CommandAsyncTask task : CurrentActionTypeTasks) { if (task.getLastTaskStatus().getStatus() == AsyncTaskStatusEnum.finished) { task.clearAsyncTask(); _listTasks.remove(task.getVdsmTaskId()); } } } } public void clearTaskByVdsmTaskId(Guid vdsmTaskId) { synchronized (_listTasks) { _listTasks.remove(vdsmTaskId); } } public void startPollingTask(Guid TaskID) { synchronized (_listTasks) { if (_listTasks.containsKey(TaskID) && _listTasks.get(TaskID).getParameters() != null && _listTasks.get(TaskID).getParameters().getDbAsyncTask() != null) { for (CommandAsyncTask task : _listTasks.values()) { if (task.getParameters() != null && task.getParameters().getDbAsyncTask() != null) { task.setState(AsyncTaskState.Polling); } } } else { log.warn("CommandMultiAsyncTasks::startPollingTask: For some reason, task '{}' has no parameters or" + " no DB task - we don't know its action type", TaskID); } } } public boolean getAllCleared() { synchronized (_listTasks) { for (CommandAsyncTask task : _listTasks.values()) { if (!taskWasCleared(task)) { log.info("[within thread]: Some of the tasks related to command id '{}' were not cleared yet" + " (Task id '{}' is in state '{}').", getCommandId(), task.getVdsmTaskId(), task.getState()); return false; } } } return true; } /** * @param task * The task to check. * @return Whether the task is cleared (succeeded or failed) or not cleared. */ private boolean taskWasCleared(CommandAsyncTask task) { AsyncTaskState taskState = task.getState(); return taskState == AsyncTaskState.Cleared || taskState == AsyncTaskState.ClearFailed; } }