diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java index f7d19d50fc9..814f5353f19 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java @@ -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; @@ -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); @@ -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) { @@ -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) { @@ -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) { @@ -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(); @@ -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(); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelPublicConstants.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelPublicConstants.java new file mode 100644 index 00000000000..bb3eb49f404 --- /dev/null +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelPublicConstants.java @@ -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"; + +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelConstants.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelConstants.java index 327db21dba5..04622a965b7 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelConstants.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelConstants.java @@ -17,6 +17,7 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.model.api.ModelPublicConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; /** @@ -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"; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/DeleteTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/DeleteTaskHandler.java index 3767229f772..ac9f9352794 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/DeleteTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/DeleteTaskHandler.java @@ -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; @@ -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; @@ -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 TaskRunResult runInternal(Task task) { @@ -125,9 +136,11 @@ public TaskRunResult runInternal(Task task) { } Class objectType; + QName objectTypeName; PrismProperty objectTypePrismProperty = task.getExtensionProperty(SchemaConstants.MODEL_EXTENSION_OBJECT_TYPE); if (objectTypePrismProperty != null && objectTypePrismProperty.getRealValue() != null) { - objectType = (Class) ObjectTypes.getObjectTypeFromTypeQName(objectTypePrismProperty.getRealValue()).getClassDefinition(); + objectTypeName = objectTypePrismProperty.getRealValue(); + objectType = (Class) ObjectTypes.getObjectTypeFromTypeQName(objectTypeName).getClassDefinition(); } else { LOGGER.error("No object type parameter in {}", task); opResult.recordFatalError("No object type parameter in " + task); @@ -198,6 +211,8 @@ public TaskRunResult runInternal(Task task) { throw new IllegalStateException("Unexpected ObjectAlreadyExistsException when updating task progress/expectedTotal", e); } + long progressLastUpdated = 0; + SearchResultList> objects; while (true) { @@ -216,14 +231,34 @@ public 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()}); @@ -293,5 +328,10 @@ public String getCategoryName(Task task) { public List 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 + } } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java index 734f845d93a..fbc972951de 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java @@ -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 getTaskPrismObject() { throw new UnsupportedOperationException("not implemented yet."); diff --git a/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/Task.java b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/Task.java index a6002cc558a..2fbbfdd38d0 100644 --- a/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/Task.java +++ b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/Task.java @@ -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 diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java index 17415128d86..7e721bada9b 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java @@ -408,6 +408,7 @@ public void setProgressImmediate(long value, OperationResult parentResult) } } + @Override public void setProgressTransient(long value) { try { taskPrism.setPropertyRealValue(TaskType.F_PROGRESS, value);