[infinispan-commits] Infinispan SVN: r1584 - in trunk: cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje and 16 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Wed Mar 10 08:42:41 EST 2010


Author: manik.surtani at jboss.com
Date: 2010-03-10 08:42:39 -0500 (Wed, 10 Mar 2010)
New Revision: 1584

Added:
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DatabaseType.java
Modified:
   trunk/cachestore/bdbje/src/main/java/org/infinispan/loaders/bdbje/BdbjeCacheStore.java
   trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreFunctionalIntegrationTest.java
   trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreIntegrationTest.java
   trunk/cachestore/cloud/src/main/java/org/infinispan/loaders/cloud/CloudCacheStore.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DataManipulationHelper.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
   trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java
   trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java
   trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest2.java
   trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java
   trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreFunctionalTest.java
   trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java
   trunk/core/src/main/java/org/infinispan/eviction/EvictionStrategy.java
   trunk/core/src/main/java/org/infinispan/loaders/CacheLoader.java
   trunk/core/src/main/java/org/infinispan/loaders/CacheLoaderManagerImpl.java
   trunk/core/src/main/java/org/infinispan/loaders/LockSupportCacheStore.java
   trunk/core/src/main/java/org/infinispan/loaders/cluster/ClusterCacheLoader.java
   trunk/core/src/main/java/org/infinispan/loaders/decorators/AbstractDelegatingStore.java
   trunk/core/src/main/java/org/infinispan/loaders/decorators/ChainingCacheStore.java
   trunk/core/src/main/java/org/infinispan/loaders/file/FileCacheStore.java
   trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java
   trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java
Log:
[ISPN-310] (CacheLoader preload should only load as many entries as configured by eviction max entries)

Modified: trunk/cachestore/bdbje/src/main/java/org/infinispan/loaders/bdbje/BdbjeCacheStore.java
===================================================================
--- trunk/cachestore/bdbje/src/main/java/org/infinispan/loaders/bdbje/BdbjeCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/bdbje/src/main/java/org/infinispan/loaders/bdbje/BdbjeCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -4,7 +4,15 @@
 import com.sleepycat.collections.CurrentTransaction;
 import com.sleepycat.collections.StoredMap;
 import com.sleepycat.collections.StoredSortedMap;
-import com.sleepycat.je.*;
+import com.sleepycat.je.Cursor;
+import com.sleepycat.je.Database;
+import com.sleepycat.je.DatabaseEntry;
+import com.sleepycat.je.DatabaseException;
+import com.sleepycat.je.Environment;
+import com.sleepycat.je.EnvironmentConfig;
+import com.sleepycat.je.JEVersion;
+import com.sleepycat.je.OperationStatus;
+import com.sleepycat.je.Transaction;
 import com.sleepycat.util.ExceptionUnwrapper;
 import org.infinispan.Cache;
 import org.infinispan.container.entries.InternalCacheEntry;
@@ -24,6 +32,7 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -40,8 +49,8 @@
  * <p/>
  * All data access is transactional.  Any attempted reads to locked records will block.  The maximum duration of this is
  * set in nanoseconds via the parameter {@link org.infinispan.loaders.bdbje.BdbjeCacheStoreConfig#getLockAcquistionTimeout()}.
- * Calls to {@link org.infinispan.loaders.CacheStore#prepare(java.util.List, org.infinispan.transaction.xa.GlobalTransaction, boolean)}  will attempt
- * to resolve deadlocks, retrying up to {@link org.infinispan.loaders.bdbje.BdbjeCacheStoreConfig#getMaxTxRetries()}
+ * Calls to {@link org.infinispan.loaders.CacheStore#prepare(java.util.List, org.infinispan.transaction.xa.GlobalTransaction,
+ * boolean)}  will attempt to resolve deadlocks, retrying up to {@link org.infinispan.loaders.bdbje.BdbjeCacheStoreConfig#getMaxTxRetries()}
  * attempts.
  * <p/>
  * Unlike the C version of SleepyCat, JE does not support MVCC or READ_COMMITTED isolation.  In other words, readers
@@ -56,503 +65,518 @@
 @CacheLoaderMetadata(configurationClass = BdbjeCacheStoreConfig.class)
 public class BdbjeCacheStore extends AbstractCacheStore {
 
-    private static final Log log = LogFactory.getLog(BdbjeCacheStore.class);
-    private static final boolean trace = log.isTraceEnabled();
+   private static final Log log = LogFactory.getLog(BdbjeCacheStore.class);
+   private static final boolean trace = log.isTraceEnabled();
 
-    private BdbjeCacheStoreConfig cfg;
+   private BdbjeCacheStoreConfig cfg;
 
-    private Environment env;
-    private StoredClassCatalog catalog;
-    private Database cacheDb;
-    private Database expiryDb;
-    private StoredMap<Object, InternalCacheEntry> cacheMap;
-    private StoredSortedMap<Long, Object> expiryMap;
+   private Environment env;
+   private StoredClassCatalog catalog;
+   private Database cacheDb;
+   private Database expiryDb;
+   private StoredMap<Object, InternalCacheEntry> cacheMap;
+   private StoredSortedMap<Long, Object> expiryMap;
 
 
-    private PreparableTransactionRunner transactionRunner;
-    private Map<GlobalTransaction, Transaction> txnMap;
-    private CurrentTransaction currentTransaction;
-    private BdbjeResourceFactory factory;
+   private PreparableTransactionRunner transactionRunner;
+   private Map<GlobalTransaction, Transaction> txnMap;
+   private CurrentTransaction currentTransaction;
+   private BdbjeResourceFactory factory;
 
-    /**
-     * {@inheritDoc} This implementation expects config to be an instance of {@link BdbjeCacheStoreConfig} <p /> note
-     * that the <code>m</code> is not currently used as SleepyCat has its own efficient solution.
-     *
-     * @see BdbjeCacheStoreConfig
-     */
-    @Override
-    public void init(CacheLoaderConfig config, Cache cache, Marshaller m) throws CacheLoaderException {
-        BdbjeCacheStoreConfig cfg = (BdbjeCacheStoreConfig) config;
-        init(cfg, new BdbjeResourceFactory(cfg), cache, m);
-    }
+   /**
+    * {@inheritDoc} This implementation expects config to be an instance of {@link BdbjeCacheStoreConfig} <p /> note
+    * that the <code>m</code> is not currently used as SleepyCat has its own efficient solution.
+    *
+    * @see BdbjeCacheStoreConfig
+    */
+   @Override
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) throws CacheLoaderException {
+      BdbjeCacheStoreConfig cfg = (BdbjeCacheStoreConfig) config;
+      init(cfg, new BdbjeResourceFactory(cfg), cache, m);
+   }
 
-    void init(BdbjeCacheStoreConfig cfg, BdbjeResourceFactory factory, Cache cache, Marshaller m) throws CacheLoaderException {
-        if (trace) log.trace("initializing BdbjeCacheStore");
-        printLicense();
-        super.init(cfg, cache, m);
-        this.cfg = cfg;
-        this.factory = factory;
-    }
+   void init(BdbjeCacheStoreConfig cfg, BdbjeResourceFactory factory, Cache cache, Marshaller m) throws CacheLoaderException {
+      if (trace) log.trace("initializing BdbjeCacheStore");
+      printLicense();
+      super.init(cfg, cache, m);
+      this.cfg = cfg;
+      this.factory = factory;
+   }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @return {@link BdbjeCacheStoreConfig}
-     */
-    public Class<? extends CacheLoaderConfig> getConfigurationClass() {
-        return BdbjeCacheStoreConfig.class;
-    }
+   /**
+    * {@inheritDoc}
+    *
+    * @return {@link BdbjeCacheStoreConfig}
+    */
+   public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+      return BdbjeCacheStoreConfig.class;
+   }
 
-    /**
-     * {@inheritDoc} Validates configuration, configures and opens the {@link Environment}, then {@link
-     * org.infinispan.loaders.bdbje.BdbjeCacheStore#openSleepyCatResources() opens the databases}.  When this is
-     * finished, transactional and purging services are instantiated.
-     */
-    public void start() throws CacheLoaderException {
-        if (trace) log.trace("starting BdbjeCacheStore");
+   /**
+    * {@inheritDoc} Validates configuration, configures and opens the {@link Environment}, then {@link
+    * org.infinispan.loaders.bdbje.BdbjeCacheStore#openSleepyCatResources() opens the databases}.  When this is
+    * finished, transactional and purging services are instantiated.
+    */
+   public void start() throws CacheLoaderException {
+      if (trace) log.trace("starting BdbjeCacheStore");
 
-        openSleepyCatResources();
-        openTransactionServices();
-        super.start();
+      openSleepyCatResources();
+      openTransactionServices();
+      super.start();
 
-        log.debug("started cache store {1}", this);
-    }
+      log.debug("started cache store {1}", this);
+   }
 
-    private void openTransactionServices() {
-        txnMap = new ConcurrentHashMap<GlobalTransaction, Transaction>(64, 0.75f, getConcurrencyLevel());
-        currentTransaction = factory.createCurrentTransaction(env);
-        transactionRunner = factory.createPreparableTransactionRunner(env);
-    }
+   private void openTransactionServices() {
+      txnMap = new ConcurrentHashMap<GlobalTransaction, Transaction>(64, 0.75f, getConcurrencyLevel());
+      currentTransaction = factory.createCurrentTransaction(env);
+      transactionRunner = factory.createPreparableTransactionRunner(env);
+   }
 
-    /**
-     * Opens the SleepyCat environment and all databases.  A {@link StoredMap} instance is provided which persists the
-     * CacheStore.
-     */
-    private void openSleepyCatResources() throws CacheLoaderException {
-        if (trace) log.trace("creating je environment with home dir {0}", cfg.getLocation());
+   /**
+    * Opens the SleepyCat environment and all databases.  A {@link StoredMap} instance is provided which persists the
+    * CacheStore.
+    */
+   private void openSleepyCatResources() throws CacheLoaderException {
+      if (trace) log.trace("creating je environment with home dir {0}", cfg.getLocation());
 
-       cfg.setCacheName(cache.getName());
-        if (cfg.getCatalogDbName() == null)
-           cfg.setCatalogDbName(cfg.getCacheDbName() + "_class_catalog");
+      cfg.setCacheName(cache.getName());
+      if (cfg.getCatalogDbName() == null)
+         cfg.setCatalogDbName(cfg.getCacheDbName() + "_class_catalog");
 
-        File location = verifyOrCreateEnvironmentDirectory(new File(cfg.getLocation()));
-        try {
-            env = factory.createEnvironment(location);
-            cacheDb = factory.createDatabase(env, cfg.getCacheDbName());
-            Database catalogDb = factory.createDatabase(env, cfg.getCatalogDbName());
-            expiryDb = factory.createDatabase(env, cfg.getExpiryDbName());
-            catalog = factory.createStoredClassCatalog(catalogDb);
-            cacheMap = factory.createStoredMapViewOfDatabase(cacheDb, catalog, marshaller);
-            expiryMap = factory.createStoredSortedMapForKeyExpiry(expiryDb, catalog, marshaller);
-        } catch (DatabaseException e) {
-            throw convertToCacheLoaderException("could not open sleepycat je resource", e);
-        }
-    }
+      File location = verifyOrCreateEnvironmentDirectory(new File(cfg.getLocation()));
+      try {
+         env = factory.createEnvironment(location);
+         cacheDb = factory.createDatabase(env, cfg.getCacheDbName());
+         Database catalogDb = factory.createDatabase(env, cfg.getCatalogDbName());
+         expiryDb = factory.createDatabase(env, cfg.getExpiryDbName());
+         catalog = factory.createStoredClassCatalog(catalogDb);
+         cacheMap = factory.createStoredMapViewOfDatabase(cacheDb, catalog, marshaller);
+         expiryMap = factory.createStoredSortedMapForKeyExpiry(expiryDb, catalog, marshaller);
+      } catch (DatabaseException e) {
+         throw convertToCacheLoaderException("could not open sleepycat je resource", e);
+      }
+   }
 
-    // not private so that this can be unit tested
-    File verifyOrCreateEnvironmentDirectory(File location) throws CacheLoaderException {
-        if (!location.exists()) {
-            boolean created = location.mkdirs();
-            if (!created) throw new CacheLoaderException("Unable to create cache loader location " + location);
+   // not private so that this can be unit tested
 
-        }
-        if (!location.isDirectory()) {
-            throw new CacheLoaderException("Cache loader location [" + location + "] is not a directory!");
-        }
-        return location;
-    }
+   File verifyOrCreateEnvironmentDirectory(File location) throws CacheLoaderException {
+      if (!location.exists()) {
+         boolean created = location.mkdirs();
+         if (!created) throw new CacheLoaderException("Unable to create cache loader location " + location);
 
-    /**
-     * Stops transaction and purge processing and closes the SleepyCat environment.  The environment and databases are
-     * not removed from the file system. Exceptions during close of databases are ignored as closing the environment will
-     * ensure the databases are also.
-     */
-    public void stop() throws CacheLoaderException {
-        if (trace) log.trace("stopping BdbjeCacheStore");
-        super.stop();
-        closeTransactionServices();
-        closeSleepyCatResources();
-        log.debug("started cache store {1}", this);
-    }
+      }
+      if (!location.isDirectory()) {
+         throw new CacheLoaderException("Cache loader location [" + location + "] is not a directory!");
+      }
+      return location;
+   }
 
-    private void closeTransactionServices() {
-        transactionRunner = null;
-        currentTransaction = null;
-        txnMap = null;
-    }
+   /**
+    * Stops transaction and purge processing and closes the SleepyCat environment.  The environment and databases are
+    * not removed from the file system. Exceptions during close of databases are ignored as closing the environment
+    * will ensure the databases are also.
+    */
+   public void stop() throws CacheLoaderException {
+      if (trace) log.trace("stopping BdbjeCacheStore");
+      super.stop();
+      closeTransactionServices();
+      closeSleepyCatResources();
+      log.debug("started cache store {1}", this);
+   }
 
-    private void closeSleepyCatResources() throws CacheLoaderException {
-        cacheMap = null;
-        expiryMap = null;
-        closeDatabases();
-        closeEnvironment();
-    }
+   private void closeTransactionServices() {
+      transactionRunner = null;
+      currentTransaction = null;
+      txnMap = null;
+   }
 
-    /**
-     * Exceptions are ignored so that {@link org.infinispan.loaders.bdbje.BdbjeCacheStore#closeEnvironment()}  will
-     * execute.
-     */
-    private void closeDatabases() {
-        if (trace) log.trace("closing databases");
-        try {
-            cacheDb.close();
-        } catch (Exception e) {
-            log.error("Error closing database", e);
-        }
-        try {
-            expiryDb.close();
-        } catch (Exception e) {
-            log.error("Error closing database", e);
-        }
-        try {
-            catalog.close();
-        } catch (Exception e) {
-            log.error("Error closing catalog", e);
-        }
-        catalog = null;
-        cacheDb = null;
-        expiryDb = null;
-    }
+   private void closeSleepyCatResources() throws CacheLoaderException {
+      cacheMap = null;
+      expiryMap = null;
+      closeDatabases();
+      closeEnvironment();
+   }
 
-    private void closeEnvironment() throws CacheLoaderException {
-        if (env != null) {
-            try {
-                env.close();
-            } catch (DatabaseException e) {
-                throw new CacheLoaderException("Unexpected exception closing cacheStore", e);
-            }
-        }
-        env = null;
-    }
+   /**
+    * Exceptions are ignored so that {@link org.infinispan.loaders.bdbje.BdbjeCacheStore#closeEnvironment()}  will
+    * execute.
+    */
+   private void closeDatabases() {
+      if (trace) log.trace("closing databases");
+      try {
+         cacheDb.close();
+      } catch (Exception e) {
+         log.error("Error closing database", e);
+      }
+      try {
+         expiryDb.close();
+      } catch (Exception e) {
+         log.error("Error closing database", e);
+      }
+      try {
+         catalog.close();
+      } catch (Exception e) {
+         log.error("Error closing catalog", e);
+      }
+      catalog = null;
+      cacheDb = null;
+      expiryDb = null;
+   }
 
-    /**
-     * {@inheritDoc} delegates to {@link BdbjeCacheStore#applyModifications(java.util.List)}, if <code>isOnePhase</code>.
-     * Otherwise, delegates to {@link BdbjeCacheStore#prepare(java.util.List, org.infinispan.transaction.xa.GlobalTransaction)} 
-     */
-    public void prepare(List<? extends Modification> mods, GlobalTransaction tx, boolean isOnePhase) throws CacheLoaderException {
-        if (isOnePhase) {
-            applyModifications(mods);
-        } else {
-            prepare(mods, tx);
-        }
-    }
+   private void closeEnvironment() throws CacheLoaderException {
+      if (env != null) {
+         try {
+            env.close();
+         } catch (DatabaseException e) {
+            throw new CacheLoaderException("Unexpected exception closing cacheStore", e);
+         }
+      }
+      env = null;
+   }
 
-    /**
-     * Perform the <code>mods</code> atomically by creating a {@link ModificationsTransactionWorker worker} and invoking
-     * them in {@link PreparableTransactionRunner#run(com.sleepycat.collections.TransactionWorker)}.
-     *
-     * @param mods actions to perform atomically
-     * @throws CacheLoaderException on problems during the transaction
-     */
-    @Override
-    protected void applyModifications(List<? extends Modification> mods) throws CacheLoaderException {
-        if (trace) log.trace("performing one phase transaction");
-        try {
-            transactionRunner.run(new ModificationsTransactionWorker(this, mods));
-        } catch (Exception caught) {
-            throw convertToCacheLoaderException("Problem committing modifications: " + mods, caught);
-        }
-    }
+   /**
+    * {@inheritDoc} delegates to {@link BdbjeCacheStore#applyModifications(java.util.List)}, if
+    * <code>isOnePhase</code>. Otherwise, delegates to {@link BdbjeCacheStore#prepare(java.util.List,
+    * org.infinispan.transaction.xa.GlobalTransaction)}
+    */
+   public void prepare(List<? extends Modification> mods, GlobalTransaction tx, boolean isOnePhase) throws CacheLoaderException {
+      if (isOnePhase) {
+         applyModifications(mods);
+      } else {
+         prepare(mods, tx);
+      }
+   }
 
-    /**
-     * Looks up the {@link Transaction SleepyCat transaction} associated with <code>tx</code>.  Creates a {@link
-     * org.infinispan.loaders.bdbje.ModificationsTransactionWorker} instance from <code>mods</code>.  Then prepares the
-     * transaction via {@link PreparableTransactionRunner#prepare(com.sleepycat.collections.TransactionWorker)}. Finally,
-     * it invalidates {@link com.sleepycat.collections.CurrentTransaction#getTransaction()} so that no other thread can
-     * accidentally commit this.
-     *
-     * @param mods modifications to be applied
-     * @param tx   transaction identifier
-     * @throws CacheLoaderException in the event of problems writing to the store
-     */
-    protected void prepare(List<? extends Modification> mods, GlobalTransaction tx) throws CacheLoaderException {
-        if (trace) log.trace("preparing transaction {0}", tx);
-        try {
-            transactionRunner.prepare(new ModificationsTransactionWorker(this, mods));
-            Transaction txn = currentTransaction.getTransaction();
-            if (trace) log.trace("transaction {0} == sleepycat transaction {1}", tx, txn);
-            txnMap.put(tx, txn);
-            ReflectionUtil.setValue(currentTransaction, "localTrans", new ThreadLocal());
-        } catch (Exception e) {
-            throw convertToCacheLoaderException("Problem preparing transaction", e);
-        }
-    }
+   /**
+    * Perform the <code>mods</code> atomically by creating a {@link ModificationsTransactionWorker worker} and invoking
+    * them in {@link PreparableTransactionRunner#run(com.sleepycat.collections.TransactionWorker)}.
+    *
+    * @param mods actions to perform atomically
+    * @throws CacheLoaderException on problems during the transaction
+    */
+   @Override
+   protected void applyModifications(List<? extends Modification> mods) throws CacheLoaderException {
+      if (trace) log.trace("performing one phase transaction");
+      try {
+         transactionRunner.run(new ModificationsTransactionWorker(this, mods));
+      } catch (Exception caught) {
+         throw convertToCacheLoaderException("Problem committing modifications: " + mods, caught);
+      }
+   }
 
+   /**
+    * Looks up the {@link Transaction SleepyCat transaction} associated with <code>tx</code>.  Creates a {@link
+    * org.infinispan.loaders.bdbje.ModificationsTransactionWorker} instance from <code>mods</code>.  Then prepares the
+    * transaction via {@link PreparableTransactionRunner#prepare(com.sleepycat.collections.TransactionWorker)}.
+    * Finally, it invalidates {@link com.sleepycat.collections.CurrentTransaction#getTransaction()} so that no other
+    * thread can accidentally commit this.
+    *
+    * @param mods modifications to be applied
+    * @param tx   transaction identifier
+    * @throws CacheLoaderException in the event of problems writing to the store
+    */
+   protected void prepare(List<? extends Modification> mods, GlobalTransaction tx) throws CacheLoaderException {
+      if (trace) log.trace("preparing transaction {0}", tx);
+      try {
+         transactionRunner.prepare(new ModificationsTransactionWorker(this, mods));
+         Transaction txn = currentTransaction.getTransaction();
+         if (trace) log.trace("transaction {0} == sleepycat transaction {1}", tx, txn);
+         txnMap.put(tx, txn);
+         ReflectionUtil.setValue(currentTransaction, "localTrans", new ThreadLocal());
+      } catch (Exception e) {
+         throw convertToCacheLoaderException("Problem preparing transaction", e);
+      }
+   }
 
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * This implementation calls {@link BdbjeCacheStore#completeTransaction(org.infinispan.transaction.xa.GlobalTransaction, boolean)}
-     * completeTransaction} with an argument of false.
-     */
-    public void rollback(GlobalTransaction tx) {
-        try {
-            completeTransaction(tx, false);
-        } catch (Exception e) {
-            log.error("Error rolling back transaction", e);
-        }
-    }
 
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * This implementation calls {@link BdbjeCacheStore#completeTransaction(org.infinispan.transaction.xa.GlobalTransaction, boolean)}
-     * completeTransaction} with an argument of true.
-     */
-    public void commit(GlobalTransaction tx) throws CacheLoaderException {
-        completeTransaction(tx, true);
-    }
+   /**
+    * {@inheritDoc}
+    * <p/>
+    * This implementation calls {@link BdbjeCacheStore#completeTransaction(org.infinispan.transaction.xa.GlobalTransaction,
+    * boolean)} completeTransaction} with an argument of false.
+    */
+   public void rollback(GlobalTransaction tx) {
+      try {
+         completeTransaction(tx, false);
+      } catch (Exception e) {
+         log.error("Error rolling back transaction", e);
+      }
+   }
 
-    /**
-     * Looks up the SleepyCat transaction associated with the parameter <code>tx</code>.  If there is no associated
-     * sleepycat transaction, an error is logged.
-     *
-     * @param tx     java transaction used to lookup a SleepyCat transaction
-     * @param commit true to commit false to abort
-     * @throws CacheLoaderException if there are problems committing or aborting the transaction
-     */
-    protected void completeTransaction(GlobalTransaction tx, boolean commit) throws CacheLoaderException {
-        Transaction txn = txnMap.remove(tx);
-        if (txn != null) {
-            if (trace) log.trace("{0} sleepycat transaction {1}", commit ? "committing" : "aborting", txn);
-            try {
-                if (commit)
-                    txn.commit();
-                else
-                    txn.abort();
-            } catch (Exception caught) {
-                throw convertToCacheLoaderException("Problem completing transaction", caught);
-            }
-        } else {
-            if (trace) log.trace("no sleepycat transaction associated  transaction {0}", tx);
-        }
-    }
+   /**
+    * {@inheritDoc}
+    * <p/>
+    * This implementation calls {@link BdbjeCacheStore#completeTransaction(org.infinispan.transaction.xa.GlobalTransaction,
+    * boolean)} completeTransaction} with an argument of true.
+    */
+   public void commit(GlobalTransaction tx) throws CacheLoaderException {
+      completeTransaction(tx, true);
+   }
 
-    /**
-     * commits or aborts the {@link com.sleepycat.collections.CurrentTransaction#getTransaction() current transaction}
-     *
-     * @param commit true to commit, false to abort
-     * @throws CacheLoaderException if there was a problem completing the transaction
-     */
-    private void completeCurrentTransaction(boolean commit) throws CacheLoaderException {
-        try {
-            if (trace)
-                log.trace("{0} current sleepycat transaction {1}", commit ? "committing" : "aborting", currentTransaction.getTransaction());
+   /**
+    * Looks up the SleepyCat transaction associated with the parameter <code>tx</code>.  If there is no associated
+    * sleepycat transaction, an error is logged.
+    *
+    * @param tx     java transaction used to lookup a SleepyCat transaction
+    * @param commit true to commit false to abort
+    * @throws CacheLoaderException if there are problems committing or aborting the transaction
+    */
+   protected void completeTransaction(GlobalTransaction tx, boolean commit) throws CacheLoaderException {
+      Transaction txn = txnMap.remove(tx);
+      if (txn != null) {
+         if (trace) log.trace("{0} sleepycat transaction {1}", commit ? "committing" : "aborting", txn);
+         try {
             if (commit)
-                currentTransaction.commitTransaction();
+               txn.commit();
             else
-                currentTransaction.abortTransaction();
-        } catch (Exception caught) {
+               txn.abort();
+         } catch (Exception caught) {
             throw convertToCacheLoaderException("Problem completing transaction", caught);
-        }
-    }
+         }
+      } else {
+         if (trace) log.trace("no sleepycat transaction associated  transaction {0}", tx);
+      }
+   }
 
-    /**
-     * {@inheritDoc} This implementation delegates to {@link StoredMap#remove(Object)}
-     */
-    public boolean remove(Object key) throws CacheLoaderException {
-        try {
-            if (cacheMap.containsKey(key)) {
-                cacheMap.remove(key);
-                return true;
-            }
-            return false;
-        } catch (RuntimeException caught) {
-            throw convertToCacheLoaderException("error removing key " + key, caught);
-        }
-    }
+   /**
+    * commits or aborts the {@link com.sleepycat.collections.CurrentTransaction#getTransaction() current transaction}
+    *
+    * @param commit true to commit, false to abort
+    * @throws CacheLoaderException if there was a problem completing the transaction
+    */
+   private void completeCurrentTransaction(boolean commit) throws CacheLoaderException {
+      try {
+         if (trace)
+            log.trace("{0} current sleepycat transaction {1}", commit ? "committing" : "aborting", currentTransaction.getTransaction());
+         if (commit)
+            currentTransaction.commitTransaction();
+         else
+            currentTransaction.abortTransaction();
+      } catch (Exception caught) {
+         throw convertToCacheLoaderException("Problem completing transaction", caught);
+      }
+   }
 
-    /**
-     * {@inheritDoc} This implementation delegates to {@link StoredMap#get(Object)}.  If the object is expired, it will
-     * not be returned.
-     */
-    public InternalCacheEntry load(Object key) throws CacheLoaderException {
-        try {
-            InternalCacheEntry s = cacheMap.get(key);
-            if (s != null && s.isExpired()) {
-                s = null;
-            }
-            return s;
-        } catch (RuntimeException caught) {
-            throw convertToCacheLoaderException("error loading key " + key, caught);
-        }
-    }
+   /**
+    * {@inheritDoc} This implementation delegates to {@link StoredMap#remove(Object)}
+    */
+   public boolean remove(Object key) throws CacheLoaderException {
+      try {
+         if (cacheMap.containsKey(key)) {
+            cacheMap.remove(key);
+            return true;
+         }
+         return false;
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error removing key " + key, caught);
+      }
+   }
 
-    /**
-     * {@inheritDoc} This implementation delegates to {@link StoredMap#put(Object, Object)}
-     */
-    public void store(InternalCacheEntry ed) throws CacheLoaderException {
-        try {
-            cacheMap.put(ed.getKey(), ed);
-            if (ed.canExpire())
-                addNewExpiry(ed);
-        } catch (IOException caught) {
-            throw convertToCacheLoaderException("error storing entry " + ed, caught);
-        }
-    }
+   /**
+    * {@inheritDoc} This implementation delegates to {@link StoredMap#get(Object)}.  If the object is expired, it will
+    * not be returned.
+    */
+   public InternalCacheEntry load(Object key) throws CacheLoaderException {
+      try {
+         InternalCacheEntry s = cacheMap.get(key);
+         if (s != null && s.isExpired()) {
+            s = null;
+         }
+         return s;
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error loading key " + key, caught);
+      }
+   }
 
+   /**
+    * {@inheritDoc} This implementation delegates to {@link StoredMap#put(Object, Object)}
+    */
+   public void store(InternalCacheEntry ed) throws CacheLoaderException {
+      try {
+         cacheMap.put(ed.getKey(), ed);
+         if (ed.canExpire())
+            addNewExpiry(ed);
+      } catch (IOException caught) {
+         throw convertToCacheLoaderException("error storing entry " + ed, caught);
+      }
+   }
 
-    private void addNewExpiry(InternalCacheEntry entry) throws IOException {
-        long expiry = entry.getExpiryTime();
-        if (entry.getMaxIdle() > 0) {
-           // Coding getExpiryTime() for transient entries has the risk of being a moving target
-           // which could lead to unexpected results, hence, InternalCacheEntry calls are required
-            expiry = entry.getMaxIdle() + System.currentTimeMillis();
-        }
-        Long at = expiry;
-        Object key = entry.getKey();
-        expiryMap.put(at, key);
-    }
 
-    /**
-     * {@inheritDoc} This implementation delegates to {@link StoredMap#clear()}
-     */
-    public void clear() throws CacheLoaderException {
-        try {
-            cacheMap.clear();
-        } catch (RuntimeException caught) {
-            throw convertToCacheLoaderException("error clearing store", caught);
-        }
-    }
+   private void addNewExpiry(InternalCacheEntry entry) throws IOException {
+      long expiry = entry.getExpiryTime();
+      if (entry.getMaxIdle() > 0) {
+         // Coding getExpiryTime() for transient entries has the risk of being a moving target
+         // which could lead to unexpected results, hence, InternalCacheEntry calls are required
+         expiry = entry.getMaxIdle() + System.currentTimeMillis();
+      }
+      Long at = expiry;
+      Object key = entry.getKey();
+      expiryMap.put(at, key);
+   }
 
-    /**
-     * {@inheritDoc} This implementation returns a Set from {@link StoredMap#values()}
-     */
-    public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
-        try {
-            return new HashSet<InternalCacheEntry>(cacheMap.values());
-        } catch (RuntimeException caught) {
-            throw convertToCacheLoaderException("error loading all entries", caught);
-        }
-    }
+   /**
+    * {@inheritDoc} This implementation delegates to {@link StoredMap#clear()}
+    */
+   public void clear() throws CacheLoaderException {
+      try {
+         cacheMap.clear();
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error clearing store", caught);
+      }
+   }
 
-    /**
-     * {@inheritDoc} This implementation reads the number of entries to load from the stream, then begins a transaction.
-     * During that transaction, the cachestore is cleared and replaced with entries from the stream.  If there are any
-     * errors during the process, the entire transaction is rolled back.  Deadlock handling is not addressed, as there is
-     * no means to rollback reads from the input stream.
-     *
-     * @see BdbjeCacheStore#toStream(java.io.ObjectOutput)
-     */
-    public void fromStream(ObjectInput ois) throws CacheLoaderException {
-        try {
-            currentTransaction.beginTransaction(null);
-            cacheMap.clear();
-            expiryMap.clear();
-            for (Database db : new Database[]{cacheDb, expiryDb}) {
-                long recordCount = ois.readLong();
-                log.debug("clearing and reading {0} records from stream", recordCount);
-                Cursor cursor = null;
-                try {
-                    cursor = db.openCursor(currentTransaction.getTransaction(), null);
-                    for (int i = 0; i < recordCount; i++) {
-                        byte[] keyBytes = (byte[]) ois.readObject();
-                        byte[] dataBytes = (byte[]) ois.readObject();
+   /**
+    * {@inheritDoc} This implementation returns a Set from {@link StoredMap#values()}
+    */
+   public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
+      try {
+         return new HashSet<InternalCacheEntry>(cacheMap.values());
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error loading all entries", caught);
+      }
+   }
 
-                        DatabaseEntry key = new DatabaseEntry(keyBytes);
-                        DatabaseEntry data = new DatabaseEntry(dataBytes);
-                        cursor.put(key, data);
-                    }
-                } finally {
-                    if (cursor != null) cursor.close();
-                }
+   @Override
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      if (numEntries < 0) return loadAll();
+      try {
+         Set<InternalCacheEntry> s = new HashSet<InternalCacheEntry>(numEntries);
+         for (Iterator<InternalCacheEntry> i = cacheMap.values().iterator(); i.hasNext() && s.size() < numEntries;)
+            s.add(i.next());
+         return s;
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error loading all entries", caught);
+      }
+   }
+
+   /**
+    * {@inheritDoc} This implementation reads the number of entries to load from the stream, then begins a transaction.
+    * During that transaction, the cachestore is cleared and replaced with entries from the stream.  If there are any
+    * errors during the process, the entire transaction is rolled back.  Deadlock handling is not addressed, as there
+    * is no means to rollback reads from the input stream.
+    *
+    * @see BdbjeCacheStore#toStream(java.io.ObjectOutput)
+    */
+   public void fromStream(ObjectInput ois) throws CacheLoaderException {
+      try {
+         currentTransaction.beginTransaction(null);
+         cacheMap.clear();
+         expiryMap.clear();
+         for (Database db : new Database[]{cacheDb, expiryDb}) {
+            long recordCount = ois.readLong();
+            log.debug("clearing and reading {0} records from stream", recordCount);
+            Cursor cursor = null;
+            try {
+               cursor = db.openCursor(currentTransaction.getTransaction(), null);
+               for (int i = 0; i < recordCount; i++) {
+                  byte[] keyBytes = (byte[]) ois.readObject();
+                  byte[] dataBytes = (byte[]) ois.readObject();
+
+                  DatabaseEntry key = new DatabaseEntry(keyBytes);
+                  DatabaseEntry data = new DatabaseEntry(dataBytes);
+                  cursor.put(key, data);
+               }
+            } finally {
+               if (cursor != null) cursor.close();
             }
-            completeCurrentTransaction(true);
-        } catch (Exception caught) {
-            completeCurrentTransaction(false);
-            clear();
-            throw convertToCacheLoaderException("Problems reading from stream", caught);
-        }
-    }
+         }
+         completeCurrentTransaction(true);
+      } catch (Exception caught) {
+         completeCurrentTransaction(false);
+         clear();
+         throw convertToCacheLoaderException("Problems reading from stream", caught);
+      }
+   }
 
-    /**
-     * Writes the current count of cachestore entries followed by a pair of byte[]s corresponding to the SleepyCat binary
-     * representation of {@link InternalCacheEntry#getKey() key} {@link InternalCacheEntry value}.
-     * <p/>
-     * This implementation holds a transaction open to ensure that we see no new records added while iterating.
-     */
-    public void toStream(ObjectOutput oos) throws CacheLoaderException {
-        try {
-            currentTransaction.beginTransaction(null);
-            for (Database db : new Database[]{cacheDb, expiryDb}) {
-                long recordCount = db.count();
-                oos.writeLong(recordCount);
-                if (trace) log.trace("writing {0} records to stream", recordCount);
-                Cursor cursor = null;
-                try {
-                    cursor = db.openCursor(currentTransaction.getTransaction(), null);
-                    DatabaseEntry key = new DatabaseEntry();
-                    DatabaseEntry data = new DatabaseEntry();
-                    int recordsWritten = 0;
-                    while (cursor.getNext(key, data, null) ==
-                            OperationStatus.SUCCESS) {
-                        oos.writeObject(key.getData());
-                        oos.writeObject(data.getData());
-                        recordsWritten++;
-                    }
-                    if (trace) log.trace("wrote {0} records to stream", recordsWritten);
-                    if (recordsWritten != recordCount)
-                        log.warn("expected to write {0} records, but wrote {1}", recordCount, recordsWritten);
-                } finally {
-                    if (cursor != null) cursor.close();
-                }
+   /**
+    * Writes the current count of cachestore entries followed by a pair of byte[]s corresponding to the SleepyCat
+    * binary representation of {@link InternalCacheEntry#getKey() key} {@link InternalCacheEntry value}.
+    * <p/>
+    * This implementation holds a transaction open to ensure that we see no new records added while iterating.
+    */
+   public void toStream(ObjectOutput oos) throws CacheLoaderException {
+      try {
+         currentTransaction.beginTransaction(null);
+         for (Database db : new Database[]{cacheDb, expiryDb}) {
+            long recordCount = db.count();
+            oos.writeLong(recordCount);
+            if (trace) log.trace("writing {0} records to stream", recordCount);
+            Cursor cursor = null;
+            try {
+               cursor = db.openCursor(currentTransaction.getTransaction(), null);
+               DatabaseEntry key = new DatabaseEntry();
+               DatabaseEntry data = new DatabaseEntry();
+               int recordsWritten = 0;
+               while (cursor.getNext(key, data, null) ==
+                     OperationStatus.SUCCESS) {
+                  oos.writeObject(key.getData());
+                  oos.writeObject(data.getData());
+                  recordsWritten++;
+               }
+               if (trace) log.trace("wrote {0} records to stream", recordsWritten);
+               if (recordsWritten != recordCount)
+                  log.warn("expected to write {0} records, but wrote {1}", recordCount, recordsWritten);
+            } finally {
+               if (cursor != null) cursor.close();
             }
-            completeCurrentTransaction(true);
-        } catch (Exception caught) {
-            completeCurrentTransaction(false);
-            throw convertToCacheLoaderException("Problems writing to stream", caught);
-        }
-    }
+         }
+         completeCurrentTransaction(true);
+      } catch (Exception caught) {
+         completeCurrentTransaction(false);
+         throw convertToCacheLoaderException("Problems writing to stream", caught);
+      }
+   }
 
-    /**
-     * In order to adhere to APIs which do not throw checked exceptions, BDBJE wraps IO and DatabaseExceptions inside
-     * RuntimeExceptions.  These special Exceptions implement {@link com.sleepycat.util.ExceptionWrapper}.  This method
-     * will look for any of that type of Exception and encapsulate it into a CacheLoaderException.  In doing so, the real
-     * root cause can be obtained.
-     *
-     * @param message what to attach to the CacheLoaderException
-     * @param caught  exception to parse
-     * @return CacheLoaderException with the correct cause
-     */
-    CacheLoaderException convertToCacheLoaderException(String message, Exception caught) {
-        caught = ExceptionUnwrapper.unwrap(caught);
-        return (caught instanceof CacheLoaderException) ? (CacheLoaderException) caught :
-                new CacheLoaderException(message, caught);
-    }
+   /**
+    * In order to adhere to APIs which do not throw checked exceptions, BDBJE wraps IO and DatabaseExceptions inside
+    * RuntimeExceptions.  These special Exceptions implement {@link com.sleepycat.util.ExceptionWrapper}.  This method
+    * will look for any of that type of Exception and encapsulate it into a CacheLoaderException.  In doing so, the
+    * real root cause can be obtained.
+    *
+    * @param message what to attach to the CacheLoaderException
+    * @param caught  exception to parse
+    * @return CacheLoaderException with the correct cause
+    */
+   CacheLoaderException convertToCacheLoaderException(String message, Exception caught) {
+      caught = ExceptionUnwrapper.unwrap(caught);
+      return (caught instanceof CacheLoaderException) ? (CacheLoaderException) caught :
+            new CacheLoaderException(message, caught);
+   }
 
-    /**
-     * Iterate through {@link com.sleepycat.collections.StoredMap#entrySet()} and remove, if expired.
-     */
-    @Override
-    protected void purgeInternal() throws CacheLoaderException {
-        try {
-            Map<Long, Object> expired = expiryMap.tailMap(System.currentTimeMillis(), true);
-            for (Map.Entry<Long, Object> entry : expired.entrySet()) {
-                expiryMap.remove(entry.getKey());
-                cacheMap.remove(entry.getValue());
-            }
-        } catch (RuntimeException caught) {
-            throw convertToCacheLoaderException("error purging expired entries", caught);
-        }
-    }
+   /**
+    * Iterate through {@link com.sleepycat.collections.StoredMap#entrySet()} and remove, if expired.
+    */
+   @Override
+   protected void purgeInternal() throws CacheLoaderException {
+      try {
+         Map<Long, Object> expired = expiryMap.tailMap(System.currentTimeMillis(), true);
+         for (Map.Entry<Long, Object> entry : expired.entrySet()) {
+            expiryMap.remove(entry.getKey());
+            cacheMap.remove(entry.getValue());
+         }
+      } catch (RuntimeException caught) {
+         throw convertToCacheLoaderException("error purging expired entries", caught);
+      }
+   }
 
-    /**
-     * prints terms of use for Berkeley DB JE
-     */
-    public void printLicense() {
-        String license = "\n*************************************************************************************\n" +
-                "Berkeley DB Java Edition version: " + JEVersion.CURRENT_VERSION.toString() + "\n" +
-                "JBoss Cache can use Berkeley DB Java Edition from Oracle \n" +
-                "(http://www.oracle.com/database/berkeley-db/je/index.html)\n" +
-                "for persistent, reliable and transaction-protected data storage.\n" +
-                "If you choose to use Berkeley DB Java Edition with JBoss Cache, you must comply with the terms\n" +
-                "of Oracle's public license, included in the file LICENSE.txt.\n" +
-                "If you prefer not to release the source code for your own application in order to comply\n" +
-                "with the Oracle public license, you may purchase a different license for use of\n" +
-                "Berkeley DB Java Edition with JBoss Cache.\n" +
-                "See http://www.oracle.com/database/berkeley-db/je/index.html for pricing and license terms\n" +
-                "*************************************************************************************";
-        System.out.println(license);
-    }
+   /**
+    * prints terms of use for Berkeley DB JE
+    */
+   public void printLicense() {
+      String license = "\n*************************************************************************************\n" +
+            "Berkeley DB Java Edition version: " + JEVersion.CURRENT_VERSION.toString() + "\n" +
+            "JBoss Cache can use Berkeley DB Java Edition from Oracle \n" +
+            "(http://www.oracle.com/database/berkeley-db/je/index.html)\n" +
+            "for persistent, reliable and transaction-protected data storage.\n" +
+            "If you choose to use Berkeley DB Java Edition with JBoss Cache, you must comply with the terms\n" +
+            "of Oracle's public license, included in the file LICENSE.txt.\n" +
+            "If you prefer not to release the source code for your own application in order to comply\n" +
+            "with the Oracle public license, you may purchase a different license for use of\n" +
+            "Berkeley DB Java Edition with JBoss Cache.\n" +
+            "See http://www.oracle.com/database/berkeley-db/je/index.html for pricing and license terms\n" +
+            "*************************************************************************************";
+      System.out.println(license);
+   }
 
 }

