Package org.jrobin.core

Source Code of org.jrobin.core.RrdDbPool

/*******************************************************************************
* Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
* Copyright (c) 2011 The OpenNMS Group, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*******************************************************************************/

package org.jrobin.core;

import java.io.IOException;
import java.util.HashMap;

import org.jrobin.core.RrdException;

/**
* This class should be used to synchronize access to RRD files
* in a multithreaded environment. This class should be also used to prevent openning of
* too many RRD files at the same time (thus avoiding operating system limits)
*/

public class RrdDbPool {
  /**
   * Initial capacity of the pool i.e. maximum number of simultaneously open RRD files. The pool will
   * never open too many RRD files at the same time.
   */
  public static final int INITIAL_CAPACITY = 200;
  private static RrdDbPool instance;

  private int capacity = INITIAL_CAPACITY;
  private HashMap<String, RrdEntry> rrdMap = new HashMap<String, RrdEntry>(INITIAL_CAPACITY);

  /**
   * Creates a single instance of the class on the first call, or returns already existing one.
   *
   * @return Single instance of this class
   * @throws RrdException Thrown if the default RRD backend is not derived from the {@link RrdFileBackendFactory}
   */
  public synchronized static RrdDbPool getInstance() throws RrdException {
    if (instance == null) {
      instance = new RrdDbPool();
    }
    return instance;
  }

  private RrdDbPool() throws RrdException {
    RrdBackendFactory factory = RrdBackendFactory.getDefaultFactory();
    if (!(factory instanceof RrdFileBackendFactory)) {
      throw new RrdException("Cannot create instance of " + getClass().getName() + " with " +
          "a default backend factory not derived from RrdFileBackendFactory");
    }
  }

  /**
   * Requests a RrdDb reference for the given RRD file path.<p>
   * <ul>
   * <li>If the file is already open, previously returned RrdDb reference will be returned. Its usage count
   * will be incremented by one.
   * <li>If the file is not already open and the number of already open RRD files is less than
   * {@link #INITIAL_CAPACITY}, the file will be open and a new RrdDb reference will be returned.
   * If the file is not already open and the number of already open RRD files is equal to
   * {@link #INITIAL_CAPACITY}, the method blocks until some RRD file is closed.
   * </ul>
   *
   * @param path Path to existing RRD file
   * @return reference for the give RRD file
   * @throws IOException  Thrown in case of I/O error
   * @throws RrdException Thrown in case of JRobin specific error
   */
  public synchronized RrdDb requestRrdDb(String path) throws IOException, RrdException {
    String canonicalPath = Util.getCanonicalPath(path);
    while (!rrdMap.containsKey(canonicalPath) && rrdMap.size() >= capacity) {
      try {
        wait();
      }
      catch (InterruptedException e) {
        throw new RrdException(e);
      }
    }
    if (rrdMap.containsKey(canonicalPath)) {
      // already open, just increase usage count
      RrdEntry entry = rrdMap.get(canonicalPath);
      entry.count++;
      return entry.rrdDb;
    }
    else {
      // not open, open it now and add to the map
      RrdDb rrdDb = new RrdDb(canonicalPath);
      rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
      return rrdDb;
    }
  }

  /**
   * Requests a RrdDb reference for the given RRD file definition object.<p>
   * <ul>
   * <li>If the file with the path specified in the RrdDef object is already open,
   * the method blocks until the file is closed.
   * <li>If the file is not already open and the number of already open RRD files is less than
   * {@link #INITIAL_CAPACITY}, a new RRD file will be created and a its RrdDb reference will be returned.
   * If the file is not already open and the number of already open RRD files is equal to
   * {@link #INITIAL_CAPACITY}, the method blocks until some RRD file is closed.
   * </ul>
   *
   * @param rrdDef Definition of the RRD file to be created
   * @return Reference to the newly created RRD file
   * @throws IOException  Thrown in case of I/O error
   * @throws RrdException Thrown in case of JRobin specific error
   */
  public synchronized RrdDb requestRrdDb(RrdDef rrdDef) throws IOException, RrdException {
    String canonicalPath = Util.getCanonicalPath(rrdDef.getPath());
    while (rrdMap.containsKey(canonicalPath) || rrdMap.size() >= capacity) {
      try {
        wait();
      }
      catch (InterruptedException e) {
        throw new RrdException(e);
      }
    }
    RrdDb rrdDb = new RrdDb(rrdDef);
    rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
    return rrdDb;
  }

