content: // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
  //  This source code is licensed under both the GPLv2 (found in the
  //  COPYING file in the root directory) and Apache 2.0 License
  //  (found in the LICENSE.Apache file in the root directory).
  
  package org.rocksdb;
  
  import java.util.List;
  import java.util.concurrent.Executors;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.TimeUnit;
  
  /**
   * <p>Helper class to collect DB statistics periodically at a period specified in
   * constructor. Callback function (provided in constructor) is called with
   * every statistics collection.</p>
   *
   * <p>Caller should call start() to start statistics collection. Shutdown() should
   * be called to stop stats collection and should be called before statistics (
   * provided in constructor) reference has been disposed.</p>
   */
  public class StatisticsCollector {
    private final List<StatsCollectorInput> _statsCollectorInputList;
    private final ExecutorService _executorService;
    private final int _statsCollectionInterval;
    private volatile boolean _isRunning = true;
  
    /**
     * Constructor for statistics collector.
     *
     * @param statsCollectorInputList List of statistics collector input.
     * @param statsCollectionIntervalInMilliSeconds Statistics collection time
     *        period (specified in milliseconds).
     */
    public StatisticsCollector(
        final List<StatsCollectorInput> statsCollectorInputList,
        final int statsCollectionIntervalInMilliSeconds) {
      _statsCollectorInputList = statsCollectorInputList;
      _statsCollectionInterval = statsCollectionIntervalInMilliSeconds;
  
      _executorService = Executors.newSingleThreadExecutor();
    }
  
    public void start() {
      _executorService.submit(collectStatistics());
    }
  
    /**
     * Shuts down statistics collector.
     *
     * @param shutdownTimeout Time in milli-seconds to wait for shutdown before
     *        killing the collection process.
     * @throws java.lang.InterruptedException thrown if Threads are interrupted.
     */
    public void shutDown(final int shutdownTimeout) throws InterruptedException {
      _isRunning = false;
  
      _executorService.shutdownNow();
      // Wait for collectStatistics runnable to finish so that disposal of
      // statistics does not cause any exceptions to be thrown.
      _executorService.awaitTermination(shutdownTimeout, TimeUnit.MILLISECONDS);
    }
  
    private Runnable collectStatistics() {
      return new Runnable() {
  
        @Override
        public void run() {
          while (_isRunning) {
            try {
              if(Thread.currentThread().isInterrupted()) {
                break;
              }
              for(final StatsCollectorInput statsCollectorInput :
                  _statsCollectorInputList) {
                Statistics statistics = statsCollectorInput.getStatistics();
                StatisticsCollectorCallback statsCallback =
                    statsCollectorInput.getCallback();
  
                // Collect ticker data
                for(final TickerType ticker : TickerType.values()) {
                  if(ticker != TickerType.TICKER_ENUM_MAX) {
                    final long tickerValue = statistics.getTickerCount(ticker);
                    statsCallback.tickerCallback(ticker, tickerValue);
                  }
                }
  
                // Collect histogram data
                for(final HistogramType histogramType : HistogramType.values()) {
                  if(histogramType != HistogramType.HISTOGRAM_ENUM_MAX) {
                    final HistogramData histogramData =
                            statistics.getHistogramData(histogramType);
                    statsCallback.histogramCallback(histogramType, histogramData);
                  }
                }
  
                Thread.sleep(_statsCollectionInterval);
              }
            }
            catch (final InterruptedException e) {
              Thread.currentThread().interrupt();
              break;
            }
            catch (final Exception e) {
              throw new RuntimeException("Error while calculating statistics", e);
            }
          }
        }
      };
    }
  }
  