From 57aa870f662a22de012c513ffafdff1e458731a4 Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Wed, 1 Apr 2020 16:07:42 +0200 Subject: [PATCH] multithreaded tasks support for thresholds (recon, livesync) --- .../configuration/InternalsCountersPanel.java | 37 +++++- .../focus/AssignmentTripleEvaluator.java | 35 +++-- .../policy/PolicyRuleSuspendTaskExecutor.java | 5 +- .../impl/sync/ReconciliationTaskHandler.java | 27 ++-- .../midpoint/repo/api/CounterManager.java | 6 +- .../repo/api/CounterSpecification.java | 17 +-- .../repo/cache/CacheCounterManager.java | 33 +++-- .../AbstractSearchIterativeResultHandler.java | 35 ++--- .../AbstractSearchIterativeTaskHandler.java | 4 + .../com/evolveum/midpoint/task/api/Task.java | 4 + .../midpoint/task/api/test/NullTaskImpl.java | 11 ++ .../task/quartzimpl/TaskQuartzImpl.java | 50 ++++++++ testing/story/pom.xml | 5 + .../testing/story/TestThresholds.java | 31 ++++- .../story/TestThresholdsLiveSyncFull.java | 8 +- .../story/TestThresholdsLiveSyncSimulate.java | 9 +- ...resholdsLiveSyncSimulateMultithreaded.java | 96 ++++++++++++++ .../story/TestThresholdsReconFull.java | 5 + .../story/TestThresholdsReconSimulate.java | 8 ++ ...tThresholdsReconSimulateMultithreaded.java | 121 ++++++++++++++++++ ...opendj-livesync-simulate-multithreaded.xml | 54 ++++++++ ...pendj-reconcile-simulate-multithreaded.xml | 61 +++++++++ 22 files changed, 587 insertions(+), 75 deletions(-) create mode 100644 testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulateMultithreaded.java create mode 100644 testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulateMultithreaded.java create mode 100644 testing/story/src/test/resources/thresholds/task-opendj-livesync-simulate-multithreaded.xml create mode 100644 testing/story/src/test/resources/thresholds/task-opendj-reconcile-simulate-multithreaded.xml diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/InternalsCountersPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/InternalsCountersPanel.java index c8fdd454e16..5a5753454d8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/InternalsCountersPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/InternalsCountersPanel.java @@ -11,6 +11,15 @@ import java.util.Collection; import java.util.List; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; + +import com.evolveum.midpoint.util.exception.*; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; + import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.basic.Label; @@ -38,6 +47,9 @@ public class InternalsCountersPanel extends BasePanel private static final String ID_COUNTER_COUNT_LABEL = "counterCount"; private static final String ID_RESET_THRESHOLD_COUNTER = "resetThresholdCounter"; + private static final String DOT_CLASS = InternalsCountersPanel.class.getName() + "."; + private static final String OPERATION_LOAD_TASK = DOT_CLASS + "loadTaskByIdentifier"; + public InternalsCountersPanel(String id) { super(id); @@ -58,7 +70,7 @@ protected void onInitialize() { @Override protected void populateItem(ListItem item) { CounterSpecification counter = item.getModelObject(); - Label task = new Label(ID_COUNTER_TASK_LABEL, counter.getTaskName()); + Label task = new Label(ID_COUNTER_TASK_LABEL, createLabelModel(counter)); item.add(task); Label policyRule = new Label(ID_COUNTER_POLICY_RULE_LABEL, counter.getPolicyRuleName()); @@ -73,7 +85,7 @@ protected void populateItem(ListItem item) { @Override public void onClick(AjaxRequestTarget target) { - ConfirmationPanel confirmPanel = new ConfirmationPanel(getPageBase().getMainPopupBodyId(), createStringResource("InternalsCountersPanel.reset.confirm.message", counter.getTaskName(), counter.getPolicyRuleName())) { + ConfirmationPanel confirmPanel = new ConfirmationPanel(getPageBase().getMainPopupBodyId(), createStringResource("InternalsCountersPanel.reset.confirm.message", counter.getOid(), counter.getPolicyRuleName())) { private static final long serialVersionUID = 1L; @@ -118,6 +130,27 @@ public String getObject() { add(countersTable); } + private IModel createLabelModel(CounterSpecification counter) { + return () -> { + Task operationTask = getPageBase().createSimpleTask(OPERATION_LOAD_TASK); + OperationResult parentResult = operationTask.getResult(); + PrismObject taskPrism = null; + try { + taskPrism = getPageBase().getTaskService().getTaskByIdentifier(counter.getOid(), null, operationTask, parentResult); + } catch (SchemaException | CommunicationException | ExpressionEvaluationException | ObjectNotFoundException | ConfigurationException | SecurityViolationException e) { + parentResult.recordPartialError("Failed to load task with identifier: " + counter.getOid() + ". Reason: " + e.getMessage()); + } + + parentResult.computeStatusIfUnknown(); + getPageBase().showResult(parentResult, false); + + if (taskPrism == null) { + return counter.getOid(); + } + return WebComponentUtil.getName(taskPrism) + "(" + counter.getOid() + ")"; + }; + } + private IModel> createThresholdCounterModel() { return new IModel>() { private static final long serialVersionUID = 1L; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java index afd742f8bb4..361b920c3cc 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/AssignmentTripleEvaluator.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.model.impl.lens.projector.focus; import java.util.Collection; +import java.util.stream.Collectors; import javax.xml.datatype.XMLGregorianCalendar; @@ -197,20 +198,22 @@ public DeltaSetTriple> processAllAssignments() throw prismContext, task, result); LOGGER.trace("Task for process: {}", task.debugDumpLazily()); - AssignmentType taskAssignment; - if (task.hasAssignments()) { - taskAssignment = new AssignmentType(prismContext); - ObjectReferenceType targetRef = new ObjectReferenceType(); - targetRef.asReferenceValue().setObject(task.getUpdatedOrClonedTaskObject()); - taskAssignment.setTargetRef(targetRef); - } else { - taskAssignment = null; - } - LOGGER.trace("Task assignment: {}", taskAssignment); + Collection allTasksToRoot = task.getPathToRootTask(result); + Collection taskAssignments = allTasksToRoot.stream() + .filter(taskPath -> taskPath.hasAssignments()) + .map(taskPath -> createTaskAssignment(taskPath)) + .collect(Collectors.toList()); + + LOGGER.trace("Task assignment: {}", taskAssignments); + + if (taskAssignments.isEmpty()) { + assignmentCollection.collect(focusContext.getObjectCurrent(), focusContext.getObjectOld(), assignmentDelta, forcedAssignments, null); + } - assignmentCollection.collect(focusContext.getObjectCurrent(), focusContext.getObjectOld(), assignmentDelta, - forcedAssignments, taskAssignment); + for (AssignmentType taskAssignment : taskAssignments) { + assignmentCollection.collect(focusContext.getObjectCurrent(), focusContext.getObjectOld(), assignmentDelta, forcedAssignments, taskAssignment); + } LOGGER.trace("Assignment collection:\n{}", assignmentCollection.debugDumpLazily(1)); @@ -229,6 +232,14 @@ public DeltaSetTriple> processAllAssignments() throw return evaluatedAssignmentTriple; } + private AssignmentType createTaskAssignment(Task fromTask) { + AssignmentType taskAssignment = new AssignmentType(prismContext); + ObjectReferenceType targetRef = new ObjectReferenceType(); + targetRef.asReferenceValue().setObject(fromTask.getUpdatedOrClonedTaskObject()); + taskAssignment.setTargetRef(targetRef); + return taskAssignment; + } + private String getNewObjectLifecycleState(LensFocusContext focusContext) { PrismObject focusNew = focusContext.getObjectNew(); AH focusTypeNew = focusNew.asObjectable(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleSuspendTaskExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleSuspendTaskExecutor.java index 0678d16dae5..5cd02011c4d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleSuspendTaskExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyRuleSuspendTaskExecutor.java @@ -43,9 +43,10 @@ public void execute(@NotNull ModelContext context, Tas return; } - TaskType taskType = task.getUpdatedOrClonedTaskObject().asObjectable(); + String id = task.getTaskTreeId(result); + for (EvaluatedPolicyRule policyRule : focusCtx.getPolicyRules()) { - CounterSpecification counterSpec = counterManager.getCounterSpec(taskType, policyRule.getPolicyRuleIdentifier(), policyRule.getPolicyRule()); + CounterSpecification counterSpec = counterManager.getCounterSpec(id, policyRule.getPolicyRuleIdentifier(), policyRule.getPolicyRule()); LOGGER.trace("Found counter specification {} for {}", counterSpec, DebugUtil.debugDumpLazily(policyRule)); int counter = 1; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java index cbae483c65d..107e8fc23ef 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java @@ -14,8 +14,11 @@ import com.evolveum.midpoint.model.impl.util.AuditHelper; import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; +import com.evolveum.midpoint.repo.common.util.RepoCommonUtils; import com.evolveum.midpoint.schema.cache.CacheConfigurationManager; import com.evolveum.midpoint.task.api.*; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.query_3.QueryType; import org.apache.commons.lang.BooleanUtils; @@ -61,14 +64,6 @@ import com.evolveum.midpoint.task.api.TaskRunResult.TaskRunResultStatus; import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; @@ -334,6 +329,15 @@ public TaskWorkBucketProcessingResult run(RunningTask localCoordinatorTask, Work } catch (ExpressionEvaluationException ex) { processErrorFinal(runResult, "Expression error", ex, TaskRunResultStatus.PERMANENT_ERROR, resource, localCoordinatorTask, opResult); return runResult; + } catch (ObjectAlreadyExistsException ex) { + processErrorFinal(runResult, "Object already existis error", ex, TaskRunResultStatus.PERMANENT_ERROR, resource, localCoordinatorTask, opResult); + return runResult; + } catch (PolicyViolationException ex) { + processErrorFinal(runResult, "Policy violation error", ex, TaskRunResultStatus.PERMANENT_ERROR, resource, localCoordinatorTask, opResult); + return runResult; + } catch (PreconditionViolationException ex) { + processErrorFinal(runResult, "Precondition violation error", ex, TaskRunResultStatus.PERMANENT_ERROR, resource, localCoordinatorTask, opResult); + return runResult; } AuditEventRecord executionRecord = new AuditEventRecord(AuditEventType.RECONCILIATION, AuditEventStage.EXECUTION); @@ -487,7 +491,7 @@ private boolean performResourceReconciliation(PrismObject resource ReconciliationTaskResult reconResult, RunningTask localCoordinatorTask, TaskPartitionDefinitionType partitionDefinition, WorkBucketType workBucket, OperationResult result, boolean intentIsNull) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, - SecurityViolationException, ExpressionEvaluationException { + SecurityViolationException, ExpressionEvaluationException, PreconditionViolationException, PolicyViolationException, ObjectAlreadyExistsException { boolean interrupted; @@ -549,6 +553,11 @@ private boolean performResourceReconciliation(PrismObject resource opResult.recordFatalError(e); throw e; } + + if (handler.getExceptionEncountered() != null) { + RepoCommonUtils.throwException(handler.getExceptionEncountered(), opResult); + } + return !interrupted; } diff --git a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterManager.java b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterManager.java index 1cb10a7404b..93722884dec 100644 --- a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterManager.java +++ b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterManager.java @@ -17,9 +17,9 @@ */ public interface CounterManager { - CounterSpecification getCounterSpec(TaskType task, String policyRuleId, PolicyRuleType policyRule); - void cleanupCounters(String taskOid); + CounterSpecification getCounterSpec(String taskId, String policyRuleId, PolicyRuleType policyRule); + void cleanupCounters(String oid); Collection listCounters(); void removeCounter(CounterSpecification counterSpecification); - void resetCounters(String taskOid); + void resetCounters(String oid); } diff --git a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterSpecification.java b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterSpecification.java index cb00d5480be..d2dff540796 100644 --- a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterSpecification.java +++ b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/CounterSpecification.java @@ -10,7 +10,6 @@ import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyRuleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyThresholdType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; /** * @author katka @@ -21,12 +20,12 @@ public class CounterSpecification implements DebugDumpable { private int count = 0; private long counterStart; - private TaskType task; + private String oid; private PolicyRuleType policyRule; private String policyRuleId; - public CounterSpecification(TaskType task, String policyRuleId, PolicyRuleType policyRule) { - this.task = task; + public CounterSpecification(String oid, String policyRuleId, PolicyRuleType policyRule) { + this.oid = oid; this.policyRuleId = policyRuleId; this.policyRule = policyRule; } @@ -48,16 +47,12 @@ public PolicyThresholdType getPolicyThreshold() { return policyRule.getPolicyThreshold(); } - public String getTaskName() { - return task.getName().getOrig(); - } - public String getPolicyRuleName() { return policyRule.getName(); } - public String getTaskOid() { - return task.getOid(); + public String getOid() { + return oid; } public String getPolicyRuleId() { @@ -73,7 +68,7 @@ public void reset(long currentTimeMillis) { @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); - sb.append("Counter for: ").append(task).append(", policy rule: ").append(policyRule).append("\n"); + sb.append("Counter for: ").append(oid).append(", policy rule: ").append(policyRule).append("\n"); sb.append("Current count: ").append(count).append("\n"); sb.append("Counter start: ").append(XmlTypeConverter.createXMLGregorianCalendar(counterStart)).append("\n"); diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/CacheCounterManager.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/CacheCounterManager.java index 0f45e294844..8f9bd88a643 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/CacheCounterManager.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/CacheCounterManager.java @@ -25,7 +25,6 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyRuleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyThresholdType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TimeIntervalType; /** @@ -41,17 +40,17 @@ public class CacheCounterManager implements CounterManager { private Map countersMap = new ConcurrentHashMap<>(); - public synchronized CounterSpecification registerCounter(TaskType task, String policyRuleId, PolicyRuleType policyRule) { + public synchronized CounterSpecification registerCounter(String taskId, String policyRuleId, PolicyRuleType policyRule) { - if (task.getOid() == null) { + if (taskId == null) { LOGGER.trace("Not persistent task, skipping registering counter."); return null; } - CounterKey key = new CounterKey(task.getOid(), policyRuleId); + CounterKey key = new CounterKey(taskId, policyRuleId); CounterSpecification counterSpec = countersMap.get(key); if (counterSpec == null) { - return initCleanCounter(key, task, policyRule); + return initCleanCounter(key, taskId, policyRule); } if (isResetCounter(counterSpec, false)) { @@ -84,7 +83,7 @@ private boolean isResetCounter(CounterSpecification counterSpec, boolean removeI } @Override - public void cleanupCounters(String taskOid) { + public synchronized void cleanupCounters(String taskOid) { Set keys = countersMap.keySet(); Set counersToRemove = new HashSet<>(); @@ -103,7 +102,7 @@ public void cleanupCounters(String taskOid) { } @Override - public void resetCounters(String taskOid) { + public synchronized void resetCounters(String taskOid) { Set keys = countersMap.keySet(); Set counersToReset = new HashSet<>(); @@ -119,8 +118,8 @@ public void resetCounters(String taskOid) { } } - private CounterSpecification initCleanCounter(CounterKey key, TaskType task, PolicyRuleType policyRule) { - CounterSpecification counterSpec = new CounterSpecification(task, key.policyRuleId, policyRule); + private CounterSpecification initCleanCounter(CounterKey key, String taskId, PolicyRuleType policyRule) { + CounterSpecification counterSpec = new CounterSpecification(taskId, key.policyRuleId, policyRule); counterSpec.setCounterStart(clock.currentTimeMillis()); countersMap.put(key, counterSpec); return counterSpec; @@ -133,18 +132,18 @@ private CounterSpecification refreshCounter(CounterKey key, CounterSpecification } @Override - public CounterSpecification getCounterSpec(TaskType task, String policyRuleId, PolicyRuleType policyRule) { - if (task.getOid() == null) { - LOGGER.trace("Cannot get counter spec for task without oid"); + public CounterSpecification getCounterSpec(String taskId, String policyRuleId, PolicyRuleType policyRule) { + if (taskId == null) { + LOGGER.trace("Cannot get counter spec for task without identifier"); return null; } - LOGGER.trace("Getting counter spec for {} and {}", task, policyRule); - CounterKey key = new CounterKey(task.getOid(), policyRuleId); + LOGGER.trace("Getting counter spec for {} and {}", taskId, policyRule); + CounterKey key = new CounterKey(taskId, policyRuleId); CounterSpecification counterSpec = countersMap.get(key); if (counterSpec == null) { - return registerCounter(task, policyRuleId, policyRule); + return registerCounter(taskId, policyRuleId, policyRule); } if (isResetCounter(counterSpec, false)) { @@ -162,11 +161,11 @@ public Collection listCounters() { @Override public void removeCounter(CounterSpecification counterSpecification) { - CounterKey key = new CounterKey(counterSpecification.getTaskOid(), counterSpecification.getPolicyRuleId()); + CounterKey key = new CounterKey(counterSpecification.getOid(), counterSpecification.getPolicyRuleId()); countersMap.remove(key); } - class CounterKey { + static class CounterKey { private String oid; private String policyRuleId; diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java index 8e115b0e249..914d890db04 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java @@ -18,7 +18,6 @@ import com.evolveum.midpoint.schema.statistics.StatisticsUtil; import com.evolveum.midpoint.schema.util.ExceptionUtil; import com.evolveum.midpoint.task.api.*; -import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LevelOverrideTurboFilter; import com.evolveum.midpoint.util.logging.TracingAppender; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -75,6 +74,7 @@ public abstract class AbstractSearchIterativeResultHandler private boolean enableActionsExecutedStatistics = false; // whether we want to collect repo objects statistics private BlockingQueue requestQueue; private AtomicBoolean stopRequestedByAnyWorker = new AtomicBoolean(false); + private volatile Throwable exceptionEncountered; private final long startTime; private static final Trace LOGGER = TraceManager.getTrace(AbstractSearchIterativeResultHandler.class); @@ -276,7 +276,7 @@ public void run(RunningTask workerTask) { workerTask.setName(workerTask.getName().getOrig() + " (" + Thread.currentThread().getName() + ")"); workerSpecificResult.addArbitraryObjectAsContext("subtaskName", workerTask.getName()); - while (workerTask.canRun()) { + while (workerTask.canRun() && !stopRequestedByAnyWorker.get()) { workerTask.refreshLowLevelStatistics(); ProcessingRequest request; try { @@ -367,14 +367,8 @@ private void processRequest(ProcessingRequest request, RunningTask workerTask, O workerTask.recordIterativeOperationEnd(objectName, objectDisplayName, null /* TODO */, object.getOid(), startTime, e); } - try { - cont = processError(object, workerTask, e, result); - } catch (ObjectNotFoundException | CommunicationException | SchemaException | ConfigurationException - | SecurityViolationException | PolicyViolationException | ExpressionEvaluationException - | ObjectAlreadyExistsException | PreconditionViolationException e1) { - // TODO Is this OK? We should not throw runtime exceptions from the handler. [pm] - throw new SystemException(e1); - } + cont = processError(object, workerTask, e, result); + } finally { RepositoryCache.exit(); workerTask.stopDynamicProfiling(); @@ -438,6 +432,10 @@ private boolean isNonScavengingWorker() { !Boolean.TRUE.equals(coordinatorTask.getWorkManagement().isScavenger()); } + public Throwable getExceptionEncountered() { + return exceptionEncountered; + } + // may be overridden protected String getDisplayName(PrismObject object) { return StatisticsUtil.getDisplayName(object); @@ -446,7 +444,7 @@ protected String getDisplayName(PrismObject object) { // TODO implement better // @pre: result is "error" or ex is not null - private boolean processError(PrismObject object, Task task, Throwable ex, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException { + private boolean processError(PrismObject object, Task task, Throwable ex, OperationResult result) { int errorsCount = errors.incrementAndGet(); LOGGER.trace("Processing error, count: {}", errorsCount); @@ -465,19 +463,24 @@ private boolean processError(PrismObject object, Task task, Throwable ex, Ope result.recordFatalError("Failed to "+getProcessShortName()+": "+ex.getMessage(), ex); } result.summarize(); - return !isStopOnError(task, ex, result); + return canContinue(task, ex, result); // return !isStopOnError(); } - private boolean isStopOnError(Task task, Throwable ex, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException { + private boolean canContinue(Task task, Throwable ex, OperationResult result) { if (stageType == null) { - return stopOnError; + return !stopOnError; } CriticalityType criticality = ExceptionUtil.getCriticality(stageType.getErrorCriticality(), ex, CriticalityType.PARTIAL); - RepoCommonUtils.processErrorCriticality(task, criticality, ex, result); + try { + RepoCommonUtils.processErrorCriticality(task, criticality, ex, result); + } catch (Throwable e) { + exceptionEncountered = e; + return false; + } - return stopOnError; + return !stopOnError; } /** diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java index 6fad2f2b07a..87c3ea84d1b 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java @@ -305,6 +305,10 @@ public TaskWorkBucketProcessingResult run(RunningTask localCoordinatorTask, Work OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); } + if (resultHandler.getExceptionEncountered() != null) { + return logErrorAndSetResult(runResult, resultHandler, resultHandler.getExceptionEncountered().getMessage(), resultHandler.getExceptionEncountered(), + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); + } // TODO: check last handler status handlers.remove(localCoordinatorTask.getOid()); 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 900eaa721aa..eb3f75b493c 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 @@ -950,6 +950,10 @@ void flushPendingModifications(OperationResult parentResult) throws ObjectNotFou */ Collection getAssignments(); + Collection getPathToRootTask(OperationResult parentResult) throws SchemaException; + + String getTaskTreeId(OperationResult result) throws SchemaException; + default boolean hasAssignments() { return !getAssignments().isEmpty(); } diff --git a/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java index e2cb6a16f95..83db38c70ed 100644 --- a/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java +++ b/repo/task-api/src/main/java/com/evolveum/midpoint/task/api/test/NullTaskImpl.java @@ -15,6 +15,7 @@ import com.evolveum.midpoint.schema.statistics.ProvisioningOperation; import com.evolveum.midpoint.schema.statistics.SynchronizationInformation; import com.evolveum.midpoint.task.api.*; +import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.jetbrains.annotations.NotNull; @@ -847,6 +848,16 @@ public Collection getAssignments() { return null; } + @Override + public Collection getPathToRootTask(OperationResult parentResult) throws SchemaException { + throw new UnsupportedOperationException(); + } + + @Override + public String getTaskTreeId(OperationResult result) throws SchemaException { + throw new UnsupportedOperationException(); + } + @Override public ObjectReferenceType getOwnerRef() { return null; 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 7442c3ebbf5..a42e100058b 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 @@ -2590,6 +2590,56 @@ public Collection getAssignments() { } } + @Override + public Collection getPathToRootTask(OperationResult parentResult) throws SchemaException { + List allTasksToRoot = new ArrayList<>(); + allTasksToRoot.add(this); + + if (getParent() == null) { + return allTasksToRoot; + } + + Task parent = getParentTaskSafe(parentResult); + if (parent == null) { + return allTasksToRoot; + } + + allTasksToRoot.addAll(parent.getPathToRootTask(parentResult)); + return allTasksToRoot; + } + + public String getTaskTreeId(OperationResult parentResult) throws SchemaException { + if (getParent() == null) { + return getOid(); + } + + Task parent = getParentTaskSafe(parentResult); + if (parent == null) { + return getOid(); + } + + return parent.getTaskTreeId(parentResult); + } + + private Task getParentTaskSafe(OperationResult parentResult) throws SchemaException { + if (getParent() == null) { + return null; + } + + OperationResult result = parentResult.createMinorSubresult(DOT_INTERFACE + "getPathToRootTask"); + result.addContext(OperationResult.CONTEXT_OID, getOid()); + result.addContext(OperationResult.CONTEXT_IMPLEMENTATION_CLASS, TaskQuartzImpl.class); + try { + Task parent = getParentTask(result); + result.recordSuccess(); + return parent; + } catch (ObjectNotFoundException e) { + LOGGER.error("Cannot find parent identified by {}, {}", getParent(), e.getMessage(), e); + result.recordFatalError("Cannot find parent identified by " + getParent() + ". Reason: " + e.getMessage(), e); + return null; + } + } + @Override public ObjectReferenceType getOwnerRef() { synchronized (prismAccess) { diff --git a/testing/story/pom.xml b/testing/story/pom.xml index 09c7de5a75c..faa7a1d9a28 100644 --- a/testing/story/pom.xml +++ b/testing/story/pom.xml @@ -291,6 +291,11 @@ ${jdbc.mysql} test + + org.assertj + assertj-core + test + diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholds.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholds.java index e961628e564..32c44666d85 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholds.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholds.java @@ -13,7 +13,11 @@ import java.util.List; import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.statistics.SynchronizationInformation; +import com.evolveum.midpoint.test.asserter.TaskAsserter; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -59,6 +63,10 @@ public abstract class TestThresholds extends AbstractStoryTest { private static final int TASK_IMPORT_TIMEOUT = 60000; + public static final int RULE_CREATE_WATERMARk = 5; + public static final int RULE_ACTIVATION_WATERMARk = 3; + + int getDefaultUsers() { return 6; } @@ -75,9 +83,10 @@ public static void stopResources() { protected abstract File getTaskFile(); protected abstract String getTaskOid(); + protected abstract int getWorkerThreads(); protected abstract int getProcessedUsers(); protected abstract void assertSynchronizationStatisticsAfterImport(Task taskAfter) throws Exception; - protected abstract void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) throws Exception; + protected abstract void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter); protected abstract void assertSynchronizationStatisticsActivation(Task taskAfter); @Override @@ -93,6 +102,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti repoAddObjectFromFile(ROLE_POLICY_RULE_CHANGE_ACTIVATION_FILE, initResult); repoAddObjectFromFile(getTaskFile(), initResult); + adapTaskConfig(initTask, initResult); } /** @@ -259,4 +269,23 @@ public void test520ImportDisabledAccounts() throws Exception { void dumpSynchronizationInformation(SynchronizationInformationType synchronizationInformation) { displayValue("Synchronization information", SynchronizationInformation.format(synchronizationInformation)); } + + protected void adapTaskConfig(Task task, OperationResult result) throws Exception { + if (getWorkerThreads() == 0) { + return; + } + + ObjectDelta delta = prismContext.deltaFor(TaskType.class) + .item(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_WORKER_THREADS)) + .add(getWorkerThreads()).asObjectDelta(getTaskOid()); + + + executeChanges(delta, null, task, result); + + PrismObject taskAfter = getTask(getTaskOid()); + + TaskAsserter.forTask(taskAfter) + .extension() + .assertPropertyValuesEqual(SchemaConstants.MODEL_EXTENSION_WORKER_THREADS, getWorkerThreads()); + } } diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncFull.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncFull.java index a5c3571e87c..503c14f4a28 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncFull.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncFull.java @@ -10,6 +10,7 @@ import java.io.File; +import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.statistics.SynchronizationInformation; import org.springframework.test.annotation.DirtiesContext; @@ -39,6 +40,11 @@ protected String getTaskOid() { return TASK_LIVESYNC_OPENDJ_FULL_OID; } + @Override + protected int getWorkerThreads() { + return 0; + } + @Override protected int getProcessedUsers() { return 4; @@ -76,7 +82,7 @@ protected void assertSynchronizationStatisticsActivation(Task taskAfter) { } @Override - protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) throws Exception { + protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) { SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); dumpSynchronizationInformation(syncInfo); diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulate.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulate.java index 8b30e8dc51c..7f72e3ee622 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulate.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulate.java @@ -10,6 +10,8 @@ import java.io.File; +import com.evolveum.midpoint.schema.result.OperationResult; + import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -37,6 +39,11 @@ protected String getTaskOid() { return TASK_LIVESYNC_OPENDJ_SIMULATE_OID; } + @Override + protected int getWorkerThreads() { + return 0; + } + @Override protected int getProcessedUsers() { return 0; @@ -73,7 +80,7 @@ protected void assertSynchronizationStatisticsActivation(Task taskAfter) { * @see com.evolveum.midpoint.testing.story.TestThresholds#assertSynchronizationStatisticsAfterSecondImport(com.evolveum.midpoint.task.api.Task) */ @Override - protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) throws Exception { + protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) { SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); dumpSynchronizationInformation(syncInfo); diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulateMultithreaded.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulateMultithreaded.java new file mode 100644 index 00000000000..dced3a01e59 --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsLiveSyncSimulateMultithreaded.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.story; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testng.Assert.assertEquals; + +import java.io.File; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; + +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationInformationType; + +/** + * @author katka + */ +@ContextConfiguration(locations = { "classpath:ctx-story-test-main.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestThresholdsLiveSyncSimulateMultithreaded extends TestThresholds { + + private static final File TASK_LIVESYNC_OPENDJ_SIMULATE_FILE = new File(TEST_DIR, "task-opendj-livesync-simulate-multithreaded.xml"); + private static final String TASK_LIVESYNC_OPENDJ_SIMULATE_OID = "10335c7c-838f-11e8-93a6-4b1dd0ab58e4"; + private static final int WORKER_THREADS = 2; + + @Override + protected File getTaskFile() { + return TASK_LIVESYNC_OPENDJ_SIMULATE_FILE; + } + + @Override + protected String getTaskOid() { + return TASK_LIVESYNC_OPENDJ_SIMULATE_OID; + } + + @Override + protected int getWorkerThreads() { + return WORKER_THREADS; + } + + @Override + protected int getProcessedUsers() { + return 0; + } + + @Override + protected void assertSynchronizationStatisticsAfterImport(Task taskAfter) throws Exception { + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + assertSyncToken(taskAfter, 4); + + // user5, user6, user7, user8, user9 (why not user4? -- because token is preset to 4) + assertThat(syncInfo.getCountUnmatchedAfter()).isBetween(RULE_CREATE_WATERMARk, RULE_CREATE_WATERMARk + WORKER_THREADS); + assertEquals(syncInfo.getCountDeletedAfter(), 0); + assertEquals(syncInfo.getCountLinkedAfter(), 0); + assertEquals(syncInfo.getCountUnlinkedAfter(), 0); + + } + + protected void assertSynchronizationStatisticsActivation(Task taskAfter) { + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + // new users: user5, user6, user7, user8, user9, user10, user11, user12, user13, user14, user15 (11 users) + //assertEquals(syncInfo.getCountUnmatched(), 11); // do we really need to check this? + assertEquals(syncInfo.getCountDeleted(), 0); + // existing users: user1, user2 (disabled - passed, watermark not reached), user3 (disabled - fails) -- these users were created during initial import + assertEquals(syncInfo.getCountLinked(), 3); // 2 + 1 + assertEquals(syncInfo.getCountUnlinked(), 0); + } + + /* (non-Javadoc) + * @see com.evolveum.midpoint.testing.story.TestThresholds#assertSynchronizationStatisticsAfterSecondImport(com.evolveum.midpoint.task.api.Task) + */ + @Override + protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) { + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + assertSyncToken(taskAfter, 4); + + // user5, user6, user7, user8, user9 + assertEquals(syncInfo.getCountUnmatchedAfter(), RULE_CREATE_WATERMARk + WORKER_THREADS - 1); + assertEquals(syncInfo.getCountDeletedAfter(), 0); + assertEquals(syncInfo.getCountLinkedAfter(), 0); + assertEquals(syncInfo.getCountUnlinkedAfter(), 0); + } +} diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconFull.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconFull.java index 1f101eebf00..c6cf557c4f5 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconFull.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconFull.java @@ -50,6 +50,11 @@ protected String getTaskOid() { return TASK_RECONCILE_OPENDJ_FULL_OID; } + @Override + protected int getWorkerThreads() { + return 0; + } + @Override protected int getProcessedUsers() { return 4; diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulate.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulate.java index 79ad5095709..ebb7b574d79 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulate.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulate.java @@ -10,6 +10,8 @@ import java.io.File; +import com.evolveum.midpoint.schema.result.OperationResult; + import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -38,11 +40,17 @@ protected String getTaskOid() { return TASK_RECONCILE_OPENDJ_SIMULATE_OID; } + @Override + protected int getWorkerThreads() { + return 0; + } + @Override protected int getProcessedUsers() { return 0; } + @Override protected void assertSynchronizationStatisticsAfterImport(Task taskAfter) { IterativeTaskInformationType infoType = taskAfter.getStoredOperationStats().getIterativeTaskInformation(); diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulateMultithreaded.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulateMultithreaded.java new file mode 100644 index 00000000000..c05b810c7e9 --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestThresholdsReconSimulateMultithreaded.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.story; + +import static org.testng.Assert.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + + + +import org.opends.server.tools.upgrade.UpgradeTask; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; + +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.IterativeTaskInformationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationInformationType; + +/** + * @author katka + */ +@ContextConfiguration(locations = { "classpath:ctx-story-test-main.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestThresholdsReconSimulateMultithreaded extends TestThresholds { + + private static final File TASK_RECONCILE_OPENDJ_SIMULATE_FILE = new File(TEST_DIR, "task-opendj-reconcile-simulate-multithreaded.xml"); + private static final String TASK_RECONCILE_OPENDJ_SIMULATE_OID = "10335c7c-838f-11e8-93a6-4b1dd0ab58e4"; + + private static final int WORKER_THREADS = 3; + + @Override + protected File getTaskFile() { + return TASK_RECONCILE_OPENDJ_SIMULATE_FILE; + } + + @Override + protected String getTaskOid() { + return TASK_RECONCILE_OPENDJ_SIMULATE_OID; + } + + @Override + protected int getProcessedUsers() { + return 0; + } + + @Override + protected int getWorkerThreads() { + return WORKER_THREADS; + } + + @Override + protected void assertSynchronizationStatisticsAfterImport(Task taskAfter) { + IterativeTaskInformationType infoType = taskAfter.getStoredOperationStats().getIterativeTaskInformation(); + assertThat(infoType.getTotalFailureCount()).isBetween(1, WORKER_THREADS); + + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + // user4, user5, user6, user7, user8 + assertThat(syncInfo.getCountUnmatched()).isBetween(RULE_CREATE_WATERMARk, RULE_CREATE_WATERMARk + WORKER_THREADS); + assertEquals(syncInfo.getCountDeleted(), 0); + // jgibbs, hbarbossa, jbeckett, user1, user2, user3 + assertEquals(syncInfo.getCountLinked(), getDefaultUsers()); + assertEquals(syncInfo.getCountUnlinked(), 0); + + assertThat(syncInfo.getCountUnmatchedAfter()).isBetween(RULE_CREATE_WATERMARk, RULE_CREATE_WATERMARk + WORKER_THREADS); + assertEquals(syncInfo.getCountDeletedAfter(), 0); + assertEquals(syncInfo.getCountLinkedAfter(), getDefaultUsers()); + assertEquals(syncInfo.getCountUnlinkedAfter(), 0); + } + + /* (non-Javadoc) + * @see com.evolveum.midpoint.testing.story.TestThresholds#assertSynchronizationStatisticsAfterSecondImport(com.evolveum.midpoint.task.api.Task) + */ + @Override + protected void assertSynchronizationStatisticsAfterSecondImport(Task taskAfter) { + IterativeTaskInformationType infoType = taskAfter.getStoredOperationStats().getIterativeTaskInformation(); + assertEquals(infoType.getTotalFailureCount(), WORKER_THREADS); + + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + // user4, user5, user6, user7, user8 + assertThat(syncInfo.getCountUnmatched()).isBetween(RULE_CREATE_WATERMARk, RULE_CREATE_WATERMARk + WORKER_THREADS); + assertEquals(syncInfo.getCountDeleted(), 0); + // jgibbs, hbarbossa, jbeckett, user1, user2, user3 + assertEquals(syncInfo.getCountLinked(), getDefaultUsers() + getProcessedUsers()); + assertEquals(syncInfo.getCountUnlinked(), 0); + + assertThat(syncInfo.getCountUnmatchedAfter()).isBetween(RULE_CREATE_WATERMARk, RULE_CREATE_WATERMARk + WORKER_THREADS); + assertEquals(syncInfo.getCountDeletedAfter(), 0); + assertEquals(syncInfo.getCountLinkedAfter(), getDefaultUsers() + getProcessedUsers()); + assertEquals(syncInfo.getCountUnlinkedAfter(), 0); + } + + @Override + protected void assertSynchronizationStatisticsActivation(Task taskAfter) { + IterativeTaskInformationType infoType = taskAfter.getStoredOperationStats().getIterativeTaskInformation(); + assertEquals(infoType.getTotalFailureCount(), 1); + + SynchronizationInformationType syncInfo = taskAfter.getStoredOperationStats().getSynchronizationInformation(); + dumpSynchronizationInformation(syncInfo); + + //user4 + assertEquals(syncInfo.getCountDeleted(), 0); + // jgibbs, hbarbossa, jbeckett, user1 (disabled-#1), user2 (disabled-#2), user3 (disabled-#3-fails) + assertEquals(syncInfo.getCountLinked(), getDefaultUsers() + getProcessedUsers()); + assertEquals(syncInfo.getCountUnlinked(), 0); + + assertEquals(syncInfo.getCountDeleted(), 0); + // jgibbs, hbarbossa, jbeckett, user1 (disabled-#1), user2 (disabled-#2), user3 (disabled-#3-fails) + assertEquals(syncInfo.getCountLinked(), getDefaultUsers() + getProcessedUsers()); + assertEquals(syncInfo.getCountUnlinked(), 0); + } +} diff --git a/testing/story/src/test/resources/thresholds/task-opendj-livesync-simulate-multithreaded.xml b/testing/story/src/test/resources/thresholds/task-opendj-livesync-simulate-multithreaded.xml new file mode 100644 index 00000000000..caa338d7ea1 --- /dev/null +++ b/testing/story/src/test/resources/thresholds/task-opendj-livesync-simulate-multithreaded.xml @@ -0,0 +1,54 @@ + + + + + + + + LiveSync Simulate: Dummy + + + ri:inetOrgPerson + account + default + 4 + + + 10335c7c-838f-11e8-93a6-4b1dd0ab58e4 + + suspended + + http://midpoint.evolveum.com/xml/ns/public/task/lightweigth-partitioning/handler-3 + + + + + 1 + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/live-sync/handler-3 + simulate + + fatal + + + + + + + recurring + tight + + 1 + + + diff --git a/testing/story/src/test/resources/thresholds/task-opendj-reconcile-simulate-multithreaded.xml b/testing/story/src/test/resources/thresholds/task-opendj-reconcile-simulate-multithreaded.xml new file mode 100644 index 00000000000..9303bd0a50a --- /dev/null +++ b/testing/story/src/test/resources/thresholds/task-opendj-reconcile-simulate-multithreaded.xml @@ -0,0 +1,61 @@ + + + + + + + + Reconciliation Simulate: Dummy + + + ri:inetOrgPerson + account + default + + + + 10335c7c-838f-11e8-93a6-4b1dd0ab58e4 + + suspended + + http://midpoint.evolveum.com/xml/ns/public/task/lightweigth-partitioning/handler-3 + + + + + 2 + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 + execute + + fatal + + + + 1 + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 + simulate + + fatal + + + + + + suspend + + recurring + + 3 + + +