diff options
author | Bernard Normier <bernard@zeroc.com> | 2007-12-12 12:03:04 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2007-12-12 12:03:04 -0500 |
commit | 28c22de9b812daeffa630656818da6ec5411a7da (patch) | |
tree | a3b5142c2144ead6aafb62dd71baf0657296e014 /java/src/Freeze/MapDb.java | |
parent | Fixed bug #2546 (diff) | |
download | ice-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-x | java/src/Freeze/MapDb.java | 433 |
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; +} |