diff options
author | Bernard Normier <bernard@zeroc.com> | 2003-07-18 19:47:14 +0000 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2003-07-18 19:47:14 +0000 |
commit | 3c02842b6143c6ce9297feecd7c9497312c76da8 (patch) | |
tree | 478210bed985772e2957ee0a65b9cd3f5f390234 /java/src/Freeze/Map.java | |
parent | use lazy initialization of communicator for each request (diff) | |
download | ice-3c02842b6143c6ce9297feecd7c9497312c76da8.tar.bz2 ice-3c02842b6143c6ce9297feecd7c9497312c76da8.tar.xz ice-3c02842b6143c6ce9297feecd7c9497312c76da8.zip |
Major Freeze update
Diffstat (limited to 'java/src/Freeze/Map.java')
-rw-r--r-- | java/src/Freeze/Map.java | 1094 |
1 files changed, 785 insertions, 309 deletions
diff --git a/java/src/Freeze/Map.java b/java/src/Freeze/Map.java index 5ca1bd5560e..af0272e68f0 100644 --- a/java/src/Freeze/Map.java +++ b/java/src/Freeze/Map.java @@ -17,10 +17,62 @@ package Freeze; public abstract class Map extends java.util.AbstractMap { public - Map(DB db) + Map(Ice.Communicator communicator, String envName, String dbName, boolean createDb) { - _db = db; - _communicator = db.getCommunicator(); + _communicator = communicator; + _dbEnvHolder = SharedDbEnv.get(communicator, envName); + _dbEnv = _dbEnvHolder; + _dbName = dbName; + _errorPrefix = "Freeze DB DbEnv(\"" + envName + "\") Db(\"" + dbName + "\") :"; + + openDb(createDb); + } + + public + Map(Ice.Communicator communicator, com.sleepycat.db.DbEnv dbEnv, String dbName, boolean createDb) + { + _communicator = communicator; + _dbEnvHolder = null; + _dbEnv = dbEnv; + _dbName = dbName; + _errorPrefix = "Freeze DB DbEnv(\"External\") Db(\"" + dbName + "\") :"; + + openDb(createDb); + } + + public void + close() + { + if(_db != null) + { + try + { + _db.close(0); + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.stat: " + e.getMessage(); + throw ex; + } + finally + { + _db = null; + } + } + + if(_dbEnvHolder != null) + { + try + { + _dbEnvHolder.close(); + } + finally + { + _dbEnvHolder = null; + } + } } // @@ -36,14 +88,12 @@ public abstract class Map extends java.util.AbstractMap public int size() { - // - // It's not necessary to close outstanding iterators. - // - // If it was it would be a problem - it doesn't change the Map - // - therefore open iterators should not be invalidated - // (according the Java spec). - // - // closeIterators(); + if(_db == null) + { + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } // // The number of records cannot be cached and then adjusted by @@ -52,130 +102,178 @@ public abstract class Map extends java.util.AbstractMap // the size adjusted) and the transaction aborted then the // cached map size() would be incorrect. // - return (int)_db.getNumberOfRecords(); + + // + // TODO: DB_FAST_STAT doesn't seem to do what the + // documentation says... + // + try + { + com.sleepycat.db.DbBtreeStat s = (com.sleepycat.db.DbBtreeStat)_db.stat(0); + return s.bt_ndata; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.stat: " + e.getMessage(); + throw ex; + } } public boolean containsValue(Object value) { - // - // It's not necessary to close outstanding iterators. - // - // If it was it would be a problem - it doesn't change the Map - // - therefore open iterators should not be invalidated - // (according the Java spec). - // - // closeIterators(); - - EntryIterator p = (EntryIterator)entrySet().iterator(); - if(value == null) + for(;;) { - while(p.hasNext()) + EntryIterator p = null; + try { - Entry e = (Entry)p.next(); - if(e.getValue() == null) + p = (EntryIterator)entrySet().iterator(); + + if(value == null) { - return true; + while(p.hasNext()) + { + Entry e = (Entry)p.next(); + if(e.getValue() == null) + { + p.close(); + return true; + } + } + } + else + { + while(p.hasNext()) + { + Entry e = (Entry)p.next(); + if(value.equals(e.getValue())) + { + p.close(); + return true; + } + } } + return false; } - } - else - { - while(p.hasNext()) + catch(DBDeadlockException ex) + { + // + // Try again + // + } + finally { - Entry e = (Entry)p.next(); - if(value.equals(e.getValue())) + if(p != null) { - return true; + p.close(); } } } - p.close(); - - return false; } public boolean containsKey(Object key) { - // - // It's not necessary to close outstanding iterators. - // - // If it was it would be a problem - it doesn't change the Map - // - therefore open iterators should not be invalidated - // (according the Java spec). - // - //closeIterators(); + if(_db == null) + { + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } byte[] k = encodeKey(key, _communicator); - return _db.contains(k); + + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(); + dbValue.set_flags(com.sleepycat.db.Db.DB_DBT_PARTIAL); + + if(_trace >= 1) + { + _communicator.getLogger().trace("DB", "checking key in database \"" + _dbName + "\""); + } + + for(;;) + { + try + { + int rc = _db.get(null, dbKey, dbValue, 0); + if(rc == com.sleepycat.db.Db.DB_NOTFOUND) + { + return false; + } + else + { + assert(rc == 0); + return true; + } + } + catch(com.sleepycat.db.DbDeadlockException e) + { + // + // Try again + // + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.get: " + e.getMessage(); + throw ex; + } + } } public Object get(Object key) { - // - // It's not necessary to close outstanding iterators. - // - // If it was it would be a problem - it doesn't change the Map - // - therefore open iterators should not be invalidated - // (according the Java spec). - // - //closeIterators(); - byte[] k = encodeKey(key, _communicator); - try + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + byte[] v = getImpl(dbKey); + if(v == null) { - byte[] v = _db.get(k); - return decodeValue(v, _communicator); + return null; } - catch(DBNotFoundException e) + else { - return null; + return decodeValue(v, _communicator); } } public Object put(Object key, Object value) { - closeIterators(); - byte[] k = encodeKey(key, _communicator); - Object o; - - try + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + byte[] v = getImpl(dbKey); + Object o = null; + if(v != null) { - byte[] v = _db.get(k); o = decodeValue(v, _communicator); } - catch(DBNotFoundException e) - { - o = null; - } - byte[] v = encodeValue(value, _communicator); - _db.put(k, v); - + putImpl(dbKey, value); return o; } public Object remove(Object key) { - closeIterators(); - byte[] k = encodeKey(key, _communicator); - Object o; - try + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + byte[] v = getImpl(dbKey); + + if(v != null && removeImpl(dbKey)) { - byte[] v = _db.get(k); - o = decodeValue(v, _communicator); + return decodeValue(v, _communicator); } - catch(DBNotFoundException e) + else { - o = null; + DBNotFoundException ex = new DBNotFoundException(); + ex.message = _errorPrefix + "Db.del: DB_NOTFOUND"; + throw ex; } - _db.del(k); - return o; } // @@ -186,11 +284,9 @@ public abstract class Map extends java.util.AbstractMap public void fastPut(Object key, Object value) { - closeIterators(); - byte[] k = encodeKey(key, _communicator); - byte[] v = encodeValue(value, _communicator); - _db.put(k, v); + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + putImpl(dbKey, value); } // @@ -199,28 +295,44 @@ public abstract class Map extends java.util.AbstractMap public boolean fastRemove(Object key) { - closeIterators(); - byte[] k = encodeKey(key, _communicator); - try - { - _db.del(k); - } - catch(Freeze.DBNotFoundException e) - { - return false; - } - return true; + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k); + return removeImpl(dbKey); } public void clear() { - closeIterators(); + if(_db == null) + { + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } - _db.clear(); + for(;;) + { + try + { + _db.truncate(null, com.sleepycat.db.Db.DB_AUTO_COMMIT); + break; + } + catch(com.sleepycat.db.DbDeadlockException e) + { + // + // Try again + // + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.truncate: " + e.getMessage(); + throw ex; + } + } } - + public java.util.Set entrySet() { @@ -231,9 +343,7 @@ public abstract class Map extends java.util.AbstractMap public java.util.Iterator iterator() { - EntryIterator p = new EntryIterator(); - _iterators.add(new java.lang.ref.WeakReference(p)); - return p; + return new EntryIterator(); } public boolean @@ -246,8 +356,8 @@ public abstract class Map extends java.util.AbstractMap Map.Entry entry = (Map.Entry)o; Object value = entry.getValue(); - Entry p = getEntry(entry.getKey()); - return p != null && valEquals(p.getValue(), value); + byte[] v = getImpl(entry.getDbKey()); + return v != null && valEquals(decodeValue(v, _communicator), value); } public boolean @@ -260,13 +370,10 @@ public abstract class Map extends java.util.AbstractMap Map.Entry entry = (Map.Entry)o; Object value = entry.getValue(); - Entry p = getEntry(entry.getKey()); - if(p != null && valEquals(p.getValue(), value)) + byte[] v = getImpl(entry.getDbKey()); + if(v != null && valEquals(decodeValue(v, _communicator), value)) { - closeIterators(); - byte[] k = encodeKey(p.getKey(), _communicator); - _db.del(k); - return true; + return removeImpl(entry.getDbKey()); } return false; } @@ -288,69 +395,183 @@ public abstract class Map extends java.util.AbstractMap return _entrySet; } - // - // Because of the way that Berkeley DB cursors implement their - // locking it's necessary to ensure that all cursors are closed - // prior to doing a database operation otherwise self-deadlocks - // will occur. See "Berkeley DB Transactional Data Store locking - // conventions" section in the Berkeley DB reference guide for - // details. - // - private void - closeIterators() + protected void + finalize() { - closeIteratorsExcept(null); + close(); } - private void - closeIteratorsExcept(java.util.Iterator i) + private static boolean + valEquals(Object o1, Object o2) { - java.util.Iterator p = _iterators.iterator(); - while(p.hasNext()) + return (o1 == null ? o2 == null : o1.equals(o2)); + } + + private byte[] + getImpl(com.sleepycat.db.Dbt dbKey) + { + if(_db == null) + { + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(); + + if(_trace >= 1) { - java.lang.ref.WeakReference ref = (java.lang.ref.WeakReference)p.next(); - EntryIterator q = (EntryIterator)ref.get(); - if(q != null && q != i) + _communicator.getLogger().trace("DB", "reading value from database \"" + _dbName + "\""); + } + + for(;;) + { + try { - q.close(); + int rc = _db.get(null, dbKey, dbValue, 0); + if(rc == com.sleepycat.db.Db.DB_NOTFOUND) + { + return null; + } + else + { + return dbValue.get_data(); + } + } + catch(com.sleepycat.db.DbDeadlockException e) + { + // + // Try again + // + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.get: " + e.getMessage(); + throw ex; } } + } - // - // This is more efficient than removing the list items element - // by element in the iteration loop. - // - _iterators.clear(); - if(i != null) + private void + putImpl(com.sleepycat.db.Dbt dbKey, Object value) + { + if(_db == null) { - _iterators.add(new java.lang.ref.WeakReference(i)); + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + byte[] v = encodeValue(value, _communicator); + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(v); + + if(_trace >= 1) + { + _communicator.getLogger().trace("DB", "writing value in database \"" + _dbName + "\""); + } + + for(;;) + { + try + { + _db.put(null, dbKey, dbValue, com.sleepycat.db.Db.DB_AUTO_COMMIT); + break; + } + catch(com.sleepycat.db.DbDeadlockException e) + { + // + // Try again + // + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.put: " + e.getMessage(); + throw ex; + } } } - private Entry - getEntry(Object key) + private boolean + removeImpl(com.sleepycat.db.Dbt dbKey) { - // - // It's not necessary to close outstanding iterators. - // - // If it was it would be a problem - it doesn't change the Map - // - therefore open iterators should not be invalidated - // (according the Java spec). - // - // closeIterators(); + if(_db == null) + { + DBException ex = new DBException(); + ex.message = _errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } - byte[] k = encodeKey(key, _communicator); - byte[] v = _db.get(k); + if(_trace >= 1) + { + _communicator.getLogger().trace("DB", "deleting value from database \"" + _dbName + "\""); + } - return new Entry(this, _communicator, key, v); + for(;;) + { + try + { + int rc = _db.del(null, dbKey, com.sleepycat.db.Db.DB_AUTO_COMMIT); + return (rc == 0); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + // + // Try again + // + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Db.del: " + e.getMessage(); + throw ex; + } + } } - private static boolean - valEquals(Object o1, Object o2) + private void + openDb(boolean createDb) { - return (o1 == null ? o2 == null : o1.equals(o2)); + _trace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.DB"); + + try + { + int flags = com.sleepycat.db.Db.DB_AUTO_COMMIT; + + if(createDb) + { + flags |= com.sleepycat.db.Db.DB_CREATE; + } + + _db = new com.sleepycat.db.Db(_dbEnv, 0); + _db.open(null, _dbName, null, com.sleepycat.db.Db.DB_BTREE, + flags, 0); + + // + // TODO: FREEZE_DB_MODE + // + } + catch(java.io.FileNotFoundException dx) + { + DBNotFoundException ex = new DBNotFoundException(); + ex.initCause(dx); + ex.message = _errorPrefix + "Db.open: " + dx.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException dx) + { + DBException ex = new DBException(); + ex.initCause(dx); + ex.message = _errorPrefix + "Db.open: " + dx.getMessage(); + throw ex; + } } + /** * * The entry iterator class needs to be public to allow clients to @@ -362,76 +583,191 @@ public abstract class Map extends java.util.AbstractMap { EntryIterator() { - try - { - _cursor = _db.getCursor(); - _next = getEntry(); - } - catch(DBNotFoundException e) - { - // Database is empty. - } + if(_trace >= 3) + { + _communicator.getLogger().trace("DB", "starting transaction for cursor on database \"" + _dbName + "\""); + } + + try + { + // + // Start transaction + // + _tx = _dbEnv.txn_begin(null, 0); + + // + // Open cursor with this transaction + // + _cursor = _db.cursor(_tx, 0); + } + catch(com.sleepycat.db.DbDeadlockException dx) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(dx); + ex.message = _errorPrefix + "EntryIterator constructor: " + dx.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException dx) + { + DBException ex = new DBException(); + ex.initCause(dx); + ex.message = _errorPrefix + "EntryIterator constructor: " + dx.getMessage(); + throw ex; + } } public boolean hasNext() { - return getNext(); + if(_current == null || _current == _lastReturned) + { + // + // Move _cursor, set _current + // + + com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(); + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(); + + try + { + if(_cursor.get(dbKey, dbValue, com.sleepycat.db.Db.DB_NEXT) == 0) + { + _current = new Entry(this, Map.this, _communicator, dbKey, dbValue.get_data()); + return true; + } + else + { + close(); + return false; + } + } + catch(com.sleepycat.db.DbDeadlockException dx) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(dx); + ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException dx) + { + DBException ex = new DBException(); + ex.initCause(dx); + ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage(); + throw ex; + } + } + else + { + return true; + } } - + public Object next() { - if(!getNext()) - { - throw new java.util.NoSuchElementException(); - } - assert(_next != null); - - if(_prev != null) - { - _prev.invalidateCursor(); - } - - _prev = _next; - _next = null; - return _prev; + if(hasNext()) + { + _lastReturned = _current; + return _lastReturned; + } + else + { + throw new java.util.NoSuchElementException(); + } } public void remove() { - if(_prev == null) - { - throw new IllegalStateException(); - } - - closeIteratorsExcept(this); - - // - // Clone the cursor so that error handling is simpler. - // - assert _cursor != null; - DBCursor clone = _cursor._clone(); - - try - { - clone.del(); - _prev.invalidateCursor(); - _prev = null; - _next = null; - } - finally - { - try - { - clone.close(); - } - catch(DBException ignore) - { - // Ignore - } - } + // + // Removes the last object returned by next() + // + if(_lastReturned == null) + { + throw new IllegalStateException(); + } + + if(_lastReturned == _current) + { + try + { + if(_cursor.del(0) == com.sleepycat.db.Db.DB_KEYEMPTY) + { + throw new IllegalStateException(); + } + } + catch(com.sleepycat.db.DbDeadlockException e) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.del: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.del: " + e.getMessage(); + throw ex; + } + } + else + { + // + // Duplicate the cursor and move the _lastReturned + // element to delete it (using the duplicate) + // + + com.sleepycat.db.Dbc clone = null; + + try + { + clone = _cursor.dup(com.sleepycat.db.Db.DB_POSITION); + + // + // No interested in data + // + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(); + dbValue.set_flags(com.sleepycat.db.Db.DB_DBT_USERMEM | + com.sleepycat.db.Db.DB_DBT_PARTIAL); + + int rc = clone.get(_lastReturned.getDbKey(), dbValue, com.sleepycat.db.Db.DB_SET); + + if(rc == com.sleepycat.db.Db.DB_NOTFOUND) + { + throw new IllegalStateException(); + } + if(clone.del(0) == com.sleepycat.db.Db.DB_KEYEMPTY) + { + throw new IllegalStateException(); + } + } + catch(com.sleepycat.db.DbDeadlockException e) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "EntryIterator.remove: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "EntryIterator.remove: " + e.getMessage(); + throw ex; + } + finally + { + if(clone != null) + { + closeCursor(clone); + } + } + } } // @@ -440,86 +776,227 @@ public abstract class Map extends java.util.AbstractMap public void close() { - DBCursor copy = _cursor; - - // - // Clear the internal iterator state. - // - _cursor = null; - _next = null; - _prev = null; - - if(copy != null) - { - copy.close(); - } - } + if(_cursor != null) + { + com.sleepycat.db.Dbc cursor = _cursor; + _cursor = null; + closeCursor(cursor); + } + + if(_tx != null) + { + if(_trace >= 3) + { + _communicator.getLogger().trace("DB", "committing transaction for cursor on database \"" + _dbName + "\""); + } - protected void + try + { + _tx.commit(0); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "DbTxn.commit: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "DbTxn.commit: " + e.getMessage(); + throw ex; + } + finally + { + _tx = null; + } + } + + } + + protected void finalize() { close(); } - private Entry - getEntry() - { - assert _cursor != null; - _cursor.curr(_keyHolder, _valueHolder); - return new Entry(Map.this, _cursor, _keyHolder.value, _valueHolder.value); - } + void + setValue(Map.Entry entry, Object value) + { + // + // Are we trying to update the current value? + // + if(_current == entry) + { + // + // Yes, update it directly + // + byte[] v = encodeValue(value, _communicator); + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(v); + + try + { + _cursor.put(entry.getDbKey(), dbValue, com.sleepycat.db.Db.DB_CURRENT); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.put: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.put: " + e.getMessage(); + throw ex; + } + } + else + { + // + // Duplicate the cursor and move the entry + // element to update it (using the duplicate cursor) + // + + com.sleepycat.db.Dbc clone = null; - private boolean - getNext() - { - if(_next == null && _cursor != null) - { - if(_cursor.next()) - { - try - { - _next = getEntry(); - } - catch(DBNotFoundException ex) - { - // No element found. - } - } - } - return _next != null; - } + try + { + clone = _cursor.dup(com.sleepycat.db.Db.DB_POSITION); + + // + // Not interested in data + // + com.sleepycat.db.Dbt dummy = new com.sleepycat.db.Dbt(); + dummy.set_flags(com.sleepycat.db.Db.DB_DBT_USERMEM | + com.sleepycat.db.Db.DB_DBT_PARTIAL); + + int rc = clone.get(entry.getDbKey(), dummy, com.sleepycat.db.Db.DB_SET); - private DBCursor _cursor; - private Entry _next; - private Entry _prev; - private Freeze.KeyHolder _keyHolder = new Freeze.KeyHolder(); - private Freeze.ValueHolder _valueHolder = new Freeze.ValueHolder(); + if(rc == com.sleepycat.db.Db.DB_NOTFOUND) + { + DBNotFoundException ex = new DBNotFoundException(); + ex.message = _errorPrefix + "Dbc.get: DB_NOTFOUND"; + throw ex; + } + + byte[] v = encodeValue(value, _communicator); + com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt(v); + clone.put(entry.getDbKey(), dbValue, com.sleepycat.db.Db.DB_CURRENT); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "EntryIterator.setValue: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "EntryIterator.setValue: " + e.getMessage(); + throw ex; + } + finally + { + if(clone != null) + { + closeCursor(clone); + } + } + } + } + + + private void + closeCursor(com.sleepycat.db.Dbc cursor) + { + try + { + cursor.close(); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + dead(); + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.close: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "Dbc.close: " + e.getMessage(); + throw ex; + } + } + + private void + dead() + { + if(_cursor != null) + { + com.sleepycat.db.Dbc cursor = _cursor; + _cursor = null; + closeCursor(cursor); + } + + if(_tx != null) + { + if(_trace >= 3) + { + _communicator.getLogger().trace("DB", "rolling back transaction for cursor on database \"" + _dbName + "\""); + } + + try + { + _tx.abort(); + } + catch(com.sleepycat.db.DbDeadlockException e) + { + DBDeadlockException ex = new DBDeadlockException(); + ex.initCause(e); + ex.message = _errorPrefix + "DbTxn.abort: " + e.getMessage(); + throw ex; + } + catch(com.sleepycat.db.DbException e) + { + DBException ex = new DBException(); + ex.initCause(e); + ex.message = _errorPrefix + "DbTxn.abort: " + e.getMessage(); + throw ex; + } + finally + { + _tx = null; + } + } + } + + private com.sleepycat.db.DbTxn _tx = null; + private com.sleepycat.db.Dbc _cursor = null; + private Entry _current = null; + private Entry _lastReturned = null; } static class Entry implements java.util.Map.Entry { public - Entry(Map map, DBCursor cursor, byte[] keyData, byte[] valueData) - { - _map = map; - _cursor = cursor; - _communicator = cursor.getCommunicator(); - _keyData = keyData; - _haveKey = false; - _valueData = valueData; - _haveValue = false; - } - - public - Entry(Map map, Ice.Communicator communicator, Object key, byte[] valueData) + Entry(Map.EntryIterator iterator, Map map, Ice.Communicator communicator, com.sleepycat.db.Dbt dbKey, byte[] valueBytes) { - _map = map; - _cursor = null; - _communicator = communicator; - _key = key; - _haveKey = true; - _valueData = valueData; - _haveValue = false; + _iterator = iterator; + _map = map; + _communicator = communicator; + _dbKey = dbKey; + _valueBytes = valueBytes; } public Object @@ -527,8 +1004,8 @@ public abstract class Map extends java.util.AbstractMap { if(!_haveKey) { - assert(_keyData != null); - _key = _map.decodeKey(_keyData, _communicator); + assert(_dbKey != null); + _key = _map.decodeKey(_dbKey.get_data(), _communicator); _haveKey = true; } return _key; @@ -539,9 +1016,13 @@ public abstract class Map extends java.util.AbstractMap { if(!_haveValue) { - assert(_valueData != null); - _value = _map.decodeValue(_valueData, _communicator); + assert(_valueBytes != null); + _value = _map.decodeValue(_valueBytes, _communicator); _haveValue = true; + // + // Not needed anymore + // + _valueBytes = null; } return _value; } @@ -549,17 +1030,9 @@ public abstract class Map extends java.util.AbstractMap public Object setValue(Object value) { - Object old = getValue(); - if(_cursor != null) - { - byte[] v = _map.encodeValue(value, _communicator); - _cursor.set(v); - } - else - { - _map.put(getKey(), value); // Invalidates iterators. - } - _value = value; + Object old = getValue(); + _iterator.setValue(this, value); + _value = value; _haveValue = true; return old; } @@ -588,11 +1061,10 @@ public abstract class Map extends java.util.AbstractMap return getKey() + "=" + getValue(); } - void - invalidateCursor() - { - _cursor = null; - } + com.sleepycat.db.Dbt getDbKey() + { + return _dbKey; + } private /*static*/ boolean eq(Object o1, Object o2) @@ -600,19 +1072,23 @@ public abstract class Map extends java.util.AbstractMap return (o1 == null ? o2 == null : o1.equals(o2)); } - private Map _map; - private DBCursor _cursor; - private Ice.Communicator _communicator; - private Object _key; - private byte[] _keyData; - private boolean _haveKey; - private Object _value; - private byte[] _valueData; - private boolean _haveValue; + private Map.EntryIterator _iterator = null; + private Map _map = null; + private Ice.Communicator _communicator = null; + private com.sleepycat.db.Dbt _dbKey = null; + private byte[] _valueBytes = null; + private Object _key = null; + private boolean _haveKey = false; + private Object _value = null; + private boolean _haveValue = false; } - private java.util.Set _entrySet; - private DB _db; - private Ice.Communicator _communicator; - private java.util.List _iterators = new java.util.LinkedList(); + private java.util.Set _entrySet = null; + private SharedDbEnv _dbEnvHolder = null; + private com.sleepycat.db.DbEnv _dbEnv = null; + private com.sleepycat.db.Db _db = null; + private String _dbName = null; + private Ice.Communicator _communicator = null; + private String _errorPrefix = null; + private int _trace = 0; } |