Modified: trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreFunctionalIntegrationTest.java
===================================================================
--- trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreFunctionalIntegrationTest.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreFunctionalIntegrationTest.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -28,6 +28,7 @@
 import org.infinispan.test.TestingUtil;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Optional;
 import org.testng.annotations.Parameters;
 import org.testng.annotations.Test;
 
@@ -38,8 +39,8 @@
 
    @BeforeTest
    @Parameters({"basedir"})
-   protected void setUpTempDir(String basedir) {
-      tmpDirectory = basedir + TestingUtil.TEST_PATH + File.separator + getClass().getSimpleName();
+   protected void setUpTempDir(@Optional("/tmp") String basedir) {
+      tmpDirectory = TestingUtil.tmpDirectory(basedir, this);
    }
    
    @AfterClass

Modified: trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreIntegrationTest.java
===================================================================
--- trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreIntegrationTest.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/bdbje/src/test/java/org/infinispan/loaders/bdbje/BdbjeCacheStoreIntegrationTest.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -12,7 +12,9 @@
 import org.infinispan.transaction.xa.GlobalTransaction;
 import org.infinispan.transaction.xa.GlobalTransactionFactory;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Optional;
 import org.testng.annotations.Parameters;
 import org.testng.annotations.Test;
 
@@ -30,10 +32,10 @@
    private String tmpDirectory;
    private GlobalTransactionFactory gts = new GlobalTransactionFactory();
 
-   @BeforeTest
+   @BeforeClass
    @Parameters({"basedir"})
-   protected void setUpTempDir(String basedir) {
-      tmpDirectory = basedir + TestingUtil.TEST_PATH + File.separator + getClass().getSimpleName();
+   protected void setUpTempDir(@Optional("/tmp") String basedir) {
+      tmpDirectory = TestingUtil.tmpDirectory(basedir, this);
    }
 
    @AfterClass

Modified: trunk/cachestore/cloud/src/main/java/org/infinispan/loaders/cloud/CloudCacheStore.java
===================================================================
--- trunk/cachestore/cloud/src/main/java/org/infinispan/loaders/cloud/CloudCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/cloud/src/main/java/org/infinispan/loaders/cloud/CloudCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -32,6 +32,7 @@
 import java.io.ObjectOutput;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -154,6 +155,20 @@
    }
 
    @Override
+   protected Set<InternalCacheEntry> loadLockSafe(int maxEntries) throws CacheLoaderException {
+      Set<InternalCacheEntry> result = new HashSet<InternalCacheEntry>(maxEntries);
+
+      for (Map.Entry<String, Blob> entry : ctx.createBlobMap(containerName).entrySet()) {
+         Bucket bucket = readFromBlob(entry.getValue(), entry.getKey());
+         if (bucket.removeExpiredEntries()) updateBucket(bucket);
+         for (Iterator<? extends InternalCacheEntry> i = bucket.getStoredEntries().iterator(); i.hasNext() && result.size() < maxEntries;)
+            result.add(i.next());
+         if (result.size() >= maxEntries) break;
+      }
+      return result;
+   }
+
+   @Override
    protected void fromStreamLockSafe(ObjectInput objectInput) throws CacheLoaderException {
       String source;
       try {

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DataManipulationHelper.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DataManipulationHelper.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DataManipulationHelper.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -176,6 +176,34 @@
       }
    }
 
+   public final Set<InternalCacheEntry> loadSome(int maxEntries) throws CacheLoaderException {
+      Connection conn = null;
+      PreparedStatement ps = null;
+      ResultSet rs = null;
+      try {
+         String sql = tableManipulation.getLoadSomeRowsSql();
+         if (log.isTraceEnabled()) log.trace("Running sql '" + sql);
+         conn = connectionFactory.getConnection();
+         ps = conn.prepareStatement(sql);
+         ps.setInt(1, maxEntries);
+         rs = ps.executeQuery();
+         rs.setFetchSize(tableManipulation.getFetchSize());
+         Set<InternalCacheEntry> result = new HashSet<InternalCacheEntry>(maxEntries);
+         while (rs.next()) {
+            loadAllProcess(rs, result);
+         }
+         return result;
+      } catch (SQLException e) {
+         String message = "SQL error while fetching all StoredEntries";
+         log.error(message, e);
+         throw new CacheLoaderException(message, e);
+      } finally {
+         JdbcUtil.safeClose(rs);
+         JdbcUtil.safeClose(ps);
+         connectionFactory.releaseConnection(conn);
+      }
+   }
+
    public abstract void loadAllProcess(ResultSet rs, Set<InternalCacheEntry> result) throws SQLException, CacheLoaderException;
 
    public abstract void toStreamProcess(ResultSet rs, InputStream is, ObjectOutput objectOutput) throws CacheLoaderException, SQLException, IOException;

Added: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DatabaseType.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DatabaseType.java	                        (rev 0)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DatabaseType.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -0,0 +1,17 @@
+package org.infinispan.loaders.jdbc;
+
+import java.util.Arrays;
+
+/**
+ * Supported database dialects for the Jdbc cache stores
+ *
+ * @author Manik Surtani
+ * @since 4.1
+ */
+public enum DatabaseType {
+   MYSQL, POSTGRES, DERBY, HSQL, H2, SQLITE,
+   DB2,
+   INFORMIX, INTERBASE, FIREBIRD,
+   SQL_SERVER, ACCESS,
+   ORACLE;
+}


Property changes on: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/DatabaseType.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/TableManipulation.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -21,6 +21,7 @@
  */
 package org.infinispan.loaders.jdbc;
 
+import org.infinispan.config.ConfigurationException;
 import org.infinispan.loaders.CacheLoaderException;
 import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactory;
 import org.infinispan.util.logging.Log;
@@ -31,6 +32,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Arrays;
 import java.util.Locale;
 
 /**
@@ -76,6 +78,8 @@
    private String deleteAllRows;
    private String selectExpiredRowsSql;
    private String deleteExpiredRowsSql;
+   private String loadSomeRowsSql;
+   public DatabaseType databaseType;
 
    public TableManipulation(String idColumnName, String idColumnType, String tableNamePrefix, String dataColumnName,
                             String dataColumnType, String timestampColumnName, String timestampColumnType) {
@@ -417,4 +421,94 @@
       this.cacheName = cacheName;
       this.tableName = null;
    }
+
+   public String getLoadSomeRowsSql() {
+      if (loadSomeRowsSql == null) {
+         // this stuff is going to be database specific!!
+         // see http://stackoverflow.com/questions/595123/is-there-an-ansi-sql-alternative-to-the-mysql-limit-keyword
+
+         switch (getDatabaseType()) {
+            case ORACLE:
+               loadSomeRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName() + " LIMIT ?";
+               break;
+            case DB2:
+               loadSomeRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName() + " LIMIT ?";
+               break;
+            case INFORMIX:
+            case INTERBASE:
+            case FIREBIRD:
+               loadSomeRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName() + " LIMIT ?";
+               break;
+            case SQL_SERVER:
+            case ACCESS:
+               loadSomeRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName() + " LIMIT ?";
+               break;
+            default:
+               // the MySQL-style LIMIT clause
+               loadSomeRowsSql = "SELECT " + dataColumnName + "," + idColumnName + " FROM " + getTableName() + " LIMIT ?";
+               break;
+         }
+
+      }
+      return loadSomeRowsSql;
+   }
+
+   private DatabaseType getDatabaseType() {
+      if (databaseType == null) {
+         // need to guess from the database type!
+         try {
+            String dbProduct = connectionFactory.getConnection().getMetaData().getDatabaseProductName();
+            databaseType = guessDatabaseType(dbProduct);
+         } catch (Exception e) {
+            log.debug("Unable to guess database type from JDBC metadata.", e);
+         }
+         if (databaseType == null) log.info("Unable to detect database type using connection metadata.  Attempting to guess on driver name.");
+         try {
+            String dbProduct = connectionFactory.getConnection().getMetaData().getDriverName();
+            databaseType = guessDatabaseType(dbProduct);
+         } catch (Exception e) {
+            log.debug("Unable to guess database type from JDBC driver name.", e);
+         }
+
+         if (databaseType == null)
+            throw new ConfigurationException("Unable to detect database type from JDBC driver name or connection metadata.  Please provide this manually using the 'databaseType' property in your configuration.  Supported database type strings are " + Arrays.toString(DatabaseType.values()));
+         else
+            log.info("Guessing database type as '" + databaseType + "'.  If this is incorrect, please specify the correct type using the 'databaseType' property in your configuration.  Supported database type strings are " + Arrays.toString(DatabaseType.values()));
+      }
+      return databaseType;
+   }
+
+   private DatabaseType guessDatabaseType(String name) {
+      DatabaseType type = null;
+      if (name != null) {
+         if (name.toLowerCase().contains("mysql"))
+            type = DatabaseType.MYSQL;
+         else if (name.toLowerCase().contains("postgres"))
+            type = DatabaseType.POSTGRES;
+         else if (name.toLowerCase().contains("derby"))
+            type = DatabaseType.DERBY;
+         else if (name.toLowerCase().contains("hsql") || name.toLowerCase().contains("hypersonic"))
+            type = DatabaseType.HSQL;
+         else if (name.toLowerCase().contains("h2"))
+            type = DatabaseType.H2;
+         else if (name.toLowerCase().contains("sqlite"))
+            type = DatabaseType.SQLITE;
+         else if (name.toLowerCase().contains("db2"))
+            type = DatabaseType.DB2;
+         else if (name.toLowerCase().contains("informix"))
+            type = DatabaseType.INFORMIX;
+         else if (name.toLowerCase().contains("interbase"))
+            type = DatabaseType.INTERBASE;
+         else if (name.toLowerCase().contains("firebird"))
+            type = DatabaseType.FIREBIRD;
+         else if (name.toLowerCase().contains("sqlserver") || name.toLowerCase().contains("microsoft"))
+            type = DatabaseType.SQL_SERVER;
+         else if (name.toLowerCase().contains("access"))
+            type = DatabaseType.ACCESS;
+         else if (name.toLowerCase().contains("oracle"))
+            type = DatabaseType.ORACLE;
+      }
+      return type;
+   }
 }
+

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -223,6 +223,11 @@
       return dmHelper.loadAllSupport(false);
    }
 
+   @Override
+   protected Set<InternalCacheEntry> loadLockSafe(int maxEntries) throws CacheLoaderException {
+      return dmHelper.loadSome(maxEntries);
+   }
+
    protected void fromStreamLockSafe(ObjectInput objectInput) throws CacheLoaderException {
       dmHelper.fromStreamSupport(objectInput);
    }

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/binary/JdbcBinaryCacheStoreConfig.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -22,6 +22,7 @@
 package org.infinispan.loaders.jdbc.binary;
 
 import org.infinispan.loaders.LockSupportCacheStoreConfig;
+import org.infinispan.loaders.jdbc.DatabaseType;
 import org.infinispan.loaders.jdbc.TableManipulation;
 import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactoryConfig;
 
@@ -213,4 +214,18 @@
    public int getBatchSize() {
       return this.tableManipulation.getBatchSize();
    }
+
+   public String getDatabaseType() {
+      return this.tableManipulation.databaseType == null ? "" : this.tableManipulation.databaseType.toString();
+   }
+
+   /**
+    * Sets the database dialect.  Valid types are reflected in the DatabaseType enum.  If unspecified, will attempt to
+    * "guess" appropriate dialect from the JDBC driver specified.
+    * @param dbType
+    */
+   public void setDatabaseType(String dbType) {
+      if (dbType != null)
+         this.tableManipulation.databaseType = DatabaseType.valueOf(dbType.toUpperCase().trim());
+   }
 }

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -116,6 +116,19 @@
       return fromBuckets;
    }
 
+   @Override
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      if (numEntries < 0) return loadAll();
+      Set<InternalCacheEntry> fromBuckets = binaryCacheStore.load(numEntries);
+
+      if (fromBuckets.size() < numEntries) {
+         Set<InternalCacheEntry> fromStrings = stringBasedCacheStore.load(numEntries - fromBuckets.size());
+         fromBuckets.addAll(fromStrings);
+      }
+
+      return fromBuckets;
+   }
+
    public void store(InternalCacheEntry ed) throws CacheLoaderException {
       getCacheStore(ed.getKey()).store(ed);
    }

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreConfig.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -23,6 +23,7 @@
 
 import org.infinispan.loaders.AbstractCacheStoreConfig;
 import org.infinispan.loaders.LockSupportCacheStoreConfig;
+import org.infinispan.loaders.jdbc.DatabaseType;
 import org.infinispan.loaders.jdbc.TableManipulation;
 import org.infinispan.loaders.jdbc.binary.JdbcBinaryCacheStoreConfig;
 import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactoryConfig;
@@ -264,6 +265,20 @@
       this.stringsTableManipulation.setBatchSize(batchSize);
    }
 
+   public String getDatabaseType() {
+      return this.binaryTableManipulation.databaseType == null ? "" : this.binaryTableManipulation.databaseType.toString();
+   }
+
+   /**
+    * Sets the database dialect.  Valid types are reflected in the DatabaseType enum.  If unspecified, will attempt to
+    * "guess" appropriate dialect from the JDBC driver specified.
+    * @param dbType
+    */
+   public void setDatabaseType(String dbType) {
+      if (dbType != null)
+         this.binaryTableManipulation.databaseType = DatabaseType.valueOf(dbType.toUpperCase().trim());
+   }
+
    @Override
    public JdbcMixedCacheStoreConfig clone() {
       JdbcMixedCacheStoreConfig dolly = (JdbcMixedCacheStoreConfig) super.clone();

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -220,6 +220,11 @@
    }
 
    @Override
+   protected Set<InternalCacheEntry> loadLockSafe(int maxEntries) throws CacheLoaderException {
+      return dmHelper.loadSome(maxEntries);
+   }
+
+   @Override
    public void purgeInternal() throws CacheLoaderException {
       Connection conn = null;
       PreparedStatement ps = null;

Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreConfig.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -22,6 +22,7 @@
 package org.infinispan.loaders.jdbc.stringbased;
 
 import org.infinispan.loaders.LockSupportCacheStoreConfig;
+import org.infinispan.loaders.jdbc.DatabaseType;
 import org.infinispan.loaders.jdbc.TableManipulation;
 import org.infinispan.loaders.jdbc.connectionfactory.ConnectionFactoryConfig;
 import org.infinispan.util.Util;
@@ -258,6 +259,21 @@
       return this.tableManipulation.getBatchSize();
    }
 
+   public String getDatabaseType() {
+      return this.tableManipulation.databaseType == null ? "" : this.tableManipulation.databaseType.toString();
+   }
+
+   /**
+    * Sets the database dialect.  Valid types are reflected in the DatabaseType enum.  If unspecified, will attempt to
+    * "guess" appropriate dialect from the JDBC driver specified.
+    * @param dbType
+    */
+   public void setDatabaseType(String dbType) {
+      if (dbType != null)
+         this.tableManipulation.databaseType = DatabaseType.valueOf(dbType.toUpperCase().trim());
+   }
+
+
    @Override
    public JdbcStringBasedCacheStoreConfig clone() {
       JdbcStringBasedCacheStoreConfig result = (JdbcStringBasedCacheStoreConfig) super.clone();

Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/mixed/JdbcMixedCacheStoreTest2.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -21,6 +21,8 @@
  */
 package org.infinispan.loaders.jdbc.mixed;
 
+import org.easymock.EasyMock;
+import org.infinispan.Cache;
 import org.infinispan.loaders.BaseCacheStoreTest;
 import org.infinispan.loaders.CacheStore;
 import org.infinispan.loaders.jdbc.TableManipulation;
@@ -43,7 +45,10 @@
       jdbcCacheStoreConfig.setBinaryTableManipulation(binaryTm);
 
       JdbcMixedCacheStore cacheStore = new JdbcMixedCacheStore();
-      cacheStore.init(jdbcCacheStoreConfig, null, getMarshaller());
+      Cache<?, ?> mockCache = EasyMock.createNiceMock(Cache.class);
+      EasyMock.expect(mockCache.getName()).andReturn(getClass().getName()).anyTimes();
+      EasyMock.replay(mockCache);
+      cacheStore.init(jdbcCacheStoreConfig, mockCache, getMarshaller());
       cacheStore.start();
       return cacheStore;
    }

