summaryrefslogtreecommitdiff
path: root/java/src/Freeze/Map.java
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2003-07-18 19:47:14 +0000
committerBernard Normier <bernard@zeroc.com>2003-07-18 19:47:14 +0000
commit3c02842b6143c6ce9297feecd7c9497312c76da8 (patch)
tree478210bed985772e2957ee0a65b9cd3f5f390234 /java/src/Freeze/Map.java
parentuse lazy initialization of communicator for each request (diff)
downloadice-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.java1094
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;
}