org.infinispan.interceptors.locking.AbstractTxLockingInterceptor Maven / Gradle / Ivy
package org.infinispan.interceptors.locking;
import org.infinispan.commands.read.GetAllCommand;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.commands.tx.RollbackCommand;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.configuration.cache.Configurations;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.partitionhandling.impl.PartitionHandlingManager;
import org.infinispan.remoting.rpc.RpcManager;
import org.infinispan.statetransfer.OutdatedTopologyException;
import org.infinispan.util.concurrent.locks.LockUtil;
import org.infinispan.util.concurrent.locks.PendingLockManager;
import org.infinispan.util.logging.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
import static org.infinispan.commons.util.Util.toStr;
/**
* Base class for transaction based locking interceptors.
*
* @author [email protected]
* @deprecated Since 8.2, no longer public API.
*/
@Deprecated
public abstract class AbstractTxLockingInterceptor extends AbstractLockingInterceptor {
private boolean trace = getLog().isTraceEnabled();
protected RpcManager rpcManager;
private PartitionHandlingManager partitionHandlingManager;
private PendingLockManager pendingLockManager;
@Inject
public void setDependencies(RpcManager rpcManager,
PartitionHandlingManager partitionHandlingManager,
PendingLockManager pendingLockManager) {
this.rpcManager = rpcManager;
this.partitionHandlingManager = partitionHandlingManager;
this.pendingLockManager = pendingLockManager;
}
@Override
public Object visitRollbackCommand(TxInvocationContext ctx, RollbackCommand command) throws Throwable {
try {
return invokeNextInterceptor(ctx, command);
} finally {
lockManager.unlockAll(ctx);
}
}
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
if (command.hasFlag(Flag.PUT_FOR_EXTERNAL_READ)) {
// Cache.putForExternalRead() is non-transactional
return visitNonTxDataWriteCommand(ctx, command);
}
return visitDataWriteCommand(ctx, command);
}
@Override
public Object visitGetAllCommand(InvocationContext ctx, GetAllCommand command) throws Throwable {
try {
return super.visitGetAllCommand(ctx, command);
} finally {
//when not invoked in an explicit tx's scope the get is non-transactional(mainly for efficiency).
//locks need to be released in this situation as they might have been acquired from L1.
if (!ctx.isInTxScope()) lockManager.unlockAll(ctx);
}
}
@Override
public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable {
boolean releaseLocks = releaseLockOnTxCompletion(ctx);
try {
return super.visitCommitCommand(ctx, command);
} catch (OutdatedTopologyException e) {
releaseLocks = false;
throw e;
} finally {
if (releaseLocks) lockManager.unlockAll(ctx);
}
}
protected final Object invokeNextAndCommitIf1Pc(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
Object result = invokeNextInterceptor(ctx, command);
if (command.isOnePhaseCommit() && releaseLockOnTxCompletion(ctx)) {
lockManager.unlockAll(ctx);
}
return result;
}
/**
* The backup (non-primary) owners keep a "backup lock" for each key they received in a lock/prepare command.
* Normally there can be many transactions holding the backup lock at the same time, but when the secondary owner
* becomes a primary owner a new transaction trying to obtain the "real" lock will have to wait for all backup
* locks to be released. The backup lock will be released either by a commit/rollback/unlock command or by
* the originator leaving the cluster (if recovery is disabled).
*
* @return {@code true} if the key was really locked.
*/
protected final boolean lockOrRegisterBackupLock(TxInvocationContext> ctx, Object key, long lockTimeout)
throws InterruptedException {
switch (LockUtil.getLockOwnership(key, cdl)) {
case PRIMARY:
if (trace) {
getLog().tracef("Acquiring locks on %s.", toStr(key));
}
checkPendingAndLockKey(ctx, key, lockTimeout);
return true;
case BACKUP:
if (trace) {
getLog().tracef("Acquiring backup locks on %s.", key);
}
ctx.getCacheTransaction().addBackupLockForKey(key);
return false;
default:
return false;
}
}
/**
* Same as {@link #lockOrRegisterBackupLock(TxInvocationContext, Object, long)}
*
* @return a collection with the keys locked.
*/
protected final Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy