package org.rrd4j.core; import java.io.IOException; import java.util.concurrent.ScheduledExecutorService; /** * Factory class which creates actual {@link org.rrd4j.core.RrdNioBackend} objects. This is the default factory since * 1.4.0 version. * <h3>Managing the thread pool</h3> * Each RrdNioBackendFactory is backed by a {@link org.rrd4j.core.RrdSyncThreadPool}, which it uses to sync the memory-mapped files to * disk. In order to avoid having these threads live longer than they should, it is recommended that clients create and * destroy thread pools at the appropriate time in their application's life time. Failure to manage thread pools * appropriately may lead to the thread pool hanging around longer than necessary, which in turn may cause memory leaks. * */ public class RrdNioBackendFactory extends RrdFileBackendFactory { /** * Period in seconds between consecutive synchronizations when * sync-mode is set to SYNC_BACKGROUND. By default in-memory cache will be * transferred to the disc every 300 seconds (5 minutes). Default value can be * changed via {@link #setSyncPeriod(int)} method. */ public static final int DEFAULT_SYNC_PERIOD = 300; // seconds private static int syncPeriod = DEFAULT_SYNC_PERIOD; /** * The core pool size for the sync executor. Defaults to 6. */ public static final int DEFAULT_SYNC_CORE_POOL_SIZE = 6; private static int syncPoolSize = DEFAULT_SYNC_CORE_POOL_SIZE; /** * The thread pool to pass to newly-created RrdNioBackend instances. */ private RrdSyncThreadPool syncThreadPool; /** * Returns time between two consecutive background synchronizations. If not changed via * {@link #setSyncPeriod(int)} method call, defaults to {@link #DEFAULT_SYNC_PERIOD}. * See {@link #setSyncPeriod(int)} for more information. * * @return Time in seconds between consecutive background synchronizations. */ public static int getSyncPeriod() { return syncPeriod; } /** * Sets time between consecutive background synchronizations. * * @param syncPeriod Time in seconds between consecutive background synchronizations. */ public static void setSyncPeriod(int syncPeriod) { RrdNioBackendFactory.syncPeriod = syncPeriod; } /** * Returns the number of synchronizing threads. If not changed via * {@link #setSyncPoolSize(int)} method call, defaults to {@link #DEFAULT_SYNC_CORE_POOL_SIZE}. * See {@link #setSyncPoolSize(int)} for more information. * * @return Number of synchronizing threads. */ public static int getSyncPoolSize() { return syncPoolSize; } /** * Sets the number of synchronizing threads. It must be set before the first use of this factory. * It will not have any effect afterward. * * @param syncPoolSize Number of synchronizing threads. */ public static void setSyncPoolSize(int syncPoolSize) { RrdNioBackendFactory.syncPoolSize = syncPoolSize; } /** * Creates a new RrdNioBackendFactory. One should call {@link #setSyncThreadPool(RrdSyncThreadPool syncThreadPool)} * or {@link #setSyncThreadPool(RrdSyncThreadPool syncThreadPool)} before the first call to * {@link #open(String path, boolean readOnly)}. * Failure to do so will lead to memory leaks in anything but the simplest applications because the underlying thread pool will not * be shut down cleanly. Read the Javadoc for this class to understand why using this constructor is discouraged. */ public RrdNioBackendFactory() { super(); } /** * <p>Setter for the field <code>syncThreadPool</code>.</p> * * @param syncThreadPool the RrdSyncThreadPool to use to sync the memory-mapped files. */ public void setSyncThreadPool(RrdSyncThreadPool syncThreadPool) { this.syncThreadPool = syncThreadPool; } /** * <p>Setter for the field <code>syncThreadPool</code>.</p> * * @param syncThreadPool the ScheduledExecutorService that will back the RrdSyncThreadPool used to sync the memory-mapped files. */ public void setSyncThreadPool(ScheduledExecutorService syncThreadPool) { this.syncThreadPool = new RrdSyncThreadPool(syncThreadPool); } /** * {@inheritDoc} * * Creates RrdNioBackend object for the given file path. */ protected RrdBackend open(String path, boolean readOnly) throws IOException { // Instantiate a thread pool if none was provided if(syncThreadPool == null) { syncThreadPool = DefaultSyncThreadPool.INSTANCE; } return new RrdNioBackend(path, readOnly, syncThreadPool, syncPeriod); } /** * <p>getName.</p> * * @return The {@link java.lang.String} "NIO". */ public String getName() { return "NIO"; } /** * This is a holder class as per the "initialisation on demand" Java idiom. The only purpose of this holder class is * to ensure that the thread pool is created lazily the first time that it is needed, and not before. * <p/> * In practice this thread pool will be used if clients rely on the factory returned by {@link * org.rrd4j.core.RrdBackendFactory#getDefaultFactory()}, but not if clients provide their own backend instance when * creating {@code RrdDb} instances. */ private static class DefaultSyncThreadPool { /** * The default thread pool used to periodically sync the mapped file to disk with. */ static RrdSyncThreadPool INSTANCE = new RrdSyncThreadPool(syncPoolSize); private DefaultSyncThreadPool() {} } }