package org.infinispan.context; import java.util.Collections; import java.util.Map; import java.util.Set; import org.infinispan.container.entries.CacheEntry; import org.infinispan.remoting.transport.Address; /** * @author Mircea Markus * @author Sanne Grinovero * @deprecated Since 9.0, this class is going to be moved to an internal package. */ @Deprecated public final class SingleKeyNonTxInvocationContext implements InvocationContext { /** * It is possible for the key to only be wrapped but not locked, e.g. when a get takes place. */ private boolean isLocked; private Object key; private CacheEntry cacheEntry; //TODO move the Origin's address to the InvocationContextFactory when isOriginLocal=true -> all addresses are the same (Memory allocation cost) //(verify if this is worth it by looking at object alignment - would need a different implementation as pointing to null wouldn't help) private final Address origin; private Object lockOwner; public SingleKeyNonTxInvocationContext(final Address origin) { this.origin = origin; } @Override public boolean isOriginLocal() { return origin == null; } @Override public boolean isInTxScope() { return false; } @Override public Object getLockOwner() { return lockOwner; } @Override public void setLockOwner(Object lockOwner) { this.lockOwner = lockOwner; } @Override public InvocationContext clone() { try { return (InvocationContext) super.clone(); } catch (CloneNotSupportedException e) { throw new IllegalStateException("Impossible!", e); } } @Override public Set<Object> getLockedKeys() { return isLocked ? Collections.singleton(key) : Collections.emptySet(); } @Override public void clearLockedKeys() { isLocked = false; // TODO Dan: this shouldn't be necessary, but we don't clear the looked up keys // when retrying a non-tx command because of a topology change cacheEntry = null; } @Override public void addLockedKey(final Object key) { if (this.key == null) { // Set the key here this.key = key; } else if (!isKeyEquals(key)) { throw illegalStateException(); } isLocked = true; } private IllegalStateException illegalStateException() { return new IllegalStateException("This is a single key invocation context, using multiple keys shouldn't be possible"); } @Override public CacheEntry lookupEntry(final Object key) { if (this.key != null && isKeyEquals(key)) return cacheEntry; return null; } public boolean isKeyEquals(Object key) { return this.key == key || this.key.equals(key); } @Override public Map<Object, CacheEntry> getLookedUpEntries() { return cacheEntry == null ? Collections.emptyMap() : Collections.singletonMap(key, cacheEntry); } @Override public void putLookedUpEntry(final Object key, final CacheEntry e) { if (this.key == null) { // Set the key here this.key = key; } else if (!isKeyEquals(key)) { throw illegalStateException(); } this.cacheEntry = e; } @Override public void removeLookedUpEntry(final Object key) { if (this.key != null && isKeyEquals(key)) { this.cacheEntry = null; } } public Object getKey() { return key; } public CacheEntry getCacheEntry() { return cacheEntry; } @Override public Address getOrigin() { return origin; } @Override public ClassLoader getClassLoader() { return null; } @Override public void setClassLoader(ClassLoader classLoader) { // No-op } @Override public boolean hasLockedKey(final Object key) { return isLocked && isKeyEquals(key); } @Override public boolean isEntryRemovedInContext(final Object key) { CacheEntry ce = lookupEntry(key); return ce != null && ce.isRemoved() && ce.isChanged(); } public void resetState() { this.key = null; this.cacheEntry = null; this.isLocked = false; } }