All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.interceptors.base.BaseStateTransferInterceptor Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.interceptors.base;

import org.infinispan.commands.TopologyAffectedCommand;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.commands.remote.GetKeysInGroupCommand;
import org.infinispan.commons.CacheException;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.context.InvocationContext;
import org.infinispan.distribution.group.GroupManager;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.remoting.RemoteException;
import org.infinispan.remoting.transport.jgroups.SuspectException;
import org.infinispan.statetransfer.OutdatedTopologyException;
import org.infinispan.statetransfer.StateTransferLock;
import org.infinispan.statetransfer.StateTransferManager;
import org.infinispan.topology.CacheTopology;
import org.infinispan.util.logging.Log;

import java.util.concurrent.TimeUnit;

/**
 * A base class for a state transfer interceptor. It contains the base code to avoid duplicating in the two current
 * different implementations.
 * 

* Also, it has some utilities methods with the most common logic. * * @author Pedro Ruivo * @since 7.0 */ public abstract class BaseStateTransferInterceptor extends CommandInterceptor { protected StateTransferManager stateTransferManager; private StateTransferLock stateTransferLock; private GroupManager groupManager; private long transactionDataTimeout; @Inject public void init(StateTransferLock stateTransferLock, Configuration configuration, StateTransferManager stateTransferManager, GroupManager groupManager) { this.stateTransferLock = stateTransferLock; this.stateTransferManager = stateTransferManager; this.groupManager = groupManager; transactionDataTimeout = configuration.clustering().sync().replTimeout(); } @Override public Object visitGetKeysInGroupCommand(InvocationContext ctx, GetKeysInGroupCommand command) throws Throwable { final String groupName = command.getGroupName(); final boolean isOwner = groupManager.isOwner(groupName); updateTopologyId(command); final int commandTopologyId = command.getTopologyId(); if (ctx.isOriginLocal()) { //invoke next and check for exception Object localResult; try { localResult = invokeNextInterceptor(ctx, command); //if we are not the owner, we rely on the reply from the primary owner. if (isOwner && currentTopologyId() != commandTopologyId) { localResult = retryVisitGetKeysInGroupCommand(ctx, command, commandTopologyId); } } catch (CacheException e) { Throwable ce = e; while (ce instanceof RemoteException) { ce = ce.getCause(); } if (!(ce instanceof OutdatedTopologyException) && !(ce instanceof SuspectException)) throw e; localResult = retryVisitGetKeysInGroupCommand(ctx, command, commandTopologyId); } return localResult; } else { Object result = invokeNextInterceptor(ctx, command); if (isOwner && currentTopologyId() != commandTopologyId) { throw new OutdatedTopologyException("Cache topology changed while the command was executing: expected " + commandTopologyId + ", got " + currentTopologyId()); } return result; } } protected final void logRetry(VisitableCommand command) { final Log log = getLog(); if (log.isTraceEnabled()) { log.tracef("Retrying command because of topology change: %s", command); } } protected final int currentTopologyId() { final CacheTopology cacheTopology = stateTransferManager.getCacheTopology(); return cacheTopology == null ? -1 : cacheTopology.getTopologyId(); } protected final void waitForTransactionData(int topologyId) throws InterruptedException { stateTransferLock.waitForTransactionData(topologyId, transactionDataTimeout, TimeUnit.MILLISECONDS); } protected final void updateTopologyId(TopologyAffectedCommand command) throws InterruptedException { // set the topology id if it was not set before (ie. this is local command) // TODO Make tx commands extend FlagAffectedCommand so we can use CACHE_MODE_LOCAL in TransactionTable.cleanupStaleTransactions if (command.getTopologyId() == -1) { CacheTopology cacheTopology = stateTransferManager.getCacheTopology(); if (cacheTopology != null) { command.setTopologyId(cacheTopology.getTopologyId()); } } } private Object retryVisitGetKeysInGroupCommand(InvocationContext context, GetKeysInGroupCommand command, int commandTopologyId) throws Throwable { logRetry(command); // We increment the topology id so that updateTopologyIdAndWaitForTransactionData waits for the next topology. // Without this, we could retry the command too fast and we could get the OutdatedTopologyException again. int newTopologyId = Math.max(currentTopologyId(), commandTopologyId + 1); command.setTopologyId(newTopologyId); waitForTransactionData(newTopologyId); return visitGetKeysInGroupCommand(context, command); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy