/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.exec.plan; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Sets; import com.opengamma.engine.cache.CacheSelectHint; import com.opengamma.engine.calcnode.CalculationJobItem; import com.opengamma.engine.depgraph.DependencyGraph; import com.opengamma.engine.depgraph.DependencyNode; import com.opengamma.engine.depgraph.impl.DependencyNodeImpl; import com.opengamma.engine.function.FunctionParameters; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.engine.view.ExecutionLogMode; import com.opengamma.engine.view.impl.ExecutionLogModeSource; /** * Produces an execution plan for a graph that will execute on a single calculation node in a single thread. */ public class SingleNodeExecutionPlanner implements GraphExecutionPlanner { private static final Logger s_logger = LoggerFactory.getLogger(SingleNodeExecutionPlanner.class); private static final class JobBuilder { private final List<CalculationJobItem> _items; private final String _calcConfigName; private final ExecutionLogModeSource _logModeSource; private final Set<ValueSpecification> _sharedValues; private final Set<ValueSpecification> _privateValues; private final Map<ValueSpecification, ?> _terminals; private final Map<ValueSpecification, FunctionParameters> _parameters; private final Set<DependencyNode> _executed; public JobBuilder(final DependencyGraph graph, final ExecutionLogModeSource logModeSource, final Set<ValueSpecification> sharedValues, final Map<ValueSpecification, FunctionParameters> parameters) { final int size = graph.getSize(); _items = new ArrayList<CalculationJobItem>(size); _calcConfigName = graph.getCalculationConfigurationName(); _logModeSource = logModeSource; _sharedValues = sharedValues; _privateValues = new HashSet<ValueSpecification>(); _terminals = graph.getTerminalOutputs(); _parameters = parameters; _executed = Sets.newHashSetWithExpectedSize(size); } public void addNodes(final DependencyNode root) { if (!_executed.add(root)) { return; } final ValueSpecification[] inputs = DependencyNodeImpl.getInputValueArray(root); for (int i = 0; i < inputs.length; i++) { final ValueSpecification input = inputs[i]; if (!_sharedValues.contains(input)) { addNodes(root.getInputNode(i)); } } final ExecutionLogMode logMode = _logModeSource.getLogMode(_calcConfigName, root.getOutputValue(0)); final ValueSpecification[] outputs = DependencyNodeImpl.getOutputValueArray(root); FunctionParameters functionParameters = root.getFunction().getParameters(); for (ValueSpecification output : outputs) { if (_terminals.containsKey(output)) { _sharedValues.add(output); } else { _privateValues.add(output); } FunctionParameters newParameters = _parameters.get(output); if (newParameters != null) { functionParameters = newParameters; } } _items.add(new CalculationJobItem(root.getFunction().getFunctionId(), functionParameters, root.getTarget(), inputs, outputs, logMode)); } public List<CalculationJobItem> getJobItems() { return _items; } public CacheSelectHint getCacheHint() { s_logger.debug("{} private values, {} shared values in graph", _privateValues.size(), _sharedValues.size()); if (_privateValues.size() < _sharedValues.size()) { return CacheSelectHint.privateValues(_privateValues); } else { return CacheSelectHint.sharedValues(_sharedValues); } } } protected static PlannedJob createJob(final DependencyGraph graph, final ExecutionLogModeSource logModeSource, final Set<ValueSpecification> sharedValues, final Map<ValueSpecification, FunctionParameters> parameters) { final JobBuilder builder = new JobBuilder(graph, logModeSource, sharedValues, parameters); final int roots = graph.getRootCount(); iLoop: for (int i = 0; i < roots; i++) { //CSIGNORE final DependencyNode root = graph.getRootNode(i); final int outputs = root.getOutputCount(); for (int j = 0; j < outputs; j++) { if (sharedValues.contains(root.getOutputValue(j))) { continue iLoop; } } builder.addNodes(root); } return new PlannedJob(0, builder.getJobItems(), builder.getCacheHint(), null, null); } // GraphExecutionPlanner @Override public GraphExecutionPlan createPlan(final DependencyGraph graph, final ExecutionLogModeSource logModeSource, final long functionInitialisationId, final Set<ValueSpecification> sharedValues, final Map<ValueSpecification, FunctionParameters> parameters) { final PlannedJob job = createJob(graph, logModeSource, sharedValues, parameters); return new GraphExecutionPlan(graph.getCalculationConfigurationName(), functionInitialisationId, Collections.singleton(job), 1, job.getItems().size(), Double.NaN, Double.NaN); } }