summaryrefslogtreecommitdiff
path: root/java/src/Freeze/Map.java
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2004-09-30 20:02:15 +0000
committerBernard Normier <bernard@zeroc.com>2004-09-30 20:02:15 +0000
commit61d07845e7640e3c5fbdc8599190dade12129d33 (patch)
treef118ec0fb9450aa0d4b90cbd2f8f2d562ee72e97 /java/src/Freeze/Map.java
parentMap index support (diff)
downloadice-61d07845e7640e3c5fbdc8599190dade12129d33.tar.bz2
ice-61d07845e7640e3c5fbdc8599190dade12129d33.tar.xz
ice-61d07845e7640e3c5fbdc8599190dade12129d33.zip
Added index support to Freeze dictionaries
Diffstat (limited to 'java/src/Freeze/Map.java')
-rw-r--r--java/src/Freeze/Map.java330
1 files changed, 308 insertions, 22 deletions
diff --git a/java/src/Freeze/Map.java b/java/src/Freeze/Map.java
index 3759827af8c..1927a8e6d47 100644
--- a/java/src/Freeze/Map.java
+++ b/java/src/Freeze/Map.java
@@ -17,8 +17,22 @@ public abstract class Map extends java.util.AbstractMap
_connection = (ConnectionI) connection;
_errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\") :";
_trace = _connection.trace();
- _db = SharedDb.get(_connection, dbName, createDb);
+ init(null, dbName, createDb);
+ }
+
+ protected
+ Map(Connection connection, String dbName)
+ {
+ _connection = (ConnectionI) connection;
+ _errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\") :";
+ _trace = _connection.trace();
+ }
+
+ protected void
+ init(Freeze.Map.Index[] indices, String dbName, boolean createDb)
+ {
+ _db = Freeze.SharedDb.get(_connection, dbName, indices, createDb);
_token = _connection.registerMap(this);
}
@@ -155,7 +169,7 @@ public abstract class Map extends java.util.AbstractMap
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);
+ dbValue.setFlags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
if(_trace >= 1)
{
@@ -347,7 +361,7 @@ public abstract class Map extends java.util.AbstractMap
public java.util.Iterator
iterator()
{
- return new EntryIterator();
+ return new EntryIterator(null, null);
}
public boolean
@@ -489,7 +503,7 @@ public abstract class Map extends java.util.AbstractMap
}
else
{
- return dbValue.get_data();
+ return dbValue.getData();
}
}
catch(com.sleepycat.db.DbDeadlockException e)
@@ -616,7 +630,7 @@ public abstract class Map extends java.util.AbstractMap
{
try
{
- int rc = _db.del(txn, dbKey, txn != null ? 0 : com.sleepycat.db.Db.DB_AUTO_COMMIT);
+ int rc = _db.delete(txn, dbKey, txn != null ? 0 : com.sleepycat.db.Db.DB_AUTO_COMMIT);
return (rc == 0);
}
catch(com.sleepycat.db.DbDeadlockException e)
@@ -652,6 +666,198 @@ public abstract class Map extends java.util.AbstractMap
}
}
+
+ protected abstract class Index implements com.sleepycat.db.DbSecondaryKeyCreate
+ {
+ //
+ // Implementation details
+ //
+
+ public int
+ secondaryKeyCreate(com.sleepycat.db.Db secondary,
+ com.sleepycat.db.Dbt key,
+ com.sleepycat.db.Dbt value,
+ com.sleepycat.db.Dbt result)
+ {
+ Ice.Communicator communicator = _connection.getCommunicator();
+ byte[] secondaryKey = marshalKey(value.getData());
+ assert(secondaryKey != null);
+
+ result.setData(secondaryKey);
+ result.setSize(secondaryKey.length);
+ return 0;
+ }
+
+
+ //
+ // Alias for Berkeley DB 4.1.25
+ //
+ public int
+ secondary_key_create(com.sleepycat.db.Db secondary,
+ com.sleepycat.db.Dbt key,
+ com.sleepycat.db.Dbt value,
+ com.sleepycat.db.Dbt result)
+ {
+ return secondaryKeyCreate(secondary, key, value, result);
+ }
+
+ com.sleepycat.db.Db
+ db()
+ {
+ return _db;
+ }
+
+ protected Index(String name)
+ {
+ _name = name;
+ }
+
+ void
+ associate(String dbName, com.sleepycat.db.Db db,
+ com.sleepycat.db.DbTxn txn, boolean createDb)
+ throws com.sleepycat.db.DbException, java.io.FileNotFoundException
+ {
+ _dbName = dbName + "." + _name;
+ assert(txn != null);
+ assert(_db == null);
+
+ _db = new com.sleepycat.db.Db(_connection.dbEnv(), 0);
+ _db.setFlags(com.sleepycat.db.Db.DB_DUP | com.sleepycat.db.Db.DB_DUPSORT);
+
+ int flags = 0;
+ if(createDb)
+ {
+ flags = com.sleepycat.db.Db.DB_CREATE;
+ }
+
+ _db.open(txn, _dbName, null, com.sleepycat.db.Db.DB_BTREE, flags, 0);
+
+ //
+ // We always populate empty indices
+ //
+ flags = com.sleepycat.db.Db.DB_CREATE;
+ db.associate(txn, _db, this, flags);
+ }
+
+ void init(Index from)
+ {
+ assert(_name.equals(from._name));
+ assert(_db == null);
+
+ _dbName = from._dbName;
+ _db = from._db;
+ }
+
+ void close()
+ {
+ //
+ // close() is called by SharedDb only on the "main" index
+ // (the one that was associated)
+ //
+
+ if(_db != null)
+ {
+ try
+ {
+ _db.close(0);
+ }
+ catch(com.sleepycat.db.DbException dx)
+ {
+ DatabaseException ex = new DatabaseException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Db.close for index \""
+ + _dbName + "\": " + dx.getMessage();
+ throw ex;
+ }
+ _db = null;
+ }
+ }
+
+ public EntryIterator
+ untypedFind(byte[] k)
+ {
+ return new EntryIterator(this, k);
+ }
+
+ public int
+ untypedCount(byte[] k)
+ {
+ com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt(k);
+ com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt();
+ //
+ // dlen is 0, so we should not retrieve any value
+ //
+ dbValue.setFlags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
+
+ try
+ {
+ for(;;)
+ {
+ com.sleepycat.db.Dbc dbc = null;
+ try
+ {
+ dbc = _db.cursor(null, 0);
+ boolean found = (dbc.get(dbKey, dbValue, com.sleepycat.db.Db.DB_SET) == 0);
+
+ if(found)
+ {
+ return dbc.count(0);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ catch(com.sleepycat.db.DbDeadlockException dx)
+ {
+ if(_connection.deadlockWarning())
+ {
+ _connection.communicator().getLogger().warning
+ ("Deadlock in Freeze.Map.Index.untypedCount while iterating over index \""
+ + _dbName + "\"; retrying ...");
+ }
+
+ //
+ // Retry
+ //
+ }
+ finally
+ {
+ if(dbc != null)
+ {
+ try
+ {
+ dbc.close();
+ }
+ catch(com.sleepycat.db.DbDeadlockException dx)
+ {
+ //
+ // Ignored
+ //
+ }
+ }
+ }
+ }
+ }
+ catch(com.sleepycat.db.DbException dx)
+ {
+ DatabaseException ex = new DatabaseException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Db.cursor for index \""
+ + _dbName + "\": " + dx.getMessage();
+ throw ex;
+ }
+ }
+
+ protected abstract byte[]
+ marshalKey(byte[] value);
+
+ private String _name;
+ private String _dbName;
+ private com.sleepycat.db.Db _db;
+ }
+
+
/**
*
* The entry iterator class needs to be public to allow clients to
@@ -661,8 +867,10 @@ public abstract class Map extends java.util.AbstractMap
**/
public class EntryIterator implements java.util.Iterator
{
- EntryIterator()
+ EntryIterator(Index index, byte[] k)
{
+ _indexed = (index != null);
+
if(_trace >= 3)
{
_connection.communicator().getLogger().trace
@@ -677,14 +885,21 @@ public abstract class Map extends java.util.AbstractMap
//
// Start transaction
//
- txn = _connection.dbEnv().txn_begin(null, 0);
+ txn = _connection.dbEnv().txnBegin(null, 0);
_txn = txn;
}
//
// Open cursor with this transaction
//
- _cursor = _db.cursor(txn, 0);
+ if(index == null)
+ {
+ _cursor = _db.cursor(txn, 0);
+ }
+ else
+ {
+ _cursor = index.db().cursor(txn, 0);
+ }
}
catch(com.sleepycat.db.DbDeadlockException dx)
{
@@ -702,19 +917,56 @@ public abstract class Map extends java.util.AbstractMap
throw ex;
}
+
+ if(_indexed)
+ {
+ com.sleepycat.db.Dbt dbIKey = new com.sleepycat.db.Dbt(k);
+ com.sleepycat.db.Dbt dbKey = new com.sleepycat.db.Dbt();
+ com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt();
+
+ try
+ {
+ if(_cursor.get(dbIKey, dbKey, dbValue, com.sleepycat.db.Db.DB_SET) == 0)
+ {
+ _current = new Entry(this, Map.this, _connection.communicator(),
+ dbKey, dbValue.getData());
+ }
+ }
+ catch(com.sleepycat.db.DbDeadlockException dx)
+ {
+ dead();
+ DeadlockException ex = new DeadlockException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage();
+ throw ex;
+ }
+ catch(com.sleepycat.db.DbException dx)
+ {
+ dead();
+ DatabaseException ex = new DatabaseException();
+ ex.initCause(dx);
+ ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage();
+ throw ex;
+ }
+ }
+
synchronized(_iteratorList)
{
_iteratorList.addFirst(this);
java.util.Iterator p = _iteratorList.iterator();
p.next();
_iteratorListToken = p;
-
}
}
public boolean
hasNext()
{
+ if(_indexed && _current == null)
+ {
+ return false;
+ }
+
if(_current == null || _current == _lastReturned)
{
//
@@ -723,13 +975,29 @@ public abstract class Map extends java.util.AbstractMap
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)
+ int err;
+ if(_indexed)
+ {
+ com.sleepycat.db.Dbt dbIKey = new com.sleepycat.db.Dbt();
+ //
+ // dlen is 0, so we should not retrieve any value
+ //
+ dbIKey.setFlags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
+
+ err = _cursor.get(dbIKey, dbKey, dbValue, com.sleepycat.db.Db.DB_NEXT_DUP);
+ }
+ else
+ {
+ err = _cursor.get(dbKey, dbValue, com.sleepycat.db.Db.DB_NEXT);
+ }
+
+ if(err == 0)
{
_current = new Entry(this, Map.this, _connection.communicator(),
- dbKey, dbValue.get_data());
+ dbKey, dbValue.getData());
return true;
}
else
@@ -793,7 +1061,7 @@ public abstract class Map extends java.util.AbstractMap
{
try
{
- if(_cursor.del(0) == com.sleepycat.db.Db.DB_KEYEMPTY)
+ if(_cursor.delete(0) == com.sleepycat.db.Db.DB_KEYEMPTY)
{
throw new IllegalStateException();
}
@@ -821,6 +1089,14 @@ public abstract class Map extends java.util.AbstractMap
// element to delete it (using the duplicate)
//
+ //
+ // This works only for non-index iterators
+ //
+ if(_indexed)
+ {
+ throw new IllegalStateException();
+ }
+
com.sleepycat.db.Dbc clone = null;
try
@@ -831,7 +1107,7 @@ public abstract class Map extends java.util.AbstractMap
// No interested in data
//
com.sleepycat.db.Dbt dbValue = new com.sleepycat.db.Dbt();
- dbValue.set_flags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
+ dbValue.setFlags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
int rc = clone.get(_lastReturned.getDbKey(), dbValue, com.sleepycat.db.Db.DB_SET);
@@ -839,7 +1115,7 @@ public abstract class Map extends java.util.AbstractMap
{
throw new IllegalStateException();
}
- if(clone.del(0) == com.sleepycat.db.Db.DB_KEYEMPTY)
+ if(clone.delete(0) == com.sleepycat.db.Db.DB_KEYEMPTY)
{
throw new IllegalStateException();
}
@@ -961,6 +1237,13 @@ public abstract class Map extends java.util.AbstractMap
void
setValue(Map.Entry entry, Object value)
{
+ if(_indexed)
+ {
+ DatabaseException ex = new DatabaseException();
+ ex.message = _errorPrefix + "Cannot set an iterator retrieved through an index";
+ throw ex;
+ }
+
if(_txn != null)
{
closeAllIteratorsExcept(this, false);
@@ -1014,7 +1297,7 @@ public abstract class Map extends java.util.AbstractMap
// Not interested in data
//
com.sleepycat.db.Dbt dummy = new com.sleepycat.db.Dbt();
- dummy.set_flags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
+ dummy.setFlags(com.sleepycat.db.Db.DB_DBT_PARTIAL);
int rc = clone.get(entry.getDbKey(), dummy, com.sleepycat.db.Db.DB_SET);
@@ -1127,6 +1410,8 @@ public abstract class Map extends java.util.AbstractMap
private Entry _current;
private Entry _lastReturned;
private java.util.Iterator _iteratorListToken;
+ private boolean _indexed;
+
}
static class Entry implements java.util.Map.Entry
@@ -1148,7 +1433,7 @@ public abstract class Map extends java.util.AbstractMap
if(!_haveKey)
{
assert(_dbKey != null);
- _key = _map.decodeKey(_dbKey.get_data(), _communicator);
+ _key = _map.decodeKey(_dbKey.getData(), _communicator);
_haveKey = true;
}
return _key;
@@ -1257,11 +1542,12 @@ public abstract class Map extends java.util.AbstractMap
public Ice.Object value;
}
- private ConnectionI _connection;
- private java.util.Iterator _token;
+ protected ConnectionI _connection;
+ protected java.util.Iterator _token;
+ protected SharedDb _db;
+ protected String _errorPrefix;
+ protected int _trace;
+
private java.util.Set _entrySet;
private LinkedList _iteratorList = new LinkedList();
- private SharedDb _db;
- private String _errorPrefix;
- private int _trace;
}