package org.ovirt.engine.ui.uicommonweb.models.events;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.ovirt.engine.core.common.job.Job;
import org.ovirt.engine.core.common.job.JobExecutionStatus;
import org.ovirt.engine.core.common.job.Step;
import org.ovirt.engine.core.common.queries.GetJobsByCorrelationIdQueryParameters;
import org.ovirt.engine.core.common.queries.GetJobsByOffsetQueryParameters;
import org.ovirt.engine.core.common.queries.IdQueryParameters;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
public class TaskListModel extends SearchableListModel {
public static final String WEBADMIN = "_WEBADMIN_"; //$NON-NLS-1$
private final Map<String, Job> detailedTaskMap = new HashMap<>();
public TaskListModel() {
}
@Override
protected void syncSearch() {
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(returnValue -> {
ArrayList<Job> taskList = returnValue.getReturnValue();
if (taskList.size() == 0) {
detailedTaskMap.clear();
}
ArrayList<Job> taskListWithCorrelationFilter = new ArrayList<>();
Map<String, Map.Entry<Job, ArrayList<Job>>> correlationTaskMap = new HashMap<>();
for (Job task : taskList) {
if (task.getCorrelationId().startsWith(WEBADMIN)) {
if (!correlationTaskMap.containsKey(task.getCorrelationId())) {
Job rootTask = new Job();
rootTask.setCorrelationId(task.getCorrelationId());
Map.Entry<Job, ArrayList<Job>> entry = new TaskEntry(rootTask);
entry.setValue(new ArrayList<Job>());
correlationTaskMap.put(rootTask.getCorrelationId(), entry);
String[] taskDescreptionArray =
rootTask.getCorrelationId().replace(WEBADMIN, "").split("_"); //$NON-NLS-1$ //$NON-NLS-2$
StringBuilder taskDesc = new StringBuilder();
for (int i = 1; i < taskDescreptionArray.length; i++) {
taskDesc.append(taskDescreptionArray[i]).append(" "); //$NON-NLS-1$
}
rootTask.setId(task.getId());
rootTask.setDescription(taskDesc.toString());
taskListWithCorrelationFilter.add(rootTask);
}
Map.Entry<Job, ArrayList<Job>> entry = correlationTaskMap.get(task.getCorrelationId());
entry.getValue().add(task);
} else {
taskListWithCorrelationFilter.add(task);
}
}
for (Map.Entry<Job, ArrayList<Job>> entry : correlationTaskMap.values()) {
entry.getKey().setStatus(JobExecutionStatus.UNKNOWN);
boolean hasFailedStatus = false;
boolean hasStartedStatus = false;
boolean hasAbortedStatus = false;
int finishedCount = 0;
for (Job task : entry.getValue()) {
switch (task.getStatus()) {
case STARTED:
hasStartedStatus = true;
break;
case FINISHED:
finishedCount++;
break;
case FAILED:
hasFailedStatus = true;
break;
case ABORTED:
hasAbortedStatus = true;
break;
case UNKNOWN:
break;
default:
break;
}
if (entry.getKey().getLastUpdateTime() == null
|| (entry.getKey().getLastUpdateTime().before(task.getLastUpdateTime())
&& !entry.getKey().getLastUpdateTime().equals(task.getLastUpdateTime()))) {
entry.getKey().setLastUpdateTime(task.getLastUpdateTime());
}
Date tempDate = task.getLastUpdateTime();
if (entry.getKey().getStartTime() == null
|| entry.getKey().getStartTime().after(task.getStartTime())) {
entry.getKey().setStartTime(task.getStartTime());
}
if (entry.getKey().getEndTime() == null
|| entry.getKey().getEndTime().before(task.getEndTime())) {
entry.getKey().setEndTime(task.getEndTime());
}
entry.getKey().setLastUpdateTime(tempDate);
}
if (hasFailedStatus) {
entry.getKey().setStatus(JobExecutionStatus.FAILED);
} else if (finishedCount == entry.getValue().size()) {
entry.getKey().setStatus(JobExecutionStatus.FINISHED);
} else if (hasStartedStatus) {
entry.getKey().setStatus(JobExecutionStatus.STARTED);
} else if (hasAbortedStatus) {
entry.getKey().setStatus(JobExecutionStatus.ABORTED);
} else {
entry.getKey().setStatus(JobExecutionStatus.UNKNOWN);
}
}
ArrayList<Job> newTaskList = new ArrayList<>();
for (Job task : taskListWithCorrelationFilter) {
String id;
if (task.getCorrelationId().startsWith(WEBADMIN)) {
id = task.getCorrelationId();
} else {
id = task.getId().toString();
}
boolean hadDetails = detailedTaskMap.containsKey(id) && detailedTaskMap.get(id) != null;
if (hadDetails
&& task.getLastUpdateTime().getTime()
- detailedTaskMap.get(id).getLastUpdateTime().getTime() < 100) {
task.setSteps(detailedTaskMap.get(id).getSteps());
} else if (hadDetails) {
detailedTaskMap.remove(id);
updateSingleTask(id);
}
newTaskList.add(task);
}
setItems(newTaskList);
});
GetJobsByOffsetQueryParameters tempVar = new GetJobsByOffsetQueryParameters();
tempVar.setRefresh(getIsQueryFirstTime());
Frontend.getInstance().runQuery(VdcQueryType.GetJobsByOffset,
tempVar, asyncQuery);
setIsQueryFirstTime(false);
}
@Override
protected String getListName() {
return "TaskListModel"; //$NON-NLS-1$
}
public boolean updateSingleTask(final String guidOrCorrelationId) {
if (!detailedTaskMap.containsKey(guidOrCorrelationId)) {
detailedTaskMap.put(guidOrCorrelationId, null);
if (guidOrCorrelationId.startsWith(WEBADMIN)) {
GetJobsByCorrelationIdQueryParameters parameters = new GetJobsByCorrelationIdQueryParameters();
parameters.setCorrelationId(guidOrCorrelationId);
Frontend.getInstance().runQuery(VdcQueryType.GetJobsByCorrelationId,
parameters, new AsyncQuery<VdcQueryReturnValue>(returnValue -> {
ArrayList<Job> retTasks = returnValue.getReturnValue();
ArrayList<Job> taskList = (ArrayList<Job>) getItems();
ArrayList<Job> newTaskList = new ArrayList<>();
for (Job task : taskList) {
if (task.getCorrelationId().equals(guidOrCorrelationId)) {
detailedTaskMap.put(guidOrCorrelationId, task);
task.setStatus(JobExecutionStatus.FINISHED);
for (Job job : retTasks) {
Step step = new Step();
step.setId(job.getId());
step.setDescription(job.getDescription());
step.setCorrelationId(job.getCorrelationId());
step.setStartTime(job.getStartTime());
step.setEndTime(job.getEndTime());
step.setStatus(job.getStatus());
step.setSteps(job.getSteps());
if (!task.getStatus().equals(JobExecutionStatus.FINISHED)
&& !job.getStatus().equals(JobExecutionStatus.FINISHED)) {
task.setStatus(job.getStatus());
}
if (task.getLastUpdateTime() == null
|| (task.getLastUpdateTime().before(job.getLastUpdateTime()) && !task.getLastUpdateTime()
.equals(job.getLastUpdateTime()))) {
task.setLastUpdateTime(job.getEndTime());
}
Date tempDate = task.getLastUpdateTime();
if (task.getStartTime() == null
|| task.getStartTime().after(job.getStartTime())) {
task.setStartTime(job.getStartTime());
}
if (task.getEndTime() != null && (task.getEndTime() == null
|| task.getEndTime().before(job.getEndTime()))) {
task.setEndTime(job.getEndTime());
}
task.addStep(step);
task.setLastUpdateTime(tempDate);
}
}
newTaskList.add(task);
}
setItems(newTaskList);
}));
} else {
IdQueryParameters parameters = new IdQueryParameters(new Guid(guidOrCorrelationId));
Frontend.getInstance().runQuery(VdcQueryType.GetJobByJobId,
parameters, new AsyncQuery<VdcQueryReturnValue>(returnValue -> {
Job retTask = returnValue.getReturnValue();
if (retTask == null) {
return;
}
detailedTaskMap.put(retTask.getId().toString(), retTask);
ArrayList<Job> taskList = (ArrayList<Job>) getItems();
ArrayList<Job> newTaskList = new ArrayList<>();
for (Job task : taskList) {
if (task.getId().equals(retTask.getId())) {
newTaskList.add(retTask);
} else {
newTaskList.add(task);
}
}
setItems(newTaskList);
}));
}
return false;
}
return true;
}
static class TaskEntry implements Map.Entry<Job, ArrayList<Job>> {
public TaskEntry(Job key) {
this.key = key;
}
Job key;
ArrayList<Job> list;
@Override
public Job getKey() {
return key;
}
@Override
public ArrayList<Job> getValue() {
return list;
}
@Override
public ArrayList<Job> setValue(ArrayList<Job> value) {
list = value;
return list;
}
}
/**
* @param actionDescription the name of the action (e.g. "Remove multiple disk from vm-Win7") cannot exceed 40 chars.
* @return frontend correlation id Description
* example: _WEBADMIN_098437232_Remove_multiple_disk_from_vm-Win7
*/
public static String createCorrelationId(String actionDescription) {
actionDescription = actionDescription.replace(' ', '_');
Random rand = new Random();
String hashStr = rand.nextInt(9000000) + 9999999 + ""; //$NON-NLS-1$
return TaskListModel.WEBADMIN + hashStr + "_" + actionDescription; //$NON-NLS-1$
}
}