giacomo 02/01/06 09:18:26 Modified: src/scratchpad/src/org/apache/cocoon/jispstore FilesystemQueueImpl.java JispFilesystemStore.java JispStringKey.java MRUMemoryStore.java Log: fixed EOL encoding Revision Changes Path 1.3 +241 -1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/FilesystemQueueImpl.java Index: FilesystemQueueImpl.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/FilesystemQueueImpl.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- FilesystemQueueImpl.java 6 Jan 2002 14:28:10 -0000 1.2 +++ FilesystemQueueImpl.java 6 Jan 2002 17:18:25 -0000 1.3 @@ -1 +1,241 @@ -/***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.jispstore; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Startable; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.logger.AbstractLoggable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.Constants; import org.apache.cocoon.components.store.FilesystemQueue; import org.apache.cocoon.components.store.FilesystemQueueObject; import org.apache.cocoon.components.store.Store; import org.apache.cocoon.util.IOUtils; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.util.LinkedList; import java.util.ListIterator; import java.util.NoSuchElementException; /** * This class provides a asynchron queue for storing objects on the filesystem. * Every store component can uses this component to store object in the * configured cache directory. * * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> */ public final class FilesystemQueueImpl extends AbstractLoggable implements FilesystemQueue, Configurable, Runnable, ThreadSafe, Composable, Disposable, Startable { private static boolean doRun = false; private int handlerinterval; private int threadpriority; private int maxobjects; private LinkedList linkedList; private Store fsstore; private Thread fsQueueHandler; private ComponentManager manager; /** * Test if queue is empty. * * @return true if queue is empty else false. */ public boolean isEmpty() { return (this.linkedList.size() == 0); } /** * Get components of the ComponentManager * * @param manager Description of Parameter * @exception ComponentException Description of Exception */ public void compose(ComponentManager manager) throws ComponentException { this.manager = manager; if (this.getLogger().isDebugEnabled() == true) { getLogger().debug("Looking up " + Store.ROLE + "/JispFilesystemStore"); } this.fsstore = (Store) manager.lookup(Store.ROLE + "/JispFilesystemStore"); } /** * Dispose the component */ public void dispose() { if (this.manager != null) { this.manager.release(this.fsstore); this.fsstore = null; } } /** * Configure the Filesystem Queue: * <UL> * <LI> handlerinterval = Interval of the Queue Handler Thread</LI> * <LI> threadpriority = Priority of the Queue Handler Thread</LI> >LI> * maxobjects = Defines the max. numbers of Objects in the queue</LI> * * </UL> * * * @param conf Description of Parameter * @exception ConfigurationException Description of Exception */ public void configure(Configuration conf) throws ConfigurationException { Parameters params = Parameters.fromConfiguration(conf); this.handlerinterval = params.getParameterAsInteger("handlerinterval", 10); this.threadpriority = params.getParameterAsInteger("threadpriority", 5); this.maxobjects = params.getParameterAsInteger("maxobjects", 100); if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Configure Filesystem Queue"); this.getLogger().debug("handlerinterval=" + handlerinterval); this.getLogger().debug("threadpriority=" + threadpriority); } this.linkedList = new LinkedList(); } /** * Starts the Queue Handler Thread */ public void start() { doRun = true; this.fsQueueHandler = new Thread(this); this.fsQueueHandler.setDaemon(true); this.fsQueueHandler.setPriority(this.threadpriority); this.fsQueueHandler.setName("fsQueueHandler"); this.fsQueueHandler.start(); } /** * Stops the Queue Handler Thread */ public void stop() { doRun = false; } /** * Main processing method for the FilesystemQueueImpl object */ public void run() { while (doRun) { while (!this.isEmpty()) { FilesystemQueueObject filesystemQueueObject = (FilesystemQueueObject) this.pop(); try { this.fsstore.store(filesystemQueueObject.getKey(), filesystemQueueObject.getObject() ); } catch (IOException e) { this.getLogger().error("Error in fsQueueHandler", e); } } try { Thread.currentThread().sleep(this.handlerinterval * 1000); } catch (InterruptedException ignore) {;} } } /** * Clear all elements from queue. */ public void clear() { if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Clearing the FilesystemQueue"); } ListIterator listIterator = linkedList.listIterator(0); while (listIterator.hasNext()) { this.linkedList.remove(listIterator.nextIndex()); } } /** * Insert an element into queue. * * @param element the element to be inserted */ public void insert(Object element) { if (this.linkedList.size() < maxobjects) { if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Insert Element in FilesystemQueue"); } this.linkedList.addFirst(element); this.reportSize(); } else { this.getLogger().warn("Filesystem Queue full!"); } } /** * Return element on top of heap but don't remove it. * * @return the element at top of heap * @exception NoSuchElementException if isEmpty() == true */ public Object peek() throws NoSuchElementException { if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Peek Element in FilesystemQueue"); } return (Comparable) linkedList.getLast(); } /** * Return element on top of heap and remove it. * * @return the element at top of heap * @exception NoSuchElementException if isEmpty() == true */ public Object pop() throws NoSuchElementException { if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Pop Element in FilesystemQueue"); } return (Comparable) linkedList.removeLast(); } private void reportSize() { if (this.getLogger().isDebugEnabled() == true) { this.getLogger().debug("Size of FilesystemQueue=" + this.linkedList.size()); } } } \ No newline at end of file +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package org.apache.cocoon.jispstore; + +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.activity.Startable; +import org.apache.avalon.framework.component.ComponentException; +import org.apache.avalon.framework.component.ComponentManager; +import org.apache.avalon.framework.component.Composable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.logger.AbstractLoggable; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.Constants; +import org.apache.cocoon.components.store.FilesystemQueue; +import org.apache.cocoon.components.store.FilesystemQueueObject; +import org.apache.cocoon.components.store.Store; +import org.apache.cocoon.util.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.NoSuchElementException; + + + +/** + * This class provides a asynchron queue for storing objects on the filesystem. + * Every store component can uses this component to store object in the + * configured cache directory. + * + * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> + */ + +public final class FilesystemQueueImpl +extends AbstractLoggable + +implements FilesystemQueue, + Configurable, + Runnable, + ThreadSafe, + Composable, + Disposable, + Startable { + + private static boolean doRun = false; + private int handlerinterval; + private int threadpriority; + private int maxobjects; + private LinkedList linkedList; + private Store fsstore; + private Thread fsQueueHandler; + private ComponentManager manager; + + /** + * Test if queue is empty. + * + * @return true if queue is empty else false. + */ + + public boolean isEmpty() { + return (this.linkedList.size() == 0); + } + + /** + * Get components of the ComponentManager + * + * @param manager Description of Parameter + * @exception ComponentException Description of Exception + */ + + public void compose(ComponentManager manager) + throws ComponentException { + + this.manager = manager; + if (this.getLogger().isDebugEnabled() == true) { + getLogger().debug("Looking up " + Store.ROLE + "/JispFilesystemStore"); + } + this.fsstore = (Store) manager.lookup(Store.ROLE + "/JispFilesystemStore"); + } + + /** + * Dispose the component + */ + public void dispose() { + if (this.manager != null) { + this.manager.release(this.fsstore); + this.fsstore = null; + } + } + + /** + * Configure the Filesystem Queue: + * <UL> + * <LI> handlerinterval = Interval of the Queue Handler Thread</LI> + * <LI> threadpriority = Priority of the Queue Handler Thread</LI> >LI> + * maxobjects = Defines the max. numbers of Objects in the queue</LI> + * + * </UL> + * + * + * @param conf Description of Parameter + * @exception ConfigurationException Description of Exception + */ + + public void configure(Configuration conf) + throws ConfigurationException { + + Parameters params = Parameters.fromConfiguration(conf); + this.handlerinterval = params.getParameterAsInteger("handlerinterval", 10); + this.threadpriority = params.getParameterAsInteger("threadpriority", 5); + this.maxobjects = params.getParameterAsInteger("maxobjects", 100); + + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Configure Filesystem Queue"); + this.getLogger().debug("handlerinterval=" + handlerinterval); + this.getLogger().debug("threadpriority=" + threadpriority); + } + this.linkedList = new LinkedList(); + } + + /** + * Starts the Queue Handler Thread + */ + public void start() { + doRun = true; + this.fsQueueHandler = new Thread(this); + this.fsQueueHandler.setDaemon(true); + this.fsQueueHandler.setPriority(this.threadpriority); + this.fsQueueHandler.setName("fsQueueHandler"); + this.fsQueueHandler.start(); + } + + /** + * Stops the Queue Handler Thread + */ + public void stop() { + doRun = false; + } + + /** + * Main processing method for the FilesystemQueueImpl object + */ + public void run() { + while (doRun) { + while (!this.isEmpty()) { + FilesystemQueueObject filesystemQueueObject = (FilesystemQueueObject) this.pop(); + try { + this.fsstore.store(filesystemQueueObject.getKey(), + filesystemQueueObject.getObject() + ); + } catch (IOException e) { + this.getLogger().error("Error in fsQueueHandler", e); + } + } try { + Thread.currentThread().sleep(this.handlerinterval * 1000); + } catch (InterruptedException ignore) {;} + } + } + + /** + * Clear all elements from queue. + */ + public void clear() { + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Clearing the FilesystemQueue"); + } + + ListIterator listIterator = linkedList.listIterator(0); + while (listIterator.hasNext()) { + this.linkedList.remove(listIterator.nextIndex()); + } + } + + /** + * Insert an element into queue. + * + * @param element the element to be inserted + */ + public void insert(Object element) { + + if (this.linkedList.size() < maxobjects) { + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Insert Element in FilesystemQueue"); + } + this.linkedList.addFirst(element); + this.reportSize(); + } else { + this.getLogger().warn("Filesystem Queue full!"); + } + } + + /** + * Return element on top of heap but don't remove it. + * + * @return the element at top of heap + * @exception NoSuchElementException if isEmpty() == true + */ + public Object peek() + throws NoSuchElementException { + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Peek Element in FilesystemQueue"); + } + + return (Comparable) linkedList.getLast(); + } + + /** + * Return element on top of heap and remove it. + * + * @return the element at top of heap + * @exception NoSuchElementException if isEmpty() == true + */ + public Object pop() + throws NoSuchElementException { + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Pop Element in FilesystemQueue"); + } + return (Comparable) linkedList.removeLast(); + } + + private void reportSize() { + if (this.getLogger().isDebugEnabled() == true) { + this.getLogger().debug("Size of FilesystemQueue=" + + this.linkedList.size()); + } + } +} + + + 1.3 +357 -1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispFilesystemStore.java Index: JispFilesystemStore.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispFilesystemStore.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- JispFilesystemStore.java 6 Jan 2002 14:28:10 -0000 1.2 +++ JispFilesystemStore.java 6 Jan 2002 17:18:26 -0000 1.3 @@ -1 +1,357 @@ -/** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * */ package org.apache.cocoon.jispstore; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.logger.AbstractLoggable; import org.apache.avalon.framework.parameters.ParameterException; import org.apache.avalon.framework.parameters.Parameterizable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.Constants; import org.apache.cocoon.components.store.Store; import org.apache.cocoon.util.IOUtils; import com.coyotegulch.jisp.BTreeIndex; import com.coyotegulch.jisp.IndexedObjectDatabase; import com.coyotegulch.jisp.KeyNotFound; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.Enumeration; /** * This store is based on the Jisp library * (http://www.coyotegulch.com/jisp/index.html). This store uses B-Tree indexes * to access variable-length serialized data stored in files. * * @author Gerhard Froehlich * <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> */ public final class JispFilesystemStore extends AbstractLoggable implements Store, Contextualizable, ThreadSafe, Initializable, Parameterizable { /** * The directory repository */ protected File mDirectoryFile; /** * Description of the Field */ protected volatile String mDirectoryPath; /** * The database */ private String mDatabaseName; private String mIndexName; private int mOrder; private IndexedObjectDatabase mDatabase; private BTreeIndex mIndex; /** * Sets the repository's location * * @param the new directory value * @exception IOException */ public void setDirectory(final String directory) throws IOException { this.setDirectory(new File(directory)); } /** * Sets the repository's location * * @param the new directory value * @exception IOException */ public void setDirectory(final File directory) throws IOException { this.mDirectoryFile = directory; /* * Save directory path prefix */ this.mDirectoryPath = IOUtils.getFullFilename(this.mDirectoryFile); this.mDirectoryPath += File.separator; /* * Does directory exist? */ if (!this.mDirectoryFile.exists()) { /* * Create it anew */ if (!this.mDirectoryFile.mkdir()) { throw new IOException( "Error creating store directory '" + this.mDirectoryPath + "': "); } } /* * Is given file actually a directory? */ if (!this.mDirectoryFile.isDirectory()) { throw new IOException("'" + this.mDirectoryPath + "' is not a directory"); } /* * Is directory readable and writable? */ if (!(this.mDirectoryFile.canRead() && this.mDirectoryFile.canWrite())) { throw new IOException( "Directory '" + this.mDirectoryPath + "' is not readable/writable" ); } } /** * Returns the repository's full pathname * * @return the directory as String */ public String getDirectoryPath() { return this.mDirectoryPath; } /** * Returns a Object from the store associated with the Key Object * * @param the Key object * @return the Object associated with Key Object */ public Object get(Object key) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("get(): Get file with key: " + key.toString()); } Object readObj = null; try { readObj = mDatabase.read(new JispStringKey(key.toString()), mIndex); if (getLogger().isDebugEnabled()) { if (readObj != null) { this.getLogger().debug("get(): FOUND!!= " + readObj); } else { this.getLogger().debug("get(): NOT_FOUND!!"); } } } catch (Exception e) { getLogger().error("get(..): Exception", e); } return readObj; } /** * Contextualize the Component * * @param the Context of the Application * @exception ContextException */ public void contextualize(final Context context) throws ContextException { try { setDirectory((File) context.get(Constants.CONTEXT_WORK_DIR)); } catch (Exception e) { // ignore } } /** * Initialize the Component */ public void initialize() { if (getLogger().isDebugEnabled()) { getLogger().debug("initialize() JispFilesystemStore"); } try { if (getLogger().isDebugEnabled()) { getLogger().debug("initialize(): Path to Datafile=" + this.getDirectoryPath() + mDatabaseName); } File myFile = new File(this.getDirectoryPath() + mDatabaseName); if (myFile.exists()) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("initialize(): Datafile exists"); } mDatabase = new IndexedObjectDatabase(getDirectoryPath() + mDatabaseName, false); mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName); mDatabase.attachIndex(mIndex); mIndex.dumpTree(); } else { if (getLogger().isDebugEnabled()) { this.getLogger().debug("initialize(): Datafile not exists"); } mDatabase = new IndexedObjectDatabase(getDirectoryPath() + mDatabaseName, false); mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName, mOrder, new JispStringKey(), false); mDatabase.attachIndex(mIndex); mIndex.dumpTree(); } } catch (KeyNotFound ignore) { } catch (Exception e) { getLogger().error("initialize(..) Exception", e); } } /** * Configure the Component. A few options can be used : * <UL> * <LI> mDatabaseName = the name of the data file (Default: cocoon.dat) * </LI> * <LI> mIndexName = the name of the index file (Default: cocoon.idx) * </LI> * <LI> mOrder = The page size of the B-Tree</LI> * </UL> * * * @param The Configuration Paramter * @exception ParameterException */ public void parameterize(Parameters params) throws ParameterException { mDatabaseName = params.getParameter("datafile", "cocoon.dat"); mIndexName = params.getParameter("indexfile", "cocoon.idx"); mOrder = params.getParameterAsInteger("order", 1001); if (getLogger().isDebugEnabled()) { this.getLogger().debug("parameterize(..): mDatabaseName=" + mDatabaseName); this.getLogger().debug("parameterize(..): mIndexName=" + mIndexName); this.getLogger().debug("parameterize(..): mOrder=" + mOrder); } } /** * Store the given Object in the indexed data file. * * @param the Key Object * @param the Value Object * @exception IOException */ public void store(Object key, Object value) throws IOException { if (getLogger().isDebugEnabled()) { this.getLogger().debug("store(): Store file with key: " + key.toString()); } if (value instanceof Serializable) { try { JispStringKey[] keyArray = new JispStringKey[1]; keyArray[0] = new JispStringKey(key.toString()); mDatabase.write(keyArray, (Serializable) value); } catch (Exception e) { this.getLogger().error("store(..): Exception", e); } } else { throw new IOException("Object not Serializable"); } } /** * Holds the given Object in the indexed data file. * * @param the Key Object * @param the Value Object * @exception IOException */ public void hold(Object key, Object value) throws IOException { this.store(key, value); } /** * Frees some values of the data file */ public void free() { //TODO: implementation } /** * Removes a value from the data file with the given key. * * @param the Key Object */ public void remove(Object key) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("remove(..) Remove item"); } try { JispStringKey[] keyArray = new JispStringKey[1]; keyArray[0] = new JispStringKey(key.toString()); mDatabase.remove(keyArray); } catch (KeyNotFound ignore) { } catch (Exception e) { this.getLogger().error("remove(..): Exception", e); } } /** * Test if the the index file contains the given key * * @param the Key Object * @return true if Key exists and false if not */ public boolean containsKey(Object key) { long res = -1; try { res = mIndex.findKey(new JispStringKey(key.toString())); if (getLogger().isDebugEnabled()) { this.getLogger().debug("containsKey(..): res=" + res); } } catch (KeyNotFound ignore) { } catch (Exception e) { this.getLogger().error("containsKey(..): Exception", e); } if (res > 0) { return true; } else { return false; } } /** * Returns a Enumeration of all Keys in the indexed file * * @return Enumeration Object with all existing keys */ public Enumeration keys() { //TODO: Implementation return null; } } \ No newline at end of file +/** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + */ +package org.apache.cocoon.jispstore; + +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.logger.AbstractLoggable; +import org.apache.avalon.framework.parameters.ParameterException; +import org.apache.avalon.framework.parameters.Parameterizable; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.Constants; +import org.apache.cocoon.components.store.Store; +import org.apache.cocoon.util.IOUtils; + +import com.coyotegulch.jisp.BTreeIndex; +import com.coyotegulch.jisp.IndexedObjectDatabase; +import com.coyotegulch.jisp.KeyNotFound; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.Enumeration; + +/** + * This store is based on the Jisp library + * (http://www.coyotegulch.com/jisp/index.html). This store uses B-Tree indexes + * to access variable-length serialized data stored in files. + * + * @author Gerhard Froehlich + * <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> + */ + +public final class JispFilesystemStore +extends AbstractLoggable +implements Store, + Contextualizable, + ThreadSafe, + Initializable, + Parameterizable { + + /** + * The directory repository + */ + protected File mDirectoryFile; + + /** + * Description of the Field + */ + protected volatile String mDirectoryPath; + + + + /** + * The database + */ + private String mDatabaseName; + private String mIndexName; + private int mOrder; + private IndexedObjectDatabase mDatabase; + private BTreeIndex mIndex; + + /** + * Sets the repository's location + * + * @param the new directory value + * @exception IOException + */ + public void setDirectory(final String directory) + throws IOException { + this.setDirectory(new File(directory)); + } + + /** + * Sets the repository's location + * + * @param the new directory value + * @exception IOException + */ + + public void setDirectory(final File directory) + throws IOException { + this.mDirectoryFile = directory; + + /* + * Save directory path prefix + */ + this.mDirectoryPath = IOUtils.getFullFilename(this.mDirectoryFile); + this.mDirectoryPath += File.separator; + + /* + * Does directory exist? + */ + if (!this.mDirectoryFile.exists()) { + /* + * Create it anew + */ + if (!this.mDirectoryFile.mkdir()) { + throw new IOException( + "Error creating store directory '" + + this.mDirectoryPath + "': "); + } + } + + /* + * Is given file actually a directory? + */ + if (!this.mDirectoryFile.isDirectory()) { + throw new IOException("'" + this.mDirectoryPath + + "' is not a directory"); + } + + /* + * Is directory readable and writable? + */ + if (!(this.mDirectoryFile.canRead() + && this.mDirectoryFile.canWrite())) { + throw new IOException( + "Directory '" + this.mDirectoryPath + + "' is not readable/writable" + ); + } + } + + /** + * Returns the repository's full pathname + * + * @return the directory as String + */ + public String getDirectoryPath() { + return this.mDirectoryPath; + } + + /** + * Returns a Object from the store associated with the Key Object + * + * @param the Key object + * @return the Object associated with Key Object + */ + public Object get(Object key) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("get(): Get file with key: " + key.toString()); + } + Object readObj = null; + + try { + readObj = mDatabase.read(new JispStringKey(key.toString()), mIndex); + if (getLogger().isDebugEnabled()) { + if (readObj != null) { + this.getLogger().debug("get(): FOUND!!= " + readObj); + } else { + this.getLogger().debug("get(): NOT_FOUND!!"); + } + } + } catch (Exception e) { + getLogger().error("get(..): Exception", e); + } + return readObj; + } + + /** + * Contextualize the Component + * + * @param the Context of the Application + * @exception ContextException + */ + public void contextualize(final Context context) + throws ContextException { + try { + setDirectory((File) context.get(Constants.CONTEXT_WORK_DIR)); + } catch (Exception e) { + // ignore + } + } + + /** + * Initialize the Component + */ + public void initialize() { + if (getLogger().isDebugEnabled()) { + getLogger().debug("initialize() JispFilesystemStore"); + } + + try { + if (getLogger().isDebugEnabled()) { + getLogger().debug("initialize(): Path to Datafile=" + + this.getDirectoryPath() + mDatabaseName); + } + File myFile = new File(this.getDirectoryPath() + mDatabaseName); + if (myFile.exists()) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("initialize(): Datafile exists"); + } + mDatabase = new IndexedObjectDatabase(getDirectoryPath() + + mDatabaseName, false); + mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName); + mDatabase.attachIndex(mIndex); + mIndex.dumpTree(); + } else { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("initialize(): Datafile not exists"); + } + mDatabase = new IndexedObjectDatabase(getDirectoryPath() + + mDatabaseName, false); + mIndex = new BTreeIndex(this.getDirectoryPath() + mIndexName, + mOrder, new JispStringKey(), false); + mDatabase.attachIndex(mIndex); + mIndex.dumpTree(); + } + } catch (KeyNotFound ignore) { + } catch (Exception e) { + getLogger().error("initialize(..) Exception", e); + } + } + + /** + * Configure the Component. A few options can be used : + * <UL> + * <LI> mDatabaseName = the name of the data file (Default: cocoon.dat) + * </LI> + * <LI> mIndexName = the name of the index file (Default: cocoon.idx) + * </LI> + * <LI> mOrder = The page size of the B-Tree</LI> + * </UL> + * + * + * @param The Configuration Paramter + * @exception ParameterException + */ + public void parameterize(Parameters params) + throws ParameterException { + mDatabaseName = params.getParameter("datafile", "cocoon.dat"); + mIndexName = params.getParameter("indexfile", "cocoon.idx"); + mOrder = params.getParameterAsInteger("order", 1001); + + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("parameterize(..): mDatabaseName=" + + mDatabaseName); + this.getLogger().debug("parameterize(..): mIndexName=" + + mIndexName); + this.getLogger().debug("parameterize(..): mOrder=" + mOrder); + } + } + + /** + * Store the given Object in the indexed data file. + * + * @param the Key Object + * @param the Value Object + * @exception IOException + */ + public void store(Object key, Object value) + throws IOException { + + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("store(): Store file with key: " + + key.toString()); + } + + if (value instanceof Serializable) { + try { + JispStringKey[] keyArray = new JispStringKey[1]; + keyArray[0] = new JispStringKey(key.toString()); + mDatabase.write(keyArray, (Serializable) value); + } catch (Exception e) { + this.getLogger().error("store(..): Exception", e); + } + } else { + throw new IOException("Object not Serializable"); + } + } + + /** + * Holds the given Object in the indexed data file. + * + * @param the Key Object + * @param the Value Object + * @exception IOException + */ + public void hold(Object key, Object value) + throws IOException { + this.store(key, value); + } + + /** + * Frees some values of the data file + */ + public void free() { + //TODO: implementation + } + + /** + * Removes a value from the data file with the given key. + * + * @param the Key Object + */ + public void remove(Object key) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("remove(..) Remove item"); + } + + try { + JispStringKey[] keyArray = new JispStringKey[1]; + keyArray[0] = new JispStringKey(key.toString()); + mDatabase.remove(keyArray); + } catch (KeyNotFound ignore) { + } catch (Exception e) { + this.getLogger().error("remove(..): Exception", e); + } + } + + /** + * Test if the the index file contains the given key + * + * @param the Key Object + * @return true if Key exists and false if not + */ + public boolean containsKey(Object key) { + long res = -1; + + try { + res = mIndex.findKey(new JispStringKey(key.toString())); + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("containsKey(..): res=" + res); + } + } catch (KeyNotFound ignore) { + } catch (Exception e) { + this.getLogger().error("containsKey(..): Exception", e); + } + + if (res > 0) { + return true; + } else { + return false; + } + } + + /** + * Returns a Enumeration of all Keys in the indexed file + * + * @return Enumeration Object with all existing keys + */ + public Enumeration keys() { + //TODO: Implementation + return null; + } +} + + + 1.3 +114 -1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispStringKey.java Index: JispStringKey.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/JispStringKey.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- JispStringKey.java 6 Jan 2002 14:28:10 -0000 1.2 +++ JispStringKey.java 6 Jan 2002 17:18:26 -0000 1.3 @@ -1 +1,114 @@ -/***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.jispstore; import com.coyotegulch.jisp.KeyObject; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; /** * Wrapper class to make our cache Key compatible with the Jisp KeyObject NOTE: * This Wrapper is only for String Keys. * * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]"> * [EMAIL PROTECTED]</a> */ final class JispStringKey extends KeyObject { final static long serialVersionUID = -6894793231339165076L; private String mKey; /** * Constructor for the JispStringKey object */ public JispStringKey() { mKey = new String(""); } /** * Constructor for the JispStringKey object * * @param the Value of the Key as String */ public JispStringKey(String keyValue) { mKey = keyValue; } /** * Compares two Keys * * @param the KeyObject to be compared * @return 0 if equal, 1 if greater, -1 if less */ public int compareTo(KeyObject key) { if (key instanceof JispStringKey) { int comp = mKey.trim().compareTo(((JispStringKey) key).mKey.trim()); if (comp == 0) { return KEY_EQUAL; } else { if (comp < 0) { return KEY_LESS; } else { return KEY_MORE; } } } else { return KEY_ERROR; } } /** * Composes a null Kewy * * @return a null Key */ public KeyObject makeNullKey() { return new JispStringKey(); } /** * * * @param out Description of Parameter * @exception IOException Description of Exception */ public void writeExternal(ObjectOutput out) throws IOException { String outKey; outKey = new String(mKey); out.writeUTF(outKey); } /** * Description of the Method * * @param in Description of Parameter * @exception IOException Description of Exception * @exception ClassNotFoundException Description of Exception */ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { mKey = in.readUTF(); } /** * Overrides the toString() method * * @return the Key as String */ public String toString() { return mKey; } } \ No newline at end of file +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package org.apache.cocoon.jispstore; + +import com.coyotegulch.jisp.KeyObject; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +/** + * Wrapper class to make our cache Key compatible with the Jisp KeyObject NOTE: + * This Wrapper is only for String Keys. + * + * @author Gerhard Froehlich <a href="mailto:[EMAIL PROTECTED]"> + * [EMAIL PROTECTED]</a> + */ + +final class JispStringKey extends KeyObject { + final static long serialVersionUID = -6894793231339165076L; + private String mKey; + + /** + * Constructor for the JispStringKey object + */ + public JispStringKey() { + mKey = new String(""); + } + + /** + * Constructor for the JispStringKey object + * + * @param the Value of the Key as String + */ + public JispStringKey(String keyValue) { + mKey = keyValue; + } + + /** + * Compares two Keys + * + * @param the KeyObject to be compared + * @return 0 if equal, 1 if greater, -1 if less + */ + + public int compareTo(KeyObject key) { + if (key instanceof JispStringKey) { + int comp = mKey.trim().compareTo(((JispStringKey) key).mKey.trim()); + if (comp == 0) { + return KEY_EQUAL; + } else { + if (comp < 0) { + return KEY_LESS; + } else { + return KEY_MORE; + } + } + } else { + return KEY_ERROR; + } + } + + /** + * Composes a null Kewy + * + * @return a null Key + */ + public KeyObject makeNullKey() { + return new JispStringKey(); + } + + /** + * + * + * @param out Description of Parameter + * @exception IOException Description of Exception + */ + public void writeExternal(ObjectOutput out) + throws IOException { + String outKey; + outKey = new String(mKey); + out.writeUTF(outKey); + } + + /** + * Description of the Method + * + * @param in Description of Parameter + * @exception IOException Description of Exception + * @exception ClassNotFoundException Description of Exception + */ + + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + mKey = in.readUTF(); + } + + /** + * Overrides the toString() method + * + * @return the Key as String + */ + public String toString() { + return mKey; + } +} + + + 1.3 +301 -1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/MRUMemoryStore.java Index: MRUMemoryStore.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/jispstore/MRUMemoryStore.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- MRUMemoryStore.java 6 Jan 2002 14:28:10 -0000 1.2 +++ MRUMemoryStore.java 6 Jan 2002 17:18:26 -0000 1.3 @@ -1 +1,301 @@ -/***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.jispstore; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.logger.AbstractLoggable; import org.apache.avalon.framework.parameters.ParameterException; import org.apache.avalon.framework.parameters.Parameterizable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.Constants; import org.apache.cocoon.components.store.FilesystemQueue; import org.apache.cocoon.components.store.FilesystemQueueObject; import org.apache.cocoon.components.store.Store; import org.apache.cocoon.components.store.StoreJanitor; import org.apache.cocoon.util.ClassUtils; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedList; /** * This class provides a cache algorithm for the requested documents. It * combines a HashMap and a LinkedList to create a so called MRU (Most Recently * Used) cache. * * @author <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> * @author <a href="mailto:[EMAIL PROTECTED]">Davanum Srinivas</a> */ public final class MRUMemoryStore extends AbstractLoggable implements Store, Parameterizable, ThreadSafe, Composable, Disposable { private int mMaxobjects; private boolean mFilesystem; private Hashtable mCache; private LinkedList mMRUList; private Store mFsstore; private StoreJanitor mStorejanitor; private FilesystemQueue mFilesystemQueue; private ComponentManager mComponetManager; /** * Get the object associated to the given unique key. * * @param the Key Object * @return the Object associated with Key Object */ public Object get(Object key) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Getting object from memory. Key: " + key); } Object tmpobject = this.mCache.get(key); if (tmpobject != null) { this.mMRUList.remove(key); this.mMRUList.addFirst(key); return tmpobject; } this.getLogger().debug("Object not found in memory"); if (this.mFilesystem) { tmpobject = this.mFsstore.get(key); if (tmpobject == null) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Object was NOT found on fs. " + "Looked for: " + key); } return null; } else { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Object was found on fs"); } if (!this.mCache.containsKey(key)) { this.hold(key, tmpobject); } return tmpobject; } } return null; } /** * Get components of the ComponentManager * * @param the Component Manager * @exception ComponentException */ public void compose(ComponentManager manager) throws ComponentException { this.mComponetManager = manager; if (getLogger().isDebugEnabled()) { getLogger().debug("Looking up " + Store.ROLE + "/JispFilesystemStore"); } this.mFsstore = (Store) manager.lookup(Store.ROLE + "/JispFilesystemStore"); if (getLogger().isDebugEnabled()) { getLogger().debug("Looking up " + StoreJanitor.ROLE); } this.mStorejanitor = (StoreJanitor) manager.lookup(StoreJanitor.ROLE); if (getLogger().isDebugEnabled()) { getLogger().debug("Looking up " + FilesystemQueue.ROLE); } this.mFilesystemQueue = (FilesystemQueue) manager.lookup(FilesystemQueue.ROLE); } /** * Configure the MRUMemoryStore. A few options can be used : * <UL> * <LI> mMaxobjects = how many objects will be stored in memory (Default: * 10 objects)</LI> * <LI> mFilesystem = use filesystem storage to keep object persistent * (Default: false)</LI> * </UL> * * * @param the Configuration Parameters * @exception ParameterException */ public void parameterize(Parameters params) throws ParameterException { this.mMaxobjects = params.getParameterAsInteger("maxobjects", 100); this.mFilesystem = params.getParameterAsBoolean("filesystem", false); if ((this.mMaxobjects < 1)) { throw new ParameterException("MRUMemoryStore maxobjects must be " + "at least 1 milli second!"); } this.mCache = new Hashtable((int) (this.mMaxobjects * 1.2)); this.mMRUList = new LinkedList(); this.mStorejanitor.register(this); } /** * Dispose the component */ public void dispose() { if (getLogger().isDebugEnabled()) { this.getLogger().debug("dispose()"); } if (this.mComponetManager != null) { this.mComponetManager.release(this.mStorejanitor); this.mStorejanitor = null; this.mComponetManager.release(this.mFilesystemQueue); this.mFilesystemQueue = null; this.mComponetManager.release(this.mFsstore); this.mFsstore = null; } } /** * Store the given object in a persistent state. It is up to the caller to * ensure that the key has a persistent state across different JVM * executions. * * @param the Key Object * @param the Value Object */ public void store(Object key, Object value) { if (this.mFilesystem) { if (this.checkSerializable(value) && !this.mFsstore.containsKey(key)) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Storing object on fs"); } try { this.mFilesystemQueue.insert(new FilesystemQueueObject(key, value)); } catch (Exception e) { this.getLogger().error("Error storing Object on fs", e); } } } } /** * This method holds the requested object in a HashMap combined with a * LinkedList to create the MRU. It also stores objects onto the filesystem * if configured. * * @param the Key Object * @param the Value Object */ public void hold(Object key, Object value) { if (getLogger().isDebugEnabled()) { getLogger().debug("Holding object in memory. key: " + key); getLogger().debug("Holding object in memory. value: " + value); } while (this.mMRUList.size() >= this.mMaxobjects) { this.free(); } this.mCache.put(key, value); this.mMRUList.remove(key); this.mMRUList.addFirst(key); if (getLogger().isDebugEnabled()) { this.getLogger().debug("Cache size=" + mCache.size()); } } /** * Remove the object associated to the given key. * * @param the Key object */ public void remove(Object key) { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Removing object from store"); } this.mCache.remove(key); this.mMRUList.remove(key); if (this.mFilesystem && key != null) { this.mFsstore.remove(key); } } /** * Indicates if the given key is associated to a contained object. * * @param the Key Object * @return true if Key exists and false if not */ public boolean containsKey(Object key) { if (mFilesystem) { return (this.mCache.containsKey(key) || this.mFsstore.containsKey(key)); } else { return this.mCache.containsKey(key); } } /** * Returns the list of used keys as an Enumeration. * * @return the enumeration of the cache */ public Enumeration keys() { return this.mCache.keys(); } /** * Frees some of the fast memory used by this store. It removes the last * element in the store. */ public void free() { try { if (this.mCache.size() > 0) { this.getLogger().debug("Freeing cache"); this.mCache.remove(this.mMRUList.getLast()); this.mMRUList.removeLast(); if (getLogger().isDebugEnabled()) { this.getLogger().debug("Cache size=" + mCache.size()); } } } catch (Exception e) { this.getLogger().error("Error in free()", e); } } /** * This method checks if an object is seriazable. FIXME: In the moment only * CachedEventObject or CachedStreamObject are stored. * * @param the Object to be tested * @return true if the object is storeable */ private boolean checkSerializable(Object object) { try { if (getLogger().isDebugEnabled()) { this.getLogger().debug("Object=" + object); } if ((object.getClass().getName().equals( "org.apache.cocoon.caching.CachedEventObject")) || (object.getClass().getName().equals( "org.apache.cocoon.caching.CachedStreamObject")) || (ClassUtils.implementsInterface(object.getClass().getName(), "org.apache.cocoon.caching.CacheValidity"))) { return true; } else { return false; } } catch (Exception e) { this.getLogger().error("Error in checkSerializable()!", e); return false; } } } \ No newline at end of file +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ +package org.apache.cocoon.jispstore; + +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.component.ComponentException; +import org.apache.avalon.framework.component.ComponentManager; +import org.apache.avalon.framework.component.Composable; +import org.apache.avalon.framework.logger.AbstractLoggable; +import org.apache.avalon.framework.parameters.ParameterException; +import org.apache.avalon.framework.parameters.Parameterizable; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.Constants; +import org.apache.cocoon.components.store.FilesystemQueue; +import org.apache.cocoon.components.store.FilesystemQueueObject; +import org.apache.cocoon.components.store.Store; +import org.apache.cocoon.components.store.StoreJanitor; +import org.apache.cocoon.util.ClassUtils; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.LinkedList; + +/** + * This class provides a cache algorithm for the requested documents. It + * combines a HashMap and a LinkedList to create a so called MRU (Most Recently + * Used) cache. + * + * @author <a href="mailto:[EMAIL PROTECTED]">Gerhard Froehlich</a> + * @author <a href="mailto:[EMAIL PROTECTED]">Davanum Srinivas</a> + */ +public final class MRUMemoryStore +extends AbstractLoggable +implements Store, + Parameterizable, + ThreadSafe, + Composable, + Disposable { + + private int mMaxobjects; + private boolean mFilesystem; + private Hashtable mCache; + private LinkedList mMRUList; + private Store mFsstore; + private StoreJanitor mStorejanitor; + private FilesystemQueue mFilesystemQueue; + private ComponentManager mComponetManager; + + /** + * Get the object associated to the given unique key. + * + * @param the Key Object + * @return the Object associated with Key Object + */ + public Object get(Object key) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Getting object from memory. Key: " + key); + } + Object tmpobject = this.mCache.get(key); + if (tmpobject != null) { + this.mMRUList.remove(key); + this.mMRUList.addFirst(key); + return tmpobject; + } + + this.getLogger().debug("Object not found in memory"); + if (this.mFilesystem) { + tmpobject = this.mFsstore.get(key); + if (tmpobject == null) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Object was NOT found on fs. " + + "Looked for: " + key); + } + return null; + } else { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Object was found on fs"); + } + if (!this.mCache.containsKey(key)) { + this.hold(key, tmpobject); + } + return tmpobject; + } + } + return null; + } + + /** + * Get components of the ComponentManager + * + * @param the Component Manager + * @exception ComponentException + */ + public void compose(ComponentManager manager) + throws ComponentException { + this.mComponetManager = manager; + if (getLogger().isDebugEnabled()) { + getLogger().debug("Looking up " + + Store.ROLE + "/JispFilesystemStore"); + } + + this.mFsstore = (Store) manager.lookup(Store.ROLE + + "/JispFilesystemStore"); + if (getLogger().isDebugEnabled()) { + getLogger().debug("Looking up " + StoreJanitor.ROLE); + } + this.mStorejanitor = (StoreJanitor) manager.lookup(StoreJanitor.ROLE); + if (getLogger().isDebugEnabled()) { + getLogger().debug("Looking up " + FilesystemQueue.ROLE); + } + this.mFilesystemQueue = (FilesystemQueue) manager.lookup(FilesystemQueue.ROLE); + } + + /** + * Configure the MRUMemoryStore. A few options can be used : + * <UL> + * <LI> mMaxobjects = how many objects will be stored in memory (Default: + * 10 objects)</LI> + * <LI> mFilesystem = use filesystem storage to keep object persistent + * (Default: false)</LI> + * </UL> + * + * + * @param the Configuration Parameters + * @exception ParameterException + */ + + public void parameterize(Parameters params) + throws ParameterException { + this.mMaxobjects = params.getParameterAsInteger("maxobjects", 100); + this.mFilesystem = params.getParameterAsBoolean("filesystem", false); + if ((this.mMaxobjects < 1)) { + throw new ParameterException("MRUMemoryStore maxobjects must be " + + "at least 1 milli second!"); + } + this.mCache = new Hashtable((int) (this.mMaxobjects * 1.2)); + this.mMRUList = new LinkedList(); + this.mStorejanitor.register(this); + } + + /** + * Dispose the component + */ + public void dispose() { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("dispose()"); + } + + if (this.mComponetManager != null) { + this.mComponetManager.release(this.mStorejanitor); + this.mStorejanitor = null; + this.mComponetManager.release(this.mFilesystemQueue); + this.mFilesystemQueue = null; + this.mComponetManager.release(this.mFsstore); + this.mFsstore = null; + } + } + + /** + * Store the given object in a persistent state. It is up to the caller to + * ensure that the key has a persistent state across different JVM + * executions. + * + * @param the Key Object + * @param the Value Object + */ + public void store(Object key, Object value) { + if (this.mFilesystem) { + if (this.checkSerializable(value) && + !this.mFsstore.containsKey(key)) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Storing object on fs"); + } + try { + this.mFilesystemQueue.insert(new FilesystemQueueObject(key, value)); + } catch (Exception e) { + this.getLogger().error("Error storing Object on fs", e); + } + } + } + } + + /** + * This method holds the requested object in a HashMap combined with a + * LinkedList to create the MRU. It also stores objects onto the filesystem + * if configured. + * + * @param the Key Object + * @param the Value Object + */ + public void hold(Object key, Object value) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Holding object in memory. key: " + key); + getLogger().debug("Holding object in memory. value: " + value); + } + + while (this.mMRUList.size() >= this.mMaxobjects) { + this.free(); + } + + this.mCache.put(key, value); + this.mMRUList.remove(key); + this.mMRUList.addFirst(key); + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Cache size=" + mCache.size()); + } + } + + /** + * Remove the object associated to the given key. + * + * @param the Key object + */ + public void remove(Object key) { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Removing object from store"); + } + this.mCache.remove(key); + this.mMRUList.remove(key); + if (this.mFilesystem && key != null) { + this.mFsstore.remove(key); + } + } + + /** + * Indicates if the given key is associated to a contained object. + * + * @param the Key Object + * @return true if Key exists and false if not + */ + public boolean containsKey(Object key) { + if (mFilesystem) { + return (this.mCache.containsKey(key) + || this.mFsstore.containsKey(key)); + } else { + return this.mCache.containsKey(key); + } + } + + /** + * Returns the list of used keys as an Enumeration. + * + * @return the enumeration of the cache + */ + public Enumeration keys() { + return this.mCache.keys(); + } + + /** + * Frees some of the fast memory used by this store. It removes the last + * element in the store. + */ + public void free() { + try { + if (this.mCache.size() > 0) { + this.getLogger().debug("Freeing cache"); + this.mCache.remove(this.mMRUList.getLast()); + this.mMRUList.removeLast(); + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Cache size=" + mCache.size()); + } + } + } catch (Exception e) { + this.getLogger().error("Error in free()", e); + } + } + + /** + * This method checks if an object is seriazable. FIXME: In the moment only + * CachedEventObject or CachedStreamObject are stored. + * + * @param the Object to be tested + * @return true if the object is storeable + */ + private boolean checkSerializable(Object object) { + try { + if (getLogger().isDebugEnabled()) { + this.getLogger().debug("Object=" + object); + } + if ((object.getClass().getName().equals( + "org.apache.cocoon.caching.CachedEventObject")) + || (object.getClass().getName().equals( + "org.apache.cocoon.caching.CachedStreamObject")) + || (ClassUtils.implementsInterface(object.getClass().getName(), + "org.apache.cocoon.caching.CacheValidity"))) { + return true; + } else { + return false; + } + } catch (Exception e) { + this.getLogger().error("Error in checkSerializable()!", e); + return false; + } + } +}
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]