Skip to content

Commit

Permalink
Recording provisioning operations (delete only). Using optimistic loc…
Browse files Browse the repository at this point in the history
…king.
  • Loading branch information
semancik committed Aug 30, 2017
1 parent 26d852e commit 3e3237f
Show file tree
Hide file tree
Showing 10 changed files with 463 additions and 98 deletions.
Expand Up @@ -90,6 +90,7 @@ public Boolean isEnabled() {

public void setEnabled(Boolean enabled) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
this.enabled = enabled;
}

Expand All @@ -99,6 +100,7 @@ public Date getValidFrom() {

public void setValidFrom(Date validFrom) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
this.validFrom = validFrom;
}

Expand All @@ -108,6 +110,7 @@ public Date getValidTo() {

public void setValidTo(Date validTo) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
this.validTo = validTo;
}

Expand Down Expand Up @@ -151,6 +154,7 @@ public void replaceAttributeValue(String name, Object value) throws SchemaViolat

public void replaceAttributeValues(String name, Collection<Object> values) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
Set<Object> currentValues = attributes.get(name);
if (currentValues == null) {
currentValues = new HashSet<Object>();
Expand All @@ -165,6 +169,7 @@ public void replaceAttributeValues(String name, Collection<Object> values) throw

public void replaceAttributeValues(String name, Object... values) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
Set<Object> currentValues = attributes.get(name);
if (currentValues == null) {
currentValues = new HashSet<Object>();
Expand All @@ -189,6 +194,7 @@ public void addAttributeValue(String name, Object value) throws SchemaViolationE

public void addAttributeValues(String name, Collection<Object> valuesToAdd) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
Set<Object> currentValues = attributes.get(name);
if (currentValues == null) {
currentValues = new HashSet<Object>();
Expand All @@ -202,6 +208,7 @@ public void addAttributeValues(String name, Collection<Object> valuesToAdd) thro

public void addAttributeValues(String name, String... valuesToAdd) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
Set<Object> currentValues = attributes.get(name);
if (currentValues == null) {
currentValues = new HashSet<Object>();
Expand All @@ -215,6 +222,7 @@ public void addAttributeValues(String name, String... valuesToAdd) throws Schema

private void addAttributeValue(String attrName, Set<Object> currentValues, Object valueToAdd) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
if (resource != null && !resource.isTolerateDuplicateValues()) {
for (Object currentValue: currentValues) {
if (currentValue.equals(valueToAdd)) {
Expand Down Expand Up @@ -253,6 +261,7 @@ public void removeAttributeValue(String name, Object value) throws SchemaViolati

public void removeAttributeValues(String name, Collection<Object> values) throws SchemaViolationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkModifyBreak();
delayOperation();
Set<Object> currentValues = attributes.get(name);
if (currentValues == null) {
currentValues = new HashSet<Object>();
Expand Down Expand Up @@ -381,6 +390,12 @@ private void recordModify() {
resource.recordModify(this);
}
}

private void delayOperation() {
if (resource != null) {
resource.delayOperation();
}
}

protected void checkSchema(String attrName, Collection<Object> values, String operationName) throws SchemaViolationException {
if (resource == null || !resource.isEnforceSchema()) {
Expand Down
Expand Up @@ -71,6 +71,7 @@
public class DummyResource implements DebugDumpable {

private static final Trace LOGGER = TraceManager.getTrace(DummyResource.class);
private static final Random RND = new Random();

public static final String ATTRIBUTE_CONNECTOR_TO_STRING = "connectorToString";
public static final String ATTRIBUTE_CONNECTOR_STATIC_VAL = "connectorStaticVal";
Expand Down Expand Up @@ -100,6 +101,7 @@ public class DummyResource implements DebugDumpable {
private int writeOperationCount = 0;
private int groupMembersReadCount = 0;
private Collection<String> forbiddenNames;
private int operationDelayRange = 0;

/**
* There is a monster that loves to eat cookies.
Expand Down Expand Up @@ -173,6 +175,8 @@ public void reset() {
syncStyle = DummySyncStyle.NONE;
deltas.clear();
latestSyncToken = 0;
writeOperationCount = 0;
operationDelayRange = 0;
resetBreakMode();
}

Expand Down Expand Up @@ -354,6 +358,14 @@ public void setForbiddenNames(Collection<String> forbiddenNames) {
this.forbiddenNames = forbiddenNames;
}

public int getOperationDelayRange() {
return operationDelayRange;
}

public void setOperationDelayRange(int operationDelayRange) {
this.operationDelayRange = operationDelayRange;
}

public boolean isMonsterization() {
return monsterization;
}
Expand Down Expand Up @@ -401,6 +413,7 @@ public void recordGroupMembersReadCount() {

public DummyObjectClass getAccountObjectClass() throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
breakIt(schemaBreakMode, "schema");
delayOperation();
return accountObjectClass;
}

Expand Down Expand Up @@ -431,6 +444,7 @@ public int getNumberOfObjectclasses() {
public Collection<DummyAccount> listAccounts() throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkBlockOperations();
breakIt(getBreakMode, "get");
delayOperation();
return accounts.values();
}

Expand All @@ -439,6 +453,7 @@ private <T extends DummyObject> T getObjectByName(Map<String,T> map, String name
throw new IllegalStateException("Attempt to search object by name while resource is in non-unique name mode");
}
checkBlockOperations();
delayOperation();
if (checkBreak) {
breakIt(getBreakMode, "get");
}
Expand Down Expand Up @@ -482,6 +497,7 @@ private <T extends DummyObject> T getObjectById(Class<T> expectedClass, String i
if (checkBreak) {
breakIt(getBreakMode, "get");
}
delayOperation();
DummyObject dummyObject = allObjects.get(id);
if (dummyObject == null) {
return null;
Expand Down Expand Up @@ -527,25 +543,29 @@ public DummyOrg getOrgById(String id, boolean checkBreak) throws ConnectExceptio
public Collection<DummyGroup> listGroups() throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkBlockOperations();
breakIt(getBreakMode, "get");
delayOperation();
return groups.values();
}

public Collection<DummyPrivilege> listPrivileges() throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkBlockOperations();
breakIt(getBreakMode, "get");
delayOperation();
return privileges.values();
}

public Collection<DummyOrg> listOrgs() throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkBlockOperations();
breakIt(getBreakMode, "get");
delayOperation();
return orgs.values();
}

private synchronized <T extends DummyObject> String addObject(Map<String,T> map, T newObject) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
checkBlockOperations();
recordWriteOperation("add");
breakIt(addBreakMode, "add");
delayOperation();

Class<? extends DummyObject> type = newObject.getClass();
String normalName = normalize(newObject.getName());
Expand Down Expand Up @@ -595,6 +615,7 @@ private synchronized <T extends DummyObject> void deleteObjectByName(Class<T> ty
checkBlockOperations();
recordWriteOperation("delete");
breakIt(deleteBreakMode, "delete");
delayOperation();

String normalName = normalize(name);
T existingObject;
Expand Down Expand Up @@ -638,6 +659,7 @@ private synchronized <T extends DummyObject> void deleteObjectById(Class<T> type
checkBlockOperations();
recordWriteOperation("delete");
breakIt(deleteBreakMode, "delete");
delayOperation();

DummyObject object = allObjects.get(id);
if (object == null) {
Expand Down Expand Up @@ -675,6 +697,7 @@ private <T extends DummyObject> void renameObject(Class<T> type, Map<String,T> m
checkBlockOperations();
recordWriteOperation("modify");
breakIt(modifyBreakMode, "modify");
delayOperation();

T existingObject;
if (enforceUniqueName) {
Expand Down Expand Up @@ -888,6 +911,20 @@ void breakIt(BreakMode breakMode, String operation) throws ConnectException, Fil
}
}

void delayOperation() {
if (operationDelayRange == 0) {
return;
}
int delay = RND.nextInt(operationDelayRange);
LOGGER.debug("Delaying dummy {} operation for {} ms", instanceName, delay);
try {
Thread.sleep(delay);
LOGGER.debug("Operation delay on dummy {} wait done", instanceName);
} catch (InterruptedException e) {
LOGGER.debug("Operation delay on dummy {} interrupted: {}", instanceName, e.getMessage());
}
}

private synchronized void checkBlockOperations() {
if (blockOperations) {
try {
Expand Down
Expand Up @@ -695,4 +695,16 @@ public static void validateObjectClassDefinition(ObjectClassComplexTypeDefinitio
throw new SchemaException("No identifiers in definition of object class "+objectClassDefinition.getTypeName()+" in resource schema of "+resource);
}
}

public static RecordPendingOperationsType getRecordPendingOperations(ResourceType resourceType) {
ResourceConsistencyType consistencyType = resourceType.getConsistency();
if (consistencyType == null) {
return RecordPendingOperationsType.ASYNCHRONOUS;
}
RecordPendingOperationsType recordPendingOperations = consistencyType.getRecordPendingOperations();
if (recordPendingOperations == null) {
return RecordPendingOperationsType.ASYNCHRONOUS;
}
return recordPendingOperations;
}
}
Expand Up @@ -779,7 +779,10 @@ public <T extends ObjectType> void deleteObject(Class<T> type, String oid, Provi
}
LOGGER.trace("**PROVISIONING: Finished deleting object.");

result.computeStatus();
if (!result.isInProgress()) {
// This is the case when there is already a conflicting pending operation.
result.computeStatus();
}
result.cleanupResult();
}

Expand Down
Expand Up @@ -808,6 +808,12 @@ public void deleteShadow(PrismObject<ShadowType> shadow, ProvisioningOperationOp

applyAttributesDefinition(ctx, shadow);

PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingDeleteOperationBeforeExecution(ctx, shadow, task, parentResult);
if (duplicateOperation != null) {
parentResult.recordInProgress();
return;
}

LOGGER.trace("Deleting object {} from the resource {}.", shadow, ctx.getResource());

AsynchronousOperationResult asyncReturnValue = null;
Expand Down

0 comments on commit 3e3237f

Please sign in to comment.