/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.calcnode.stats; import org.fudgemsg.FudgeContext; import org.fudgemsg.FudgeMsgEnvelope; import org.fudgemsg.mapping.FudgeDeserializer; import com.opengamma.engine.calcnode.msg.Invocations; import com.opengamma.engine.calcnode.msg.Invocations.PerConfiguration; import com.opengamma.engine.calcnode.msg.Invocations.PerConfiguration.PerFunction; import com.opengamma.engine.calcnode.msg.RemoteCalcNodeMessage; import com.opengamma.engine.calcnode.msg.Scaling; import com.opengamma.transport.FudgeMessageReceiver; import com.opengamma.util.ArgumentChecker; /** * Receives statistics from a {@link FunctionInvocationStatisticsSender}. * <p> * This is run centrally and receives statistics from each node. * The statistics are aggregated into the {@code FunctionCost} instance. */ public class FunctionInvocationStatisticsReceiver implements FudgeMessageReceiver { /** * The underlying function cost implementation. */ private final FunctionCosts _underlying; /** * Creates an instance wrapping an underlying function cost instance. * * @param underlying the underlying function cost, not null */ public FunctionInvocationStatisticsReceiver(final FunctionCosts underlying) { ArgumentChecker.notNull(underlying, "underlying"); _underlying = underlying; } //------------------------------------------------------------------------- /** * Gets the underlying function cost. * * @return the function cost, not null */ public FunctionCosts getUnderlying() { return _underlying; } //------------------------------------------------------------------------- /** * Handle a message. * * @param underlying the underlying function cost, not null * @param invocations the invocations to handle, not null * @return the scaling factor, null if no remote invocation cost */ public static Scaling messageReceived(final FunctionCosts underlying, final Invocations invocations) { double remoteInvocationCost = 0; double localInvocationCost = 0; for (PerConfiguration configuration : invocations.getConfiguration()) { final FunctionCostsPerConfiguration configurationStats = underlying.getStatistics(configuration.getConfiguration()); for (PerFunction function : configuration.getFunction()) { final FunctionInvocationStatistics statistics = configurationStats.getStatistics(function.getIdentifier()); localInvocationCost += statistics.getInvocationCost(); statistics.recordInvocation(function.getCount(), function.getInvocation(), function.getDataInput(), function.getDataOutput()); remoteInvocationCost += function.getInvocation() / function.getCount(); } } if (remoteInvocationCost > 0) { return new Scaling(localInvocationCost / remoteInvocationCost); } else { return null; } } @Override public void messageReceived(final FudgeContext fudgeContext, final FudgeMsgEnvelope msgEnvelope) { final FudgeDeserializer deserializer = new FudgeDeserializer(fudgeContext); final RemoteCalcNodeMessage message = deserializer.fudgeMsgToObject(RemoteCalcNodeMessage.class, msgEnvelope.getMessage()); if (message instanceof Invocations) { messageReceived(getUnderlying(), (Invocations) message); } else { throw new UnsupportedOperationException("Unexpected message - " + message); } } }