/* * 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.dataplacement.DataPlacementManager; import org.infinispan.dataplacement.ObjectRequest; import org.infinispan.dataplacement.lookup.ObjectLookup; import org.infinispan.remoting.transport.Address; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; /** * The command used to send information among nodes * * @author Pedro Ruivo * @since 5.2 */ public class DataPlacementCommand extends BaseRpcCommand { public static final short COMMAND_ID = 102; private static final Log log = LogFactory.getLog(DataPlacementCommand.class); private DataPlacementManager dataPlacementManager; //message data private Type type; private long roundId; private int intValue; private ObjectRequest objectRequest; private ObjectLookup objectLookup; private Address[] members; public DataPlacementCommand(String cacheName, Type type, long roundId) { super(cacheName); this.type = type; this.roundId = roundId; } public DataPlacementCommand(String cacheName) { super(cacheName); } public final void initialize(DataPlacementManager dataPlacementManager) { this.dataPlacementManager = dataPlacementManager; } public void setObjectRequest(ObjectRequest objectRequest) { this.objectRequest = objectRequest; } public void setObjectLookup(ObjectLookup objectLookup) { this.objectLookup = objectLookup; } public void setIntValue(int intValue) { this.intValue = intValue; } public void setMembers(Address[] members) { this.members = members; } @Override public Object perform(InvocationContext ctx) throws Throwable { try { switch (type) { case DATA_PLACEMENT_REQUEST: dataPlacementManager.dataPlacementRequest(); break; case DATA_PLACEMENT_START: dataPlacementManager.startDataPlacement(roundId, members); break; case REMOTE_TOP_LIST_PHASE: dataPlacementManager.addRequest(getOrigin(), objectRequest, roundId); break; case OBJECT_LOOKUP_PHASE: dataPlacementManager.addObjectLookup(getOrigin(), objectLookup, roundId); break; case ACK_COORDINATOR_PHASE: dataPlacementManager.addAck(roundId, getOrigin()); break; case SET_COOL_DOWN_TIME: dataPlacementManager.internalSetCoolDownTime(intValue); break; case REPLICATION_DEGREE: dataPlacementManager.handleNewReplicationDegree(intValue); break; } } catch (Exception e) { log.errorf(e, "Exception caught while processing command. Type is %s", type); } return null; } @Override public byte getCommandId() { return COMMAND_ID; } @Override public Object[] getParameters() { switch (type) { case DATA_PLACEMENT_REQUEST: return new Object[]{(byte) type.ordinal()}; case DATA_PLACEMENT_START: Object[] retVal = new Object[2 + (members == null ? 0 : members.length)]; retVal[0] = (byte) type.ordinal(); retVal[1] = roundId; if (members != null && members.length != 0) { System.arraycopy(members, 0, retVal, 2, members.length); } return retVal; case ACK_COORDINATOR_PHASE: return new Object[]{(byte) type.ordinal(), roundId}; case REMOTE_TOP_LIST_PHASE: return new Object[]{(byte) type.ordinal(), roundId, objectRequest}; case OBJECT_LOOKUP_PHASE: return new Object[]{(byte) type.ordinal(), roundId, objectLookup}; case SET_COOL_DOWN_TIME: case REPLICATION_DEGREE: return new Object[]{(byte) type.ordinal(), intValue}; } throw new IllegalStateException("This should never happen!"); } @SuppressWarnings("unchecked") @Override public void setParameters(int commandId, Object[] parameters) { type = Type.values()[(Byte) parameters[0]]; switch (type) { case DATA_PLACEMENT_START: roundId = (Long) parameters[1]; if (parameters.length > 2) { members = new Address[parameters.length - 2]; for (int i = 0; i < members.length; ++i) { members[i] = (Address) parameters[i + 2]; } } break; case ACK_COORDINATOR_PHASE: roundId = (Long) parameters[1]; break; case REMOTE_TOP_LIST_PHASE: roundId = (Long) parameters[1]; objectRequest = (ObjectRequest) parameters[2]; break; case OBJECT_LOOKUP_PHASE: roundId = (Long) parameters[1]; objectLookup = (ObjectLookup) parameters[2]; break; case SET_COOL_DOWN_TIME: case REPLICATION_DEGREE: intValue = (Integer) parameters[1]; break; } } @Override public boolean isReturnValueExpected() { return false; } public static enum Type { /** * send to the coordinator to request the start of the algorithm */ DATA_PLACEMENT_REQUEST, /** * coordinator broadcast this to start the algorithm */ DATA_PLACEMENT_START, /** * contains the remote top list */ REMOTE_TOP_LIST_PHASE, /** * contains the object lookup */ OBJECT_LOOKUP_PHASE, /** * contains the final ACK to start the state transfer */ ACK_COORDINATOR_PHASE, /** * sets the new cool down period */ SET_COOL_DOWN_TIME, /** * sets the new replication degree */ REPLICATION_DEGREE } }