) (parameters.length>5 ? parameters[5] : Collections.EMPTY_SET); //TODO remove conditional check in future - eases migration for now
}
@Override
@@ -174,6 +179,7 @@ public String toString() {
return "ReplaceCommand{" +
"oldValue=" + oldValue +
", newValue=" + newValue +
+ ", flags=" + flags +
", successful=" + successful +
'}';
}
diff --git a/core/src/main/java/org/infinispan/commands/write/WriteCommand.java b/core/src/main/java/org/infinispan/commands/write/WriteCommand.java
index 6da46589e2d9..da39c307b75b 100644
--- a/core/src/main/java/org/infinispan/commands/write/WriteCommand.java
+++ b/core/src/main/java/org/infinispan/commands/write/WriteCommand.java
@@ -1,5 +1,6 @@
package org.infinispan.commands.write;
+import org.infinispan.commands.FlagAffectedCommand;
import org.infinispan.commands.VisitableCommand;
import java.util.Set;
@@ -10,7 +11,7 @@
* @author Manik Surtani
* @since 4.0
*/
-public interface WriteCommand extends VisitableCommand {
+public interface WriteCommand extends VisitableCommand, FlagAffectedCommand {
/**
* Some commands may want to provide information on whether the command was successful or not. This is different
* from a failure, which usually would result in an exception being thrown. An example is a putIfAbsent() not doing
diff --git a/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java b/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
index a91ec857a674..3cd7c8b9887b 100644
--- a/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
+++ b/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
@@ -240,6 +240,7 @@ public final boolean acquireLock(InvocationContext ctx, Object key) throws Inter
return false;
}
+ //TODO resolve code duplication with org.infinispan.util.concurrent.locks.LockManagerImpl.getLockAcquisitionTimeout(InvocationContext)
private long getLockAcquisitionTimeout(InvocationContext ctx) {
return ctx.hasFlag(Flag.ZERO_LOCK_ACQUISITION_TIMEOUT) ?
0 : configuration.getLockAcquisitionTimeout();
diff --git a/core/src/main/java/org/infinispan/context/Flag.java b/core/src/main/java/org/infinispan/context/Flag.java
index 494bc7150041..fd92908d8f13 100644
--- a/core/src/main/java/org/infinispan/context/Flag.java
+++ b/core/src/main/java/org/infinispan/context/Flag.java
@@ -1,5 +1,9 @@
package org.infinispan.context;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
import org.infinispan.Cache;
import org.infinispan.config.Configuration;
import org.infinispan.AdvancedCache;
@@ -93,8 +97,9 @@ public enum Flag {
*/
SKIP_CACHE_LOAD,
/**
- * Swallows any exceptions, logging them instead at a low log level. Will prevent a failing operation from
- * affecting any ongoing JTA transactions as well.
+ * Swallows any exceptions, logging them instead at a low log level. Will prevent a failing operation from
+ * affecting any ongoing JTA transactions as well.
+ * This Flag will not be replicated to remote nodes, but it will still protect the invoker from remote exceptions.
*/
FAIL_SILENTLY,
/**
@@ -113,5 +118,28 @@ public enum Flag {
/**
* If this flag is enabled, if a cache store is shared, then storage to the store is skipped.
*/
- SKIP_SHARED_CACHE_STORE
+ SKIP_SHARED_CACHE_STORE;
+
+ /**
+ * Creates a copy of a Flag Set removing instances of FAIL_SILENTLY.
+ * The copy might be the same instance if no change is required,
+ * and should be considered immutable.
+ * @param flags
+ * @return might return the same instance
+ */
+ protected static Set copyWithouthRemotableFlags(Set flags) {
+ //FAIL_SILENTLY should not be sent to remote nodes
+ if (flags.contains(Flag.FAIL_SILENTLY)) {
+ EnumSet copy = EnumSet.copyOf(flags);
+ copy.remove(Flag.FAIL_SILENTLY);
+ if (copy.isEmpty()) {
+ return Collections.emptySet();
+ }
+ else {
+ return copy;
+ }
+ } else {
+ return flags;
+ }
+ }
}
diff --git a/core/src/main/java/org/infinispan/context/FlagContainer.java b/core/src/main/java/org/infinispan/context/FlagContainer.java
index e9545794f3e2..6fb51907335c 100644
--- a/core/src/main/java/org/infinispan/context/FlagContainer.java
+++ b/core/src/main/java/org/infinispan/context/FlagContainer.java
@@ -21,5 +21,4 @@ public interface FlagContainer {
void reset();
- boolean isFlagsUninitialized();
}
diff --git a/core/src/main/java/org/infinispan/context/InvocationContextContainer.java b/core/src/main/java/org/infinispan/context/InvocationContextContainer.java
index 5c01001bba2c..7b5c066685da 100644
--- a/core/src/main/java/org/infinispan/context/InvocationContextContainer.java
+++ b/core/src/main/java/org/infinispan/context/InvocationContextContainer.java
@@ -1,5 +1,6 @@
package org.infinispan.context;
+import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.context.impl.RemoteTxInvocationContext;
import org.infinispan.context.impl.NonTxInvocationContext;
@@ -56,7 +57,14 @@ public interface InvocationContextContainer {
* The context is also associated with the current thread, so further calls to
* {@link #getInvocationContext()} will return same instance.
*/
- NonTxInvocationContext createRemoteInvocationContext();
+ InvocationContext createRemoteInvocationContext();
+
+ /**
+ * As {@link #createRemoteInvocationContext()}, but returning the flags to the context from
+ * the Command if any Flag was set.
+ * @param cacheCommand
+ */
+ InvocationContext createRemoteInvocationContextForCommand(VisitableCommand cacheCommand);
/**
* Returns the {@link InvocationContext} that is currently associated with the calling thread.
@@ -77,4 +85,5 @@ public interface InvocationContextContainer {
* Associates the supplied {@link InvocationContext} with the calling thread.
*/
void resume(InvocationContext ic);
+
}
diff --git a/core/src/main/java/org/infinispan/context/InvocationContextContainerImpl.java b/core/src/main/java/org/infinispan/context/InvocationContextContainerImpl.java
index 057e0bd8c68f..5faae4da0f69 100644
--- a/core/src/main/java/org/infinispan/context/InvocationContextContainerImpl.java
+++ b/core/src/main/java/org/infinispan/context/InvocationContextContainerImpl.java
@@ -21,7 +21,11 @@
*/
package org.infinispan.context;
+import java.util.Set;
+
import org.infinispan.CacheException;
+import org.infinispan.commands.FlagAffectedCommand;
+import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.context.impl.NonTxInvocationContext;
import org.infinispan.context.impl.RemoteTxInvocationContext;
@@ -111,6 +115,19 @@ public NonTxInvocationContext createNonTxInvocationContext() {
icTl.set(remoteTxContext);
return remoteTxContext;
}
+
+ @Override
+ public InvocationContext createRemoteInvocationContextForCommand(VisitableCommand cacheCommand) {
+ InvocationContext context = createRemoteInvocationContext();
+ if (cacheCommand != null && cacheCommand instanceof FlagAffectedCommand) {
+ FlagAffectedCommand command = (FlagAffectedCommand) cacheCommand;
+ Set flags = command.getFlags();
+ if (flags != null && !flags.isEmpty()) {
+ return new InvocationContextFlagsOverride(context, flags);
+ }
+ }
+ return context;
+ }
public NonTxInvocationContext createRemoteInvocationContext() {
InvocationContext existing = icTl.get();
@@ -149,4 +166,5 @@ private Transaction getRunningTx() {
throw new CacheException(e);
}
}
+
}
\ No newline at end of file
diff --git a/core/src/main/java/org/infinispan/context/InvocationContextFlagsOverride.java b/core/src/main/java/org/infinispan/context/InvocationContextFlagsOverride.java
new file mode 100644
index 000000000000..c5b2a625f23d
--- /dev/null
+++ b/core/src/main/java/org/infinispan/context/InvocationContextFlagsOverride.java
@@ -0,0 +1,162 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+package org.infinispan.context;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.util.BidirectionalMap;
+
+
+/**
+ * Wraps an existing {@link InvocationContext} without changing the context directly
+ * but making sure the specified flags are considered enabled.
+ * @author Sanne Grinovero (C) 2011 Red Hat Inc.
+ * @since 5.0
+ */
+public class InvocationContextFlagsOverride implements InvocationContext {
+
+ private final InvocationContext delegate;
+ private final Set flags;
+
+ /**
+ * Wraps an existing {@link InvocationContext} without changing the context directly
+ * but making sure the specified flags are considered enabled.
+ * @param delegate
+ * @param flags
+ */
+ public InvocationContextFlagsOverride(InvocationContext delegate, Set flags) {
+ if (delegate == null || flags == null) {
+ throw new IllegalArgumentException("parameters shall not be null");
+ }
+ this.delegate = delegate;
+ this.flags = Flag.copyWithouthRemotableFlags(flags);
+ }
+
+ @Override
+ public CacheEntry lookupEntry(Object key) {
+ return delegate.lookupEntry(key);
+ }
+
+ @Override
+ public BidirectionalMap