  /**
   * Requests a RrdDb reference for the given path. The file will be created from
   * external data (from XML dump, RRD file or RRDTool's binary RRD file).<p>
   * <ul>
   * <li>If the file with the path specified is already open,
   * the method blocks until the file is closed.
   * <li>If the file is not already open and the number of already open RRD files is less than
   * {@link #INITIAL_CAPACITY}, a new RRD file will be created and a its RrdDb reference will be returned.
   * If the file is not already open and the number of already open RRD files is equal to
   * {@link #INITIAL_CAPACITY}, the method blocks until some RRD file is closed.
   * </ul>
   *
   * @param path     Path to RRD file which should be created
   * @param sourcePath Path to external data which is to be converted to JRobin's native RRD file format
   * @return Reference to the newly created RRD file
   * @throws IOException  Thrown in case of I/O error
   * @throws RrdException Thrown in case of JRobin specific error
   */
  public synchronized RrdDb requestRrdDb(String path, String sourcePath)
      throws IOException, RrdException,RrdException {
    String canonicalPath = Util.getCanonicalPath(path);
    while (rrdMap.containsKey(canonicalPath) || rrdMap.size() >= capacity) {
      try {
        wait();
      }
      catch (InterruptedException e) {
        throw new RrdException(e);
      }
    }
    RrdDb rrdDb = new RrdDb(canonicalPath, sourcePath);
    rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
    return rrdDb;
  }

  /**
   * Releases RrdDb reference previously obtained from the pool. When a reference is released, its usage
   * count is decremented by one. If usage count drops to zero, the underlying RRD file will be closed.
   *
   * @param rrdDb RrdDb reference to be returned to the pool
   * @throws IOException  Thrown in case of I/O error
   * @throws RrdException Thrown in case of JRobin specific error
   */
  public synchronized void release(RrdDb rrdDb) throws IOException, RrdException {
    // null pointer should not kill the thread, just ignore it
    if (rrdDb == null) {
      return;
    }
    String canonicalPath = Util.getCanonicalPath(rrdDb.getPath());
    if (!rrdMap.containsKey(canonicalPath)) {
      throw new RrdException("Could not release [" + canonicalPath + "], the file was never requested");
    }
    RrdEntry entry = rrdMap.get(canonicalPath);
    if (--entry.count <= 0) {
      // no longer used
      rrdMap.remove(canonicalPath);
      notifyAll();
      entry.rrdDb.close();
    }
  }

  /**
   * Returns the maximum number of simultaneously open RRD files.
   *
   * @return maximum number of simultaneously open RRD files
   */
  public synchronized int getCapacity() {
    return capacity;
  }

  /**
   * Sets the maximum number of simultaneously open RRD files.
   *
   * @param capacity Maximum number of simultaneously open RRD files.
   */
  public synchronized void setCapacity(int capacity) {
    this.capacity = capacity;
  }

  /**
   * Returns an array of open file names.
   *
   * @return Array with canonical paths to open RRD files held in the pool.
   */
  public synchronized String[] getOpenFiles() {
    return rrdMap.keySet().toArray(new String[0]);
  }

  /**
   * Returns the number of open RRD files.
   *
   * @return Number of currently open RRD files held in the pool.
   */
  public synchronized int getOpenFileCount() {
    return rrdMap.size();
  }

  private final static class RrdEntry {
    RrdDb rrdDb;
    int count;

    RrdEntry(final RrdDb rrdDb) {
      this.rrdDb = rrdDb;
      this.count = 1;
    }
  }
}

// OLDER VERSION IS HERE

