package org.infinispan.remoting.inboundhandler.action; import org.infinispan.remoting.inboundhandler.TrianglePerCacheInboundInvocationHandler; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; /** * An {@link Action} that checks if the command is the next to be executed. * <p> * This action is used by the triangle algorithm to order updates from the primary owner to the backup owner. * * @author Pedro Ruivo * @since 9.0 */ public class TriangleOrderAction implements Action { private static final Log log = LogFactory.getLog(TriangleOrderAction.class); private static final boolean trace = log.isTraceEnabled(); private final Object key; private final long sequenceNumber; private final TrianglePerCacheInboundInvocationHandler handler; private volatile int segmentId = -1; public TriangleOrderAction(TrianglePerCacheInboundInvocationHandler handler, long sequenceNumber, Object key) { this.handler = handler; this.sequenceNumber = sequenceNumber; this.key = key; } @Override public ActionStatus check(ActionState state) { int localSegmentId = computeSegmentIdIfNeeded(); if (trace) { log.tracef("Checking if next for segment %s and sequence %s", localSegmentId, sequenceNumber); } return handler.getTriangleOrderManager().isNext(localSegmentId, sequenceNumber, state.getCommandTopologyId()) ? ActionStatus.READY : ActionStatus.NOT_READY; } @Override public void onFinally(ActionState state) { handler.getTriangleOrderManager().markDelivered(computeSegmentIdIfNeeded(), sequenceNumber, state.getCommandTopologyId()); handler.getRemoteExecutor().checkForReadyTasks(); } private int computeSegmentIdIfNeeded() { int tmp = segmentId; if (tmp == -1) { tmp = handler.getClusteringDependentLogic().getCacheTopology().getSegment(key); segmentId = tmp; } return tmp; } }