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

org.voltdb.dtxn.LatencyHistogramStats Maven / Gradle / Ivy

There is a newer version: 10.1.1
Show newest version
/* This file is part of VoltDB.
 * Copyright (C) 2008-2018 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see .
 */

package org.voltdb.dtxn;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.HdrHistogram_voltpatches.AbstractHistogram;
import org.HdrHistogram_voltpatches.AtomicHistogram;
import org.HdrHistogram_voltpatches.Histogram;
import org.voltcore.utils.CompressionStrategySnappy;
import org.voltdb.ClientInterface;
import org.voltdb.SiteStatsSource;
import org.voltdb.VoltDB;
import org.voltdb.VoltTable.ColumnInfo;
import org.voltdb.VoltType;

import com.google_voltpatches.common.base.Supplier;
import com.google_voltpatches.common.base.Suppliers;

/** Source of @Statistics LATENCY_COMPRESSED.
 * Latency information is provided in buckets. Each bucket contains the
 * number of procedures with latencies in the range.
 */
public class LatencyHistogramStats extends SiteStatsSource {
    /**
     * A dummy iterator that wraps and int and provides the
     * Iterator necessary for getStatsRowKeyIterator()
     *
     */
    private static class DummyIterator implements Iterator {
        boolean oneRow = false;

        @Override
        public boolean hasNext() {
            if (!oneRow) {
                oneRow = true;
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            return null;
        }

        @Override
        public void remove() {

        }
    }

    public static AbstractHistogram constructHistogram(boolean threadSafe) {
        final long highestTrackableValue = 60L * 60L * 1000000L;
        final int numberOfSignificantValueDigits = 3;
        if (threadSafe) {
            return new AtomicHistogram( highestTrackableValue, numberOfSignificantValueDigits);
        } else {
            return new Histogram( highestTrackableValue, numberOfSignificantValueDigits);
        }
    }

    private WeakReference m_compressedCache = null;
    private WeakReference m_serializedCache = null;

    private AbstractHistogram m_totals = constructHistogram(false);

    private final static int EXPIRATION = Integer.getInteger("LATENCY_CACHE_EXPIRATION", 900);

    private Supplier getHistogramSupplier() {
        return Suppliers.memoizeWithExpiration(new Supplier() {
            @Override
            public AbstractHistogram get() {
                m_totals.reset();
                ClientInterface ci = VoltDB.instance().getClientInterface();
                if (ci != null) {
                    List thisci = ci.getLatencyStats();
                    for (AbstractHistogram info : thisci) {
                        m_totals.add(info);
                    }
                }
                m_compressedCache = null;
                m_serializedCache = null;

                return m_totals;
            }
        }, EXPIRATION, TimeUnit.MILLISECONDS);
    }
    private Supplier m_histogramSupplier = getHistogramSupplier();

    public byte[] getSerializedCache() {
        byte[] retval = null;
        if (m_serializedCache == null || (retval = m_serializedCache.get()) == null) {
            retval = m_histogramSupplier.get().toUncompressedBytes();
            m_serializedCache = new WeakReference(retval);
        }
        return retval;
    }

    public byte[] getCompressedCache() {
        byte[] retval = null;
        if (m_compressedCache == null || (retval = m_compressedCache.get()) == null) {
            retval = AbstractHistogram.toCompressedBytes(getSerializedCache(), CompressionStrategySnappy.INSTANCE);
            m_compressedCache = new WeakReference(retval);
        }
        return retval;
    }

    public AbstractHistogram getHistogram() {
        return m_histogramSupplier.get();
    }

    public LatencyHistogramStats(long siteId) {
        super(siteId, false);
    }

    @Override
    protected Iterator getStatsRowKeyIterator(boolean interval) {
        m_histogramSupplier.get();
        return new DummyIterator();
    }

    @Override
    protected void populateColumnSchema(ArrayList columns) {
        super.populateColumnSchema(columns);
        columns.add(new ColumnInfo("HISTOGRAM", VoltType.VARBINARY));
    }

    @Override
    protected void updateStatsRow(Object rowKey, Object[] rowValues) {
        rowValues[columnNameToIndex.get("HISTOGRAM")] = getCompressedCache();
        super.updateStatsRow(rowKey, rowValues);
    }
}