/* * INESC-ID, Instituto de Engenharia de Sistemas e Computadores Investigação e Desevolvimento em Lisboa * Copyright 2013 INESC-ID and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3.0 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY 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 along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.commands.remote; import org.infinispan.context.InvocationContext; import org.infinispan.reconfigurableprotocol.manager.ReconfigurableReplicationManager; import java.util.concurrent.CountDownLatch; /** * Command use when switch between protocol to broadcast data between all members * * @author Pedro Ruivo * @since 5.2 */ public class ReconfigurableProtocolCommand extends BaseRpcCommand { public static final byte COMMAND_ID = 104; public static enum Type { SWITCH(false, true), REGISTER(false), DATA(true), SWITCH_REQ(false, true), SET_COOL_DOWN_TIME(true); final boolean hasData; final boolean hasBoolean; Type(boolean hasData, boolean hasBoolean) { this.hasData = hasData; this.hasBoolean = hasBoolean; } Type(boolean hasData) { this.hasData = hasData; this.hasBoolean = false; } } private ReconfigurableReplicationManager manager; private Type type; private String protocolId; private Object data; private boolean forceStop; private boolean abortOnStop; public ReconfigurableProtocolCommand(String cacheName, Type type, String protocolId) { super(cacheName); this.type = type; this.protocolId = protocolId; } public ReconfigurableProtocolCommand(String cacheName) { super(cacheName); } public final void init(ReconfigurableReplicationManager manager) { this.manager = manager; } @Override public final Object perform(InvocationContext ctx) throws Throwable { switch (type) { case SWITCH: CountDownLatch notifier = new CountDownLatch(1); manager.startSwitchTask(protocolId, forceStop, abortOnStop, notifier); notifier.await(); break; case REGISTER: manager.internalRegister(protocolId); break; case DATA: manager.handleProtocolData(protocolId, data, getOrigin()); break; case SWITCH_REQ: manager.switchTo(protocolId, forceStop, abortOnStop); break; case SET_COOL_DOWN_TIME: manager.internalSetSwitchCoolDownTime((Integer) data); break; default: break; } return null; } @Override public final byte getCommandId() { return COMMAND_ID; } @Override public final Object[] getParameters() { if (type.hasData) { return new Object[] {(byte)type.ordinal(), protocolId, data}; } if (type.hasBoolean) { byte bool = (byte) (forceStop ? 1 : 0); bool |= abortOnStop ? 1 << 1 : 0; return new Object[] {(byte)type.ordinal(), protocolId, bool}; } else { return new Object[] {(byte)type.ordinal(), protocolId}; } } @Override public final void setParameters(int commandId, Object[] parameters) { this.type = Type.values()[(Byte) parameters[0]]; this.protocolId = (String) parameters[1]; if (type.hasData) { data = parameters[2]; } else if (type.hasBoolean) { byte bool = (Byte) parameters[2]; forceStop = (bool & 1) != 0; abortOnStop = (bool & 1 << 1) != 0; } } @Override public final boolean isReturnValueExpected() { return false; } public final void setData(Object data) { this.data = data; } public final void setForceStop(boolean forceStop) { this.forceStop = forceStop; } public final void setAbortOnStop(boolean abortOnStop) { this.abortOnStop = abortOnStop; } @Override public String toString() { return String.format("ReconfigurableProtocolCommand{type=%s, protocolId='%s', data=%s, forceStop=%s, abortOnStop=%s}" , type, protocolId, data, forceStop, abortOnStop); } }