Skip to content

Commit

Permalink
MID-2497: Delete task improvements: better name + report state/progress
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Oct 13, 2015
1 parent ab9da95 commit eeefece
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 19 deletions.
Expand Up @@ -17,6 +17,7 @@
package com.evolveum.midpoint.web.page.admin.configuration;

import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
Expand Down Expand Up @@ -663,10 +664,10 @@ private void deleteAllIdentitiesConfirmed(AjaxRequestTarget target, DeleteAllDto
try {
if (dto.getDeleteUsers()) {
ObjectQuery query = createDeleteAllUsersQuery();
deleteObjectsAsync(UserType.COMPLEX_TYPE, query, true, result);
deleteObjectsAsync(UserType.COMPLEX_TYPE, query, true, "Delete all users", result);
}
if (dto.getDeleteOrgs()) {
deleteObjectsAsync(OrgType.COMPLEX_TYPE, null, true, result);
deleteObjectsAsync(OrgType.COMPLEX_TYPE, null, true, "Delete all orgs", result);
}
if (dto.getDeleteAccountShadow()) {
deleteAllShadowsConfirmed(result, true);
Expand Down Expand Up @@ -698,14 +699,17 @@ private void deleteAllShadowsConfirmed(OperationResult result, boolean deleteAcc
ObjectFilter kind = EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class,
getPrismContext(), null, ShadowKindType.ACCOUNT);

String taskName;
ObjectQuery query;
if (deleteAccountShadows) {
taskName = "Delete all account shadows";
query = ObjectQuery.createObjectQuery(kind);
} else {
taskName = "Delete all non-account shadows";
query = ObjectQuery.createObjectQuery(NotFilter.createNot(kind));
}

deleteObjectsAsync(ShadowType.COMPLEX_TYPE, query, true, result);
deleteObjectsAsync(ShadowType.COMPLEX_TYPE, query, true, taskName, result);
}

private void exportSelected(AjaxRequestTarget target, DebugObjectItem item) {
Expand Down Expand Up @@ -795,7 +799,7 @@ private void deleteAllTypeConfirmed(AjaxRequestTarget target) {

QName type = dto.getType().getTypeQName();

deleteObjectsAsync(type, query, true, result);
deleteObjectsAsync(type, query, true, "Delete all of type " + type.getLocalPart(), result);

info(getString("pageDebugList.messsage.deleteAllOfType", dto.getType()));
} catch (Exception ex) {
Expand Down Expand Up @@ -866,7 +870,7 @@ private void deleteAllShadowsOnResourceConfirmed(AjaxRequestTarget target) {

QName type = ShadowType.COMPLEX_TYPE;

deleteObjectsAsync(type, objectQuery, true, result);
deleteObjectsAsync(type, objectQuery, true, "Delete shadows on " + dto.getResource().getName(), result);

info(getString("pageDebugList.messsage.deleteAllShadowsStarted", dto.getResource().getName()));
} catch (Exception ex) {
Expand All @@ -880,12 +884,11 @@ private void deleteAllShadowsOnResourceConfirmed(AjaxRequestTarget target) {
target.add(getFeedbackPanel());
}

private void deleteObjectsAsync(QName type, ObjectQuery objectQuery, boolean raw, OperationResult result)
private void deleteObjectsAsync(QName type, ObjectQuery objectQuery, boolean raw, String taskName, OperationResult result)
throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException {

Task task = createSimpleTask(result.getOperation());
// toto this should be a constant referenced from somewhere
task.setHandlerUri("http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/delete/handler-3");
task.setHandlerUri(ModelPublicConstants.DELETE_TASK_HANDLER_URI);

if (objectQuery == null) {
objectQuery = new ObjectQuery();
Expand All @@ -911,6 +914,7 @@ private void deleteObjectsAsync(QName type, ObjectQuery objectQuery, boolean raw
rawProp.setRealValue(raw);
task.setExtensionProperty(rawProp);

task.setName(taskName);
task.savePendingModifications(result);

TaskManager taskManager = getTaskManager();
Expand Down
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2010-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.model.api;

import com.evolveum.midpoint.schema.constants.SchemaConstants;

import javax.xml.namespace.QName;

/**
* Model constants referenced from the outside.
* (TODO reconsider with regards to SchemaConstants)
*
* @author mederly
*/
public class ModelPublicConstants {

public static final String NS_SYNCHRONIZATION_PREFIX = SchemaConstants.NS_MODEL +"/synchronization";
public static final String NS_SYNCHRONIZATION_TASK_PREFIX = NS_SYNCHRONIZATION_PREFIX + "/task";
public static final String DELETE_TASK_HANDLER_URI = NS_SYNCHRONIZATION_TASK_PREFIX + "/delete/handler-3";

}
Expand Up @@ -17,6 +17,7 @@

import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;

/**
Expand All @@ -27,8 +28,7 @@ public class ModelConstants {

public static final String NS_MODEL_TRIGGER_PREFIX = SchemaConstants.NS_MODEL +"/trigger";

public static final String NS_SYNCHRONIZATION_PREFIX = SchemaConstants.NS_MODEL +"/synchronization";
public static final String NS_SYNCHRONIZATION_TASK_PREFIX = NS_SYNCHRONIZATION_PREFIX + "/task";
public static final String NS_SYNCHRONIZATION_TASK_PREFIX = ModelPublicConstants.NS_SYNCHRONIZATION_TASK_PREFIX;

public static final String NS_IMPORT_OBJECTS_PREFIX = SchemaConstants.NS_MODEL +"/import-objects";
public static final String NS_IMPORT_OBJECTS_TASK_PREFIX = NS_IMPORT_OBJECTS_PREFIX + "/task";
Expand Down
Expand Up @@ -24,14 +24,18 @@
import javax.annotation.PostConstruct;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.model.api.ModelPublicConstants;
import com.evolveum.midpoint.model.impl.sync.TaskHandlerUtil;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.statistics.StatisticsUtil;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.prism.xml.ns._public.query_3.QueryType;

Expand Down Expand Up @@ -76,8 +80,10 @@
@Component
public class DeleteTaskHandler implements TaskHandler {

public static final String HANDLER_URI = ModelConstants.NS_SYNCHRONIZATION_TASK_PREFIX + "/delete/handler-3";

public static final String HANDLER_URI = ModelPublicConstants.DELETE_TASK_HANDLER_URI;

public static final long PROGRESS_UPDATE_INTERVAL = 3000L;

@Autowired(required=true)
protected TaskManager taskManager;

Expand All @@ -96,7 +102,12 @@ private void initialize() {

@Override
public TaskRunResult run(Task task) {
return runInternal(task);
try {
TaskHandlerUtil.initAllStatistics(task, true, false);
return runInternal(task);
} finally {
updateState(task);
}
}

public <O extends ObjectType> TaskRunResult runInternal(Task task) {
Expand Down Expand Up @@ -125,9 +136,11 @@ public <O extends ObjectType> TaskRunResult runInternal(Task task) {
}

Class<O> objectType;
QName objectTypeName;
PrismProperty<QName> objectTypePrismProperty = task.getExtensionProperty(SchemaConstants.MODEL_EXTENSION_OBJECT_TYPE);
if (objectTypePrismProperty != null && objectTypePrismProperty.getRealValue() != null) {
objectType = (Class<O>) ObjectTypes.getObjectTypeFromTypeQName(objectTypePrismProperty.getRealValue()).getClassDefinition();
objectTypeName = objectTypePrismProperty.getRealValue();
objectType = (Class<O>) ObjectTypes.getObjectTypeFromTypeQName(objectTypeName).getClassDefinition();
} else {
LOGGER.error("No object type parameter in {}", task);
opResult.recordFatalError("No object type parameter in " + task);
Expand Down Expand Up @@ -198,6 +211,8 @@ public <O extends ObjectType> TaskRunResult runInternal(Task task) {
throw new IllegalStateException("Unexpected ObjectAlreadyExistsException when updating task progress/expectedTotal", e);
}

long progressLastUpdated = 0;

SearchResultList<PrismObject<O>> objects;
while (true) {

Expand All @@ -216,14 +231,34 @@ public <O extends ObjectType> TaskRunResult runInternal(Task task) {
skipped++;
continue;
}

ObjectDelta<?> delta = ObjectDelta.createDeleteDelta(objectType, object.getOid(), prismContext);
modelService.executeChanges(MiscSchemaUtil.createCollection(delta), execOptions, task, opResult);

String objectName = PolyString.getOrig(object.getName());
String objectDisplayName = StatisticsUtil.getDisplayName(object);
String objectOid = object.getOid();

task.recordIterativeOperationStart(objectName, objectDisplayName, objectTypeName, objectOid);
long objectDeletionStarted = System.currentTimeMillis();
try {
modelService.executeChanges(MiscSchemaUtil.createCollection(delta), execOptions, task, opResult);
task.recordIterativeOperationEnd(objectName, objectDisplayName, objectTypeName, objectOid, objectDeletionStarted, null);
} catch (Throwable t) {
task.recordIterativeOperationEnd(objectName, objectDisplayName, objectTypeName, objectOid, objectDeletionStarted, t);
throw t; // TODO we don't want to continue processing if an error occurs?
}

progress++;
task.setProgressTransient(progress);

if (System.currentTimeMillis() - progressLastUpdated > PROGRESS_UPDATE_INTERVAL) {
task.setProgress(progress);
updateState(task);
progressLastUpdated = System.currentTimeMillis();
}
}

opResult.summarize();
task.setProgress(progress);

opResult.summarize();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Search returned {} objects, {} skipped, progress: {}, result:\n{}",
new Object[]{objects.size(), skipped, progress, opResult.debugDump()});
Expand Down Expand Up @@ -293,5 +328,10 @@ public String getCategoryName(Task task) {
public List<String> getCategoryNames() {
return null;
}

private void updateState(Task task) {
TaskHandlerUtil.storeAllStatistics(task, true, false);
// includes savePendingModifications - this is necessary for the progress to be immediately available in GUI
}

}
Expand Up @@ -383,6 +383,10 @@ public void setProgressImmediate(long progress, OperationResult parentResult)
throw new UnsupportedOperationException("not implemented yet.");
}

@Override
public void setProgressTransient(long value) {
}

@Override
public PrismObject<TaskType> getTaskPrismObject() {
throw new UnsupportedOperationException("not implemented yet.");
Expand Down
Expand Up @@ -743,6 +743,8 @@ public void setResultImmediate(OperationResult result, OperationResult parentRes
*/
public void setProgressImmediate(long progress, OperationResult parentResult) throws ObjectNotFoundException, SchemaException;

void setProgressTransient(long value);

/**
* Returns expected total progress.
* @return
Expand Down
Expand Up @@ -408,6 +408,7 @@ public void setProgressImmediate(long value, OperationResult parentResult)
}
}

@Override
public void setProgressTransient(long value) {
try {
taskPrism.setPropertyRealValue(TaskType.F_PROGRESS, value);
Expand Down

0 comments on commit eeefece

Please sign in to comment.