/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.depgraph; import java.lang.ref.WeakReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Supplier; /** * Estimates the percentage completion of the graph build. */ /* package */final class BuildFractionEstimate implements Supplier<Double> { private static final Logger s_logger = LoggerFactory.getLogger(BuildFractionEstimate.class); private final WeakReference<DependencyGraphBuilder> _builder; private long _maxRemaining; public BuildFractionEstimate(final DependencyGraphBuilder builder) { _builder = new WeakReference<DependencyGraphBuilder>(builder); } @Override public Double get() { final DependencyGraphBuilder builder = _builder.get(); if ((builder == null) || builder.isCancelled()) { return 1d; } // Note that this will break for big jobs that are > 2^63 steps. Is this a limit that can be reasonably hit? // Loose synchronization okay; this is only a guesstimate final long completed = builder.getCompletedSteps(); long scheduled = builder.getScheduledSteps(); if ((scheduled <= 0) || (completed <= 0)) { return 0d; } while (completed >= scheduled) { if (builder.isGraphBuilt()) { return 1d; } else { // spin and have another go; scheduled steps will eventually increase scheduled = builder.getScheduledSteps(); if (scheduled <= 0) { // 2^63 overflow return 0d; } } } s_logger.info("Completed {} of {} scheduled steps", completed, scheduled); builder.reportStateSize(); // TODO: What can we do based on sampling the counters available and applying knowledge of typical graph shapes? Don't want anything too heavyweight. final long remaining = scheduled - completed; if (remaining > _maxRemaining) { _maxRemaining = remaining; } return (double) (_maxRemaining - remaining) / (double) _maxRemaining; } @Override public String toString() { return (get() * 100) + "%"; } }