All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.utilint.LongDiffStat Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.utilint;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import com.sleepycat.utilint.FormatUtil;

/**
 * A long JE stat component that computes the difference between another stat
 * and a specified value.  Reports 0 if the value is greater than the stat
 * value.  The computed difference remains valid for a specified amount of
 * time, which should represent the maximum amount of time expected to elapse
 * between when new values are provided.  If no value is specified within the
 * validity interval, then the difference is recomputed using the current base
 * stat value and the last specified value.  The idea is to treat the specified
 * value as up-to-date for a certain period of time, and then represent that
 * the lack of updates means it is falling behind.
 */
public class LongDiffStat extends MapStatComponent {
    private static final long serialVersionUID = 1L;

    /** The stat that supplies the base value for computing differences. */
    private final Stat base;

    /**
     * The maximum time, in milliseconds, that a computed difference is
     * valid.
     */
    private final long validityMillis;

    /**
     * The previous value, or 0.  Synchronize on this instance when accessing
     * this field.
     */
    private long prevValue;

    /**
     * The time in milliseconds of the previous value, or 0.  Synchronize on
     * this instance when accessing this field.
     */
    private long prevTime;

    /**
     * The last computed difference, or 0.  Synchronize on this instance when
     * accessing this field.
     */
    private long diff;

    /**
     * Creates an instance of this class.
     *
     * @param base the base stat used for computing differences
     * @param validityMillis the amount of time, in milliseconds, which a
     * computed difference remains valid
     */
    public LongDiffStat(Stat base, long validityMillis) {
        assert base != null;
        assert validityMillis > 0;
        this.base = base;
        this.validityMillis = validityMillis;
    }

    private LongDiffStat(LongDiffStat other) {
        base = other.base.copy();
        validityMillis = other.validityMillis;
        synchronized (this) {
            synchronized (other) {
                prevValue = other.prevValue;
                prevTime = other.prevTime;
                diff = other.diff;
            }
        }
    }

    /**
     * Returns the value of the stat for the specified time.
     *
     * @param time the time
     * @return the value of the stat
     */
    public long get(long time) {
        assert time > 0;
        synchronized (this) {
            if (prevTime == 0) {
                return 0;
            }
            if (time < (prevTime + validityMillis)) {
                return diff;
            }
        }
        final long baseValue = base.get();
        synchronized (this) {
            return Math.max(baseValue - prevValue, 0);
        }
    }

    /**
     * Specifies a new value for the current time.
     *
     * @param newValue the new value
     */
    public void set(long newValue) {
        set(newValue, System.currentTimeMillis());
    }

    /**
     * Specifies a new value for the specified time.
     *
     * @param newValue the new value
     * @param time the time
     */
    public void set(long newValue, long time) {
        assert time > 0;
        final long baseValue = base.get();
        synchronized (this) {
            prevValue = newValue;
            prevTime = time;
            diff = Math.max(baseValue - newValue, 0);
        }
    }

    /**
     * Returns the value of the stat for the current time.
     */
    @Override
    public Long get() {
        return get(System.currentTimeMillis());
    }

    @Override
    public synchronized void clear() {
        prevValue = 0;
        prevTime = 0;
        diff = 0;
    }

    @Override
    public LongDiffStat copy() {
        return new LongDiffStat(this);
    }

    @Override
    protected synchronized String getFormattedValue(boolean useCommas) {
        if (isNotSet()) {
            return "Unknown";
        } else if (useCommas) {
            return FormatUtil.decimalScale0().format(
                get(System.currentTimeMillis()));
        } else {
            return String.valueOf(get(System.currentTimeMillis()));
        }
    }

    @Override
    public synchronized boolean isNotSet() {
       return prevTime == 0;
    }

    @Override
    public synchronized String toString() {
        return "LongDiffStat[prevValue=" + prevValue +
            ", prevTime=" + prevTime + ", diff=" + diff + "]";
    }

    /** Synchronize access to fields. */
    private synchronized void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException {

        in.defaultReadObject();
    }

    /** Synchronize access to fields. */
    private synchronized void writeObject(ObjectOutputStream out)
        throws IOException {

        out.defaultWriteObject();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy