cziegeler 2003/08/25 02:50:57
Modified: store/src/java/org/apache/excalibur/store/impl
AbstractFilesystemStore.java
AbstractJispFilesystemStore.java
Added: store/src/java/org/apache/excalibur/store/impl
AbstractReadWriteStore.java
Log:
Better synchronization of the File Store
Revision Changes Path
1.11 +179 -103
avalon-excalibur/store/src/java/org/apache/excalibur/store/impl/AbstractFilesystemStore.java
Index: AbstractFilesystemStore.java
===================================================================
RCS file:
/home/cvs/avalon-excalibur/store/src/java/org/apache/excalibur/store/impl/AbstractFilesystemStore.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- AbstractFilesystemStore.java 29 Jul 2003 03:58:33 -0000 1.10
+++ AbstractFilesystemStore.java 25 Aug 2003 09:50:56 -0000 1.11
@@ -49,23 +49,12 @@
*/
package org.apache.excalibur.store.impl;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.io.*;
import java.util.BitSet;
import java.util.Enumeration;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.excalibur.store.Store;
@@ -76,10 +65,11 @@
*
* @author ?
* @author <a href="mailto:[EMAIL PROTECTED]">Vadim Gritsenko</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @version CVS $Id$
*/
public abstract class AbstractFilesystemStore
-extends AbstractLogEnabled
+extends AbstractReadWriteStore
implements Store, ThreadSafe {
/** The directory repository */
@@ -90,7 +80,8 @@
* Sets the repository's location
*/
public void setDirectory(final String directory)
- throws IOException {
+ throws IOException
+ {
this.setDirectory(new File(directory));
}
@@ -98,7 +89,8 @@
* Sets the repository's location
*/
public void setDirectory(final File directory)
- throws IOException {
+ throws IOException
+ {
this.m_directoryFile = directory;
/* Save directory path prefix */
@@ -106,21 +98,25 @@
this.m_directoryPath += File.separator;
/* Does directory exist? */
- if (!this.m_directoryFile.exists()) {
+ if (!this.m_directoryFile.exists())
+ {
/* Create it anew */
- if (!this.m_directoryFile.mkdir()) {
+ if (!this.m_directoryFile.mkdir())
+ {
throw new IOException(
"Error creating store directory '" + this.m_directoryPath + "': ");
}
}
/* Is given file actually a directory? */
- if (!this.m_directoryFile.isDirectory()) {
+ if (!this.m_directoryFile.isDirectory())
+ {
throw new IOException("'" + this.m_directoryPath + "' is not a
directory");
}
/* Is directory readable and writable? */
- if (!(this.m_directoryFile.canRead() && this.m_directoryFile.canWrite())) {
+ if (!(this.m_directoryFile.canRead() && this.m_directoryFile.canWrite()))
+ {
throw new IOException(
"Directory '" + this.m_directoryPath + "' is not readable/writable"
);
@@ -130,27 +126,36 @@
/**
* Returns the repository's full pathname
*/
- public String getDirectoryPath() {
+ public String getDirectoryPath()
+ {
return this.m_directoryPath;
}
/**
* Get the File object associated with the given unique key name.
*/
- public synchronized Object get(final Object key) {
+ protected Object doGet(final Object key)
+ {
final File file = fileFromKey(key);
- if (file != null && file.exists()) {
- if (getLogger().isDebugEnabled()) {
+ if (file != null && file.exists())
+ {
+ if (getLogger().isDebugEnabled())
+ {
getLogger().debug("Found file: " + key);
}
- try {
+ try
+ {
return this.deserializeObject(file);
- } catch (Exception any) {
+ }
+ catch (Exception any) {
getLogger().error("Error during deseralization.", any);
}
- } else {
- if (getLogger().isDebugEnabled()) {
+ }
+ else
+ {
+ if (getLogger().isDebugEnabled())
+ {
getLogger().debug("NOT Found file: " + key);
}
}
@@ -164,53 +169,52 @@
* 2) String values are dumped to text files
* 3) Object values are serialized
*/
- public synchronized void store(final Object key, final Object value)
- throws IOException {
+ protected void doStore(final Object key, final Object value)
+ throws IOException
+ {
final File file = fileFromKey(key);
/* Create subdirectories as needed */
final File parent = file.getParentFile();
- if (parent != null) {
+ if (parent != null)
+ {
parent.mkdirs();
}
/* Store object as file */
- if (value == null) { /* Directory */
- if (file.exists()) {
- if (!file.delete()) { /* FAILURE */
+ if (value == null)
+ { /* Directory */
+ if (file.exists())
+ {
+ if (!file.delete())
+ { /* FAILURE */
getLogger().error("File cannot be deleted: " + file.toString());
return;
}
}
file.mkdir();
- } else if (value instanceof String) {
+ }
+ else if (value instanceof String)
+ {
/* Text file */
this.serializeString(file, (String) value);
- } else {
+ }
+ else
+ {
/* Serialized Object */
this.serializeObject(file, value);
}
}
/**
- * Holds the given object in a volatile state.
- */
- public synchronized void hold(final Object key, final Object value)
- throws IOException {
- this.store(key, value);
- final File file = (File) this.fileFromKey(key);
- if (file != null) {
- file.deleteOnExit();
- }
- }
-
- /**
* Remove the object associated to the given key.
*/
- public synchronized void remove(final Object key) {
+ protected void doRemove(final Object key)
+ {
final File file = fileFromKey(key);
- if (file != null) {
+ if (file != null)
+ {
file.delete();
}
}
@@ -218,23 +222,28 @@
/**
* Clear the Store of all elements
*/
- public synchronized void clear() {
- Enumeration enum = this.keys();
- while (enum.hasMoreElements()) {
- Object key = enum.nextElement();
- if (key == null) {
- continue;
- }
- this.remove(key);
- }
+ protected void doClear()
+ {
+ Enumeration enum = this.keys();
+ while (enum.hasMoreElements())
+ {
+ Object key = enum.nextElement();
+ if (key == null)
+ {
+ continue;
+ }
+ this.remove(key);
+ }
}
/**
* Indicates if the given key is associated to a contained object.
*/
- public synchronized boolean containsKey(final Object key) {
+ protected boolean doContainsKey(final Object key)
+ {
final File file = fileFromKey(key);
- if (file == null) {
+ if (file == null)
+ {
return false;
}
return file.exists();
@@ -243,7 +252,8 @@
/**
* Returns the list of stored files as an Enumeration of Files
*/
- public synchronized Enumeration keys() {
+ protected Enumeration doGetKeys()
+ {
final FSEnumeration enum = new FSEnumeration();
this.addKeys(enum, this.m_directoryFile);
return enum;
@@ -253,48 +263,63 @@
* Returns count of the objects in the store, or -1 if could not be
* obtained.
*/
- public synchronized int size() {
+ protected int doGetSize()
+ {
return countKeys(this.m_directoryFile);
}
- protected void addKeys(FSEnumeration enum, File directory) {
+ protected void addKeys(FSEnumeration enum, File directory)
+ {
final int subStringBegin = this.m_directoryFile.getAbsolutePath().length()
+ 1;
final File[] files = directory.listFiles();
- for (int i=0; i<files.length; i++) {
- if (files[i].isDirectory()) {
+ for (int i=0; i<files.length; i++)
+ {
+ if (files[i].isDirectory())
+ {
this.addKeys(enum, files[i]);
- } else {
+ }
+ else
+ {
enum.add(this.decode(files[i].getAbsolutePath().substring(subStringBegin)));
}
}
}
- protected int countKeys(File directory) {
+ protected int countKeys(File directory)
+ {
int count = 0;
final File[] files = directory.listFiles();
- for (int i=0; i<files.length; i++) {
- if (files[i].isDirectory()) {
+ for (int i=0; i<files.length; i++)
+ {
+ if (files[i].isDirectory())
+ {
count += this.countKeys(files[i]);
- } else {
+ }
+ else
+ {
count ++;
}
}
return count;
}
- final class FSEnumeration implements Enumeration {
+ final class FSEnumeration implements Enumeration
+ {
private String[] array;
private int index;
private int length;
- FSEnumeration() {
+ FSEnumeration()
+ {
this.array = new String[16];
this.length = 0;
this.index = 0;
}
- public void add(String key) {
- if (this.length == array.length) {
+ public void add(String key)
+ {
+ if (this.length == array.length)
+ {
String[] newarray = new String[this.length + 16];
System.arraycopy(this.array, 0, newarray, 0, this.array.length);
this.array = newarray;
@@ -303,12 +328,15 @@
this.length++;
}
- public boolean hasMoreElements() {
+ public boolean hasMoreElements()
+ {
return (this.index < this.length);
}
- public Object nextElement() {
- if (this.hasMoreElements()) {
+ public Object nextElement()
+ {
+ if (this.hasMoreElements())
+ {
this.index++;
return this.array[index-1];
}
@@ -317,7 +345,8 @@
}
/* Utility Methods*/
- protected File fileFromKey(final Object key) {
+ protected File fileFromKey(final Object key)
+ {
File file = new File(this.m_directoryFile, this.encode(key.toString()));
File parent = file.getParentFile();
if (parent != null) parent.mkdirs();
@@ -325,25 +354,53 @@
}
public String getString(final Object key)
- throws IOException {
+ throws IOException
+ {
final File file = (File) this.fileFromKey(key);
- if (file != null) {
+ if (file != null)
+ {
return this.deserializeString(file);
}
return null;
}
- public synchronized void free() {}
+ public void free()
+ {
+ // if we ever implement this, we should implement doFree()
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.excalibur.store.impl.AbstractReadWriteStore#doFree()
+ */
+ protected void doFree()
+ {
+ }
public synchronized Object getObject(final Object key)
throws IOException, ClassNotFoundException
{
- final File file = (File) this.fileFromKey(key);
- if (file != null) {
- return this.deserializeObject(file);
+ Object value = null;
+ Sync sync = this.lock.writeLock();
+ try
+ {
+ sync.acquire();
+ try
+ {
+ final File file = (File) this.fileFromKey(key);
+ if (file != null) {
+ return this.deserializeObject(file);
+ }
+ }
+ finally
+ {
+ sync.release();
+ }
}
-
+ catch (InterruptedException ignore)
+ {
+ }
+
return null;
}
@@ -357,7 +414,8 @@
{
// if the key is longer than 127 bytes a File.separator
// is added each 127 bytes
- if (filename.length() > 127) {
+ if (filename.length() > 127)
+ {
int c = filename.length() / 127;
int pos = c * 127;
StringBuffer out = new StringBuffer(filename);
@@ -407,7 +465,8 @@
* it may normally happen). For this reason, it's highly recommended
* (even if not mandated) that Strings be used as keys.
*/
- protected String encode(String s) {
+ protected String encode(String s)
+ {
final StringBuffer out = new StringBuffer( s.length() );
final ByteArrayOutputStream buf = new ByteArrayOutputStream( 32 );
final OutputStreamWriter writer = new OutputStreamWriter( buf );
@@ -471,12 +530,16 @@
* @exception IOException IO Error
*/
public void serializeString(File file, String string)
- throws IOException {
+ throws IOException
+ {
final Writer fw = new FileWriter(file);
- try {
+ try
+ {
fw.write(string);
fw.flush();
- } finally {
+ }
+ finally
+ {
if (fw != null) fw.close();
}
}
@@ -490,16 +553,21 @@
* @exception IOException IO Error
*/
public String deserializeString(File file)
- throws IOException {
+ throws IOException
+ {
int len;
char[] chr = new char[4096];
final StringBuffer buffer = new StringBuffer();
final FileReader reader = new FileReader(file);
- try {
- while ((len = reader.read(chr)) > 0) {
+ try
+ {
+ while ((len = reader.read(chr)) > 0)
+ {
buffer.append(chr, 0, len);
}
- } finally {
+ }
+ finally
+ {
if (reader != null) reader.close();
}
return buffer.toString();
@@ -514,13 +582,17 @@
*/
public void serializeObject(File file, Object object)
- throws IOException {
+ throws IOException
+ {
FileOutputStream fos = new FileOutputStream(file);
- try {
+ try
+ {
ObjectOutputStream oos = new ObjectOutputStream(new
BufferedOutputStream(fos));
oos.writeObject(object);
oos.flush();
- } finally {
+ }
+ finally
+ {
if (fos != null) fos.close();
}
}
@@ -533,13 +605,17 @@
* @exception IOException IOError
*/
public Object deserializeObject(File file)
- throws IOException, ClassNotFoundException {
+ throws IOException, ClassNotFoundException
+ {
FileInputStream fis = new FileInputStream(file);
Object object = null;
- try {
+ try
+ {
ObjectInputStream ois = new ObjectInputStream(new
BufferedInputStream(fis));
object = ois.readObject();
- } finally {
+ }
+ finally
+ {
if (fis != null) fis.close();
}
return object;
1.18 +75 -149
avalon-excalibur/store/src/java/org/apache/excalibur/store/impl/AbstractJispFilesystemStore.java
Index: AbstractJispFilesystemStore.java
===================================================================
RCS file:
/home/cvs/avalon-excalibur/store/src/java/org/apache/excalibur/store/impl/AbstractJispFilesystemStore.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- AbstractJispFilesystemStore.java 25 Aug 2003 09:20:30 -0000 1.17
+++ AbstractJispFilesystemStore.java 25 Aug 2003 09:50:56 -0000 1.18
@@ -62,14 +62,9 @@
import com.coyotegulch.jisp.KeyNotFound;
import com.coyotegulch.jisp.KeyObject;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.excalibur.store.Store;
-import EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock;
-import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
-import EDU.oswego.cs.dl.util.concurrent.Sync;
-
/**
* This store is based on the Jisp library
* (http://www.coyotegulch.com/jisp/index.html). This store uses B-Tree indexes
@@ -81,7 +76,7 @@
* @version CVS $Id$
*/
public abstract class AbstractJispFilesystemStore
-extends AbstractLogEnabled
+extends AbstractReadWriteStore
implements Store, ThreadSafe {
/** The directory repository */
@@ -93,9 +88,6 @@
/** And the index */
protected BTreeIndex m_Index;
- /** The lock */
- protected ReadWriteLock lock = new FIFOReadWriteLock();
-
/**
* Sets the repository's location
*/
@@ -136,40 +128,29 @@
* @param key the Key object
* @return the Object associated with Key Object
*/
- public Object get(Object key)
+ protected Object doGet(Object key)
{
Object value = null;
- Sync sync = this.lock.writeLock();
- try
+
+ try
{
- sync.acquire();
- try
+ value = m_Database.read(this.wrapKeyObject(key), m_Index);
+ if (getLogger().isDebugEnabled())
{
- value = m_Database.read(this.wrapKeyObject(key), m_Index);
- if (getLogger().isDebugEnabled())
+ if (value != null)
{
- if (value != null)
- {
- getLogger().debug("Found key: " + key);
- }
- else
- {
- getLogger().debug("NOT Found key: " + key);
- }
+ getLogger().debug("Found key: " + key);
+ }
+ else
+ {
+ getLogger().debug("NOT Found key: " + key);
}
- }
- catch (Exception e)
- {
- getLogger().error("get(..): Exception", e);
- }
- finally
- {
- sync.release();
}
- }
- catch (InterruptedException ignore)
- {
}
+ catch (Exception e)
+ {
+ getLogger().error("get(..): Exception", e);
+ }
return value;
}
@@ -181,7 +162,7 @@
* @param value the value object
* @exception IOException
*/
- public void store(Object key, Object value)
+ protected void doStore(Object key, Object value)
throws IOException
{
@@ -195,29 +176,16 @@
if (value instanceof Serializable)
{
- Sync sync = this.lock.writeLock();
- try
- {
- sync.acquire();
-
- try
- {
- KeyObject[] keyArray = new KeyObject[1];
- keyArray[0] = this.wrapKeyObject(key);
- m_Database.write(keyArray, (Serializable) value);
- }
- catch (Exception e)
- {
- getLogger().error("store(..): Exception", e);
- }
- finally
- {
- sync.release();
- }
- }
- catch (InterruptedException ignore)
+ try
{
+ KeyObject[] keyArray = new KeyObject[1];
+ keyArray[0] = this.wrapKeyObject(key);
+ m_Database.write(keyArray, (Serializable) value);
}
+ catch (Exception e)
+ {
+ getLogger().error("store(..): Exception", e);
+ }
}
else
{
@@ -226,31 +194,24 @@
}
/**
- * Holds the given object in the indexed data file.
- *
- * @param key the key object
- * @param value the value object
- * @exception IOException
- */
- public void hold(Object key, Object value)
- throws IOException
- {
- // store is synced!
- this.store(key, value);
- }
-
- /**
* Frees some values of the data file.<br>
* TODO: implementation
*/
public void free()
{
+ // if we ever implement this, we should implement doFree()
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.excalibur.store.impl.AbstractReadWriteStore#doFree()
+ */
+ protected void doFree() {
}
/**
* Clear the Store of all elements
*/
- public void clear()
+ protected void doClear()
{
if (getLogger().isDebugEnabled())
@@ -258,41 +219,29 @@
getLogger().debug("clear(): Clearing the database ");
}
- Sync sync = this.lock.writeLock();
- try
+ try
{
- sync.acquire();
- try
+ final BTreeIterator iter = new BTreeIterator(m_Index);
+ Object tmp;
+ do
{
- final BTreeIterator iter = new BTreeIterator(m_Index);
- Object tmp;
- do
+ tmp = iter.getKey();
+ if ( tmp != null )
{
- tmp = iter.getKey();
- if ( tmp != null )
+ if (getLogger().isDebugEnabled())
{
- if (getLogger().isDebugEnabled())
- {
- getLogger().debug("clear(): Removing key: " +
tmp.toString());
- }
- iter.moveNext();
- this.remove( tmp );
+ getLogger().debug("clear(): Removing key: " +
tmp.toString());
}
- }
- while (tmp != null);
+ iter.moveNext();
+ this.remove( tmp );
+ }
}
- catch (Exception ignore)
- {
- getLogger().error("store(..): Exception", ignore);
- }
- finally
- {
- sync.release();
- }
- }
- catch (InterruptedException ignore)
- {
+ while (tmp != null);
}
+ catch (Exception ignore)
+ {
+ getLogger().error("store(..): Exception", ignore);
+ }
}
/**
@@ -300,38 +249,26 @@
*
* @param key the key object
*/
- public void remove(Object key)
+ protected void doRemove(Object key)
{
if (getLogger().isDebugEnabled())
{
getLogger().debug("remove(..) Remove item");
}
- Sync sync = this.lock.writeLock();
- try
+ try
{
- sync.acquire();
- try
- {
- KeyObject[] keyArray = new KeyObject[1];
- keyArray[0] = this.wrapKeyObject(key);
- m_Database.remove(keyArray);
- }
- catch (KeyNotFound ignore)
- {
- }
- catch (Exception e)
- {
- getLogger().error("remove(..): Exception", e);
- }
- finally
- {
- sync.release();
- }
- }
- catch (InterruptedException ignore)
+ KeyObject[] keyArray = new KeyObject[1];
+ keyArray[0] = this.wrapKeyObject(key);
+ m_Database.remove(keyArray);
+ }
+ catch (KeyNotFound ignore)
{
}
+ catch (Exception e)
+ {
+ getLogger().error("remove(..): Exception", e);
+ }
}
/**
@@ -340,37 +277,25 @@
* @param key the key object
* @return true if Key exists and false if not
*/
- public boolean containsKey(Object key)
+ protected boolean doContainsKey(Object key)
{
long res = -1;
- Sync sync = this.lock.readLock();
- try
+ try
{
- sync.acquire();
- try
+ res = m_Index.findKey(this.wrapKeyObject(key));
+ if (getLogger().isDebugEnabled())
{
- res = m_Index.findKey(this.wrapKeyObject(key));
- if (getLogger().isDebugEnabled())
- {
- getLogger().debug("containsKey(..): res=" + res);
- }
- }
- catch (KeyNotFound ignore)
- {
- }
- catch (Exception e)
- {
- getLogger().error("containsKey(..): Exception", e);
- }
- finally
- {
- sync.release();
+ getLogger().debug("containsKey(..): res=" + res);
}
- }
- catch (InterruptedException ignore)
+ }
+ catch (KeyNotFound ignore)
{
}
+ catch (Exception e)
+ {
+ getLogger().error("containsKey(..): Exception", e);
+ }
if (res > 0)
{
@@ -387,7 +312,7 @@
*
* @return Enumeration Object with all existing keys
*/
- public Enumeration keys()
+ protected Enumeration doGetKeys()
{
try
{
@@ -399,7 +324,7 @@
}
}
- public int size()
+ protected int doGetSize()
{
return m_Index.count();
}
@@ -489,4 +414,5 @@
return ((JispKey) tmp).getKey();
}
}
+
}
1.1
avalon-excalibur/store/src/java/org/apache/excalibur/store/impl/AbstractReadWriteStore.java
Index: AbstractReadWriteStore.java
===================================================================
/*
============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
must not be used to endorse or promote products derived from this software
without prior written permission. For written permission, please contact
[EMAIL PROTECTED]
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation. For more information on the
Apache Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.excalibur.store.impl;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock;
import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
import EDU.oswego.cs.dl.util.concurrent.Sync;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.excalibur.store.Store;
/**
* This is a base implementation for stores that are synchronized by
* using a read/write lock.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @version CVS $Id: AbstractReadWriteStore.java,v 1.1 2003/08/25 09:50:56 cziegeler
Exp $
*/
public abstract class AbstractReadWriteStore
extends AbstractLogEnabled
implements Store, ThreadSafe {
/** The lock */
protected ReadWriteLock lock = new FIFOReadWriteLock();
/**
* Returns a Object from the store associated with the Key Object
*
* @param key the Key object
* @return the Object associated with Key Object
*/
public Object get(Object key)
{
Object value = null;
Sync sync = this.lock.writeLock();
try
{
sync.acquire();
try
{
this.doGet(key);
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
}
return value;
}
/**
* Store the given object in the indexed data file.
*
* @param key the key object
* @param value the value object
* @exception IOException
*/
public void store(Object key, Object value)
throws IOException
{
Sync sync = this.lock.writeLock();
try
{
sync.acquire();
try
{
this.doStore(key, value);
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
}
}
/**
* Frees some values of the data file.<br>
*/
public void free()
{
Sync sync = this.lock.writeLock();
try
{
sync.acquire();
try
{
this.doFree();
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
}
}
/**
* Clear the Store of all elements
*/
public void clear()
{
if (getLogger().isDebugEnabled())
{
getLogger().debug("clear(): Clearing the database ");
}
Sync sync = this.lock.writeLock();
try
{
sync.acquire();
try
{
this.doClear();
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
}
}
/**
* Removes a value from the data file with the given key.
*
* @param key the key object
*/
public void remove(Object key)
{
Sync sync = this.lock.writeLock();
try
{
sync.acquire();
try
{
this.doRemove(key);
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
}
}
/**
* Test if the the index file contains the given key
*
* @param key the key object
* @return true if Key exists and false if not
*/
public boolean containsKey(Object key)
{
Sync sync = this.lock.readLock();
try
{
sync.acquire();
try
{
return this.doContainsKey(key);
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
return false;
}
}
/**
* Returns a Enumeration of all Keys in the indexed file.<br>
*
* @return Enumeration Object with all existing keys
*/
public Enumeration keys()
{
Sync sync = this.lock.readLock();
try
{
sync.acquire();
try
{
return this.doGetKeys();
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
return Collections.enumeration(Collections.EMPTY_LIST);
}
}
public int size()
{
Sync sync = this.lock.readLock();
try
{
sync.acquire();
try
{
return this.doGetSize();
}
finally
{
sync.release();
}
}
catch (InterruptedException ignore)
{
return 0;
}
}
/**
* Get the object associated to the given unique key.
*/
protected abstract Object doGet( Object key );
/**
* Store the given object. It is up to the
* caller to ensure that the key has a persistent state across
* different JVM executions.
*/
protected abstract void doStore( Object key, Object value ) throws IOException;
/**
* Try to free some used memory. The transient store can simply remove
* some hold data, the persistent store can free all memory by
* writing the data to a persistent store etc.
*/
protected abstract void doFree();
/**
* Remove the object associated to the given key.
*/
protected abstract void doRemove( Object key );
/**
* Clear the Store of all data it holds
*/
protected abstract void doClear();
/**
* Indicates if the given key is associated to a contained object.
*/
protected abstract boolean doContainsKey( Object key );
/**
* Returns the list of used keys as an Enumeration of Objects.
*/
protected abstract Enumeration doGetKeys();
/**
* Returns count of the objects in the store, or -1 if could not be
* obtained.
*/
protected abstract int doGetSize();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]