package org.ovirt.engine.core.bll; import java.util.List; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.asynctasks.EndedTaskInfo; import org.ovirt.engine.core.common.asynctasks.EndedTasksInfo; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; public class EntityMultiAsyncTasks { private VdcActionType privateActionType = VdcActionType.forValue(0); public VdcActionType getActionType() { return privateActionType; } public void setActionType(VdcActionType value) { privateActionType = value; } private java.util.HashMap<Guid, EntityAsyncTask> _listTasks; private Object privateContainerId; public Object getContainerId() { return privateContainerId; } private void setContainerId(Object value) { privateContainerId = value; } public EntityMultiAsyncTasks(Object containerID) { _listTasks = new java.util.HashMap<Guid, EntityAsyncTask>(); setContainerId(containerID); } public void AttachTask(EntityAsyncTask asyncTask) { synchronized (_listTasks) { if (!_listTasks.containsKey(asyncTask.getTaskID())) { log.infoFormat("EntityMultiAsyncTasks::AttachTask: Attaching task '{0}' to entity '{1}'.", asyncTask.getTaskID(), getContainerId()); _listTasks.put(asyncTask.getTaskID(), asyncTask); } } } private java.util.ArrayList<EntityAsyncTask> GetCurrentActionTypeTasks() { java.util.ArrayList<EntityAsyncTask> retValue = new java.util.ArrayList<EntityAsyncTask>(); for (EntityAsyncTask task : _listTasks.values()) { if (task.getParameters() != null && task.getParameters().getDbAsyncTask() != null && task.getParameters().getDbAsyncTask().getaction_type() == getActionType() && (task.getState() == AsyncTaskState.Polling || task.getState() == AsyncTaskState.Ended || task .getState() == AsyncTaskState.AttemptingEndAction)) { retValue.add(task); } } return retValue; } public boolean ShouldEndAction() { synchronized (_listTasks) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask task : CurrentActionTypeTasks) { if (task.getState() != AsyncTaskState.Ended) { return false; } } } return true; } public void MarkAllWithAttemptingEndAction() { synchronized (_listTasks) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask task : CurrentActionTypeTasks) { task.setState(AsyncTaskState.AttemptingEndAction); } } } public EndedTasksInfo getEndedTasksInfo() { EndedTasksInfo endedTasksInfo = new EndedTasksInfo(); java.util.ArrayList<EndedTaskInfo> endedTaskInfoList = new java.util.ArrayList<EndedTaskInfo>(); synchronized (_listTasks) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask 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) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); returnValue = CurrentActionTypeTasks.size(); } return returnValue; } public void Repoll() { synchronized (_listTasks) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask task : CurrentActionTypeTasks) { task.setState(AsyncTaskState.Ended); } } } /** * Reset the action type if all the current action type's tasks are cleared, so that if there are any other tasks * in the list they will get treated correctly. */ protected void resetActionTypeIfNecessary() { boolean allCleared = true; synchronized (_listTasks) { List<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask task : CurrentActionTypeTasks) { allCleared = allCleared && taskWasCleared(task); } if (allCleared) { setActionType(VdcActionType.Unknown); } } } public void ClearTasks() { synchronized (_listTasks) { java.util.ArrayList<EntityAsyncTask> CurrentActionTypeTasks = GetCurrentActionTypeTasks(); for (EntityAsyncTask task : CurrentActionTypeTasks) { task.ClearAsyncTask(); } StartPollingNextTask(); } } // call this method after ending action and clearing tasks of current // ActionType. protected void StartPollingNextTask() { synchronized (_listTasks) { for (EntityAsyncTask task : _listTasks.values()) { if (task.getState() == AsyncTaskState.WaitForPoll && task.getParameters() != null && task.getParameters().getDbAsyncTask() != null) { log.infoFormat( "EntityMultiAsyncTasks::StartPollingNextTask: Starting to poll next task " + "(task ID: '{0}', action type '{1}')", task.getTaskID(), task.getParameters().getDbAsyncTask().getaction_type()); setActionType(VdcActionType.Unknown); StartPollingTask(task.getTaskID()); break; } } } } public void StartPollingTask(Guid TaskID) { synchronized (_listTasks) { if (_listTasks.containsKey(TaskID) && _listTasks.get(TaskID).getParameters() != null && _listTasks.get(TaskID).getParameters().getDbAsyncTask() != null) { if (getActionType() == VdcActionType.Unknown) { // still no ActionType chosen -> determine the ActionType by // the // TaskID that we want to start polling and start polling // all of // its siblings: setActionType(_listTasks.get(TaskID).getParameters().getDbAsyncTask().getaction_type()); log.infoFormat( "EntityMultiAsyncTasks::StartPollingTask: Current Action Type for entity '{0}' is '{1}' (determined by task '{2}')", getContainerId(), getActionType(), TaskID); for (EntityAsyncTask task : _listTasks.values()) { if (task.getParameters() != null && task.getParameters().getDbAsyncTask() != null && task.getParameters().getDbAsyncTask().getaction_type() == getActionType() && (task.getState() == AsyncTaskState.Initializing || task.getState() == AsyncTaskState.WaitForPoll)) { task.setState(AsyncTaskState.Polling); } } } else { // ActionType is already determined -> set the task and its // siblings // to 'wait for poll': VdcActionType currTaskActionType = _listTasks.get(TaskID).getParameters().getDbAsyncTask() .getaction_type(); for (EntityAsyncTask task : _listTasks.values()) { if (task.getParameters() != null && task.getParameters().getDbAsyncTask() != null && task.getParameters().getDbAsyncTask().getaction_type() == currTaskActionType && task.getState() == AsyncTaskState.Initializing) { task.setState(AsyncTaskState.WaitForPoll); } } } } else { log.warnFormat( "EntityMultiAsyncTasks::StartPollingTask: For some reason, task '{0}' has no parameters or no DB task - we don't know its action type", TaskID); } } } public boolean getAllCleared() { synchronized (_listTasks) { for (EntityAsyncTask task : _listTasks.values()) { if (!taskWasCleared(task)) { 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(EntityAsyncTask task) { AsyncTaskState taskState = task.getState(); return taskState == AsyncTaskState.Cleared || taskState == AsyncTaskState.ClearFailed; } private static LogCompat log = LogFactoryCompat.getLog(EntityMultiAsyncTasks.class); }