package org.infinispan.distribution.rehash; import java.util.Collections; import org.infinispan.AdvancedCache; import org.infinispan.commands.VisitableCommand; import org.infinispan.commands.functional.ReadWriteKeyCommand; import org.infinispan.commands.functional.ReadWriteKeyValueCommand; import org.infinispan.commands.write.PutKeyValueCommand; import org.infinispan.commands.write.PutMapCommand; import org.infinispan.commands.write.RemoveCommand; import org.infinispan.commands.write.ReplaceCommand; import org.infinispan.commands.write.ValueMatcher; /** * Represents a write operation to test. * * @author Dan Berindei * @since 6.0 */ public enum TestWriteOperation { PUT_CREATE(PutKeyValueCommand.class, "v1", ValueMatcher.MATCH_ALWAYS, null, null, "v1"), PUT_OVERWRITE(PutKeyValueCommand.class, "v1", ValueMatcher.MATCH_ALWAYS, "v0", "v0", "v1"), PUT_IF_ABSENT(PutKeyValueCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, null, null, null), REPLACE(ReplaceCommand.class, "v1", ValueMatcher.MATCH_NON_NULL, "v0", "v0", "v1"), REPLACE_EXACT(ReplaceCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, "v0", true, true), REMOVE(RemoveCommand.class, null, ValueMatcher.MATCH_NON_NULL, "v0", "v0", null), REMOVE_EXACT(RemoveCommand.class, null, ValueMatcher.MATCH_EXPECTED, "v0", true, true), PUT_MAP_CREATE(PutMapCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, null, false, false), // Functional put create must return null even on retry (as opposed to non-functional) PUT_CREATE_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_ALWAYS, null, null, null), // Functional put overwrite must return the previous value (as opposed to non-functional) PUT_OVERWRITE_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_ALWAYS, "v0", "v0", "v0"), PUT_IF_ABSENT_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, null, null, null), // Functional replace must return the previous value (as opposed to non-functional) REPLACE_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_NON_NULL, "v0", "v0", "v0"), REMOVE_FUNCTIONAL(ReadWriteKeyCommand.class, null, ValueMatcher.MATCH_NON_NULL, "v0", "v0", null), REPLACE_EXACT_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, "v0", true, true), REMOVE_EXACT_FUNCTIONAL(ReadWriteKeyValueCommand.class, null, ValueMatcher.MATCH_EXPECTED, "v0", true, true), // Functional replace REPLACE_META_FUNCTIONAL(ReadWriteKeyValueCommand.class, "v1", ValueMatcher.MATCH_EXPECTED, null, true, true) ; private final Class<? extends VisitableCommand> commandClass; private final Object value; private final ValueMatcher valueMatcher; private final Object previousValue; private final Object returnValue; // When retrying a write operation, we don't always have the previous value, so we sometimes // return the new value instead. For "exact" conditional operations, however, we always return the same value. // See https://issues.jboss.org/browse/ISPN-3422 private final Object returnValueWithRetry; TestWriteOperation(Class<? extends VisitableCommand> commandClass, Object value, ValueMatcher valueMatcher, Object previousValue, Object returnValue, Object returnValueWithRetry) { this.commandClass = commandClass; this.value = value; this.valueMatcher = valueMatcher; this.previousValue = previousValue; this.returnValue = returnValue; this.returnValueWithRetry = returnValueWithRetry; } public Class<? extends VisitableCommand> getCommandClass() { return commandClass; } public Object getValue() { return value; } public Object getPreviousValue() { return previousValue; } public Object getReturnValue() { return returnValue; } public Object perform(AdvancedCache<Object, Object> cache, Object key) { switch (this) { case PUT_CREATE: case PUT_OVERWRITE: case PUT_CREATE_FUNCTIONAL: case PUT_OVERWRITE_FUNCTIONAL: return cache.put(key, value); case PUT_IF_ABSENT: case PUT_IF_ABSENT_FUNCTIONAL: return cache.putIfAbsent(key, value); case REPLACE: case REPLACE_FUNCTIONAL: return cache.replace(key, value); case REPLACE_EXACT: case REPLACE_EXACT_FUNCTIONAL: return cache.replace(key, previousValue, value); case REMOVE: case REMOVE_FUNCTIONAL: return cache.remove(key); case REMOVE_EXACT: case REMOVE_EXACT_FUNCTIONAL: return cache.remove(key, previousValue); case PUT_MAP_CREATE: cache.putAll(Collections.singletonMap(key, value)); return null; default: throw new IllegalArgumentException("Unsupported operation: " + this); } } public ValueMatcher getValueMatcher() { return valueMatcher; } public Object getReturnValueWithRetry() { return returnValueWithRetry; } }