/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.view.worker.trigger; import com.google.common.base.Supplier; import com.opengamma.engine.view.ViewDefinition; import com.opengamma.util.ArgumentChecker; /** * Trigger that honours the minimum and maximum recomputation periods in a view definition. */ public class RecomputationPeriodTrigger implements ViewCycleTrigger { private static final long NANOS_PER_MILLISECOND = 1000000; private final Supplier<ViewDefinition> _viewDefinition; private long _eligibleForDeltaComputationFromNanos = Long.MIN_VALUE; private long _deltaComputationRequiredByNanos = Long.MIN_VALUE; private long _eligibleForFullComputationFromNanos = Long.MIN_VALUE; private long _fullComputationRequiredByNanos = Long.MIN_VALUE; public RecomputationPeriodTrigger(Supplier<ViewDefinition> viewDefinition) { ArgumentChecker.notNull(viewDefinition, "viewComputationJob"); _viewDefinition = viewDefinition; } @Override public ViewCycleTriggerResult query(long cycleTimeNanos) { if (_fullComputationRequiredByNanos < cycleTimeNanos) { return new ViewCycleTriggerResult(ViewCycleEligibility.FORCE, ViewCycleType.FULL); } if (_deltaComputationRequiredByNanos < cycleTimeNanos) { return new ViewCycleTriggerResult(ViewCycleEligibility.FORCE, ViewCycleType.DELTA); } long nanosWhenRequired = Math.min(_fullComputationRequiredByNanos, _deltaComputationRequiredByNanos); if (_eligibleForFullComputationFromNanos < cycleTimeNanos) { return new ViewCycleTriggerResult(ViewCycleEligibility.ELIGIBLE, ViewCycleType.FULL, nanosWhenRequired); } if (_eligibleForDeltaComputationFromNanos < cycleTimeNanos) { return new ViewCycleTriggerResult(ViewCycleEligibility.ELIGIBLE, ViewCycleType.DELTA, nanosWhenRequired); } long nanosWhenEligible = Math.min(_eligibleForDeltaComputationFromNanos, _eligibleForFullComputationFromNanos); return ViewCycleTriggerResult.preventUntil(nanosWhenEligible); } @Override public void cycleTriggered(long cycleTimeNanos, ViewCycleType cycleType) { updateComputationTimes(cycleTimeNanos, cycleType == ViewCycleType.DELTA); } @Override public String toString() { return "RecomputationPeriodTrigger[eligibleForDeltaFrom=" + _eligibleForDeltaComputationFromNanos + ", deltaRequiredBy=" + _deltaComputationRequiredByNanos + ", eligibleForFullFrom=" + _eligibleForFullComputationFromNanos + ", _fullRequiredBy=" + _fullComputationRequiredByNanos + "]"; } //------------------------------------------------------------------------- private ViewDefinition getViewDefinition() { return _viewDefinition.get(); } private void updateComputationTimes(long currentNanos, boolean deltaOnly) { _eligibleForDeltaComputationFromNanos = getUpdatedTime(currentNanos, getViewDefinition().getMinDeltaCalculationPeriod(), 0); _deltaComputationRequiredByNanos = getUpdatedTime(currentNanos, getViewDefinition().getMaxDeltaCalculationPeriod(), Long.MAX_VALUE); if (!deltaOnly) { _eligibleForFullComputationFromNanos = getUpdatedTime(currentNanos, getViewDefinition().getMinFullCalculationPeriod(), 0); _fullComputationRequiredByNanos = getUpdatedTime(currentNanos, getViewDefinition().getMaxFullCalculationPeriod(), Long.MAX_VALUE); } } private long getUpdatedTime(long currentNanos, Long computationPeriod, long nullEquivalent) { if (computationPeriod == null) { return nullEquivalent; } long result = currentNanos + NANOS_PER_MILLISECOND * computationPeriod; // Check for overflow return result < currentNanos ? Long.MAX_VALUE : result; } }