Modified: trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest2.java
===================================================================
--- trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest2.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbc/src/test/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStoreTest2.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -21,6 +21,8 @@
  */
 package org.infinispan.loaders.jdbc.stringbased;
 
+import org.easymock.EasyMock;
+import org.infinispan.Cache;
 import org.infinispan.container.entries.InternalCacheEntry;
 import org.infinispan.container.entries.InternalEntryFactory;
 import org.infinispan.loaders.CacheLoaderException;
@@ -62,7 +64,10 @@
       config.setKey2StringMapperClass(PersonKey2StringMapper.class.getName());
       config.setPurgeSynchronously(true);
       cacheStore = new JdbcStringBasedCacheStore();
-      cacheStore.init(config, null, getMarshaller());
+      Cache<?, ?> mockCache = EasyMock.createNiceMock(Cache.class);
+      EasyMock.expect(mockCache.getName()).andReturn(getClass().getName()).anyTimes();
+      EasyMock.replay(mockCache);
+      cacheStore.init(config, mockCache, getMarshaller());
       cacheStore.start();
    }
 

Modified: trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java
===================================================================
--- trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbm/src/main/java/org/infinispan/loaders/jdbm/JdbmCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -130,7 +130,12 @@
 
    public InternalCacheEntry load(Object key) throws CacheLoaderException {
       try {
-         return unmarshall(tree.get(key), key);
+         InternalCacheEntry ice = unmarshall(tree.get(key), key);
+         if (ice != null && ice.isExpired()) {
+            remove(key);
+            return null;
+         }
+         return ice;
       } catch (IOException e) {
          throw new CacheLoaderException(e);
       } catch (ClassNotFoundException e) {
@@ -142,6 +147,11 @@
       return new BTreeSet();
    }
 
+   @Override
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      return new BTreeSet(numEntries);
+   }
+
    /**
     * Opens all databases and initializes database related information.
     */
@@ -436,6 +446,15 @@
 
    private final class BTreeSet extends AbstractSet<InternalCacheEntry> {
 
+      int maxSize = -1;
+
+      private BTreeSet(int maxSize) {
+         this.maxSize = maxSize;
+      }
+
+      private BTreeSet() {
+      }
+
       @Override
       public Iterator<InternalCacheEntry> iterator() {
          final FastIterator fi;
@@ -446,7 +465,7 @@
          }
 
          return new Iterator<InternalCacheEntry>() {
-
+            int entriesReturned = 0;
             InternalCacheEntry current = null;
             boolean next = true;
 
@@ -465,6 +484,7 @@
                      }
                   }
                }
+               if (next == true && entriesReturned >= maxSize && maxSize > -1) next = false;
                return next;
             }
 
