summaryrefslogtreecommitdiff
path: root/java/src/Freeze/MapDb.java
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2007-12-12 12:03:04 -0500
committerBernard Normier <bernard@zeroc.com>2007-12-12 12:03:04 -0500
commit28c22de9b812daeffa630656818da6ec5411a7da (patch)
treea3b5142c2144ead6aafb62dd71baf0657296e014 /java/src/Freeze/MapDb.java
parentFixed bug #2546 (diff)
downloadice-28c22de9b812daeffa630656818da6ec5411a7da.tar.bz2
ice-28c22de9b812daeffa630656818da6ec5411a7da.tar.xz
ice-28c22de9b812daeffa630656818da6ec5411a7da.zip
Fixed bug #2557 (closing database within transaction)
Diffstat (limited to 'java/src/Freeze/MapDb.java')
-rwxr-xr-xjava/src/Freeze/MapDb.java433
1 files changed, 433 insertions, 0 deletions
diff --git a/java/src/Freeze/MapDb.java b/java/src/Freeze/MapDb.java
new file mode 100755
index 00000000000..8579b670870
--- /dev/null
+++ b/java/src/Freeze/MapDb.java
@@ -0,0 +1,433 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Freeze;
+
+//
+// A MapDb represents the Db object underneath Freeze Maps. Several Freeze Maps often
+// share the very same MapDb object; SharedDbEnv manages these shared MapDb objects.
+//
+
+class MapDb
+{
+
+ MapDb(ConnectionI connection, String dbName, String key, String value,
+ java.util.Comparator comparator, Map.Index[] indices, java.util.Map indexComparators,
+ boolean createDb)
+ {
+ _communicator = connection.communicator();
+ _dbName = dbName;
+ _errorPrefix = "Freeze DB DbEnv(\"" + connection.dbEnv().getEnvName() + "\") Db(\"" + dbName + "\"): ";
+ _indices = indices;
+ _trace = connection.trace();
+
+ Catalog catalog = new Catalog(connection, Util.catalogName(), true);
+ CatalogData catalogData = (CatalogData)catalog.get(_dbName);
+ if(catalogData != null)
+ {
+ if(catalogData.evictor)
+ {
+ throw new DatabaseException(_errorPrefix + "is not an evictor");
+ }
+ _key = catalogData.key;
+ _value = catalogData.value;
+ checkTypes(key, value);
+ }
+ else
+ {
+ _key = key;
+ _value = value;
+ }
+
+ com.sleepycat.db.DatabaseConfig config = new com.sleepycat.db.DatabaseConfig();
+
+
+ config.setAllowCreate(createDb);
+ config.setType(com.sleepycat.db.DatabaseType.BTREE);
+
+ if(comparator != null)
+ {
+ config.setBtreeComparator(comparator);
+ }
+ Ice.Properties properties = _communicator.getProperties();
+ String propPrefix = "Freeze.Map." + _dbName + ".";
+
+ int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey");
+ if(btreeMinKey > 2)
+ {
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "Setting \"" + _dbName + "\"'s btree minkey to " + btreeMinKey);
+ }
+ config.setBtreeMinKey(btreeMinKey);
+ }
+
+ boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0;
+ if(checksum)
+ {
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "Turning checksum on for \"" + _dbName + "\"");
+ }
+
+ config.setChecksum(true);
+ }
+
+ int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize");
+ if(pageSize > 0)
+ {
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "Setting \"" + _dbName + "\"'s pagesize to " + pageSize);
+ }
+ config.setPageSize(pageSize);
+ }
+
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace("Freeze.Map", "opening Db \"" + _dbName + "\"");
+ }
+
+ Transaction tx = connection.currentTransaction();
+ boolean ownTx = (tx == null);
+
+ for(;;)
+ {
+ try
+ {
+ if(ownTx)
+ {
+ tx = null;
+ tx = connection.beginTransaction();
+ }
+
+ com.sleepycat.db.Transaction txn = Util.getTxn(tx);
+
+ _db = connection.dbEnv().getEnv().openDatabase(txn, _dbName, null, config);
+
+ String[] oldIndices = null;
+ java.util.List<String> newIndices = new java.util.LinkedList<String>();
+
+ CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true);
+
+ if(createDb)
+ {
+ oldIndices = (String[])catalogIndexList.get(_dbName);
+ }
+
+
+ if(_indices != null)
+ {
+ for(int i = 0; i < _indices.length; ++i)
+ {
+ String indexName = _indices[i].name();
+
+ java.util.Comparator indexComparator = null;
+ if(indexComparators != null)
+ {
+ indexComparator = (java.util.Comparator)indexComparators.get(indexName);
+ }
+
+ _indices[i].associate(_dbName, _db, txn, createDb, indexComparator);
+
+ if(createDb)
+ {
+ if(oldIndices != null)
+ {
+ int j = java.util.Arrays.asList(oldIndices).indexOf(indexName);
+ if(j != -1)
+ {
+ oldIndices[j] = null;
+ }
+ }
+ newIndices.add(indexName);
+ }
+ }
+ }
+
+ if(catalogData == null)
+ {
+ catalogData = new CatalogData();
+ catalogData.evictor = false;
+ catalogData.key = key;
+ catalogData.value = value;
+ catalog.put(_dbName, catalogData);
+ }
+
+ if(createDb)
+ {
+ boolean indexRemoved = false;
+
+ if(oldIndices != null)
+ {
+ //
+ // Remove old indices and write the new ones
+ //
+ for(int i = 0; i < oldIndices.length; ++i)
+ {
+ String index = oldIndices[i];
+ if(index != null)
+ {
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "removing old index \"" + index + "\" on Db \"" + _dbName + "\"");
+ }
+
+ indexRemoved = true;
+
+ try
+ {
+ connection.removeMapIndex(_dbName, index);
+ }
+ catch(IndexNotFoundException ife)
+ {
+ // Ignored
+
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "index \"" + index + "\" on Db \"" + _dbName + "\" does not exist");
+ }
+ }
+ }
+ }
+ }
+
+ int oldSize = oldIndices == null ? 0 : oldIndices.length;
+
+ if(indexRemoved || newIndices.size() != oldSize)
+ {
+ if(newIndices.size() == 0)
+ {
+ catalogIndexList.remove(_dbName);
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "Removed catalogIndexList entry for Db \"" + _dbName + "\"");
+ }
+
+ }
+ else
+ {
+ catalogIndexList.put(_dbName, newIndices.toArray(new String[0]));
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace(
+ "Freeze.Map", "Updated catalogIndexList entry for Db \"" + _dbName + "\"");
+ }
+ }
+ }
+ }
+
+ if(ownTx)
+ {
+ try
+ {
+ tx.commit();
+ }
+ finally
+ {
+ tx = null;
+ }
+ }
+ break; // for(;;)
+ }
+ catch(java.io.FileNotFoundException dx)
+ {
+ clearIndices();
+ NotFoundException ex = new NotFoundException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Db.open: " + dx.getMessage();
+ throw ex;
+ }
+ catch(com.sleepycat.db.DeadlockException dx)
+ {
+ if(ownTx)
+ {
+ if(connection.deadlockWarning())
+ {
+ connection.communicator().getLogger().warning(
+ "Deadlock in Freeze.Shared.Shared on Db \""
+ + _dbName + "\"; retrying ...");
+ }
+ tx = null;
+ }
+ else
+ {
+ clearIndices();
+ DeadlockException ex = new DeadlockException(_errorPrefix + "Db.open: " + dx.getMessage(), tx);
+ ex.initCause(dx);
+ throw ex;
+ }
+ }
+ catch(com.sleepycat.db.DatabaseException dx)
+ {
+ clearIndices();
+ DatabaseException ex = new DatabaseException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Db.open: " + dx.getMessage();
+ throw ex;
+ }
+ finally
+ {
+ if(ownTx && tx != null)
+ {
+ try
+ {
+ tx.rollback();
+ }
+ catch(DatabaseException de)
+ {
+ }
+ }
+ }
+ }
+ }
+
+
+ //
+ // The constructor for catalogs
+ //
+
+ MapDb(Ice.Communicator communicator, String envName, String dbName, String key, String value,
+ com.sleepycat.db.Environment dbEnv)
+ throws com.sleepycat.db.DatabaseException
+ {
+ _communicator = communicator;
+ _dbName = dbName;
+ _errorPrefix = "Freeze DB DbEnv(\"" + envName + "\") Db(\"" + dbName + "\"): ";
+ _key = key;
+ _value = value;
+ _trace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Map");
+
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace("Freeze.Map", "opening Db \"" + _dbName + "\"");
+ }
+
+ com.sleepycat.db.DatabaseConfig config = new com.sleepycat.db.DatabaseConfig();
+ config.setAllowCreate(true);
+ config.setType(com.sleepycat.db.DatabaseType.BTREE);
+ config.setTransactional(true);
+
+ try
+ {
+ _db = dbEnv.openDatabase(null, _dbName, null, config);
+ }
+ catch(java.io.FileNotFoundException dx)
+ {
+ //
+ // This should never happen
+ //
+ NotFoundException ex = new NotFoundException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Db.open: " + dx.getMessage();
+ throw ex;
+ }
+ }
+
+ void close()
+ {
+ if(_trace >= 1)
+ {
+ _communicator.getLogger().trace("Freeze.Map", "closing Db \"" + _dbName + "\"");
+ }
+
+ clearIndices();
+
+ if(_db != null)
+ {
+ try
+ {
+ _db.close();
+ }
+ catch(com.sleepycat.db.DatabaseException dx)
+ {
+ DatabaseException ex = new DatabaseException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "close: " + dx.getMessage();
+ throw ex;
+ }
+ finally
+ {
+ _db = null;
+ }
+ }
+ }
+
+
+ void
+ connectIndices(Map.Index[] indices)
+ {
+ if(indices != null)
+ {
+ assert(_indices != null && indices.length == _indices.length);
+
+ for(int i = 0; i < indices.length; ++i)
+ {
+ indices[i].init(_indices[i]);
+ }
+ }
+ }
+
+ void
+ clearIndices()
+ {
+ if(_indices != null)
+ {
+ for(int i = 0; i < _indices.length; ++i)
+ {
+ _indices[i].close();
+ }
+ _indices = null;
+ }
+ }
+
+
+ com.sleepycat.db.Database
+ db()
+ {
+ return _db;
+ }
+
+ String
+ dbName()
+ {
+ return _dbName;
+ }
+
+ void
+ checkTypes(String key, String value)
+ {
+ if(!key.equals(_key))
+ {
+ throw new DatabaseException(_errorPrefix + _dbName + "'s key type is " + _key +
+ ", not " + key);
+ }
+
+ if(!value.equals(_value))
+ {
+ throw new DatabaseException(_errorPrefix + _dbName + "'s value type is " + _value +
+ ", not " + value);
+ }
+ }
+
+ private com.sleepycat.db.Database _db;
+ private final Ice.Communicator _communicator;
+ private final String _dbName;
+ private final String _errorPrefix;
+ private String _key;
+ private String _value;
+ private final int _trace;
+ private Map.Index[] _indices;
+}