Package com.opengamma.engine.depgraph

Source Code of com.opengamma.engine.depgraph.TargetDigestStep

/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.depgraph;

import java.util.Collection;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.CompiledFunctionDefinition;
import com.opengamma.engine.function.ParameterizedFunction;
import com.opengamma.engine.function.resolver.ResolutionRule;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.util.test.Profiler;
import com.opengamma.util.tuple.Triple;

/**
* Calculates the target digest and considers existing nodes for a pattern to use for direct application.
* <p>
* Note that this step will produce unexpected dependency graphs if functions in the repository have applicability rules or behaviors that differ for two targets with the same digest. Care should be
* taken when enabling this algorithm.
*/
/* package */final class TargetDigestStep extends FunctionIterationStep.IterationBaseStep {

  private static final Logger s_logger = LoggerFactory.getLogger(TargetDigestStep.class);

  private static final Profiler s_profilerSuccess = Profiler.create(TargetDigestStep.class, "success");
  private static final Profiler s_profilerWaste = Profiler.create(TargetDigestStep.class, "waste");

  private GraphBuildingContext.ResolutionIterator _resolutions;
  private long _timeSpent;
  private ValueRequirement _desiredValue;

  public TargetDigestStep(final ResolveTask task, final GraphBuildingContext.ResolutionIterator resolutions) {
    super(task);
    _resolutions = resolutions;
  }

  @Override
  protected boolean run(final GraphBuildingContext context) {
    final ValueRequirement requirement = getValueRequirement();
    final ComputationTarget target = getComputationTarget(context);
    if (_resolutions != null) {
      final long startTime = System.nanoTime();
      try {
        final ValueProperties constraints = requirement.getConstraints();
        do {
          final ValueProperties properties = _resolutions.getValueProperties();
          if (constraints.isSatisfiedBy(properties)) {
            s_logger.info("Trying digest resolution {} for {}", properties, requirement);
            final ParameterizedFunction function = _resolutions.getFunction();
            final CompiledFunctionDefinition functionDef = function.getFunction();
            if (!functionDef.getTargetType().isCompatible(target.getType())) {
              s_logger.debug("Function {} type is not compatible with {}", functionDef, target);
              continue;
            }
            final ComputationTarget adjustedTarget = ResolutionRule.adjustTarget(functionDef.getTargetType(), target);
            if (!functionDef.canApplyTo(context.getCompilationContext(), adjustedTarget)) {
              s_logger.debug("Function {} cannot be applied to {}", functionDef, target);
              continue;
            }
            Collection<ValueSpecification> results = functionDef.getResults(context.getCompilationContext(), adjustedTarget);
            if ((results == null) || results.isEmpty()) {
              s_logger.debug("Function {} applied to {} produced no results", functionDef, target);
              continue;
            }
            final ValueProperties composedConstraints;
            if (constraints.getValues(ValuePropertyNames.FUNCTION) != null) {
              composedConstraints = properties.compose(constraints);
            } else {
              // Note: some functions on OG-Financial do stupid things with their desired value if it constrains the function identifier.
              // it is easier to take action here rather than work through to fix them.
              composedConstraints = properties.withoutAny(ValuePropertyNames.FUNCTION).compose(constraints);
            }
            ValueRequirement composedRequirement = null;
            ValueSpecification matchedResult = null;
            ValueSpecification resolvedOutput = null;
            for (ValueSpecification result : results) {
              // value names are interned
              if (requirement.getValueName() == result.getValueName()) {
                if (composedConstraints.isSatisfiedBy(result.getProperties())) {
                  if (composedConstraints == constraints) {
                    composedRequirement = requirement;
                  } else {
                    composedRequirement = new ValueRequirement(requirement.getValueName(), requirement.getTargetReference(), composedConstraints);
                  }
                  matchedResult = context.simplifyType(result);
                  resolvedOutput = matchedResult.compose(composedRequirement);
                  if (resolvedOutput != matchedResult) {
                    resolvedOutput = context.simplifyType(resolvedOutput);
                    s_logger.debug("Composed original output of {} to {}", matchedResult, resolvedOutput);
                  }
                  break;
                }
              }
            }
            if (resolvedOutput == null) {
              s_logger.debug("Requirement {} not satisfied by results {}", requirement, results);
              continue;
            }
            s_logger.info("Inferred requirement {} for {}", composedRequirement, requirement);
            _desiredValue = composedRequirement;
            if (!_resolutions.hasNext()) {
              _resolutions = null;
            }
            functionApplication(context, resolvedOutput, Triple.of(function, matchedResult, context.simplifyTypes(results)));
            return true;
          } else {
            s_logger.debug("Ignoring digest resolution {} for {}", properties, requirement);
          }
        } while (_resolutions.hasNext());
      } finally {
        _timeSpent += System.nanoTime() - startTime;
      }
      s_profilerWaste.tick(_timeSpent);
    }
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("No more digest resolutions for {} ({}us wasted)", requirement, (double) _timeSpent / 1e3);
    }
    GetFunctionsStep.getFunctions(target, context, this);
    return true;
  }

  @Override
  protected ValueRequirement getDesiredValue() {
    return _desiredValue;
  }

  @Override
  protected ValueSpecification getResolvedOutputs(final GraphBuildingContext context, final Set<ValueSpecification> newOutputValues, final Set<ValueSpecification> resolvedOutputValues) {
    final ValueRequirement desiredValue = getDesiredValue();
    final ValueProperties originalConstraints = getValueRequirement().getConstraints();
    ValueSpecification resolvedOutput = null;
    for (ValueSpecification outputValue : newOutputValues) {
      if ((resolvedOutput == null) && (desiredValue.getValueName() == outputValue.getValueName()) && desiredValue.getConstraints().isSatisfiedBy(outputValue.getProperties()) &&
          originalConstraints.isSatisfiedBy(outputValue.getProperties())) {
        resolvedOutput = context.simplifyType(outputValue.compose(desiredValue));
        s_logger.debug("Raw output {} resolves to {}", outputValue, resolvedOutput);
        resolvedOutputValues.add(resolvedOutput);
      } else {
        resolvedOutputValues.add(context.simplifyType(outputValue));
      }
    }
    return resolvedOutput;
  }

  @Override
  public String toString() {
    return "TARGET_DIGEST" + getObjectId();
  }

  @Override
  protected void reportResult() {
    s_logger.debug("Successful digest resolution of {} via {}", getValueRequirement(), getDesiredValue());
    s_profilerSuccess.tick(_timeSpent);
    _timeSpent = 0;
  }

}
TOP

Related Classes of com.opengamma.engine.depgraph.TargetDigestStep

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.