@@ -472,6 +492,7 @@
                if (!hasNext())
                   throw new NoSuchElementException();
                try {
+                  entriesReturned ++;
                   return current;
                } finally {
                   current = null;

Modified: trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreFunctionalTest.java
===================================================================
--- trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreFunctionalTest.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreFunctionalTest.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -27,7 +27,9 @@
 import org.infinispan.loaders.CacheStoreConfig;
 import org.infinispan.test.TestingUtil;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Optional;
 import org.testng.annotations.Parameters;
 import org.testng.annotations.Test;
 
@@ -36,10 +38,10 @@
 
    private String tmpDirectory;
 
-   @BeforeTest
+   @BeforeClass
    @Parameters({"basedir"})
-   protected void setUpTempDir(String basedir) {
-      tmpDirectory = basedir + TestingUtil.TEST_PATH + File.separator + getClass().getSimpleName();
+   protected void setUpTempDir(@Optional("/tmp") String basedir) {
+      tmpDirectory = TestingUtil.tmpDirectory(basedir, this);
    }
 
    @AfterClass

Modified: trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java
===================================================================
--- trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/cachestore/jdbm/src/test/java/org/infinispan/loaders/jdbm/JdbmCacheStoreTest.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -12,6 +12,7 @@
 import org.infinispan.loaders.CacheStore;
 import org.infinispan.test.TestingUtil;
 import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Optional;
 import org.testng.annotations.Parameters;
@@ -23,11 +24,10 @@
    private JdbmCacheStore fcs;
    private String tmpDirectory;
 
-   @BeforeTest
+   @BeforeClass
    @Parameters({"basedir"})
-   protected void setUpTempDir(@Optional(value = "/tmp")String basedir) {
-      tmpDirectory = basedir + File.separator +
-            TestingUtil.TEST_PATH + File.separator + getClass().getSimpleName();
+   protected void setUpTempDir(@Optional("/tmp") String basedir) {
+      tmpDirectory = TestingUtil.tmpDirectory(basedir, this);
    }
 
    @AfterClass

Modified: trunk/core/src/main/java/org/infinispan/eviction/EvictionStrategy.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/eviction/EvictionStrategy.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/eviction/EvictionStrategy.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -10,5 +10,9 @@
    NONE,
    UNORDERED,
    FIFO,
-   LRU
+   LRU;
+   
+   public boolean isEnabled() {
+      return this != NONE;
+   }
 }

Modified: trunk/core/src/main/java/org/infinispan/loaders/CacheLoader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/CacheLoader.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/CacheLoader.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -44,6 +44,15 @@
    Set<InternalCacheEntry> loadAll() throws CacheLoaderException;
 
    /**
+    * Loads up to a specific number of entries.  There is no guarantee as to order of entries loaded.  The set returned
+    * would contain up to a maximum of <tt>numEntries</tt> entries, and no more.
+    * @param numEntries maximum number of entries to load
+    * @return a set of entries, which would contain between 0 and numEntries entries.
+    * @throws CacheLoaderException
+    */
+   Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException;
+
+   /**
     * @param key key to test
     * @return true if the key exists, false otherwise
     * @throws CacheLoaderException in the event of problems reading from source

Modified: trunk/core/src/main/java/org/infinispan/loaders/CacheLoaderManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/CacheLoaderManagerImpl.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/CacheLoaderManagerImpl.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -24,6 +24,7 @@
 import org.infinispan.util.logging.Log;
 import org.infinispan.util.logging.LogFactory;
 
+import java.util.Collections;
 import java.util.Set;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
@@ -120,7 +121,7 @@
             if (log.isDebugEnabled()) start = System.currentTimeMillis();
             Set<InternalCacheEntry> state;
             try {
-               state = loader.loadAll();
+               state = loadState();
             } catch (CacheLoaderException e) {
                throw new CacheException("Unable to preload!", e);
             }
@@ -135,6 +136,24 @@
       }
    }
 
+   private Set<InternalCacheEntry> loadState() throws CacheLoaderException {
+      int ne = -1;
+      if (configuration.getEvictionStrategy().isEnabled()) ne = configuration.getEvictionMaxEntries();
+      Set<InternalCacheEntry> state;
+      switch (ne) {
+         case -1:
+            state = loader.loadAll();
+            break;
+         case 0:
+            state = Collections.emptySet();
+            break;
+         default:
+            state = loader.load(ne);
+            break;
+      }
+      return state;
+   }
+
    @Stop
    public void stop() {
       if (loader != null) try {

Modified: trunk/core/src/main/java/org/infinispan/loaders/LockSupportCacheStore.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/LockSupportCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/LockSupportCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -90,28 +90,34 @@
    }
 
    public final InternalCacheEntry load(Object key) throws CacheLoaderException {
-      if (trace) log.trace("load ({0})", key);
       String lockingKey = getLockFromKey(key);
       lockForReading(lockingKey);
       try {
          return loadLockSafe(key, lockingKey);
       } finally {
          unlock(lockingKey);
-         if (trace) log.trace("Exit load (" + key + ")");
       }
    }
 
    public final Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
-      if (trace) log.trace("loadAll()");
       acquireGlobalLock(false);
       try {
          return loadAllLockSafe();
       } finally {
          releaseGlobalLock(false);
-         if (trace) log.trace("Exit loadAll()");
       }
    }
 
+   public final Set<InternalCacheEntry> load(int maxEntries) throws CacheLoaderException {
+      if (maxEntries < 0) return loadAll();
+      acquireGlobalLock(false);
+      try {
+         return loadLockSafe(maxEntries);
+      } finally {
+         releaseGlobalLock(false);
+      }
+   }
+
    public final void store(InternalCacheEntry ed) throws CacheLoaderException {
       if (trace) log.trace("store(" + ed + ")");
       if (ed == null) return;
@@ -185,6 +191,8 @@
 
    protected abstract Set<InternalCacheEntry> loadAllLockSafe() throws CacheLoaderException;
 
+   protected abstract Set<InternalCacheEntry> loadLockSafe(int maxEntries) throws CacheLoaderException;
+
    protected abstract void toStreamLockSafe(ObjectOutput oos) throws CacheLoaderException;
 
    protected abstract void fromStreamLockSafe(ObjectInput ois) throws CacheLoaderException;

Modified: trunk/core/src/main/java/org/infinispan/loaders/cluster/ClusterCacheLoader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/cluster/ClusterCacheLoader.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/cluster/ClusterCacheLoader.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -27,6 +27,8 @@
 import java.util.List;
 import java.util.Set;
 
+import static java.util.Collections.emptySet;
+
 /**
  * Cache loader that consults other members in the cluster for values. A <code>timeout</code> property is required, a
  * <code>long</code> that specifies in milliseconds how long to wait for results before returning a null.
@@ -66,9 +68,13 @@
 
    @SuppressWarnings(value = "unchecked")
    public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
-      return Collections.emptySet();
+      return emptySet();
    }
 
+   public Set<InternalCacheEntry> load(int maxElems) throws CacheLoaderException {
+      return emptySet();
+   }
+
    public void start() throws CacheLoaderException {
       //nothing to do here
    }

Modified: trunk/core/src/main/java/org/infinispan/loaders/decorators/AbstractDelegatingStore.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/decorators/AbstractDelegatingStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/decorators/AbstractDelegatingStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -90,6 +90,11 @@
       return delegate.loadAll();
    }
 
+   @Override
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      return delegate.load(numEntries);
+   }
+
    public boolean containsKey(Object key) throws CacheLoaderException {
       return delegate.containsKey(key);
    }

Modified: trunk/core/src/main/java/org/infinispan/loaders/decorators/ChainingCacheStore.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/decorators/ChainingCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/decorators/ChainingCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -14,6 +14,7 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -115,6 +116,19 @@
       return set;
    }
 
+   @Override
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      if (numEntries < 0) return loadAll();
+      Set<InternalCacheEntry> set = new HashSet<InternalCacheEntry>(numEntries);
+      for (CacheStore s: stores.keySet()) {
+         Set<InternalCacheEntry> localSet = s.load(numEntries);
+         Iterator<InternalCacheEntry> i = localSet.iterator();
+         while (set.size() < numEntries && i.hasNext()) set.add(i.next());
+         if (set.size() >= numEntries) break;
+      }
+      return set;
+   }
+
    public boolean containsKey(Object key) throws CacheLoaderException {
       for (CacheLoader l : loaders.keySet()) {
          if (l.containsKey(key)) return true;

Modified: trunk/core/src/main/java/org/infinispan/loaders/file/FileCacheStore.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/file/FileCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/main/java/org/infinispan/loaders/file/FileCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -25,6 +25,7 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 /**
@@ -73,6 +74,22 @@
       return result;
    }
 
+   protected Set<InternalCacheEntry> loadLockSafe(int max) throws CacheLoaderException {
+      Set<InternalCacheEntry> result = new HashSet<InternalCacheEntry>(max);
+      for (File bucketFile : root.listFiles()) {
+         Bucket bucket = loadBucket(bucketFile);
+         if (bucket != null) {
+            if (bucket.removeExpiredEntries()) {
+               updateBucket(bucket);
+            }
+            Iterator<? extends InternalCacheEntry> i = bucket.getStoredEntries().iterator();
+            while (result.size() < max && i.hasNext()) result.add(i.next());
+         }
+         if (result.size() >= max) break;
+      }
+      return result;
+   }
+
    protected void fromStreamLockSafe(ObjectInput objectInput) throws CacheLoaderException {
       try {
          int numFiles = objectInput.readInt();

Modified: trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/test/java/org/infinispan/loaders/BaseCacheStoreTest.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -404,6 +404,22 @@
       assert expected.isEmpty();
    }
 
+   public void testPreloadWithMaxSize() throws CacheLoaderException {
+      cs.store(InternalEntryFactory.create("k1", "v1"));
+      cs.store(InternalEntryFactory.create("k2", "v2"));
+      cs.store(InternalEntryFactory.create("k3", "v3"));
+
+      Set<InternalCacheEntry> set = cs.load(2);
+
+      assert set.size() == 2;
+      Set expected = new HashSet();
+      expected.add("k1");
+      expected.add("k2");
+      expected.add("k3");
+      for (InternalCacheEntry se : set) assert expected.remove(se.getKey());
+      assert expected.size() == 1;
+   }
+
    public void testStoreAndRemoveAll() throws CacheLoaderException {
       cs.store(InternalEntryFactory.create("k1", "v1"));
       cs.store(InternalEntryFactory.create("k2", "v2"));

Modified: trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java	2010-03-10 11:17:38 UTC (rev 1583)
+++ trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java	2010-03-10 13:42:39 UTC (rev 1584)
@@ -109,6 +109,21 @@
       return s;
    }
 
+   public Set<InternalCacheEntry> load(int numEntries) throws CacheLoaderException {
+      if (numEntries < 0) return loadAll();
+      Set<InternalCacheEntry> s = new HashSet<InternalCacheEntry>(numEntries);
+      for (Iterator<InternalCacheEntry> i = store.values().iterator(); i.hasNext() && s.size() < numEntries;) {
+         InternalCacheEntry se = i.next();
+         if (se.isExpired()) {
+            log.debug("Key {0} exists, but has expired.  Entry is {1}", se.getKey(), se);
+            i.remove();
+         } else if (s.size() < numEntries) {
+            s.add(se);
+         }
+      }
+      return s;
+   }
+
    public Class<? extends CacheLoaderConfig> getConfigurationClass() {
       return Cfg.class;
    }



More information about the infinispan-commits mailing list