///* ============================================================
// * JRobin : Pure java implementation of RRDTool's functionality
// * ============================================================
// *
// * Project Info:  http://www.jrobin.org
// * Project Lead:  Sasa Markovic (saxon@jrobin.org);
// *
// * (C) Copyright 2003-2005, by Sasa Markovic.
// *
// * Developers:    Sasa Markovic (saxon@jrobin.org)
// *
// *
// * This library is free software; you can redistribute it and/or modify it under the terms
// * of the GNU Lesser General Public License as published by the Free Software Foundation;
// * either version 2.1 of the License, or (at your option) any later version.
// *
// * This library 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 Lesser General Public License for more details.
// *
// * You should have received a copy of the GNU Lesser General Public License along with this
// * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// * Boston, MA 02111-1307, USA.
// */
//package org.jrobin.core;
//
//import java.io.IOException;
//import java.util.HashMap;
//import java.util.Iterator;
//import java.util.LinkedHashMap;
//import java.util.Set;
//
///**
// * Class to represent the pool of open RRD files.<p>
// *
// * To open already existing RRD file with JRobin, you have to create a
// * {@link org.jrobin.core.RrdDb RrdDb} object by specifying RRD file path
// * as constructor argument. This operation can be time consuming
// * especially with large RRD files with many datasources and
// * several long archives.<p>
// *
// * In a multithreaded environment you might probably need a reference to the
// * same RRD file from two different threads (RRD file updates are performed in
// * one thread but data fetching and graphing is performed in another one). To make
// * the RrdDb construction process more efficient it might be convenient to open all
// * RRD files in a centralized place. That's the purpose of RrdDbPool class.<p>
// *
// * How does it work? The typical usage scenario goes like this:<p>
// *
// * <pre>
// * // obtain instance to RrdDbPool object
// * RrdDbPool pool = RrdDbPool.getInstance();
// *
// * // request a reference to RrdDb object
// * String path = "some_relative_or_absolute_path_to_any_RRD_file";
// * RrdDb rrdDb = RrdDbPool.requestRrdDb(path);
// *
// * // reference obtained, do whatever you want with it...
// * ...
// * ...
// *
// * // once you don't need the reference, release it.
// * // DO NOT CALL rrdDb.close() - files no longer in use are eventually closed by the pool
// * pool.release(rrdDb);
// * </pre>
// *
// * It's that simple. When the reference is requested for the first time, RrdDbPool will open the RRD file
// * for you and make some internal note that the RRD file is used only once. When the reference
// * to the same file (same RRD file path) is requested for the second time, the same RrdDb
// * reference will be returned, and its usage count will be increased by one. When the
// * reference is released its usage count will be decremented by one.<p>
// *
// * When the reference count drops to zero, RrdDbPool will not close the underlying
// * RRD file immediatelly. Instead of it, it will be marked as 'eligible for closing'.
// * If someone request the same RRD file again (before it gets closed), the same
// * reference will be returned again.<p>
// *
// * RrdDbPool has a 'garbage collector' which runs in a separate, low-priority
// * thread and gets activated only when the number of RRD files kept in the
// * pool is too big (greater than number returned from {@link #getCapacity getCapacity()}).
// * Only RRD files with a reference count equal to zero
// * will be eligible for closing. Unreleased RrdDb references are never invalidated.
// * RrdDbPool object keeps track of the time when each RRD file
// * becomes eligible for closing so that the oldest RRD file gets closed first.<p>
// *
// * Initial RrdDbPool capacity is set to {@link #INITIAL_CAPACITY}. Use {@link #setCapacity(int)}
// * method to change it at any time.<p>
// *
// * <b>WARNING:</b>Never use close() method on the reference returned from the pool.
// * When the reference is no longer needed, return it to the pool with the
// * {@link #release(RrdDb) release()} method.<p>
// *
// * However, you are not forced to use RrdDbPool methods to obtain RrdDb references
// * to RRD files, 'ordinary' RrdDb constructors are still available. But RrdDbPool class
// * offers serious performance improvement especially in complex applications with many
// * threads and many simultaneously open RRD files.<p>
// *
// * The pool is thread-safe. Not that the {@link RrdDb} objects returned from the pool are
// * also thread-safe<p>
// *
// * You should know that each operating system has its own internal limit on the number
// * of simultaneously open files. The capacity of your RrdDbPool should be
// * reasonably smaller than the limit imposed by your operating system.<p>
// *
// * <b>WARNING:</b> The pool cannot be used to manipulate RrdDb objects
// * with {@link RrdBackend backends} different from default.<p>
// */
//public class RrdDbPool implements Runnable {
//  static final String GC_THREAD_NAME = "RrdDbPool GC thread";
//  static final String CLOSING_THREAD_NAME = "RrdDbPool closing thread";
//  private static final boolean DEBUG = false;
//
//  // singleton pattern
//  private static RrdDbPool ourInstance;
//  private boolean closingOnExit = true;
//
//  private Thread shutdownHook = new Thread(CLOSING_THREAD_NAME) {
//    public void run() {
//      try {
//        close();
//      }
//      catch (IOException e) {
//        e.printStackTrace();
//      }
//    }
//  };
//
//  /**
//   * Constant to represent the maximum number of internally open RRD files
//   * which still does not force garbage collector (the process which closes RRD files) to run.
//   */
//  public static final int INITIAL_CAPACITY = 500;
//  private int capacity = INITIAL_CAPACITY, maxUsedCapacity;
//  private boolean active = true;
//
//  /**
//   * Constant to represent the internal behaviour of the pool.
//   * Defaults to <code>true</code> but can be changed at runtime. See
//   * {@link #setLimitedCapacity(boolean)} for more information.
//   */
//  public static final boolean LIMITED_CAPACITY = false;
//  private boolean limitedCapacity = LIMITED_CAPACITY;
//
//  /**
//   * Constant to represent the priority of the background thread which closes excessive RRD files
//   * which are no longer in use.
//   */
//  public static final int GC_THREAD_PRIORITY = /** Thread.NORM_PRIORITY - */ 1;
//
//  private HashMap<String, RrdEntry> rrdMap = new HashMap<String, RrdEntry>(INITIAL_CAPACITY);
//  private LinkedHashMap<String, RrdEntry> rrdIdleMap = new LinkedHashMap<String, RrdEntry>(INITIAL_CAPACITY);
//  private RrdBackendFactory factory;
//  private int poolHitsCount = 0, poolRequestsCount = 0;
//
//  /**
//   * Returns an instance to RrdDbPool object. Only one such object may exist in each JVM.
//   *
//   * @return Instance to RrdDbPool object.
//   */
//  public synchronized static RrdDbPool getInstance() {
//    if (ourInstance == null) {
//      ourInstance = new RrdDbPool();
//      ourInstance.startGarbageCollector();
//    }
//    return ourInstance;
//  }
//
//  private RrdDbPool() {
//    setClosingOnExit(closingOnExit);
//  }
//
//  /**
//   * Checks the exiting behaviour of RrdDbPool.
//   * @return <code>True</code>, if all RRD files are to be closed
//   * when application invokes <code>System.exit()</code>.
//   * <code>False</code> otherwise. The default behaviour is <code>true</code>
//   * (all RRD files will be closed on exit).
//   */
//  public synchronized boolean isClosingOnExit() {
//    return closingOnExit;
//  }
//
//  /**
//   * Sets the exiting behaviour of RrdDbPool.
//   * @param closingOnExit <code>True</code>, if all RRD files are to be closed
//   * when application invokes <code>System.exit()</code>.
//   * <code>False</code> otherwise. The default behaviour is <code>true</code>
//   * (all RRD files will be closed on exit).
//   */
//  public synchronized void setClosingOnExit(boolean closingOnExit) {
//    Runtime runtime = Runtime.getRuntime();
//    runtime.removeShutdownHook(shutdownHook);
//    if(closingOnExit) {
//      runtime.addShutdownHook(shutdownHook);
//    }
//    this.closingOnExit = closingOnExit;
//  }
//
//  private void startGarbageCollector() {
//    Thread gcThread = new Thread(this, GC_THREAD_NAME);
//    gcThread.setPriority(GC_THREAD_PRIORITY);
//    gcThread.setDaemon(true);
//    gcThread.start();
//  }
//
//  /**
//   * Returns a reference to an existing RRD file with the specified path.
//   * If the file is already open in the pool, existing reference to it will be returned.
//   * Otherwise, the file is open and a newly created reference to it is returned.
//   *
//   * @param path Relative or absolute path to a RRD file.
//   * @return Reference to a RrdDb object (RRD file).
//   * @throws IOException  Thrown in case of I/O error.
//   * @throws RrdException Thrown in case of JRobin specific error.
//   */
//  public synchronized RrdDb requestRrdDb(String path) throws IOException, RrdException {
//    proveActive();
//    poolRequestsCount++;
//    String canonicalPath = getCanonicalPath(path);
//    for(;;) {
//      RrdEntry rrdEntry = rrdMap.get(canonicalPath);
//      if (rrdEntry != null) {
//        // already open, use it!
//        reportUsage(canonicalPath, rrdEntry);
//        poolHitsCount++;
////        debug("CACHED: " + rrdEntry.dump());
//        return rrdEntry.getRrdDb();
//      }
//      else if(!limitedCapacity || rrdMap.size() < capacity) {
//        // not found, open it
//        RrdDb rrdDb = createRrdDb(path, null);
//        rrdEntry = new RrdEntry(rrdDb);
//        addRrdEntry(canonicalPath, rrdEntry);
////        debug("ADDED: " + rrdEntry.dump());
//        return rrdDb;
//      }
//      else {
//        // we have to wait
//        try {
//          wait();
//        }
//        catch (InterruptedException e) {
//          throw new RrdException("Request for file '" + path + "' was interrupted");
//        }
//      }
//    }
//  }
//
//  /**
//   * Returns a reference to a new RRD file. The new file will have the specified
//   * relative or absolute path, and its contents will be provided from the specified
//   * XML file (RRDTool comaptible).
//   *
//   * @param path    Relative or absolute path to a new RRD file.
//   * @param xmlPath Relative or absolute path to an existing XML dump file (RRDTool comaptible)
//   * @return Reference to a RrdDb object (RRD file).
//   * @throws IOException  Thrown in case of I/O error.
//   * @throws RrdException Thrown in case of JRobin specific error.
//   */
//  public synchronized RrdDb requestRrdDb(String path, String xmlPath)
//      throws IOException, RrdException {
//    return requestNewRrdDb(path, xmlPath);
//  }
//
//  /**
//   * Returns a reference to a new RRD file. The new file will be created based on the
//   * definition contained in a RrdDef object.
//   *
//   * @param rrdDef RRD definition object
//   * @return Reference to a RrdDb object (RRD file).
//   * @throws IOException  Thrown in case of I/O error.
//   * @throws RrdException Thrown in case of JRobin specific error.
//   */
//  public synchronized RrdDb requestRrdDb(RrdDef rrdDef) throws IOException, RrdException {
//    return requestNewRrdDb(rrdDef.getPath(), rrdDef);
//  }
//
//  private RrdDb requestNewRrdDb(String path, Object creationDef) throws IOException, RrdException {
//    proveActive();
//    poolRequestsCount++;
//    String canonicalPath = getCanonicalPath(path);
//    for(;;) {
//      RrdEntry rrdEntry = rrdMap.get(canonicalPath);
//      if(rrdEntry != null) {
//        // already open
//        removeIfIdle(canonicalPath, rrdEntry);
//      }
//      else if(!limitedCapacity || rrdMap.size() < capacity) {
//        RrdDb rrdDb = createRrdDb(path, creationDef);
//        RrdEntry newRrdEntry = new RrdEntry(rrdDb);
//        addRrdEntry(canonicalPath, newRrdEntry);
////        debug("ADDED: " + newRrdEntry.dump());
//        return rrdDb;
//      }
//      else {
//         // we have to wait
//        try {
//          wait();
//        }
//        catch (InterruptedException e) {
//          throw new RrdException("Request for file '" + path + "' was interrupted");
//        }
//      }
//    }
//  }
//
//  private RrdDb createRrdDb(String path, Object creationDef) throws RrdException, IOException {
//    if(creationDef == null) {
//      // existing RRD
//      return new RrdDb(path, getFactory());
//    }
//    else if(creationDef instanceof String) {
//      // XML input
//      return new RrdDb(path, (String) creationDef, getFactory());
//    }
//    else if(creationDef instanceof RrdDef) {
//      // RrdDef
//      return new RrdDb((RrdDef) creationDef, getFactory());
//    }
//    else {
//      throw new RrdException("Unexpected input object type: " +
//        creationDef.getClass().getName());
//    }
//  }
//
//  private void reportUsage(String canonicalPath, RrdEntry rrdEntry) {
//    if (rrdEntry.reportUsage() == 1) {
//      // must not be garbage collected
//      rrdIdleMap.remove(canonicalPath);
//    }
//  }
//
//  private void reportRelease(String canonicalPath, RrdEntry rrdEntry) {
//    if (rrdEntry.reportRelease() == 0) {
//      // ready to be garbage collected
//      rrdIdleMap.put(canonicalPath, rrdEntry);
//    }
//  }
//
//  private void addRrdEntry(String canonicalPath, RrdEntry newRrdEntry) {
//    rrdMap.put(canonicalPath, newRrdEntry);
//    maxUsedCapacity = Math.max(rrdMap.size(), maxUsedCapacity);
//    // notify waiting threads
//    notifyAll();
//  }
//
//  private void removeIfIdle(String canonicalPath, RrdEntry rrdEntry)
//      throws RrdException, IOException {
//    // already open, check if active (not released)
//    if (rrdEntry.isInUse()) {
//      // not released, not allowed here
//      throw new RrdException("Cannot create new RrdDb file: " +
//          "File '" + canonicalPath + "' already in use");
//    } else {
//      // open but released... safe to close it
////      debug("WILL BE RECREATED: " + rrdEntry.dump());
//      removeRrdEntry(canonicalPath, rrdEntry);
//    }
//  }
//
//  private void removeRrdEntry(String canonicalPath, RrdEntry rrdEntry) throws IOException {
//    rrdEntry.closeRrdDb();
//    rrdMap.remove(canonicalPath);
//    rrdIdleMap.remove(canonicalPath);
////    debug("REMOVED: " + rrdEntry.dump());
//  }
//
//  /**
//   * Method used to report that the reference to a RRD file is no longer needed. File that
//   * is no longer needed (all references to it are released) is marked 'eligible for
//   * closing'. It will be eventually closed by the pool when the number of open RRD files
//   * becomes too big. Most recently released files will be closed last.
//   *
//   * @param rrdDb Reference to RRD file that is no longer needed.
//   * @throws IOException  Thrown in case of I/O error.
//   * @throws RrdException Thrown in case of JRobin specific error.
//   */
//  public synchronized void release(RrdDb rrdDb) throws IOException, RrdException {
//    proveActive();
//    if (rrdDb == null) {
//      // we don't want NullPointerException
//      return;
//    }
//    if (rrdDb.isClosed()) {
//      throw new RrdException("File " + rrdDb.getPath() + " already closed");
//    }
//    String canonicalPath = getCanonicalPath(rrdDb.getPath());
//    if (rrdMap.containsKey(canonicalPath)) {
//      RrdEntry rrdEntry = rrdMap.get(canonicalPath);
//      reportRelease(canonicalPath, rrdEntry);
////      debug("RELEASED: " + rrdEntry.dump());
//    } else {
//      throw new RrdException("RRD file " + rrdDb.getPath() + " not in the pool");
//    }
//    // notify waiting threads
//    notifyAll();
//  }
//
//  /**
//   * This method runs garbage collector in a separate thread. If the number of
//   * open RRD files kept in the pool is too big (greater than number
//   * returned from {@link #getCapacity getCapacity()}), garbage collector will try
//   * to close and remove RRD files with a reference count equal to zero.
//   * Never call this method directly.
//   */
//  public void run() {
////    debug("GC: started");
//    while (active) {
//      synchronized (this) {
//        if (rrdMap.size() >= capacity && rrdIdleMap.size() > 0) {
//          try {
//            String canonicalPath = rrdIdleMap.keySet().iterator().next();
//            RrdEntry rrdEntry = rrdIdleMap.get(canonicalPath);
////            debug("GC: closing " + rrdEntry.dump());
//            removeRrdEntry(canonicalPath, rrdEntry);
//          } catch (IOException e) {
//            e.printStackTrace();
//          }
//          notifyAll();
//        }
//        else {
//          try {
////            debug("GC: waiting");
//            wait();
////            debug("GC: running");
//          } catch (InterruptedException e) {
//            e.printStackTrace();
//          }
//        }
//      }
//    }
//  }
//
//  protected void finalize() throws IOException {
//    close();
//  }
//
//  /**
//   * Clears the internal state of the pool entirely. All open RRD files are closed.
//   *
//   * @throws IOException Thrown in case of I/O related error.
//   */
//  public synchronized void reset() throws IOException {
//    Iterator<RrdEntry> it = rrdMap.values().iterator();
//    while (it.hasNext()) {
//      RrdEntry rrdEntry = it.next();
//      rrdEntry.closeRrdDb();
//    }
//    rrdMap.clear();
//    rrdIdleMap.clear();
////    debug("Pool cleared");
//  }
//
//  /**
//   * Closes the pool and all RRD files currently held in the pool.
//   * No further operations on the pool are allowed.
//   * @throws IOException Thrown in case of I/O error.
//   */
//  public synchronized void close() throws IOException {
//    if(active) {
//      active = false;
//      reset();
////      debug("The pool is closed.");
//    }
//    else {
////      debug("The pool is already closed!");
//    }
//  }
//
//  private static String getCanonicalPath(String path) throws IOException {
//    return Util.getCanonicalPath(path);
//  }
//
//  static void debug(String msg) {
//    if (DEBUG) {
//      System.out.println("POOL: " + msg);
//    }
//  }
//
//  /**
//   * Returns the internal state of the pool. Useful for debugging purposes.
//   *
//   * @param dumpFiles <code>true</code>, if dumped information should contain paths to open files
//   * currently held in the pool, <code>false</code> otherwise
//   * @return Internal pool state (with an optional list of open RRD files and
//   * the current number of usages for each one).
//   * @throws IOException Thrown in case of I/O error.
//   */
//  public synchronized String dump(boolean dumpFiles) throws IOException {
//    StringBuffer buff = new StringBuffer();
//    buff.append("==== POOL DUMP ===========================\n");
//    buff.append("open=" + rrdMap.size() + ", idle=" + rrdIdleMap.size() + "\n");
//    buff.append("capacity=" + capacity + ", " + "maxUsedCapacity=" + maxUsedCapacity + "\n");
//    buff.append("hits=" + poolHitsCount + ", " + "requests=" + poolRequestsCount + "\n");
//    buff.append("efficiency=" + getPoolEfficiency() + "\n");
//    if(dumpFiles) {
//      buff.append("---- CACHED FILES ------------------------\n");
//      Iterator<RrdEntry> it = rrdMap.values().iterator();
//      while (it.hasNext()) {
//        RrdEntry rrdEntry = it.next();
//        buff.append(rrdEntry.dump() + "\n");
//      }
//    }
//    return buff.toString();
//  }
//
//  /**
//   * Returns the complete internal state of the pool. Useful for debugging purposes.
//   *
//   * @return Internal pool state (with a list of open RRD files and the current number of
//   * usages for each one).
//   * @throws IOException Thrown in case of I/O error.
//   */
//  public synchronized String dump() throws IOException {
//    return dump(true);
//  }
//
//  /**
//   * Returns paths to all open files currently held in the pool.
//   * @return An array containing open file paths.
//   */
//  public synchronized String[] getCachedFilePaths() {
//    Set<String> keySet = rrdMap.keySet();
//    int n = keySet.size(), i = 0;
//    String[] files = new String[n];
//    Iterator<String> it = keySet.iterator();
//    while(it.hasNext()) {
//      files[i++] = it.next();
//    }
//    return files;
//  }
//
//  /**
//   * Returns maximum number of internally open RRD files
//   * which still does not force garbage collector to run.
//   *
//   * @return Desired nuber of open files held in the pool.
//   */
//  public synchronized int getCapacity() {
//    return capacity;
//  }
//
//  /**
//   * Sets maximum number of internally open RRD files
//   * which still does not force garbage collector to run.
//   *
//   * @param capacity Desired number of open files to hold in the pool
//   */
//  public synchronized void setCapacity(int capacity) {
//    this.capacity = capacity;
////    debug("Capacity set to: " + capacity);
//  }
//
//  private RrdBackendFactory getFactory() throws RrdException {
//    if (factory == null) {
//      factory = RrdBackendFactory.getDefaultFactory();
//      if (!(factory instanceof RrdFileBackendFactory)) {
//        factory = null;
//        throw new RrdException(
//          "RrdDbPool cannot work with factories not derived from RrdFileBackendFactory");
//      }
//    }
//    return factory;
//  }
//
//  private class RrdEntry {
//    private RrdDb rrdDb;
//    private int usageCount = 1;
//
//    public RrdEntry(RrdDb rrdDb) {
//      this.rrdDb = rrdDb;
//    }
//
//    RrdDb getRrdDb() {
//      return rrdDb;
//    }
//
//    int reportUsage() {
//      assert usageCount >= 0: "Unexpected reportUsage count: " + usageCount;
//      return ++usageCount;
//    }
//
//    int reportRelease() {
//      assert usageCount > 0: "Unexpected reportRelease count: " + usageCount;
//      return --usageCount;
//    }
//
//    boolean isInUse() {
//      return usageCount > 0;
//    }
//
//    void closeRrdDb() throws IOException {
//      rrdDb.close();
//    }
//
//    String dump() throws IOException {
//      String canonicalPath = getCanonicalPath(rrdDb.getPath());
//      return canonicalPath + " [" + usageCount + "]";
//    }
//  }
//
//  /**
//   * Calculates pool's efficency ratio. The ratio is obtained by dividing the number of
//   * RrdDb requests served from the internal pool of open RRD files
//   * with the number of total RrdDb requests.
//   *
//   * @return Pool's efficiency ratio as a double between 1 (best) and 0 (worst).
//   * If no RrdDb reference was ever requested, 1 would be returned.
//   */
//  public synchronized double getPoolEfficiency() {
//    if (poolRequestsCount == 0) {
//      return 1.0;
//    }
//    double ratio = (double) poolHitsCount / (double) poolRequestsCount;
//    // round to 3 decimal digits
//    return Math.round(ratio * 1000.0) / 1000.0;
//  }
//
//  /**
//   * Returns the number of RRD requests served from the internal pool of open RRD files
//   *
//   * @return The number of pool "hits".
//   */
//  public synchronized int getPoolHitsCount() {
//    return poolHitsCount;
//  }
//
//  /**
//   * Returns the total number of RRD requests successfully served by this pool.
//   *
//   * @return Total number of RRD requests
//   */
//  public synchronized int getPoolRequestsCount() {
//    return poolRequestsCount;
//  }
//
//  /**
//   * Returns the maximum number of open RRD files over the lifetime
//   * of the pool.
//   * @return maximum number of open RRD files.
//   */
//  public synchronized int getMaxUsedCapacity() {
//    return maxUsedCapacity;
//  }
//
//  /**
//   * Checks the internal behaviour of the pool. See {@link #setLimitedCapacity(boolean)} for
//   * more information.
//   *
//   * @return <code>true</code> if the pool is 'flexible' (by not imposing the strict
//   * limit on the number of simultaneously open files), <code>false</code> otherwise.
//   */
//  public synchronized boolean isLimitedCapacity() {
//    return limitedCapacity;
//  }
//
//  /**
//   * Sets the behaviour of the pool. If <code>true</code> is passed as argument, the pool will never
//   * open more than {@link #getCapacity()} files at any time. If set to <code>false</code>,
//   * the pool might keep more open files, but only for a short period of time. This method might be
//   * useful if you want avoid OS limits when it comes to the number of simultaneously open files.<p>
//   *
//   * By default, the pool behaviour is 'flexible' (<code>limitedCapacity</code> property defaults
//   * to false<p>
//   *
//   * @param limitedCapacity <code>true</code> if the pool should be 'flexible' (not imposing the strict
//   * limit on the number of simultaneously open files), <code>false</code> otherwise.
//   */
//  public synchronized void setLimitedCapacity(boolean limitedCapacity) {
//    this.limitedCapacity = limitedCapacity;
//  }
//
//  private void proveActive() throws IOException {
//    if(!active) {
//      throw new IOException("RrdDbPool is already closed");
//    }
//  }
//
//  /**
//   * Checks if the pool is active. You can request RrdDb references only from the active pool. The
//   * pool is deactived when the {@link #close()} method is called.
//   * @return <code>true</code> if active, <code>false</code> otherwise.
//   */
//  public synchronized boolean isActive() {
//    return active;
//  }
//}
//


TOP

Related Classes of org.jrobin.core.RrdDbPool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.