From: Sasa M. <sa...@us...> - 2004-11-09 11:37:04
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12665/org/jrobin/core Modified Files: Archive.java Datasource.java Header.java RrdBackendFactory.java RrdDouble.java RrdDoubleArray.java RrdInt.java RrdLong.java RrdPrimitive.java RrdString.java Added Files: RrdSafeFileBackend.java RrdSafeFileBackendFactory.java Log Message: Major core update: added one more backend type (SAFE - basically it's a FILE, but with RRD file locking and minimal in-memory caching). Could be useful when RRD files are used by two JVMs running at the same time. Index: RrdPrimitive.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdPrimitive.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdPrimitive.java 8 Nov 2004 11:18:49 -0000 1.9 --- RrdPrimitive.java 9 Nov 2004 11:36:53 -0000 1.10 *************** *** 36,48 **** private int byteCount; private final long pointer; ! RrdPrimitive(RrdUpdater updater, int type) throws IOException { ! this(updater, type, 1); } ! RrdPrimitive(RrdUpdater updater, int type, int count) throws IOException { this.backend = updater.getRrdBackend(); this.byteCount = RRD_PRIM_SIZES[type] * count; this.pointer = updater.getRrdAllocator().allocate(byteCount); } --- 36,50 ---- private int byteCount; private final long pointer; + private final boolean cachingAllowed; ! RrdPrimitive(RrdUpdater updater, int type, boolean isConstant) throws IOException { ! this(updater, type, 1, isConstant); } ! RrdPrimitive(RrdUpdater updater, int type, int count, boolean isConstant) throws IOException { this.backend = updater.getRrdBackend(); this.byteCount = RRD_PRIM_SIZES[type] * count; this.pointer = updater.getRrdAllocator().allocate(byteCount); + this.cachingAllowed = isConstant || backend.isCachingAllowed(); } *************** *** 111,115 **** final boolean isCachingAllowed() { ! return backend.isCachingAllowed(); } } --- 113,117 ---- final boolean isCachingAllowed() { ! return cachingAllowed; } } Index: Header.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Header.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** Header.java 22 Jul 2004 09:34:10 -0000 1.7 --- Header.java 9 Nov 2004 11:36:53 -0000 1.8 *************** *** 52,59 **** boolean shouldInitialize = rrdDef != null; this.parentDb = parentDb; ! signature = new RrdString(this); ! step = new RrdLong(this); ! dsCount = new RrdInt(this); ! arcCount = new RrdInt(this); lastUpdateTime = new RrdLong(this); if(shouldInitialize) { --- 52,59 ---- boolean shouldInitialize = rrdDef != null; this.parentDb = parentDb; ! signature = new RrdString(this, true); // constant, may be cached ! step = new RrdLong(this, true); // constant, may be cached ! dsCount = new RrdInt(this, true); // constant, may be cached ! arcCount = new RrdInt(this, true); // constant, may be cached lastUpdateTime = new RrdLong(this); if(shouldInitialize) { Index: Archive.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Archive.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** Archive.java 21 Sep 2004 08:42:09 -0000 1.18 --- Archive.java 9 Nov 2004 11:36:53 -0000 1.19 *************** *** 52,59 **** boolean shouldInitialize = arcDef != null; this.parentDb = parentDb; ! consolFun = new RrdString(this); xff = new RrdDouble(this); ! steps = new RrdInt(this); ! rows = new RrdInt(this); if(shouldInitialize) { consolFun.set(arcDef.getConsolFun()); --- 52,59 ---- boolean shouldInitialize = arcDef != null; this.parentDb = parentDb; ! consolFun = new RrdString(this, true); // constant, may be cached xff = new RrdDouble(this); ! steps = new RrdInt(this, true); // constant, may be cached ! rows = new RrdInt(this, true); // constant, may be cached if(shouldInitialize) { consolFun.set(arcDef.getConsolFun()); Index: RrdInt.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdInt.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdInt.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdInt.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,39 **** private boolean cached = false; RrdInt(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_INT); } ! void set(int value) throws IOException { if(!isCachingAllowed()) { --- 32,43 ---- private boolean cached = false; + RrdInt(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_INT, isConstant); + } + RrdInt(RrdUpdater updater) throws IOException { ! this(updater, false); } ! void set(int value) throws IOException { if(!isCachingAllowed()) { Index: RrdDouble.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDouble.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdDouble.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdDouble.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,37 **** private boolean cached = false; RrdDouble(RrdUpdater updater) throws IOException { ! super(updater, RrdDouble.RRD_DOUBLE); } --- 32,41 ---- private boolean cached = false; + RrdDouble(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdDouble.RRD_DOUBLE, isConstant); + } + RrdDouble(RrdUpdater updater) throws IOException { ! super(updater, RrdDouble.RRD_DOUBLE, false); } Index: RrdString.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdString.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdString.java 8 Nov 2004 11:18:49 -0000 1.10 --- RrdString.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 31,36 **** private String cache; RrdString(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_STRING); } --- 31,40 ---- private String cache; + RrdString(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_STRING, isConstant); + } + RrdString(RrdUpdater updater) throws IOException { ! this(updater, false); } Index: RrdLong.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdLong.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdLong.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdLong.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,37 **** private boolean cached = false; RrdLong(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_LONG); } --- 32,41 ---- private boolean cached = false; + RrdLong(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_LONG, isConstant); + } + RrdLong(RrdUpdater updater) throws IOException { ! this(updater, false); } Index: RrdBackendFactory.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdBackendFactory.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** RrdBackendFactory.java 13 Jul 2004 18:42:19 -0000 1.7 --- RrdBackendFactory.java 9 Nov 2004 11:36:53 -0000 1.8 *************** *** 37,41 **** * Each factory creates unlimited number of specific backend objects. * ! * JRobin supports three different backend types (backend factories) out of the box:<p> * <ul> * <li>{@link RrdFileBackend}: objects of this class are created from the --- 37,41 ---- * Each factory creates unlimited number of specific backend objects. * ! * JRobin supports four different backend types (backend factories) out of the box:<p> * <ul> * <li>{@link RrdFileBackend}: objects of this class are created from the *************** *** 44,47 **** --- 44,55 ---- * RRD data in files on the disk. * + * <li>{@link RrdSafeFileBackend}: objects of this class are created from the + * {@link RrdSafeFileBackendFactory} class. It uses java.io.* package and RandomAccessFile class to store + * RRD data in files on the disk. This backend is SAFE: + * it locks the underlying RRD file during update/fetch operations, and caches only static + * parts of a RRD file in memory. Therefore, this backend is safe to be used when RRD files should + * be shared <b>between several JVMs</b> at the same time. However, this backend is *slow* since it does + * not use fast java.nio.* package (it's still based on the RandomAccessFile class). + * * <li>{@link RrdNioBackend}: objects of this class are created from the * {@link RrdNioBackendFactory} class. The backend uses java.io.* and java.nio.* *************** *** 72,75 **** --- 80,85 ---- RrdNioBackendFactory nioFactory = new RrdNioBackendFactory(); registerFactory(nioFactory); + RrdSafeFileBackendFactory safeFactory = new RrdSafeFileBackendFactory(); + registerFactory(safeFactory); // Here is the default backend factory *************** *** 87,90 **** --- 97,104 ---- * <li><b>FILE</b>: Default factory which creates backends based on the * java.io.* package. RRD data is stored in files on the disk + * <li><b>SAFE</b>: Default factory which creates backends based on the + * java.io.* package. RRD data is stored in files on the disk. This backend + * is "safe". Being safe means that RRD files can be safely shared between + * several JVM's. * <li><b>NIO</b>: Factory which creates backends based on the * java.nio.* package. RRD data is stored in files on the disk *************** *** 149,155 **** * Replaces the default backend factory with a new one. This method must be called before * the first RRD gets created. <p> ! * @param factoryName Name of the default factory. Out of the box, JRobin supports three ! * different RRD backends: "FILE" (java.io.* based), "NIO" (java.nio.* based) and "MEMORY" ! * (byte[] based). * @throws RrdException Thrown if invalid factory name is supplied or not called before * the first RRD is created. --- 163,170 ---- * Replaces the default backend factory with a new one. This method must be called before * the first RRD gets created. <p> ! * @param factoryName Name of the default factory. Out of the box, JRobin supports four ! * different RRD backends: "FILE" (java.io.* based), "SAFE" (java.io.* based - use this ! * backend if RRD files may be accessed from several JVMs at the same time), ! * "NIO" (java.nio.* based) and "MEMORY" (byte[] based). * @throws RrdException Thrown if invalid factory name is supplied or not called before * the first RRD is created. --- NEW FILE: RrdSafeFileBackendFactory.java --- package org.jrobin.core; import java.io.IOException; /** * Factory class which creates actual {@link RrdSafeFileBackend} objects. */ public class RrdSafeFileBackendFactory extends RrdFileBackendFactory { /** factory name, "SAFE" */ public static final String NAME = "SAFE"; /** * Creates RrdSafeFileBackend object for the given file path. * @param path File path * @param readOnly True, if the file should be accessed in read/only mode. * False otherwise. * @param lockMode This parameter is ignored since this backend implements its own * locking mechanism. * @return RrdSafeFileBackend object which handles all I/O operations for the given file path * @throws IOException Thrown in case of I/O error. */ protected RrdBackend open(String path, boolean readOnly, int lockMode) throws IOException { return new RrdSafeFileBackend(path, readOnly, lockMode); } /** * Returns the name of this factory. * @return Factory name (equals to string "SAFE") */ public String getFactoryName() { return NAME; } } --- NEW FILE: RrdSafeFileBackend.java --- package org.jrobin.core; import java.io.IOException; import java.nio.channels.FileLock; /** * JRobin backend which is used to store RRD data to ordinary files on the disk. This backend * is SAFE: it locks the underlying RRD file during update/fetch operations, and caches only static * parts of a RRD file in memory. Therefore, this backend is safe to be used when RRD files should * be shared between several JVMs at the same time. However, this backend is *slow* since it does * not use fast java.nio.* package (it's still based on the RandomAccessFile class). */ public class RrdSafeFileBackend extends RrdFileBackend { /** Number of locking retries. This backend will not give up if the first locking request fails. */ public static final int LOCK_RETRY_COUNT = 40; /** Number of milliseconds between locking retries */ public static final int LOCK_RETRY_DELAY = 50; // milliseconds private FileLock lock; /** * Creates RrdFileBackend object for the given file path, backed by RandomAccessFile object. * @param path Path to a file * @param readOnly True, if file should be open in a read-only mode. False otherwise * @param lockMode Ignored, since this backend implements its own locking mechanism * @throws IOException Thrown in case of I/O error */ public RrdSafeFileBackend(String path, boolean readOnly, int lockMode) throws IOException { // this backend implements its own locking mechanism - we'll simply ignore the suggested lockMode super(path, readOnly, RrdDb.NO_LOCKS); } private void lockFile() throws IOException { if(lock != null) { // lock already obtained return; } for(int i = 0; i < LOCK_RETRY_COUNT; i++) { lock = channel.tryLock(); if(lock != null) { return; } try { Thread.sleep(LOCK_RETRY_DELAY); } catch (InterruptedException e) { // NOP } } throw new IOException("Could not obtain lock on file: " + getPath() + "] after " + LOCK_RETRY_COUNT + " consecutive retries"); } private void unlockFile() throws IOException { if(lock != null) { lock.release(); lock = null; } } /** * Defines the caching policy for this backend. * @return <code>false</code> */ protected boolean isCachingAllowed() { return false; } /** * Locks the underlying RRD file just before the next RRD update operation. * @throws IOException Thrown if the file lock could not be obtained. */ protected void beforeUpdate() throws IOException { super.beforeUpdate(); lockFile(); } /** * Unlocks the underlying RRD file just after the RRD update operation. * @throws IOException Thrown if the lock could not be released. */ protected void afterUpdate() throws IOException { unlockFile(); super.afterUpdate(); } /** * Locks the underlying RRD file just before the next RRD fetch operation. * @throws IOException Thrown if the file lock could not be obtained. */ protected void beforeFetch() throws IOException { super.beforeFetch(); lockFile(); } /** * Unlocks the underlying RRD file just after the RRD fetch operation. * @throws IOException Thrown if the lock could not be released. */ protected void afterFetch() throws IOException { unlockFile(); super.afterFetch(); } /** * Releases the file lock before closing the RRD file (if not already released). * @throws IOException Thrown if the lock could not be released. */ protected void beforeClose() throws IOException { // just in case unlockFile(); super.beforeClose(); } } Index: Datasource.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Datasource.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** Datasource.java 21 Sep 2004 08:42:09 -0000 1.9 --- Datasource.java 9 Nov 2004 11:36:53 -0000 1.10 *************** *** 54,59 **** boolean shouldInitialize = dsDef != null; this.parentDb = parentDb; ! dsName = new RrdString(this); ! dsType = new RrdString(this); heartbeat = new RrdLong(this); minValue = new RrdDouble(this); --- 54,59 ---- boolean shouldInitialize = dsDef != null; this.parentDb = parentDb; ! dsName = new RrdString(this, true); // constant, may be cached ! dsType = new RrdString(this, true); // constant, may be cached heartbeat = new RrdLong(this); minValue = new RrdDouble(this); Index: RrdDoubleArray.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDoubleArray.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** RrdDoubleArray.java 20 May 2004 10:29:33 -0000 1.6 --- RrdDoubleArray.java 9 Nov 2004 11:36:53 -0000 1.7 *************** *** 32,36 **** RrdDoubleArray(RrdUpdater updater, int length) throws IOException { ! super(updater, RrdPrimitive.RRD_DOUBLE, length); this.length = length; } --- 32,36 ---- RrdDoubleArray(RrdUpdater updater, int length) throws IOException { ! super(updater, RrdPrimitive.RRD_DOUBLE, length, false); this.length = length; } |