Skip to content

Commit

Permalink
More parallelism improvements, bugfixies and test improvements (MID-4…
Browse files Browse the repository at this point in the history
…154) ... but still work in progress
  • Loading branch information
semancik committed Sep 28, 2017
1 parent 56489a8 commit e3b79c0
Show file tree
Hide file tree
Showing 38 changed files with 712 additions and 650 deletions.
Expand Up @@ -11880,6 +11880,18 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="error">
<xsd:annotation>
<xsd:documentation>
Operation should be end with an error.
This is a recoverable error (precondition failed).
TODO: align with "fail"
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="ERROR"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="restart">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -11915,6 +11927,8 @@
<xsd:documentation>
The whole operation should fail. This is to be used mainly for testing purposes,
to check if conflict detection algorithm does not yield false positive results.
This fails with a system error. This is a definitive, non-recoverable fauilure.
TODO: align with "error"
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="FAIL"/>
Expand Down
Expand Up @@ -101,7 +101,7 @@ public static void assertFocusDefinition(ComplexTypeDefinition complexTypeDefini
assertFalse("Metadata is runtime", metadataContainer.isRuntimeSchema());
assertFalse("Metadata is dynamic", metadataContainer.isDynamic());
assertTrue("Metadata is NOT operational", metadataContainer.isOperational());
assertEquals("Metadata size", 12, metadataContainer.getDefinitions().size());
assertEquals("Metadata size", 13, metadataContainer.getDefinitions().size());

PrismReferenceDefinition tenantRefDef = complexTypeDefinition.findItemDefinition(UserType.F_TENANT_REF, PrismReferenceDefinition.class);
PrismAsserts.assertDefinition(tenantRefDef, UserType.F_TENANT_REF, ObjectReferenceType.COMPLEX_TYPE, 0, 1);
Expand Down
Expand Up @@ -47,6 +47,7 @@
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.PreconditionViolationException;
import com.evolveum.midpoint.repo.api.RepoAddOptions;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.cache.RepositoryCache;
Expand Down Expand Up @@ -604,6 +605,15 @@ public Collection<ObjectDeltaOperation<? extends ObjectType>> executeChanges(fin
CommunicationException|ConfigurationException|PolicyViolationException|SecurityViolationException|RuntimeException e) {
ModelUtils.recordFatalError(result, e);
throw e;

} catch (PreconditionViolationException e) {
ModelUtils.recordFatalError(result, e);
// TODO: Temporary fix for 3.6.1
// We do not want to propagate PreconditionViolationException to model API as that might break compatiblity
// ... and we do not really need that in 3.6.1
// TODO: expose PreconditionViolationException in 3.7
throw new SystemException(e);

} finally {
task.markObjectActionExecutedBoundary();
}
Expand Down Expand Up @@ -720,33 +730,20 @@ public <F extends ObjectType> void recompute(Class<F> type, String oid, ModelExe

result.cleanupResult();

} catch (ExpressionEvaluationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (SchemaException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (PolicyViolationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ObjectNotFoundException e) {
} catch (ExpressionEvaluationException | SchemaException | PolicyViolationException | ObjectNotFoundException |
ObjectAlreadyExistsException | CommunicationException | ConfigurationException | SecurityViolationException |
RuntimeException | Error e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ObjectAlreadyExistsException e) {

} catch (PreconditionViolationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (CommunicationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ConfigurationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (SecurityViolationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (RuntimeException e) {
ModelUtils.recordFatalError(result, e);
throw e;
// TODO: Temporary fix for 3.6.1
// We do not want to propagate PreconditionViolationException to model API as that might break compatiblity
// ... and we do not really need that in 3.6.1
// TODO: expose PreconditionViolationException in 3.7
throw new SystemException(e);

} finally {
RepositoryCache.exit();
}
Expand Down
Expand Up @@ -87,6 +87,7 @@
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.prism.query.TypeFilter;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.PreconditionViolationException;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
Expand Down Expand Up @@ -195,6 +196,15 @@ public <F extends ObjectType> ModelContext<F> previewChanges(
ExpressionEvaluationException e) {
ModelUtils.recordFatalError(result, e);
throw e;

} catch (PreconditionViolationException e) {
ModelUtils.recordFatalError(result, e);
// TODO: Temporary fix for 3.6.1
// We do not want to propagate PreconditionViolationException to model API as that might break compatiblity
// ... and we do not really need that in 3.6.1
// TODO: expose PreconditionViolationException in 3.7
throw new SystemException(e);

} finally {
RepositoryCache.exit();
}
Expand Down
Expand Up @@ -23,6 +23,7 @@
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.PreconditionViolationException;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskCategory;
Expand Down Expand Up @@ -122,7 +123,7 @@ public TaskRunResult run(Task task) {
result.computeStatus();
}
runResult.setRunResultStatus(TaskRunResult.TaskRunResultStatus.FINISHED);
} catch (RuntimeException|CommonException e) {
} catch (CommonException | PreconditionViolationException | RuntimeException | Error e) {
String message = "An exception occurred within model operation, in task " + task;
LoggingUtils.logUnexpectedException(LOGGER, message, e);
result.recordPartialError(message, e);
Expand Down
Expand Up @@ -181,7 +181,13 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
policySituationUpdater.storeFocusPolicySituation(context);
}

if (focusDelta != null) {
if (focusDelta == null && !context.hasProjectionChange()) {
LOGGER.trace("Skipping focus change execute, because user delta is null");
} else {

if (focusDelta == null) {
focusDelta = focusContext.getObjectAny().createModifyDelta();
}

ObjectPolicyConfigurationType objectPolicyConfigurationType = focusContext
.getObjectPolicyConfigurationType();
Expand Down Expand Up @@ -221,6 +227,9 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas

} catch (PreconditionViolationException e) {

if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Modification precondition failed for {}: {}", focusContext.getHumanReadableName(), e.getMessage());
}
// TODO: fatal error if the conflict resolution is "error" (later)
result.recordHandledError(e);
throw e;
Expand All @@ -235,8 +244,6 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
} finally {
context.reportProgress(new ProgressInformation(FOCUS_OPERATION, subResult));
}
} else {
LOGGER.trace("Skipping focus change execute, because user delta is null");
}
}

Expand All @@ -254,7 +261,7 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
if (!projCtx.isCanProject()) {
continue;
}

// we should not get here, but just to be sure
if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.IGNORE) {
LOGGER.trace("Skipping ignored projection context {}", projCtx.toHumanReadableString());
Expand Down Expand Up @@ -318,7 +325,7 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
subResult.computeStatus();
subResult.recordNotApplicableIfUnknown();
continue;

} else if (projDelta.isDelete() && projCtx.getResourceShadowDiscriminator() != null
&& projCtx.getResourceShadowDiscriminator().getOrder() > 0) {
// HACK ... for higher-order context check if this was
Expand Down Expand Up @@ -377,26 +384,12 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
restartRequested = true;
break; // we will process remaining projections when retrying
// the wave
} catch (CommunicationException e) {
recordProjectionExecutionException(e, projCtx, subResult,
SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ConfigurationException e) {
recordProjectionExecutionException(e, projCtx, subResult,
SynchronizationPolicyDecision.BROKEN);
continue;
} catch (SecurityViolationException e) {
recordProjectionExecutionException(e, projCtx, subResult,
SynchronizationPolicyDecision.BROKEN);
continue;
} catch (ExpressionEvaluationException e) {
recordProjectionExecutionException(e, projCtx, subResult,
SynchronizationPolicyDecision.BROKEN);
continue;
} catch (RuntimeException e) {

} catch (CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | Error e) {
recordProjectionExecutionException(e, projCtx, subResult,
SynchronizationPolicyDecision.BROKEN);
continue;

} finally {
context.reportProgress(new ProgressInformation(RESOURCE_OBJECT_OPERATION,
projCtx.getResourceShadowDiscriminator(), subResult));
Expand All @@ -410,18 +403,7 @@ public <O extends ObjectType> boolean executeChanges(LensContext<O> context, Tas
}

private <O extends ObjectType> void applyLastProvisioningTimestamp(LensContext<O> context, ObjectDelta<O> focusDelta) throws SchemaException {
Collection<LensProjectionContext> projectionContexts = context.getProjectionContexts();
if (projectionContexts == null) {
return;
}
boolean hasProjectionChange = false;
for (LensProjectionContext projectionContext: projectionContexts) {
if (projectionContext.hasPrimaryDelta() || projectionContext.hasSecondaryDelta()) {
hasProjectionChange = true;
break;
}
}
if (!hasProjectionChange) {
if (!context.hasProjectionChange()) {
return;
}
if (focusDelta.isAdd()) {
Expand Down Expand Up @@ -520,7 +502,7 @@ private <O extends ObjectType> void applyObjectPolicy(LensFocusContext<O> focusC
}
}

private <P extends ObjectType> void recordProjectionExecutionException(Exception e,
private <P extends ObjectType> void recordProjectionExecutionException(Throwable e,
LensProjectionContext accCtx, OperationResult subResult, SynchronizationPolicyDecision decision) {
subResult.recordFatalError(e);
LOGGER.error("Error executing changes for {}: {}",
Expand Down Expand Up @@ -584,7 +566,7 @@ private <O extends ObjectType, F extends FocusType> void updateLinks(
// Already linked, nothing to do, only be sure, the
// situation is set with the good value
LOGGER.trace("Updating situation in already linked shadow.");
updateSituationInShadow(task, SynchronizationSituationType.LINKED, focusObjectContext,
updateSituationInShadow(task, SynchronizationSituationType.LINKED, null, focusObjectContext,
projCtx, result);
return;
}
Expand All @@ -594,7 +576,7 @@ private <O extends ObjectType, F extends FocusType> void updateLinks(
linkShadow(focusContext.getOid(), projOid, focusObjectContext, projCtx, task, result);
// be sure, that the situation is set correctly
LOGGER.trace("Updating situation after shadow was linked.");
updateSituationInShadow(task, SynchronizationSituationType.LINKED, focusObjectContext, projCtx,
updateSituationInShadow(task, SynchronizationSituationType.LINKED, null, focusObjectContext, projCtx,
result);
} else {
// Link should NOT exist
Expand All @@ -621,7 +603,7 @@ private <O extends ObjectType, F extends FocusType> void updateLinks(
LOGGER.trace("Resource object {} deleted, updating also situation in shadow.", projOid);
// HACK HACK?
try {
updateSituationInShadow(task, SynchronizationSituationType.DELETED, focusObjectContext,
updateSituationInShadow(task, SynchronizationSituationType.DELETED, true, focusObjectContext,
projCtx, result);
} catch (ObjectNotFoundException e) {
// HACK HACK?
Expand All @@ -635,7 +617,7 @@ private <O extends ObjectType, F extends FocusType> void updateLinks(
// situation here. Reflect that in the shadow.
LOGGER.trace("Resource object {} unlinked from the user, updating also situation in shadow.",
projOid);
updateSituationInShadow(task, null, focusObjectContext, projCtx, result);
updateSituationInShadow(task, null, null, focusObjectContext, projCtx, result);
}
// Not linked, that's OK
}
Expand Down Expand Up @@ -760,7 +742,7 @@ private <F extends ObjectType> void unlinkShadow(String focusOid, PrismReference
}

private <F extends ObjectType> void updateSituationInShadow(Task task,
SynchronizationSituationType situation, LensFocusContext<F> focusContext,
SynchronizationSituationType situation, Boolean dead, LensFocusContext<F> focusContext,
LensProjectionContext projectionCtx, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException {

Expand All @@ -783,6 +765,11 @@ private <F extends ObjectType> void updateSituationInShadow(Task task,
List<PropertyDelta<?>> syncSituationDeltas = SynchronizationUtils
.createSynchronizationSituationAndDescriptionDelta(account, situation, task.getChannel(),
projectionCtx.hasFullShadow());

if (dead != null) {
PropertyDelta<Boolean> deadDelta = PropertyDelta.createModificationReplaceProperty(ShadowType.F_DEAD, account.getDefinition(), dead);
syncSituationDeltas.add(deadDelta);
}

try {
Utils.setRequestee(task, focusContext);
Expand Down Expand Up @@ -1337,7 +1324,8 @@ private <T extends ObjectType, F extends ObjectType> void executeModification(Ob
if (conflictResolution != null) {
String readVersion = objectContext.getObjectReadVersion();
if (readVersion != null) {
precondition = new VersionPrecondition<>(readVersion);
LOGGER.trace("Modification with precondition, readVersion={}", readVersion);
precondition = new VersionPrecondition<>(readVersion);
} else {
LOGGER.warn("Requested careful modification of {}, but there is no read version", objectContext.getHumanReadableName());
}
Expand Down

0 comments on commit e3b79c0

Please sign in to comment.