diff options
author | Bernard Normier <bernard@zeroc.com> | 2007-11-16 14:49:07 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2007-11-16 14:49:07 -0500 |
commit | 340886aa0e34e47099009c155d0de48522b25a87 (patch) | |
tree | cdac947ca5add954e84c103e02fd13b30905d9c1 /java/src | |
parent | Merge branch 'master' of ssh://cvs.zeroc.com/home/git/ice (diff) | |
download | ice-340886aa0e34e47099009c155d0de48522b25a87.tar.bz2 ice-340886aa0e34e47099009c155d0de48522b25a87.tar.xz ice-340886aa0e34e47099009c155d0de48522b25a87.zip |
Recreate implementation in Java
Diffstat (limited to 'java/src')
-rw-r--r-- | java/src/Freeze/Map.java | 237 | ||||
-rwxr-xr-x | java/src/Freeze/SharedDb.java | 262 |
2 files changed, 389 insertions, 110 deletions
diff --git a/java/src/Freeze/Map.java b/java/src/Freeze/Map.java index 63e9a9a1f8f..0a66a4b3f48 100644 --- a/java/src/Freeze/Map.java +++ b/java/src/Freeze/Map.java @@ -15,7 +15,7 @@ public abstract class Map extends java.util.AbstractMap public abstract byte[] encodeValue(Object o, Ice.Communicator communicator); public abstract Object decodeValue(byte[] b, Ice.Communicator communicator); - public + protected Map(Connection connection, String dbName, String key, String value, boolean createDb, java.util.Comparator comparator) { @@ -38,13 +38,235 @@ public abstract class Map extends java.util.AbstractMap _trace = _connection.trace(); } + + protected static void + recreate(Map map, String dbName, String key, String value, + Freeze.Map.Index[] indices, java.util.Map indexComparators) + { + ConnectionI connection = map._connection; + String envName = connection.dbEnv().getEnvName(); + + if(dbName.equals(Util.catalogName()) || dbName.equals(Util.catalogIndexListName())) + { + throw new DatabaseException(errorPrefix(envName, dbName) + "You cannot destroy recreate the \"" + + dbName + "\" database"); + } + + if(connection.trace() >= 1) + { + connection.communicator().getLogger().trace("Freeze.Map", + "Recreating \"" + dbName + "\""); + } + + Transaction tx = connection.currentTransaction(); + boolean ownTx = (tx == null); + + com.sleepycat.db.DatabaseEntry keyEntry = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry valueEntry = new com.sleepycat.db.DatabaseEntry(); + + com.sleepycat.db.Database oldDb = null; + SharedDb newDb = null; + + for(;;) + { + try + { + if(ownTx) + { + tx = null; + tx = connection.beginTransaction(); + } + + com.sleepycat.db.Transaction txn = connection.dbTxn(); + + if(connection.trace() >= 2) + { + connection.communicator().getLogger().trace( + "Freeze.Map", "Removing all existing indices for \"" + dbName + "\""); + } + CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true); + String[] oldIndices = (String[])catalogIndexList.remove(dbName); + + + if(oldIndices != null) + { + for(int i = 0; i < oldIndices.length; ++i) + { + try + { + connection.removeMapIndex(dbName, oldIndices[i]); + } + catch(IndexNotFoundException e) + { + // + // Ignored + // + } + } + } + + // + // Rename existing database + // + String oldDbName = dbName + ".old-" + Ice.Util.generateUUID(); + + if(connection.trace() >= 2) + { + connection.communicator().getLogger().trace( + "Freeze.Map", "Renaming \"" + dbName + "\" to \"" + oldDbName + "\""); + } + + connection.dbEnv().getEnv().renameDatabase(txn, dbName, null, oldDbName); + + com.sleepycat.db.DatabaseConfig oldDbConfig = new com.sleepycat.db.DatabaseConfig(); + oldDbConfig.setType(com.sleepycat.db.DatabaseType.BTREE); + + oldDb = connection.dbEnv().getEnv().openDatabase(txn, oldDbName, null, oldDbConfig); + + newDb = SharedDb.create(connection, dbName, key, value, indices, map._comparator, indexComparators); + map.init(newDb, indices); + + + if(connection.trace() >= 2) + { + connection.communicator().getLogger().trace( + "Freeze.Map", "Writing contents of \"" + oldDbName + "\" to fresh \"" + dbName + "\""); + } + + // + // Now simply write all of oldDb into newDb + // + com.sleepycat.db.Cursor dbc = null; + try + { + dbc = oldDb.openCursor(txn, null); + + while(dbc.getNext(keyEntry, valueEntry, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + newDb.db().put(txn, keyEntry, valueEntry); + } + } + finally + { + if(dbc != null) + { + dbc.close(); + } + } + + if(connection.trace() >= 2) + { + connection.communicator().getLogger().trace( + "Freeze.Map", "Transfer complete; removing \"" + oldDbName + "\""); + } + connection.dbEnv().getEnv().removeDatabase(txn, oldDbName, null); + + if(ownTx) + { + try + { + tx.commit(); + } + finally + { + tx = null; + } + } + + break; // for (;;) + } + catch(com.sleepycat.db.DeadlockException dx) + { + if(ownTx) + { + if(connection.deadlockWarning()) + { + connection.communicator().getLogger().warning( + "Deadlock in Freeze.Map.recreate on Db \"" + + dbName + "\"; retrying ..."); + } + + // + // Ignored, try again + // + } + else + { + DeadlockException ex = new DeadlockException(errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException(errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + catch(java.io.FileNotFoundException fne) + { + DatabaseException ex = new DatabaseException(errorPrefix(envName, dbName) + "Map.recreate: " + fne.getMessage()); + ex.initCause(fne); + throw ex; + } + finally + { + if(ownTx && tx != null) + { + try + { + tx.rollback(); + } + catch(DatabaseException de) + { + } + } + + try + { + if(newDb != null) + { + newDb.close(); + } + + if(oldDb != null) + { + try + { + oldDb.close(); + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException( + errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + } + } + finally + { + newDb = null; + oldDb = null; + } + } + } + } + + protected void init(Freeze.Map.Index[] indices, String dbName, String key, String value, boolean createDb, java.util.Map indexComparators) { - _db = Freeze.SharedDb.get(_connection, dbName, key, - value, indices, createDb, _comparator, - indexComparators); + init(SharedDb.get(_connection, dbName, key, + value, indices, createDb, _comparator, + indexComparators), indices); + } + + protected void + init(SharedDb db, Freeze.Map.Index[] indices) + { + _db = db; _token = _connection.registerMap(this); if(indices != null) @@ -56,6 +278,7 @@ public abstract class Map extends java.util.AbstractMap } } + public void close() { @@ -820,6 +1043,12 @@ public abstract class Map extends java.util.AbstractMap return _connection; } + private static String + errorPrefix(String envName, String dbName) + { + return "Freeze DB DbEnv(\"" + envName + "\") Db(\"" + dbName + "\"): "; + } + private static boolean valEquals(Object o1, Object o2) { diff --git a/java/src/Freeze/SharedDb.java b/java/src/Freeze/SharedDb.java index 6b95e819b2e..c212510c309 100755 --- a/java/src/Freeze/SharedDb.java +++ b/java/src/Freeze/SharedDb.java @@ -41,21 +41,21 @@ class SharedDb SharedDb result = (SharedDb)_map.get(mapKey); if(result == null) { + ConnectionI insertConnection = (ConnectionI)Util.createConnection(mapKey.communicator, mapKey.envName); + try { - result = new SharedDb(mapKey, key, value, connection, + result = new SharedDb(mapKey, key, value, insertConnection, indices, createDb, comparator, indexComparators); } - catch(com.sleepycat.db.DatabaseException dx) + finally { - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = errorPrefix(mapKey) + "creation: " + dx.getMessage(); - throw ex; + insertConnection.close(); } Object previousValue = _map.put(mapKey, result); assert(previousValue == null); + result._inMap = true; } else { @@ -66,6 +66,19 @@ class SharedDb return result; } } + + public static SharedDb + create(ConnectionI connection, String dbName, String key, String value, + Map.Index[] indices, java.util.Comparator comparator, + java.util.Map indexComparators) + { + + MapKey mapKey = new MapKey(connection.envName(), connection.communicator(), dbName); + + return new SharedDb(mapKey, key, value, connection, + indices, true, comparator, indexComparators); + + } public static SharedDb[] openCatalogs(SharedDbEnv dbEnv) @@ -139,12 +152,17 @@ class SharedDb synchronized(_map) { if(--_refCount == 0) - { - // - // Remove from map - // - Object value = _map.remove(_mapKey); - assert(value == this); + { + + if(_inMap) + { + // + // Remove from map + // + + Object value = _map.remove(_mapKey); + assert(value == this); + } if(_trace >= 1) { @@ -180,120 +198,126 @@ class SharedDb private SharedDb(MapKey mapKey, String key, String value, ConnectionI connection, Map.Index[] indices, boolean createDb, java.util.Comparator comparator, java.util.Map indexComparators) - throws com.sleepycat.db.DatabaseException { _mapKey = mapKey; _indices = indices; _trace = connection.trace(); - Connection catalogConnection = Util.createConnection(_mapKey.communicator, connection.dbEnv().getEnvName()); - - try + + Catalog catalog = new Catalog(connection, Util.catalogName(), true); + CatalogData catalogData = (CatalogData)catalog.get(_mapKey.dbName); + if(catalogData != null) { - Catalog catalog = new Catalog(catalogConnection, Util.catalogName(), true); - CatalogData catalogData = (CatalogData)catalog.get(_mapKey.dbName); - if(catalogData != null) - { - if(catalogData.evictor) - { - DatabaseException ex = new DatabaseException(); - ex.message = errorPrefix(_mapKey) + "is not an evictor"; - throw ex; - } - _key = catalogData.key; - _value = catalogData.value; - checkTypes(this, key, value); - } - else + if(catalogData.evictor) { - _key = key; - _value = value; + DatabaseException ex = new DatabaseException(); + ex.message = errorPrefix(_mapKey) + "is not an evictor"; + throw ex; } + _key = catalogData.key; + _value = catalogData.value; + checkTypes(this, key, value); + } + else + { + _key = key; + _value = value; + } - com.sleepycat.db.DatabaseConfig config = new com.sleepycat.db.DatabaseConfig(); + com.sleepycat.db.DatabaseConfig config = new com.sleepycat.db.DatabaseConfig(); - config.setAllowCreate(createDb); - config.setType(com.sleepycat.db.DatabaseType.BTREE); + config.setAllowCreate(createDb); + config.setType(com.sleepycat.db.DatabaseType.BTREE); - if(comparator != null) - { - config.setBtreeComparator(comparator); - } - Ice.Properties properties = _mapKey.communicator.getProperties(); - String propPrefix = "Freeze.Map." + _mapKey.dbName + "."; + if(comparator != null) + { + config.setBtreeComparator(comparator); + } + Ice.Properties properties = _mapKey.communicator.getProperties(); + String propPrefix = "Freeze.Map." + _mapKey.dbName + "."; - int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey"); - if(btreeMinKey > 2) + int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey"); + if(btreeMinKey > 2) + { + if(_trace >= 1) { - if(_trace >= 1) - { - _mapKey.communicator.getLogger().trace( - "Freeze.Map", "Setting \"" + _mapKey.dbName + "\"'s btree minkey to " + btreeMinKey); - } - config.setBtreeMinKey(btreeMinKey); + _mapKey.communicator.getLogger().trace( + "Freeze.Map", "Setting \"" + _mapKey.dbName + "\"'s btree minkey to " + btreeMinKey); } + config.setBtreeMinKey(btreeMinKey); + } - boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; - if(checksum) + boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; + if(checksum) + { + if(_trace >= 1) { - if(_trace >= 1) - { - _mapKey.communicator.getLogger().trace( - "Freeze.Map", "Turning checksum on for \"" + _mapKey.dbName + "\""); - } - - config.setChecksum(true); + _mapKey.communicator.getLogger().trace( + "Freeze.Map", "Turning checksum on for \"" + _mapKey.dbName + "\""); } + + config.setChecksum(true); + } - int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); - if(pageSize > 0) + int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); + if(pageSize > 0) + { + if(_trace >= 1) { - if(_trace >= 1) - { - _mapKey.communicator.getLogger().trace( - "Freeze.Map", "Setting \"" + _mapKey.dbName + "\"'s pagesize to " + pageSize); - } - config.setPageSize(pageSize); + _mapKey.communicator.getLogger().trace( + "Freeze.Map", "Setting \"" + _mapKey.dbName + "\"'s pagesize to " + pageSize); } + config.setPageSize(pageSize); + } + + if(_trace >= 1) + { + _mapKey.communicator.getLogger().trace("Freeze.Map", "opening Db \"" + _mapKey.dbName + "\""); + } + Transaction tx = connection.currentTransaction(); + boolean ownTx = (tx == null); + + for(;;) + { try { - Transaction tx = catalogConnection.beginTransaction(); - com.sleepycat.db.Transaction txn = Util.getTxn(tx); - - if(_trace >= 1) + if(ownTx) { - _mapKey.communicator.getLogger().trace("Freeze.Map", "opening Db \"" + _mapKey.dbName + "\""); + tx = null; + tx = connection.beginTransaction(); } - + + com.sleepycat.db.Transaction txn = Util.getTxn(tx); + _db = connection.dbEnv().getEnv().openDatabase(txn, mapKey.dbName, null, config); - + String[] oldIndices = null; java.util.List<String> newIndices = new java.util.LinkedList<String>(); - - CatalogIndexList catalogIndexList = new CatalogIndexList(catalogConnection, Util.catalogIndexListName(), true); - + + CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true); + if(createDb) { oldIndices = (String[])catalogIndexList.get(_mapKey.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(mapKey.dbName, _db, txn, createDb, indexComparator); - + if(createDb) { if(oldIndices != null) @@ -308,7 +332,7 @@ class SharedDb } } } - + if(catalogData == null) { catalogData = new CatalogData(); @@ -317,11 +341,11 @@ class SharedDb catalogData.value = value; catalog.put(_mapKey.dbName, catalogData); } - + if(createDb) { boolean indexRemoved = false; - + if(oldIndices != null) { // @@ -337,17 +361,17 @@ class SharedDb _mapKey.communicator.getLogger().trace( "Freeze.Map", "removing old index \"" + index + "\" on Db \"" + _mapKey.dbName + "\""); } - + indexRemoved = true; - + try { - catalogConnection.removeMapIndex(mapKey.dbName, index); + connection.removeMapIndex(mapKey.dbName, index); } catch(IndexNotFoundException ife) { // Ignored - + if(_trace >= 1) { _mapKey.communicator.getLogger().trace( @@ -357,9 +381,9 @@ class SharedDb } } } - + int oldSize = oldIndices == null ? 0 : oldIndices.length; - + if(indexRemoved || newIndices.size() != oldSize) { if(newIndices.size() == 0) @@ -370,22 +394,32 @@ class SharedDb _mapKey.communicator.getLogger().trace( "Freeze.Map", "Removed catalogIndexList entry for Db \"" + _mapKey.dbName + "\""); } - + } else { catalogIndexList.put(_mapKey.dbName, newIndices.toArray(new String[0])); if(_trace >= 1) { - _mapKey.communicator.getLogger().trace( - "Freeze.Map", "Updated catalogIndexList entry for Db \"" + _mapKey.dbName + "\""); + _mapKey.communicator.getLogger().trace( + "Freeze.Map", "Updated catalogIndexList entry for Db \"" + _mapKey.dbName + "\""); } } } } - - tx.commit(); + if(ownTx) + { + try + { + tx.commit(); + } + finally + { + tx = null; + } + } + break; // for(;;) // // TODO: FREEZE_DB_MODE @@ -399,6 +433,26 @@ class SharedDb ex.message = errorPrefix(_mapKey) + "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 \"" + + mapKey.dbName + "\"; retrying ..."); + } + tx = null; + } + else + { + cleanupIndices(); + DeadlockException ex = new DeadlockException(errorPrefix(_mapKey) + "Db.open: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + } catch(com.sleepycat.db.DatabaseException dx) { cleanupIndices(); @@ -409,8 +463,7 @@ class SharedDb } finally { - Transaction tx = catalogConnection.currentTransaction(); - if(tx != null) + if(ownTx && tx != null) { try { @@ -422,13 +475,9 @@ class SharedDb } } } - finally - { - catalogConnection.close(); - } - _refCount = 1; } + private SharedDb(MapKey mapKey, String key, String value, com.sleepycat.db.Environment dbEnv) throws com.sleepycat.db.DatabaseException @@ -562,9 +611,10 @@ class SharedDb private int _refCount = 0; private int _trace; private Map.Index[] _indices; + private boolean _inMap = false; - // - // Hash map of (MapKey, SharedDb) - // +// +// Hash map of (MapKey, SharedDb) +// private static java.util.Map _map = new java.util.HashMap(); } |