[infinispan-commits] Infinispan SVN: r220 - in trunk: cachestore and 15 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed May 6 14:18:25 EDT 2009
Author: genman
Date: 2009-05-06 14:18:25 -0400 (Wed, 06 May 2009)
New Revision: 220
Added:
trunk/cachestore/jdbm/
trunk/cachestore/jdbm/pom.xml
trunk/cachestore/jdbm/src/
trunk/cachestore/jdbm/src/main/
trunk/cachestore/jdbm/src/main/java/
trunk/cachestore/jdbm/src/main/java/org/
trunk/cachestore/jdbm/src/main/java/org/infinispan/
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStoreConfig.java
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmSerializer.java
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/NaturalComparator.java
trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/package-info.java
trunk/cachestore/jdbm/src/test/
trunk/cachestore/jdbm/src/test/java/
trunk/cachestore/jdbm/src/test/java/org/
trunk/cachestore/jdbm/src/test/java/org/infinispan/
trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/
trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/
trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java
trunk/cachestore/jdbm/src/test/resources/
Modified:
trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java
trunk/pom.xml
Log:
ISPN-75
JDBM support; hope it doesn't cause trouble
Added: trunk/cachestore/jdbm/pom.xml
===================================================================
--- trunk/cachestore/jdbm/pom.xml (rev 0)
+++ trunk/cachestore/jdbm/pom.xml 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ <relativePath>../../parent/pom.xml</relativePath>
+ </parent>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-cachestore-jdbm</artifactId>
+ <name>Infinispan JDBM CacheStore</name>
+ <description>Infinispan JDBM CacheStore module</description>
+ <properties>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project-package}</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>${project-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project-package}</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>${project-version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <!-- Contains fixes not officially released by JDBM group -->
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-jdbm</artifactId>
+ <version>1.5.4</version>
+ </dependency>
+
+ <!--
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+ -->
+
+ </dependencies>
+ <build>
+ </build>
+
+</project>
Property changes on: trunk/cachestore/jdbm/pom.xml
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java (rev 0)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,459 @@
+package org.infinispan.loaders.jdbm;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.text.SimpleDateFormat;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+import java.util.Set;
+
+import jdbm.RecordManager;
+import jdbm.RecordManagerFactory;
+import jdbm.btree.BTree;
+import jdbm.helper.Serializer;
+import jdbm.helper.Tuple;
+import jdbm.helper.TupleBrowser;
+import net.jcip.annotations.ThreadSafe;
+
+import org.infinispan.Cache;
+import org.infinispan.CacheException;
+import org.infinispan.config.ConfigurationException;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.loaders.AbstractCacheStore;
+import org.infinispan.loaders.CacheLoaderConfig;
+import org.infinispan.loaders.CacheLoaderException;
+import org.infinispan.loaders.modifications.Modification;
+import org.infinispan.loaders.modifications.Remove;
+import org.infinispan.loaders.modifications.Store;
+import org.infinispan.marshall.Marshaller;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
+/**
+ * A persistent <code>CacheLoader</code> based on the JDBM project. See
+ * http://jdbm.sourceforge.net/ . Does not support transaction isolation.
+ * <p/>
+ * Supports removal of expired entries.
+ * <p/>
+ * It would probably be better if meta-data (expiry time) was stored independent
+ * of the value of the entry. That is, if (key,"m") == meta and (key,"v") ==
+ * value.
+ *
+ * @author Elias Ross
+ * @version $Id: JdbmCacheLoader.java 7261 2008-12-07 18:53:38Z genman $
+ */
+ at ThreadSafe
+public class JdbmCacheStore extends AbstractCacheStore {
+
+ private static final Log log = LogFactory.getLog(JdbmCacheStore.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ private static final String NAME = "CacheLoader";
+ private static final String EXPIRY = "Expiry";
+ private final String DATE = "HH:mm:ss.SSS";
+
+ private final Object expiryLock = new Object();
+
+ private JdbmCacheStoreConfig config;
+ private RecordManager recman;
+ private BTree tree;
+ private BTree expiryTree;
+ private Cache cache;
+
+ public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+ return JdbmCacheStoreConfig.class;
+ }
+
+ @Override
+ public void init(CacheLoaderConfig clc, Cache cache, Marshaller m) {
+ super.init(clc, cache, m);
+ this.config = (JdbmCacheStoreConfig) clc;
+ this.cache = cache;
+ }
+
+ @Override
+ public void start() throws CacheLoaderException {
+ String locationStr = config.getLocation();
+ if (locationStr == null) {
+ locationStr = System.getProperty("java.io.tmpdir");
+ config.setLocation(locationStr);
+ }
+
+ // JBCACHE-1448 db name parsing fix courtesy of Ciro Cavani
+ /* Parse config string. */
+ int offset = locationStr.indexOf('#');
+ String cacheDbName;
+ if (offset >= 0 && offset < locationStr.length() - 1) {
+ cacheDbName = locationStr.substring(offset + 1);
+ locationStr = locationStr.substring(0, offset);
+ } else {
+ cacheDbName = cache.getName(); // TODO
+ if (cacheDbName == null)
+ cacheDbName = "jdbm";
+ }
+
+ // test location
+ File location = new File(locationStr);
+ if (!location.exists()) {
+ boolean created = location.mkdirs();
+ if (!created)
+ throw new ConfigurationException("Unable to create cache loader location " + location);
+ }
+ if (!location.isDirectory()) {
+ throw new ConfigurationException("Cache loader location [" + location + "] is not a directory!");
+ }
+
+ try {
+ openDatabase(new File(location, cacheDbName));
+ } catch (Exception e) {
+ throw new ConfigurationException(e);
+ }
+
+ log.debug("cleaning up expired entries...");
+ purgeInternal();
+
+ log.debug("started");
+ super.start();
+ }
+
+ public InternalCacheEntry load(Object key) throws CacheLoaderException {
+ try {
+ return (InternalCacheEntry) tree.find(key);
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
+ return new BTreeSet();
+ }
+
+ /**
+ * Opens all databases and initializes database related information.
+ */
+ private void openDatabase(File f) throws Exception {
+ Properties props = new Properties();
+ // Incorporate properties from setConfig() ?
+ // props.put(RecordManagerOptions.SERIALIZER,
+ // RecordManagerOptions.SERIALIZER_EXTENSIBLE);
+ // props.put(RecordManagerOptions.PROFILE_SERIALIZATION, "false");
+ recman = RecordManagerFactory.createRecordManager(f.toString(), props);
+ long recid = recman.getNamedObject(NAME);
+ log.debug(NAME + " located as " + recid);
+ if (recid == 0) {
+ createTree();
+ } else {
+ tree = BTree.load(recman, recid);
+ recid = recman.getNamedObject(EXPIRY);
+ expiryTree = BTree.load(recman, recid);
+ setSerializer();
+ }
+
+ log.info("JDBM database " + f + " opened with " + tree.size() + " entries");
+ }
+
+ /**
+ * Resets the value serializer to point to our marshaller.
+ */
+ private void setSerializer() {
+ tree.setValueSerializer(new JdbmSerializer(getMarshaller()));
+ expiryTree.setValueSerializer(new JdbmSerializer(getMarshaller()));
+ }
+
+ private void createTree() throws IOException {
+ tree = BTree.createInstance(recman, config.createComparator(), (Serializer) null, (Serializer) null);
+ expiryTree = BTree.createInstance(recman, new NaturalComparator(), (Serializer) null, (Serializer) null);
+ recman.setNamedObject(NAME, tree.getRecid());
+ recman.setNamedObject(EXPIRY, expiryTree.getRecid());
+ setSerializer();
+ }
+
+ /**
+ * Closes all databases, ignoring exceptions, and nulls references to all
+ * database related information.
+ */
+ @Override
+ public void stop() {
+ if (recman != null) {
+ try {
+ recman.close();
+ } catch (IOException e) {
+ throw new CacheException(e);
+ }
+ }
+ recman = null;
+ tree = null;
+ expiryTree = null;
+ }
+
+ public void clear() throws CacheLoaderException {
+ if (trace)
+ log.trace("clear()");
+ try {
+ recman.delete(tree.getRecid());
+ recman.delete(expiryTree.getRecid());
+ createTree();
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ public boolean remove(Object key) throws CacheLoaderException {
+ try {
+ return remove0(key);
+ } finally {
+ commit();
+ }
+ }
+
+ private void commit() throws CacheLoaderException {
+ try {
+ recman.commit();
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ public boolean remove0(Object key) throws CacheLoaderException {
+ if (trace)
+ log.trace("remove() " + key);
+ try {
+ return tree.remove(key) != null;
+ } catch (IllegalArgumentException e) {
+ // can happen during normal operation
+ return false;
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ public void store(InternalCacheEntry entry) throws CacheLoaderException {
+ store0(entry);
+ commit();
+ }
+
+ private void store0(InternalCacheEntry entry) throws CacheLoaderException {
+ Object key = entry.getKey();
+ if (trace)
+ log.trace("store() " + key);
+ try {
+ tree.insert(key, entry, true); // TODO a waste to ignore the return
+ // value
+ if (entry.canExpire())
+ addNewExpiry(entry);
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ private void addNewExpiry(InternalCacheEntry entry) throws IOException {
+ long expiry = entry.getExpiryTime();
+ if (entry.getMaxIdle() > 0) {
+ // TODO do we need both?
+ expiry = entry.getMaxIdle() + System.currentTimeMillis();
+ }
+ Long at = new Long(expiry);
+ Object key = entry.getKey();
+ if (trace)
+ log.trace("at " + new SimpleDateFormat(DATE).format(new Date(at)) + " expire " + key);
+ // TODO could store expiry entries in a separate thread; would remove this
+ // lock as well
+ synchronized (expiryLock) {
+ Object existing = expiryTree.insert(at, key, false);
+ if (existing != null) {
+ // in the case of collision make the key a List ...
+ if (existing instanceof List) {
+ ((List) existing).add(key);
+ expiryTree.insert(at, existing, true);
+ } else {
+ List<Object> al = new ArrayList<Object>(2);
+ al.add(existing);
+ al.add(key);
+ expiryTree.insert(at, al, true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes to a stream the number of entries (long) then the entries
+ * themselves.
+ */
+ public void toStream(ObjectOutput outputStream) throws CacheLoaderException {
+ try {
+ Set<InternalCacheEntry> loadAll = loadAll();
+ outputStream.writeLong(loadAll.size());
+ log.debug("toStream() " + loadAll.size() + " entries");
+ for (InternalCacheEntry entry : loadAll)
+ outputStream.writeObject(entry);
+ log.debug("done!");
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ /**
+ * Reads from a stream the number of entries (long) then the entries
+ * themselves.
+ */
+ public void fromStream(ObjectInput inputStream) throws CacheLoaderException {
+ try {
+ long count = inputStream.readLong();
+ log.debug("fromStream() " + count + " entries");
+ for (int i = 0; i < count; i++) {
+ InternalCacheEntry entry = (InternalCacheEntry) inputStream.readObject();
+ store(entry);
+ }
+ log.debug("done!");
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ } catch (ClassNotFoundException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ /**
+ * Purge expired entries.
+ */
+ @Override
+ protected void purgeInternal() throws CacheLoaderException {
+ log.trace("purgeInternal");
+ try {
+ purgeInternal0();
+ } catch (IOException e) {
+ throw new CacheLoaderException(e);
+ }
+ }
+
+ /**
+ * Find all times less than current time. Build a list of keys for those
+ * times. Then purge those keys, assuming those keys' expiry has not changed.
+ */
+ private void purgeInternal0() throws IOException {
+ TupleBrowser browse = expiryTree.browse();
+ Tuple tuple = new Tuple();
+ List<Long> times = new ArrayList<Long>();
+ List<Object> keys = new ArrayList<Object>();
+ synchronized (expiryLock) {
+ while (browse.getNext(tuple)) {
+ Long time = (Long) tuple.getKey();
+ if (time > System.currentTimeMillis())
+ break;
+ times.add(time);
+ Object key = tuple.getValue();
+ if (key instanceof List)
+ keys.addAll((List) key);
+ else
+ keys.add(key);
+ }
+ for (Long time : times) {
+ expiryTree.remove(time);
+ }
+ }
+
+ if (!keys.isEmpty())
+ log.debug("purge (up to) " + keys.size() + " entries");
+ int count = 0;
+ for (Object key : keys) {
+ InternalCacheEntry ice = (InternalCacheEntry) tree.find(key);
+ if (ice == null)
+ continue;
+ if (ice.isExpired()) {
+ // somewhat inefficient to FIND then REMOVE...
+ tree.remove(key);
+ count++;
+ }
+ }
+ if (count != 0)
+ log.debug("purged " + count + " entries");
+ recman.commit();
+ }
+
+ @Override
+ protected void applyModifications(List<? extends Modification> mods) throws CacheLoaderException {
+ for (Modification m : mods) {
+ switch (m.getType()) {
+ case STORE:
+ store0(((Store) m).getStoredEntry());
+ break;
+ case CLEAR:
+ clear();
+ break;
+ case REMOVE:
+ remove0(((Remove) m).getKey());
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+ commit();
+ }
+
+ @Override
+ public String toString() {
+ BTree bt = tree;
+ BTree et = expiryTree;
+ int size = (bt == null) ? -1 : bt.size();
+ int expiry = (et == null) ? -1 : et.size();
+ return "JdbmCacheLoader locationStr=" + config.getLocation() + " size=" + size + " expirySize=" + expiry;
+ }
+
+ private final class BTreeSet extends AbstractSet<InternalCacheEntry> {
+
+ @Override
+ public Iterator<InternalCacheEntry> iterator() {
+ final TupleBrowser browse;
+ try {
+ browse = tree.browse();
+ } catch (IOException e) {
+ throw new CacheException(e);
+ }
+
+ return new Iterator<InternalCacheEntry>() {
+
+ final Tuple tuple = new Tuple();
+ InternalCacheEntry current = null;
+ boolean next = true;
+
+ public boolean hasNext() {
+ if (current == null) {
+ try {
+ next = browse.getNext(tuple);
+ current = (InternalCacheEntry) tuple.getValue();
+ } catch (IOException e) {
+ throw new CacheException(e);
+ }
+ }
+ return next;
+ }
+
+ public InternalCacheEntry next() {
+ if (!hasNext())
+ throw new NoSuchElementException();
+ try {
+ return current;
+ } finally {
+ current = null;
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+
+ @Override
+ public int size() {
+ return tree.size();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStoreConfig.java (rev 0)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStoreConfig.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,68 @@
+package org.infinispan.loaders.jdbm;
+
+import java.util.Comparator;
+
+import org.infinispan.CacheException;
+import org.infinispan.loaders.LockSupportCacheStoreConfig;
+import org.infinispan.marshall.Marshaller;
+
+/**
+ * Configures {@link JdbmCacheStore}.
+ * <p/>
+ * <ul>
+ * <li><tt>location</tt> - a location on disk where the store can write internal
+ * files.</li>
+ * <li><tt>comparatorClassName</tt> - comparator class used to sort the keys
+ * by the cache loader. This should only need to be set when using keys that
+ * do not have a natural ordering.
+ * </ul>
+ *
+ * @author Elias Ross
+ * @since 4.0
+ */
+public class JdbmCacheStoreConfig extends LockSupportCacheStoreConfig {
+
+ private static final long serialVersionUID = 1L;
+
+ String location = "jdbm";
+ String comparatorClassName = NaturalComparator.class.getName();
+
+ public JdbmCacheStoreConfig() {
+ setCacheLoaderClassName(JdbmCacheStore.class.getName());
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ testImmutability("location");
+ this.location = location;
+ }
+
+ /**
+ * Returns comparatorClassName.
+ */
+ public String getComparatorClassName() {
+ return comparatorClassName;
+ }
+
+ /**
+ * Sets comparatorClassName.
+ */
+ public void setComparatorClassName(String comparatorClassName) {
+ this.comparatorClassName = comparatorClassName;
+ }
+
+ /**
+ * Returns a new comparator instance based on {@link #setComparatorClassName(String)}.
+ */
+ public Comparator createComparator() {
+ try {
+ return (Comparator) Class.forName(comparatorClassName).newInstance();
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+}
Added: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmSerializer.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmSerializer.java (rev 0)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmSerializer.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,41 @@
+package org.infinispan.loaders.jdbm;
+
+import java.io.IOException;
+
+import org.infinispan.marshall.Marshaller;
+
+import jdbm.helper.Serializer;
+
+/**
+ * Uses the configured (runtime) {@link Marshaller} of the cache.
+ * This Serializer is thus not really serializiable.
+ *
+ * @author Elias Ross
+ */
+ at SuppressWarnings("serial")
+public class JdbmSerializer implements Serializer {
+
+ private transient Marshaller marshaller;
+
+ /**
+ * Constructs a new JdbmSerializer.
+ */
+ public JdbmSerializer(Marshaller marshaller) {
+ if (marshaller == null)
+ throw new NullPointerException("marshaller");
+ this.marshaller = marshaller;
+ }
+
+ public Object deserialize(byte[] buf) throws IOException {
+ try {
+ return marshaller.objectFromByteBuffer(buf);
+ } catch (ClassNotFoundException e) {
+ throw (IOException)new IOException().initCause(e);
+ }
+ }
+
+ public byte[] serialize(Object obj) throws IOException {
+ return marshaller.objectToByteBuffer(obj);
+ }
+
+}
Added: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/NaturalComparator.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/NaturalComparator.java (rev 0)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/NaturalComparator.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,20 @@
+package org.infinispan.loaders.jdbm;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Compares keys using their <i>natural ordering</i>.
+ * <p/>
+ *
+ * @author Elias Ross
+ */
+public class NaturalComparator implements Comparator, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ public int compare(Object o1, Object o2) {
+ return ((Comparable)o1).compareTo(o2);
+ }
+
+}
Added: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/package-info.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/package-info.java (rev 0)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/package-info.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,5 @@
+/**
+ * This package contains a {@link org.infinispan.loaders.CacheStore} implementation based on
+ * persisting to JDBM.
+ */
+package org.infinispan.loaders.jdbm;
\ No newline at end of file
Added: trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java
===================================================================
--- trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java (rev 0)
+++ trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -0,0 +1,120 @@
+package org.infinispan.loaders.jdbm;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.container.entries.InternalEntryFactory;
+import org.infinispan.io.UnclosableObjectOutputStream;
+import org.infinispan.loaders.BaseCacheStoreTest;
+import org.infinispan.loaders.CacheLoaderException;
+import org.infinispan.loaders.CacheStore;
+import org.infinispan.test.TestingUtil;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Parameters;
+import org.testng.annotations.Test;
+
+ at Test(groups = "unit", testName = "loaders.jdbm.JdbmCacheStoreTest")
+public class JdbmCacheStoreTest extends BaseCacheStoreTest {
+
+ private JdbmCacheStore fcs;
+ private String tmpDirectory;
+
+ @BeforeTest
+ @Parameters({"basedir"})
+ protected void setUpTempDir() {
+ tmpDirectory = "." + TestingUtil.TEST_PATH + File.separator + getClass().getSimpleName();
+ }
+
+ @AfterTest
+ protected void clearTempDir() {
+ TestingUtil.recursiveFileRemove(tmpDirectory);
+ new File(tmpDirectory).mkdirs();
+ }
+
+ @Override
+ protected CacheStore createCacheStore() throws CacheLoaderException {
+ clearTempDir();
+ fcs = new JdbmCacheStore();
+ JdbmCacheStoreConfig cfg = new JdbmCacheStoreConfig();
+ cfg.setLocation(tmpDirectory);
+ cfg.setPurgeSynchronously(true); // for more accurate unit testing
+ fcs.init(cfg, getCache(), getMarshaller());
+ fcs.start();
+ return fcs;
+ }
+
+ @Override
+ public void testPreload() throws CacheLoaderException {
+ super.testPreload();
+ }
+
+ @Override
+ public void testPurgeExpired() throws Exception {
+ long lifespan = 1000;
+ InternalCacheEntry k1 = InternalEntryFactory.create("k1", "v1", lifespan);
+ InternalCacheEntry k2 = InternalEntryFactory.create("k2", "v2", lifespan);
+ InternalCacheEntry k3 = InternalEntryFactory.create("k3", "v3", lifespan);
+ cs.store(k1);
+ cs.store(k2);
+ cs.store(k3);
+ assert cs.containsKey("k1");
+ assert cs.containsKey("k2");
+ assert cs.containsKey("k3");
+ Thread.sleep(lifespan + 100);
+ cs.purgeExpired();
+ JdbmCacheStore fcs = (JdbmCacheStore) cs;
+ assert fcs.load("k1") == null;
+ assert fcs.load("k2") == null;
+ assert fcs.load("k3") == null;
+ }
+
+ public void testIterator() throws Exception {
+ InternalCacheEntry k1 = InternalEntryFactory.create("k1", "v1");
+ InternalCacheEntry k2 = InternalEntryFactory.create("k2", "v2");
+ cs.store(k1);
+ cs.store(k2);
+
+ Set<InternalCacheEntry> set = cs.loadAll();
+ Iterator<InternalCacheEntry> i = set.iterator();
+ assert i.hasNext() == true;
+ assert i.hasNext() == true;
+ assert i.next().getKey().equals("k1");
+ assert i.next().getKey().equals("k2");
+ assert i.hasNext() == false;
+ assert i.hasNext() == false;
+ try {
+ i.next();
+ assert false;
+ } catch (NoSuchElementException e) {}
+ }
+
+ public void testToStream() throws Exception {
+ cs.store(InternalEntryFactory.create("k1", "v1", -1, -1));
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ cs.toStream(new UnclosableObjectOutputStream(oos));
+ oos.flush();
+ oos.close();
+ out.close();
+
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+ assert ois.readLong() == 1 : "we have 3 different buckets";
+ Object readObject = ois.readObject();
+ assert readObject instanceof InternalCacheEntry;
+ // assert ois.readInt() > 0; //size on disk
+ } finally {
+ if (ois != null) ois.close();
+ }
+ }
+}
Modified: trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java 2009-05-06 15:52:12 UTC (rev 219)
+++ trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java 2009-05-06 18:18:25 UTC (rev 220)
@@ -113,6 +113,7 @@
se = InternalEntryFactory.create("k", "v", lifespan);
cs.store(se);
Thread.sleep(100);
+ cs.purgeExpired();
assert se.isExpired();
assert cs.load("k") == null;
assert !cs.containsKey("k");
@@ -135,6 +136,7 @@
se = InternalEntryFactory.create("k", "v", -1, idle);
cs.store(se);
Thread.sleep(100);
+ cs.purgeExpired();
assert se.isExpired();
assert cs.load("k") == null;
assert !cs.containsKey("k");
@@ -158,6 +160,7 @@
se = InternalEntryFactory.create("k", "v", lifespan, idle);
cs.store(se);
Thread.sleep(100);
+ cs.purgeExpired();
assert se.isExpired();
assert cs.load("k") == null;
assert !cs.containsKey("k");
@@ -557,4 +560,5 @@
if (!exceptions.isEmpty()) throw exceptions.get(0);
}
-}
+
+}
\ No newline at end of file
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2009-05-06 15:52:12 UTC (rev 219)
+++ trunk/pom.xml 2009-05-06 18:18:25 UTC (rev 220)
@@ -26,6 +26,7 @@
<module>cachestore/bdbje</module>
<module>cachestore/s3</module>
<module>cachestore/jdbc</module>
+ <module>cachestore/jdbm</module>
<module>gui-demo</module>
</modules>
@@ -81,6 +82,7 @@
<fileset dir="cachestore/bdbje/target/classes"/>
<fileset dir="cachestore/jdbc/target/classes"/>
<fileset dir="cachestore/s3/target/classes"/>
+ <fileset dir="cachestore/jdbm/target/classes"/>
<fileset dir="core/target/classes"/>
<fileset dir="tree/target/classes"/>
</zip>
More information about the infinispan-commits
mailing list