Skip to content

Commit

Permalink
Light recompute/clockwork partial execution (MID-3384, MID-1876)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Mar 3, 2017
1 parent 2f53ee1 commit de1b3a8
Show file tree
Hide file tree
Showing 25 changed files with 1,131 additions and 641 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2015 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -114,7 +114,11 @@ public static ReferenceDelta createModificationReplace(ItemPath path, PrismObjec
PrismReferenceValue refValue) {
PrismReferenceDefinition referenceDefinition = objectDefinition.findItemDefinition(path, PrismReferenceDefinition.class);
ReferenceDelta referenceDelta = new ReferenceDelta(path, referenceDefinition, objectDefinition.getPrismContext()); // hoping the prismContext is there
referenceDelta.setValueToReplace(refValue);
if (refValue == null) {
referenceDelta.setValueToReplace();
} else {
referenceDelta.setValueToReplace(refValue);
}
return referenceDelta;
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2016 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -127,6 +127,7 @@ public abstract class SchemaConstants {
public static final QName C_ITEM_PATH_FIELD = new QName(NS_C, "itemPathField");
public static final QName C_ACTIVATION_STATUS_TYPE = new QName(NS_C, "ActivationStatusType");
public static final QName C_SECURITY_POLICY = new QName(NS_C, "securityPolicy");
public static final QName C_MODEL_EXECUTE_OPTIONS = new QName(NS_C, "modelExecuteOptions");

public static final QName T_POLY_STRING_TYPE = new QName(SchemaConstantsGenerated.NS_TYPES,
"PolyStringType");
Expand Down
Expand Up @@ -12135,6 +12135,16 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="reconcileFocus" type="xsd:boolean" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Option to reconcile focus while executing changes.
If this option is set and the reconcile option is not set then the projections
reconciliation will not be forced (but it may still happen if other configuration
loads full projection).
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="reconcileAffected" type="xsd:boolean" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -12203,6 +12213,7 @@
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="modelExecuteOptions" type="tns:ModelExecuteOptionsType"/>

<xsd:complexType name="OperationBusinessContextType">
<xsd:annotation>
Expand Down
Expand Up @@ -50,9 +50,18 @@ public class ModelExecuteOptions extends AbstractOptions implements Serializable
private Boolean noCrypt;

/**
* Option to reconcile focus while executing changes.
* Option to reconcile focus and all projections while executing changes.
* (implies reconcileFocus)
*/
private Boolean reconcile;

/**
* Option to reconcile focus while executing changes.
* If this option is set and the reconcile option is not set then the projections
* reconciliation will not be forced (but it may still happen if other configuration
* loads full projection).
*/
private Boolean reconcileFocus;

/**
* Option to reconcile affected objects after executing changes.
Expand Down Expand Up @@ -196,7 +205,7 @@ public void setReconcile(Boolean reconcile) {
this.reconcile = reconcile;
}

public static boolean isReconcile(ModelExecuteOptions options){
public static boolean isReconcile(ModelExecuteOptions options) {
if (options == null){
return false;
}
Expand All @@ -206,16 +215,40 @@ public static boolean isReconcile(ModelExecuteOptions options){
return options.reconcile;
}

public static ModelExecuteOptions createReconcile(){
public static ModelExecuteOptions createReconcile() {
ModelExecuteOptions opts = new ModelExecuteOptions();
opts.setReconcile(true);
return opts;
}

public ModelExecuteOptions setReconcile(){
public ModelExecuteOptions setReconcile() {
setReconcile(true);
return this;
}

public Boolean getReconcileFocus() {
return reconcileFocus;
}

public void setReconcileFocus(Boolean reconcileFocus) {
this.reconcileFocus = reconcileFocus;
}

public static ModelExecuteOptions createReconcileFocus() {
ModelExecuteOptions opts = new ModelExecuteOptions();
opts.setReconcileFocus(true);
return opts;
}

public static boolean isReconcileFocus(ModelExecuteOptions options) {
if (options == null){
return false;
}
if (options.reconcileFocus == null){
return false;
}
return options.reconcileFocus;
}

public Boolean getReconcileAffected() {
return reconcileAffected;
Expand Down Expand Up @@ -456,13 +489,15 @@ public ModelExecuteOptionsType toModelExecutionOptionsType() {
retval.setRaw(raw);
retval.setNoCrypt(noCrypt);
retval.setReconcile(reconcile);
retval.setReconcileFocus(reconcileFocus);
retval.setExecuteImmediatelyAfterApproval(executeImmediatelyAfterApproval);
retval.setOverwrite(overwrite);
retval.setIsImport(isImport);
retval.setLimitPropagation(limitPropagation);
retval.setReevaluateSearchFilters(reevaluateSearchFilters);
// preAuthorized is purposefully omitted (security reasons)
retval.setRequestBusinessContext(requestBusinessContext);
retval.setPartialProcessing(partialProcessing);
return retval;
}

Expand All @@ -475,13 +510,15 @@ public static ModelExecuteOptions fromModelExecutionOptionsType(ModelExecuteOpti
retval.setRaw(type.isRaw());
retval.setNoCrypt(type.isNoCrypt());
retval.setReconcile(type.isReconcile());
retval.setReconcileFocus(type.isReconcileFocus());
retval.setExecuteImmediatelyAfterApproval(type.isExecuteImmediatelyAfterApproval());
retval.setOverwrite(type.isOverwrite());
retval.setIsImport(type.isIsImport());
retval.setLimitPropagation(type.isLimitPropagation());
retval.setReevaluateSearchFilters(type.isReevaluateSearchFilters());
// preAuthorized is purposefully omitted (security reasons)
retval.setRequestBusinessContext(type.getRequestBusinessContext());
retval.setPartialProcessing(type.getPartialProcessing());
return retval;
}

Expand Down Expand Up @@ -537,6 +574,7 @@ public String toString() {
appendFlag(sb, "preAuthorized", preAuthorized);
appendFlag(sb, "raw", raw);
appendFlag(sb, "reconcile", reconcile);
appendFlag(sb, "reconcileFocus", reconcileFocus);
appendFlag(sb, "reevaluateSearchFilters", reevaluateSearchFilters);
appendFlag(sb, "reconcileAffected", reconcileAffected);
appendFlag(sb, "requestBusinessContext", requestBusinessContext == null ? null : true);
Expand Down
Expand Up @@ -241,8 +241,15 @@ Collection<ObjectDeltaOperation<? extends ObjectType>> executeChanges(Collection
CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException;

/**
* <p>
* Recomputes focal object with the specified OID. The operation considers all the applicable policies and
* mapping and tries to re-apply them as necessary.
* </p>
* <p>
* This method is DEPRECATED. It is provided for compatibility only. Please use the version with options
* instead of this one. This method will assume the reconcile option to keep compatible behavior with
* previous versions.
* </p>
*
* @param type type (class) of an object to recompute
* @param oid OID of the object to recompute
Expand All @@ -252,9 +259,28 @@ Collection<ObjectDeltaOperation<? extends ObjectType>> executeChanges(Collection
* Task instance. It gives context to the execution (e.g. security context)
* @param parentResult parent OperationResult (in/out)
*/
@Deprecated
<F extends ObjectType> void recompute(Class<F> type, String oid, Task task, OperationResult parentResult)
throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException;

/**
* Recomputes focal object with the specified OID. The operation considers all the applicable policies and
* mapping and tries to re-apply them as necessary.
*
* @since 3.6
*
* @param type type (class) of an object to recompute
* @param oid OID of the object to recompute
* @param options execute options
* @param parentResult
* parent OperationResult (in/out)
* @param task
* Task instance. It gives context to the execution (e.g. security context)
* @param parentResult parent OperationResult (in/out)
*/
<F extends ObjectType> void recompute(Class<F> type, String oid, ModelExecuteOptions options, Task task, OperationResult parentResult)
throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException;

/**
* <p>
* Returns the User object representing owner of specified account (account
Expand Down
Expand Up @@ -580,7 +580,7 @@ public Collection<ObjectDeltaOperation<? extends ObjectType>> executeChanges(fin

LOGGER.debug("Recomputing {} because there was explosive projection", focus);

LensContext<? extends ObjectType> recomputeContext = contextFactory.createRecomputeContext(focus, task, result);
LensContext<? extends ObjectType> recomputeContext = contextFactory.createRecomputeContext(focus, options, task, result);
recomputeContext.setDoReconciliationForAllProjections(true);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Recomputing {}, context:\n{}", focus, recomputeContext.debugDump());
Expand Down Expand Up @@ -670,6 +670,12 @@ private <T extends ObjectType> void reevaluateSearchFilters(Class<T> objectTypeC

@Override
public <F extends ObjectType> void recompute(Class<F> type, String oid, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
ModelExecuteOptions options = ModelExecuteOptions.createReconcile();
recompute(type, oid, options, task, parentResult);
}

@Override
public <F extends ObjectType> void recompute(Class<F> type, String oid, ModelExecuteOptions options, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {

OperationResult result = parentResult.createMinorSubresult(RECOMPUTE);
result.addParams(new String[] { "oid", "type" }, oid, type);
Expand All @@ -683,11 +689,11 @@ public <F extends ObjectType> void recompute(Class<F> type, String oid, Task tas

LOGGER.debug("Recomputing {}", focus);

LensContext<F> syncContext = contextFactory.createRecomputeContext(focus, task, result);
LensContext<F> lensContext = contextFactory.createRecomputeContext(focus, options, task, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Recomputing {}, context:\n{}", focus, syncContext.debugDump());
LOGGER.trace("Recomputing {}, context:\n{}", focus, lensContext.debugDump());
}
clockwork.run(syncContext, task, result);
clockwork.run(lensContext, task, result);

result.computeStatus();

Expand Down
Expand Up @@ -910,7 +910,7 @@ public <F extends FocusType> void recompute(Class<F> type, String oid) throws Sc
ExpressionEvaluationException, ObjectNotFoundException,
ObjectAlreadyExistsException, CommunicationException,
ConfigurationException, SecurityViolationException {
modelService.recompute(type, oid, getCurrentTask(), getCurrentResult());
modelService.recompute(type, oid, null, getCurrentTask(), getCurrentResult());
}

@Override
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013 Evolveum
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -161,41 +161,42 @@ public <F extends ObjectType> LensContext<F> createContext(


public <F extends ObjectType, O extends ObjectType> LensContext<F> createRecomputeContext(
PrismObject<O> object, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
PrismObject<O> object, ModelExecuteOptions options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
Class<O> typeClass = object.getCompileTimeClass();
LensContext<F> context;
if (isFocalClass(typeClass)) {
context = createRecomputeFocusContext((Class<F>)typeClass, (PrismObject<F>) object, task, result);
context = createRecomputeFocusContext((Class<F>)typeClass, (PrismObject<F>) object, options, task, result);
} else if (ShadowType.class.isAssignableFrom(typeClass)) {
context = createRecomputeProjectionContext((PrismObject<ShadowType>) object, task, result);
context = createRecomputeProjectionContext((PrismObject<ShadowType>) object, options, task, result);
} else {
throw new IllegalArgumentException("Cannot create recompute context for "+object);
}
context.setOptions(options);
context.setLazyAuditRequest(true);
return context;
}

public <F extends ObjectType> LensContext<F> createRecomputeFocusContext(
Class<F> focusType, PrismObject<F> focus, Task task, OperationResult result) {
Class<F> focusType, PrismObject<F> focus, ModelExecuteOptions options, Task task, OperationResult result) {
LensContext<F> syncContext = new LensContext<F>(focusType,
prismContext, provisioningService);
LensFocusContext<F> focusContext = syncContext.createFocusContext();
focusContext.setLoadedObject(focus);
focusContext.setOid(focus.getOid());
syncContext.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE));
syncContext.setDoReconciliationForAllProjections(true);
syncContext.setDoReconciliationForAllProjections(ModelExecuteOptions.isReconcile(options));
return syncContext;
}

public <F extends ObjectType> LensContext<F> createRecomputeProjectionContext(
PrismObject<ShadowType> shadow, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
PrismObject<ShadowType> shadow, ModelExecuteOptions options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
provisioningService.applyDefinition(shadow, result);
LensContext<F> syncContext = new LensContext<F>(null,
prismContext, provisioningService);
LensProjectionContext projectionContext = syncContext.createProjectionContext();
projectionContext.setLoadedObject(shadow);
projectionContext.setOid(shadow.getOid());
projectionContext.setDoReconciliation(true);
projectionContext.setDoReconciliation(ModelExecuteOptions.isReconcile(options));
syncContext.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE));
return syncContext;
}
Expand Down

0 comments on commit de1b3a8

Please sign in to comment.