/* * 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.distribution.wrappers; import org.infinispan.commands.ReplicableCommand; import org.infinispan.commands.remote.ClusteredGetCommand; import org.infinispan.commands.remote.recovery.TxCompletionNotificationCommand; import org.infinispan.commands.tx.CommitCommand; import org.infinispan.commands.tx.PrepareCommand; import org.infinispan.commands.tx.RollbackCommand; import org.infinispan.commands.tx.VersionedCommitCommand; import org.infinispan.commands.tx.VersionedPrepareCommand; import org.infinispan.remoting.RpcException; import org.infinispan.remoting.responses.Response; import org.infinispan.remoting.rpc.ResponseFilter; import org.infinispan.remoting.rpc.ResponseMode; import org.infinispan.remoting.rpc.RpcManager; import org.infinispan.remoting.transport.Address; import org.infinispan.remoting.transport.Transport; import org.infinispan.remoting.transport.jgroups.JGroupsTransport; import org.infinispan.stats.TransactionsStatisticsRegistry; import org.infinispan.stats.translations.ExposedStatistics.IspnStats; import org.infinispan.util.concurrent.NotifyingNotifiableFuture; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.jgroups.blocks.RpcDispatcher; import org.jgroups.util.Buffer; import java.util.Collection; import java.util.Map; /** * @author Mircea Markus <mircea.markus@jboss.com> (C) 2011 Red Hat Inc. * @author Diego Didona <didona@gsd.inesc-id.pt> * @author Pedro Ruivo * @since 5.2 */ public class RpcManagerWrapper implements RpcManager { private static final Log log = LogFactory.getLog(RpcManagerWrapper.class); private final RpcManager actual; private final RpcDispatcher.Marshaller marshaller; public RpcManagerWrapper(RpcManager actual) { this.actual = actual; Transport t = actual.getTransport(); if (t instanceof JGroupsTransport) { marshaller = ((JGroupsTransport) t).getCommandAwareRpcDispatcher().getMarshaller(); } else { marshaller = null; } } @Override public Map<Address, Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean totalOrder){ long currentTime = System.nanoTime(); Map<Address, Response> ret = actual.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter, totalOrder); updateStats(rpcCommand, mode.isSynchronous(), currentTime, recipients); return ret; } @Override public Map<Address, Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, boolean totalOrder) { long currentTime = System.nanoTime(); Map<Address, Response> ret = actual.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, totalOrder); updateStats(rpcCommand, mode.isSynchronous(), currentTime, recipients); return ret; } @Override public Map<Address, Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout) { long currentTime = System.nanoTime(); Map<Address, Response> ret = actual.invokeRemotely(recipients, rpcCommand, mode, timeout); updateStats(rpcCommand, mode.isSynchronous(), currentTime, recipients); return ret; } @Override public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync, boolean totalOrder) throws RpcException { long currentTime = System.nanoTime(); actual.broadcastRpcCommand(rpc, sync, totalOrder); updateStats(rpc, sync, currentTime, null); } @Override public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync, boolean usePriorityQueue, boolean totalOrder) throws RpcException { long currentTime = System.nanoTime(); actual.broadcastRpcCommand(rpc, sync, usePriorityQueue, totalOrder); updateStats(rpc, sync, currentTime, null); } @Override public void broadcastRpcCommandInFuture(ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) { long currentTime = System.nanoTime(); actual.broadcastRpcCommandInFuture(rpc, future); updateStats(rpc, false, currentTime, null); } @Override public void broadcastRpcCommandInFuture(ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) { long currentTime = System.nanoTime(); actual.broadcastRpcCommandInFuture(rpc, usePriorityQueue, future); updateStats(rpc, false, currentTime, null); } @Override public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync) throws RpcException { long currentTime = System.nanoTime(); actual.invokeRemotely(recipients, rpc, sync); updateStats(rpc, sync, currentTime, recipients); } @Override public Map<Address, Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync, boolean usePriorityQueue, boolean totalOrder) throws RpcException { long currentTime = System.nanoTime(); Map<Address, Response> ret = actual.invokeRemotely(recipients, rpc, sync, usePriorityQueue, totalOrder); updateStats(rpc, sync, currentTime, recipients); return ret; } @Override public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) { long currentTime = System.nanoTime(); actual.invokeRemotelyInFuture(recipients, rpc, future); updateStats(rpc, false, currentTime, recipients); } @Override public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) { long currentTime = System.nanoTime(); actual.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future); updateStats(rpc, false, currentTime, recipients); } @Override public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future, long timeout) { long currentTime = System.nanoTime(); actual.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future, timeout); updateStats(rpc, false, currentTime, recipients); } @Override public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future, long timeout, boolean ignoreLeavers) { long currentTime = System.nanoTime(); actual.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future, timeout, ignoreLeavers); updateStats(rpc, false, currentTime, recipients); } @Override public Transport getTransport() { return actual.getTransport(); } @Override public Address getAddress() { return actual.getAddress(); } private void updateStats(ReplicableCommand command, boolean sync, long init, Collection<Address> recipients) { if (!TransactionsStatisticsRegistry.hasStatisticCollector() && !(command instanceof TxCompletionNotificationCommand)) { if (log.isTraceEnabled()) { log.tracef("Does not update stats for command %s. No statistic collector found", command); } return; } IspnStats durationStat; IspnStats counterStat; IspnStats recipientSizeStat; IspnStats commandSizeStat = null; switch (command.getCommandId()) { case PrepareCommand.COMMAND_ID: case VersionedPrepareCommand.COMMAND_ID: if (sync) { durationStat = IspnStats.RTT_PREPARE; counterStat = IspnStats.NUM_RTTS_PREPARE; } else { durationStat = IspnStats.ASYNC_PREPARE; counterStat = IspnStats.NUM_ASYNC_PREPARE; } recipientSizeStat = IspnStats.NUM_NODES_PREPARE; commandSizeStat = IspnStats.PREPARE_COMMAND_SIZE; break; case RollbackCommand.COMMAND_ID: if (sync) { durationStat = IspnStats.RTT_ROLLBACK; counterStat = IspnStats.NUM_RTTS_ROLLBACK; } else { durationStat = IspnStats.ASYNC_ROLLBACK; counterStat = IspnStats.NUM_ASYNC_ROLLBACK; } recipientSizeStat = IspnStats.NUM_NODES_ROLLBACK; break; case CommitCommand.COMMAND_ID: case VersionedCommitCommand.COMMAND_ID: if (sync) { durationStat = IspnStats.RTT_COMMIT; counterStat = IspnStats.NUM_RTTS_COMMIT; } else { durationStat = IspnStats.ASYNC_COMMIT; counterStat = IspnStats.NUM_ASYNC_COMMIT; } recipientSizeStat = IspnStats.NUM_NODES_COMMIT; commandSizeStat = IspnStats.COMMIT_COMMAND_SIZE; break; case TxCompletionNotificationCommand.COMMAND_ID: durationStat = IspnStats.ASYNC_COMPLETE_NOTIFY; counterStat = IspnStats.NUM_ASYNC_COMPLETE_NOTIFY; recipientSizeStat = IspnStats.NUM_NODES_COMPLETE_NOTIFY; if (log.isTraceEnabled()) { log.tracef("Update stats for command %s. Is sync? %s. Duration stat is %s, counter stats is %s, " + "recipient size stat is %s", command, sync, durationStat, counterStat, recipientSizeStat); } TransactionsStatisticsRegistry.addValueAndFlushIfNeeded(durationStat, System.nanoTime() - init, true); TransactionsStatisticsRegistry.incrementValueAndFlushIfNeeded(counterStat, true); TransactionsStatisticsRegistry.addValueAndFlushIfNeeded(recipientSizeStat, recipientListSize(recipients), true); return; case ClusteredGetCommand.COMMAND_ID: durationStat = IspnStats.RTT_GET; counterStat = IspnStats.NUM_RTTS_GET; recipientSizeStat = IspnStats.NUM_NODES_GET; commandSizeStat = IspnStats.CLUSTERED_GET_COMMAND_SIZE; break; default: if (log.isTraceEnabled()) { log.tracef("Does not update stats for command %s. The command is not needed", command); } return; } if (log.isTraceEnabled()) { log.tracef("Update stats for command %s. Is sync? %s. Duration stat is %s, counter stats is %s, " + "recipient size stat is %s", command, sync, durationStat, counterStat, recipientSizeStat); } TransactionsStatisticsRegistry.addValue(durationStat, System.nanoTime() - init); TransactionsStatisticsRegistry.incrementValue(counterStat); TransactionsStatisticsRegistry.addValue(recipientSizeStat, recipientListSize(recipients)); if (commandSizeStat != null) { TransactionsStatisticsRegistry.addValue(commandSizeStat, getCommandSize(command)); } } private int recipientListSize(Collection<Address> recipients) { return recipients == null ? actual.getTransport().getMembers().size() : recipients.size(); } private int getCommandSize(ReplicableCommand command) { try { Buffer buffer = marshaller.objectToBuffer(command); return buffer != null ? buffer.getLength() : 0; } catch (Exception e) { return 0; } } }