Logo Search packages:      
Sourcecode: zeroc-ice-java version File versions  Download package

Map.java

// **********************************************************************
//
// Copyright (c) 2003-2006 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;

public abstract class Map extends java.util.AbstractMap 
    implements java.util.SortedMap, KeyCodec
{
    public abstract byte[] encodeValue(Object o, Ice.Communicator communicator);
    public abstract Object decodeValue(byte[] b, Ice.Communicator communicator);

    public
    Map(Connection connection, String dbName, String key, String value, 
      boolean createDb, java.util.Comparator comparator)
    {
      _connection = (ConnectionI) connection;
      _comparator = (comparator == null) ? null : new Comparator(comparator);
            
      _errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\"): ";
      _trace = _connection.trace();
      
      init(null, dbName, key, value, createDb, null);
    }

    protected
    Map(Connection connection, String dbName, java.util.Comparator comparator)
    {
      _connection = (ConnectionI) connection;
      _comparator = (comparator == null) ? null : new Comparator(comparator);

      _errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\"): ";
      _trace = _connection.trace();
    }

    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);
      _token = _connection.registerMap(this);

      if(indices != null)
      {
          for(int i = 0; i < indices.length; ++i)
          {
            _indexMap.put(indices[i].name(), indices[i]);
          }
      }
    }

    public void
    close()
    {
      close(false);
    }

    //
    // SortedMap methods
    //

    public java.util.Comparator
    comparator()
    {
      if(_comparator == null)
      {
          return null;
      }
      else
      {
          //
          // Return's the user's comparator, not the DB comparator.
          //
          return _comparator.comparator();
      }
    }

    public Object firstKey()
    {
      return firstKey(null, null);
    }
    
    public Object lastKey()
    {
      return lastKey(null, null);
    }

    Object firstKey(Object fromKey, Object toKey)
    {
      byte[] fk = fromKey == null ? null :
          encodeKey(fromKey, _connection.communicator());

      byte[] k = getFirstOrLastKey(_db.db(), _db.dbName(), fk, true);
      if(k == null)
      {
          throw new NoSuchElementException();
      }
      else
      {
          Object key = decodeKey(k, _connection.communicator());
          if(toKey != null && comparator().compare(key, toKey) >= 0)
          {
            throw new NoSuchElementException();
          }
          return key;
      }
    }

    Object lastKey(Object fromKey, Object toKey)
    {
      byte[] tk = toKey == null ? null :
          encodeKey(toKey, _connection.communicator());

      byte[] k = getFirstOrLastKey(_db.db(), _db.dbName(), tk, false);
      if(k == null)
      {
          throw new NoSuchElementException();
      }
      else
      {
          Object key = decodeKey(k, _connection.communicator());
          if(fromKey != null && comparator().compare(fromKey, key) > 0)
          {
            throw new NoSuchElementException();
          }
          return key;
      }
    }

    public java.util.SortedMap headMap(Object toKey)
    {
      if(toKey == null)
      {
          throw new NullPointerException();
      }
      if(_comparator == null)
      {
          throw new UnsupportedOperationException();
      }

      return new SubMap(this, null, toKey);
    }
    
    public java.util.SortedMap tailMap(Object fromKey)
    {
      if(fromKey == null)
      {
          throw new NullPointerException();
      }
      if(_comparator == null)
      {
          throw new UnsupportedOperationException();
      }

      return new SubMap(this, fromKey, null);
    } 
   
    public java.util.SortedMap subMap(Object fromKey, Object toKey)
    {
      if(fromKey == null || toKey == null )
      {
          throw new NullPointerException();
      }
      if(_comparator == null)
      {
          throw new UnsupportedOperationException();
      }
      return new SubMap(this, fromKey, toKey);
    }

    
    //
    // Additional non-standard xxMapForIndex methods
    //
    public java.util.SortedMap headMapForIndex(String indexName, Object toKey)
    {
      if(toKey == null)
      {
          throw new NullPointerException();
      }
      
      Map.Index index = (Map.Index)_indexMap.get(indexName);
      if(index == null)
      {
          throw new IllegalArgumentException("Can't find index '" + indexName + "'");
      }
      else if(index.comparator() == null)
      {
          throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator");
      }
      return new SubMap(index, null, toKey);
    }
    
    public java.util.SortedMap tailMapForIndex(String indexName, Object fromKey)
    {
      if(fromKey == null)
      {
          throw new NullPointerException();
      }
      Map.Index index = (Map.Index)_indexMap.get(indexName);
      if(index == null)
      {
          throw new IllegalArgumentException("Can't find index '" + indexName + "'");
      }
      else if(index.comparator() == null)
      {
          throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator");
      }
      return new SubMap(index, fromKey, null);
    } 
   
    public java.util.SortedMap subMapForIndex(String indexName, Object fromKey, Object toKey)
    {
      if(fromKey == null || toKey == null )
      {
          throw new NullPointerException();
      }
      Map.Index index = (Map.Index)_indexMap.get(indexName);
      if(index == null)
      {
          throw new IllegalArgumentException("Can't find index '" + indexName + "'");
      }
      else if(index.comparator() == null)
      {
          throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator");
      }
      return new SubMap(index, fromKey, toKey);
    }

    public java.util.SortedMap mapForIndex(String indexName)
    {
      Map.Index index = (Map.Index)_indexMap.get(indexName);
      if(index == null)
      {
          throw new IllegalArgumentException("Can't find index '" + indexName + "'");
      }
      else if(index.comparator() == null)
      {
          throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator");
      }
      return new SubMap(index, null, null);
    }
    
    //
    // Plain Map methods
    //
    public int
    size()
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      //
      // The number of records cannot be cached and then adjusted by
      // the member functions since the map would no longer work in
      // the presence of transactions - if a record is added (and
      // the size adjusted) and the transaction aborted then the
      // cached map size() would be incorrect.
      //
      
      //
      // TODO: DB_FAST_STAT doesn't seem to do what the
      // documentation says...
      //
      try
      {
          com.sleepycat.db.StatsConfig config = new com.sleepycat.db.StatsConfig();
          //
          // TODO: DB_FAST_STAT doesn't seem to do what the
          // documentation says...
          //      
          //config.setFast(true);
          com.sleepycat.db.BtreeStats s = (com.sleepycat.db.BtreeStats)_db.db().getStats(null, config);
          return s.getNumData();
      }
      catch(com.sleepycat.db.DatabaseException e)
      {
          DatabaseException ex = new DatabaseException();
          ex.initCause(e);
          ex.message = _errorPrefix + "Db.stat: " + e.getMessage();
          throw ex;
      }
    }

    public boolean
    containsValue(Object value)
    {
      for(;;)
      {
          EntryIterator p = null;
          try
          {
            p = (EntryIterator)entrySet().iterator();

            if(value == null)
            {
                while(p.hasNext())
                {
                  Entry e = (Entry)p.next();
                  if(e.getValue() == null)
                  {
                      return true;
                  }
                }
            } 
            else 
            {
                while(p.hasNext()) 
                {
                  Entry e = (Entry)p.next();
                  if(value.equals(e.getValue()))
                  {
                      return true;
                  }
                }
            }
            return false;
          }
          catch(DeadlockException e)
          {
            if(_connection.dbTxn() != null)
            {
                throw e;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.containsValue while " +
                                                       "iterating over Db \"" + _db.dbName()  +
                                                       "\"; retrying...");
                }

                //
                // Try again
                //
            }
          }
          finally
          {
            if(p != null)
            {
                p.close();
            }
          }
      }
    }

    public boolean
    containsKey(Object key)
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      byte[] k = encodeKey(key, _connection.communicator());

      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
      dbValue.setPartial(true);

      if(_trace >= 1)
      {
          _connection.communicator().getLogger().trace(
            "Freeze.Map", "checking key in Db \"" + _db.dbName() + "\"");
      }

      for(;;)
      {
          try
          {
            return _db.db().get(_connection.dbTxn(), dbKey, dbValue, null)
                == com.sleepycat.db.OperationStatus.SUCCESS;
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            if(_connection.dbTxn() != null)
            {
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.get: " + e.getMessage();
                throw ex;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning(
                      "Deadlock in Freeze.Map.containsKey while " +
                      "reading Db \"" + _db.dbName() +
                      "\"; retrying...");
                }
                //
                // Try again
                //
            }
          }
          catch(com.sleepycat.db.DatabaseException e)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Db.get: " + e.getMessage();
            throw ex;
          }
      }
    }

    public Object
    get(Object key)
    {
      byte[] k = encodeKey(key, _connection.communicator());
      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      byte[] v = getImpl(dbKey);
      if(v == null)
      {
          return null;
      }
      else
      {
          return decodeValue(v, _connection.communicator());
      }
    }

    public Object
    put(Object key, Object value)
    {
      byte[] k = encodeKey(key, _connection.communicator());
      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      byte[] v = getImpl(dbKey);
      Object o = null;
      if(v != null)
      {
          o = decodeValue(v, _connection.communicator());
      }
      putImpl(dbKey, value);
      return o;
    }

    public Object
    remove(Object key)
    {
      byte[] k = encodeKey(key, _connection.communicator());
      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      byte[] v = getImpl(dbKey);
      
      if(v != null && removeImpl(dbKey))
      {
          return decodeValue(v, _connection.communicator());
      }
      else
      {
          return null;
      }
    }

    //
    // Proprietary API calls. These are much faster than the
    // corresponding Java collections API methods since the unwanted
    // reads are avoided.
    //
    public void
    fastPut(Object key, Object value)
    {
      byte[] k = encodeKey(key, _connection.communicator());
      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      putImpl(dbKey, value);
    }

    //
    // Returns true if the record was removed, false otherwise.
    //
    public boolean
    fastRemove(Object key)
    {
      byte[] k = encodeKey(key, _connection.communicator());
      com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
      return removeImpl(dbKey);
    }

    public void
    clear()
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      com.sleepycat.db.Transaction txn = _connection.dbTxn();

      for(;;)
      {
          try
          {
            _db.db().truncate(txn, false);
            break;
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            if(txn != null)
            {
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.truncate: " + e.getMessage();
                throw ex;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.clear on Db \"" +
                                                       _db.dbName() + "\"; retrying...");
                }
                
                //
                // Try again
                //
            }
          }
          catch(com.sleepycat.db.DatabaseException e)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Db.truncate: " + e.getMessage();
            throw ex;
          }
      }
    }
      
    public java.util.Set
    entrySet()
    {
        if(_entrySet == null)
      {
            _entrySet = new java.util.AbstractSet()
          {
            public java.util.Iterator
            iterator()
            {
                return new EntryIteratorImpl(null, null, null, false, false);
            }
            
            public boolean
            contains(Object o)
            {
                if(!(o instanceof Map.Entry))
                {
                  return false;
                }
                Map.Entry entry = (Map.Entry)o;
                Object value = entry.getValue();
                
                byte[] v = getImpl(entry.getDbKey());
                return v != null && valEquals(decodeValue(v, _connection.communicator()), value);
            }
            
            public boolean
            remove(Object o)
            {
                if(!(o instanceof Map.Entry))
                {
                  return false;
                }
                Map.Entry entry = (Map.Entry)o;
                Object value = entry.getValue();

                byte[] v = getImpl(entry.getDbKey());
                if(v != null && valEquals(decodeValue(v, _connection.communicator()), value))
                {
                  return removeImpl(entry.getDbKey());
                }
                return false;
            }
            
            public int
            size()
            {
                return Map.this.size();
            }
            
            public void
            clear()
            {
                Map.this.clear();
            }
            };
        }

        return _entrySet;
    }

    public void
    closeAllIterators()
    {
      closeAllIteratorsExcept(null, false);
    }
    
    void
    closeAllIteratorsExcept(Object except, boolean finalizing)
    {
      synchronized(_iteratorList)
      {
          java.util.Iterator p = _iteratorList.iterator();

          while(p.hasNext())
          {
            Object obj = p.next();
            if(obj != except)
            {
                ((EntryIteratorImpl)obj).close(finalizing);
            }
          }
      }
    }

    protected void
    finalize()
    {
      close(true);
    }

    //
    // The synchronization is only needed when finalizing is true
    //
    void 
    close(boolean finalizing)
    {
      synchronized(_connection)
      {
          if(_db != null)
          {
            closeAllIteratorsExcept(null, finalizing);
            try
            {
                _db.close();
            }
            finally
            {
                _db = null;
                _connection.unregisterMap(_token);
                _token = null;
            }
          }
      }
    }

    EntryIterator 
    createIterator(Index index, Object fromKey, Object toKey)
    {
      KeyCodec codec = index == null ? (KeyCodec)this : (KeyCodec)index;

      Ice.Communicator communicator = _connection.getCommunicator();

      return new EntryIteratorImpl(index, 
                         fromKey == null ? null : codec.encodeKey(fromKey, communicator),
                         toKey == null ? null : codec.encodeKey(toKey, communicator),
                         false, true);
    }
      
    ConnectionI connection()
    {
      return _connection;
    }

    private static boolean
    valEquals(Object o1, Object o2)
    {
        return (o1 == null ? o2 == null : o1.equals(o2));
    }

    private byte[]
    getFirstOrLastKey(com.sleepycat.db.Database db, String dbName, byte[] key, boolean first)
    {
      if(db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + dbName + "\" has been closed";
          throw ex;
      }
      
      if(_trace >= 1)
      {
          _connection.communicator().getLogger().trace(
            "Freeze.Map", "Searching db \"" + dbName + "\"");
      }
      
      com.sleepycat.db.DatabaseEntry dbKey = key == null ?
          new com.sleepycat.db.DatabaseEntry():
          new com.sleepycat.db.DatabaseEntry(key);

      com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
      dbValue.setPartial(true); // not interested in value

      try
      {
          for(;;)
          {
            com.sleepycat.db.Cursor dbc = null;
            try
            {
                dbc = db.openCursor(_connection.dbTxn(), null);
                com.sleepycat.db.OperationStatus status;

                if(key == null)
                {
                  status = first ?
                      dbc.getFirst(dbKey, dbValue, null) : dbc.getLast(dbKey, dbValue, null);
                }
                else if(first)
                {
                  status = dbc.getSearchKeyRange(dbKey, dbValue, null);
                }
                else
                {
                  status = dbc.getSearchKeyRange(dbKey, dbValue, null);

                  if(status == com.sleepycat.db.OperationStatus.SUCCESS)
                  {
                      //
                      // goto the previous pair, which must be < key
                      //
                      status = dbc.getPrevNoDup(dbKey, dbValue, null);
                  }
                  else if(status == com.sleepycat.db.OperationStatus.NOTFOUND)
                  {
                      //
                      // All keys < desired toKey, so we pick the largest of
                      // all, the last one
                      //
                      status = dbc.getLast(dbKey, dbValue, null);
                  }
                }
               
                if(status == com.sleepycat.db.OperationStatus.SUCCESS)
                {
                  return dbKey.getData();
                }
                else
                {
                  return null;
                }
            }
            catch(com.sleepycat.db.DeadlockException dx)
            {
                if(_connection.dbTxn() != null)
                {
                  DeadlockException ex = new DeadlockException();
                  ex.initCause(dx);
                  ex.message = _errorPrefix + "Dbc.getXXX: " + dx.getMessage();
                  throw ex;
                }
                else
                {
                  if(_connection.deadlockWarning())
                  {
                      _connection.communicator().getLogger().warning(
                        "Deadlock in Freeze.Map while searching \"" + db.getDatabaseName() +
                        "\"; retrying...");
                  }
                  
                  //
                  // Retry
                  //
                }
            }
            finally
            {
                if(dbc != null)
                {
                  try
                  {
                      dbc.close();
                  }
                  catch(com.sleepycat.db.DeadlockException dx)
                  {
                      //
                      // Ignored
                      //
                  }
                }
            }
          }
      }
      catch(com.sleepycat.db.DatabaseException dx)
      {
          DatabaseException ex = new DatabaseException();
          ex.initCause(dx);
          ex.message = _errorPrefix + "Db.openCursor/Dbc.getXXX: " + dx.getMessage();
          throw ex; 
      }
    }

    private byte[]
    getImpl(com.sleepycat.db.DatabaseEntry dbKey)
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();

      if(_trace >= 1)
      {
          _connection.communicator().getLogger().trace("Freeze.Map", "reading value from Db \"" + _db.dbName() +
                                           "\"");
      }

      for(;;)
      {
          try
          {
            com.sleepycat.db.OperationStatus rc = _db.db().get(_connection.dbTxn(), dbKey, dbValue, null);
            if(rc == com.sleepycat.db.OperationStatus.SUCCESS)
            {
                return dbValue.getData();
            }
            else
            {
                return null;
            }
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            if(_connection.dbTxn() != null)
            {
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.get: " + e.getMessage();
                throw ex;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.getImpl while " +
                                                       "reading Db \"" + _db.dbName() +
                                                       "\"; retrying...");
                }

                //
                // Try again
                //
            }
          }
          catch(com.sleepycat.db.DatabaseException e)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Db.get: " + e.getMessage();
            throw ex;
          }
      }
    }

    private void
    putImpl(com.sleepycat.db.DatabaseEntry dbKey, Object value)
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      byte[] v = encodeValue(value, _connection.communicator());  
      com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v);
      
      if(_trace >= 1)
      {
          _connection.communicator().getLogger().trace("Freeze.Map", "writing value in Db \"" + _db.dbName() + "\"");
      }

      com.sleepycat.db.Transaction txn = _connection.dbTxn();
      if(txn == null)
      {
          closeAllIterators();
      }

      for(;;)
      {
          try
          {
            _db.db().put(txn, dbKey, dbValue);
            break;
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            if(txn != null)
            {
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.put: " + e.getMessage();
                throw ex;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.putImpl while " +
                                                       "writing into Db \"" + _db.dbName() +
                                                       "\"; retrying...");
                }

                //
                // Try again
                //
            }
          }
          catch(com.sleepycat.db.DatabaseException e)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Db.put: " + e.getMessage();
            throw ex;
          }
      }
    }

    private boolean
    removeImpl(com.sleepycat.db.DatabaseEntry dbKey)
    {
      if(_db == null)
      {
          DatabaseException ex = new DatabaseException();
          ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed";
          throw ex;
      }

      if(_trace >= 1)
      {
          _connection.communicator().getLogger().trace("Freeze.Map", "deleting value from Db \"" + _db.dbName() +
                                           "\"");
      }

      com.sleepycat.db.Transaction txn = _connection.dbTxn();
      if(txn == null)
      {
          closeAllIterators();
      }

      for(;;)
      {
          try
          {
            com.sleepycat.db.OperationStatus rc = _db.db().delete(txn, dbKey);
            return (rc == com.sleepycat.db.OperationStatus.SUCCESS);
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            if(txn != null)
            {
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.del: " + e.getMessage();
                throw ex;
            }
            else
            {
                if(_connection.deadlockWarning())
                {
                  _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.removeImpl while " +
                                                       "writing into Db \"" + _db.dbName() +
                                                       "\"; retrying...");
                }

                //
                // Try again
                //
            }
          }
          catch(com.sleepycat.db.DatabaseException e)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Db.del: " + e.getMessage();
            throw ex;
          }
      }
    }

    private class Comparator implements java.util.Comparator
    {
      Comparator(java.util.Comparator comparator)
      {
          _comparator = comparator;
      }
      
      public java.util.Comparator comparator()
      {
          return _comparator;
      }
      
      public int compare(Object o1, Object o2)
      {
          byte[] d1 = (byte[])o1;
          byte[] d2 = (byte[])o2;

          Ice.Communicator communicator = _connection.communicator();

          return _comparator.compare(decodeKey(d1, communicator),
                               decodeKey(d2, communicator));
      }

      //
      // The user-supplied comparator
      //
      private final java.util.Comparator _comparator;
    }

    public abstract class Index 
      implements com.sleepycat.db.SecondaryKeyCreator, java.util.Comparator, KeyCodec
    {
      //
      // Implementation details
      //
      public boolean
      createSecondaryKey(com.sleepycat.db.SecondaryDatabase secondary,
                     com.sleepycat.db.DatabaseEntry key,
                     com.sleepycat.db.DatabaseEntry value,
                     com.sleepycat.db.DatabaseEntry result)
          throws com.sleepycat.db.DatabaseException
      {
          Ice.Communicator communicator = _connection.getCommunicator();   
          byte[] secondaryKey = marshalKey(value.getData());
          assert(secondaryKey != null);
         
          result.setData(secondaryKey);
          result.setSize(secondaryKey.length);
          return true;
      }
      
      com.sleepycat.db.SecondaryDatabase
      db()
      {
          return _db;
      }
      
      String name()
      {
          return _name;
      }

      protected Index(String name)
      {
          _name = name;
      }

      void
      associate(String dbName, com.sleepycat.db.Database db, 
              com.sleepycat.db.Transaction txn, boolean createDb,
              java.util.Comparator comparator)
          throws com.sleepycat.db.DatabaseException, java.io.FileNotFoundException
      {
          _dbName = dbName + "." + _name;
          _comparator = comparator;

          assert(txn != null);
          assert(_db == null);

          com.sleepycat.db.SecondaryConfig config = new com.sleepycat.db.SecondaryConfig();
          config.setAllowCreate(createDb);
          config.setAllowPopulate(true); // We always populate empty indices
          config.setSortedDuplicates(true);
          config.setType(com.sleepycat.db.DatabaseType.BTREE);
          if(_comparator != null)
          {
            config.setBtreeComparator(this);
          }
          config.setKeyCreator(this);

          _db = _connection.dbEnv().getEnv().openSecondaryDatabase(txn, _dbName, null, db, config);
      }
      
      void init(Index from)
      {
          assert(_name.equals(from._name));
          assert(_db == null);

          _dbName = from._dbName;
          _db = from._db;
          _comparator = from._comparator;
      }

      java.util.Comparator comparator()
      {
          return _comparator;
      }
      
      Map parent()
      {
          return Map.this;
      }

      Object firstKey(Object fromKey, Object toKey)
      {
          byte[] fk = fromKey == null ? null :
            encodeKey(fromKey, _connection.communicator());
          
          byte[] k = getFirstOrLastKey(_db, _dbName, fk, true);
          if(k == null)
          {
            throw new NoSuchElementException();
          }
          else
          {
            Object key = decodeKey(k, _connection.communicator());
            if(toKey != null && _comparator.compare(key, toKey) >= 0)
            {
                throw new NoSuchElementException();
            }
            return key;
          }
      }

      Object lastKey(Object fromKey, Object toKey)
      {
          byte[] tk = toKey == null ? null :
            encodeKey(toKey, _connection.communicator());
          
          byte[] k = getFirstOrLastKey(_db, _dbName, tk, false);
          if(k == null)
          {
            throw new NoSuchElementException();
          }
          else
          {
            Object key = decodeKey(k, _connection.communicator());
            if(fromKey != null && _comparator.compare(fromKey, key) > 0)
            {
                throw new NoSuchElementException();
            }
            return key;
          }
      }

      void close()
      {
          //
          // close() is called by SharedDb only on the "main" index
          // (the one that was associated)
          //

          if(_db != null)
          {
            try
            {
                _db.close();
            }
            catch(com.sleepycat.db.DatabaseException 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(Object key, boolean onlyDups)
      {
          byte[] k = encodeKey(key, _connection.communicator());
          return new EntryIteratorImpl(this, k, null, onlyDups, false);
      }

      public int
      untypedCount(Object key)
      {
          byte[] k = encodeKey(key, _connection.communicator());

          com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
          com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
          //
          // dlen is 0, so we should not retrieve any value 
          // 
          dbValue.setPartial(true);
          
          try
          {
            for(;;)
            {
                com.sleepycat.db.Cursor dbc = null;
                try
                {
                  dbc = _db.openCursor(null, null);   
                  if(dbc.getSearchKey(dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS)
                  {
                      return dbc.count();
                  }
                  else
                  {
                      return 0;
                  }
                }
                catch(com.sleepycat.db.DeadlockException 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.DeadlockException dx)
                      {
                        //
                        // Ignored
                        //
                      }
                  }
                }
            }
          }
          catch(com.sleepycat.db.DatabaseException dx)
          {
            DatabaseException ex = new DatabaseException();
            ex.initCause(dx);
            ex.message = _errorPrefix + "Db.cursor for index \"" + _dbName + "\": " + dx.getMessage();
            throw ex; 
          }
      } 
      
      boolean containsKey(Object key)
      {
          byte[] k = encodeKey(key, _connection.communicator());

          com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k);
          com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
          dbValue.setPartial(true);

          if(_trace >= 1)
          {
            _connection.communicator().getLogger().trace(
                "Freeze.Map.Index", "checking key in Db \"" + _dbName + "\"");
          }
          
          for(;;)
          {
            try
            {
                return _db.get(_connection.dbTxn(), dbKey, dbValue, null)
                  == com.sleepycat.db.OperationStatus.SUCCESS;
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                if(_connection.dbTxn() != null)
                {
                  DeadlockException ex = new DeadlockException();
                  ex.initCause(e);
                  ex.message = _errorPrefix + "Db.get: " + e.getMessage();
                  throw ex;
                }
                else
                {
                  if(_connection.deadlockWarning())
                  {
                      _connection.communicator().getLogger().warning(
                        "Deadlock in Freeze.Map.Index.containsKey while " +
                        "reading Db \"" + _dbName + "\"; retrying...");
                  }
                  //
                  // Try again
                  //
                }
            }
            catch(com.sleepycat.db.DatabaseException e)
            {
                DatabaseException ex = new DatabaseException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Db.get: " + e.getMessage();
                throw ex;
            }
          }
      }
      
      //
      // Extracts the index key from this value
      //
      public abstract Object extractKey(Object value);

      protected byte[] marshalKey(byte[] value)
      {
          Object decodedValue = decodeValue(value, _connection.communicator());
          return encodeKey(extractKey(decodedValue), _connection.communicator());
      }

      //
      // The user-supplied comparator
      //
      protected java.util.Comparator _comparator;

      private String _name;
      private String _dbName;
      private com.sleepycat.db.SecondaryDatabase _db;
    }

    /**
     *
     * The entry iterator allows clients to explicitly close the iterator 
     * and free resources allocated for the iterator as soon as possible.
     *
     **/
01334     public interface EntryIterator extends java.util.Iterator
    {
      void close();
      void destroy(); // an alias for close
    }

    class EntryIteratorImpl implements EntryIterator
    {
        EntryIteratorImpl(Index index, byte[] fromKey, byte[] toKey, 
                    boolean onlyFromKeyDups, boolean skipDups)
        {
          _index = index;
          _fromKey = fromKey;
          _toKey = toKey;
          _onlyFromKeyDups = onlyFromKeyDups;
          _skipDups = skipDups;

          try
          {
            com.sleepycat.db.Transaction txn = _connection.dbTxn();
            if(txn == null)
            {
                //
                // Start transaction
                //
                txn = _connection.dbEnv().getEnv().beginTransaction(null, null);
                _txn = txn;

                if(_connection.txTrace() >= 1)
                {
                  String txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); 

                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "started transaction " + txnId + " for cursor");
                }
            }
            
            //
            // Open cursor with this transaction
            //
            if(index == null)
            {
                _cursor = _db.db().openCursor(txn, null);
            }
            else
            {
                _cursor = index.db().openSecondaryCursor(txn, null);
            }
          }
          catch(com.sleepycat.db.DeadlockException dx)
          {
            dead();
            DeadlockException ex = new DeadlockException();
            ex.initCause(dx);
            ex.message = _errorPrefix + "EntryIterator constructor: " + dx.getMessage();
            throw ex;
          }
          catch(com.sleepycat.db.DatabaseException dx)
          {
            dead();
            DatabaseException ex = new DatabaseException();
            ex.initCause(dx);
            ex.message = _errorPrefix + "EntryIterator constructor: " + dx.getMessage();
            throw ex;
          }

          synchronized(_iteratorList)
          {
            _iteratorList.addFirst(this);
            java.util.Iterator p = _iteratorList.iterator();
            p.next();
            _iteratorListToken = p;
          }
        }

        public boolean
        hasNext()
        {
          if(_current == null || _current == _lastReturned)
          {
            com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry();
            com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
            com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry();
            com.sleepycat.db.OperationStatus status = null;

            try
            {
                if(_index != null)
                {
                  com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)_cursor;
                  if(_current == null)
                  {
                      //
                      // First key
                      //
                      if(_fromKey != null)
                      {
                        dbIKey.setData(_fromKey);
                        status = c.getSearchKeyRange(dbIKey, dbKey, dbValue, null);
                      }
                      else
                      {
                        status = c.getFirst(dbIKey, dbKey, dbValue, null);
                      }
                  }
                  else
                  {   
                      if(_onlyFromKeyDups)
                      {
                        status = c.getNextDup(dbIKey, dbKey, dbValue, null);
                      }
                      else if(_skipDups)
                      {
                        status = c.getNextNoDup(dbIKey, dbKey, dbValue, null);
                      }
                      else
                      {
                        status = c.getNext(dbIKey, dbKey, dbValue, null);
                      }
                  }
                }
                else
                {
                  if(_current == null && _fromKey != null)
                  {
                      dbKey.setData(_fromKey);
                      status = _cursor.getSearchKey(dbKey, dbValue, null);
                  }
                  else
                  {
                      status = _cursor.getNext(dbKey, dbValue, null);
                  }
                }
            }
            catch(com.sleepycat.db.DeadlockException dx)
            {
                dead();
                DeadlockException ex = new DeadlockException();
                ex.initCause(dx);
                ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException dx)
            {
                dead();
                DatabaseException ex = new DatabaseException();
                ex.initCause(dx);
                ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage();
                throw ex;
            }
            
            if(status == com.sleepycat.db.OperationStatus.SUCCESS)
            {
                //
                // Verify it's < _toKey
                //
                boolean inRange = true;
                if(_toKey != null)
                {
                  if(_index != null)
                  {
                      inRange = _index.compare(dbIKey.getData(), _toKey) < 0;
                  }
                  else
                  {
                      inRange = _comparator.compare(dbKey.getData(), _toKey) < 0;
                  }
                }
                
                if(inRange)
                {
                  _current = new Entry(this, Map.this, _connection.communicator(), dbKey, 
                                   dbValue.getData(), dbIKey.getData());
                  return true;
                }
            }
            return false;
          }
          else
          {
            return true;
          }
        }
      
        public Object
        next()
        {
          if(hasNext())
          {
            _lastReturned = _current;
            return _lastReturned;
          }
          else
          {
            throw new java.util.NoSuchElementException();
          }
        }

        public void
        remove()
        {
          if(_txn != null)
          {
            closeAllIteratorsExcept(this, false);
          }

          //
          // Removes the last object returned by next()
          //
          if(_lastReturned == null)
          {
            throw new IllegalStateException();
          }
          
          if(_lastReturned == _current)
          {
            try
            {
                if(_cursor.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY)
                {
                  throw new IllegalStateException();
                }
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                dead();
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Dbc.del: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            { 
                DatabaseException ex = new DatabaseException();
                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)
            //
            
            //
            // This works only for non-index iterators
            //
            if(_index != null)
            {
                throw new UnsupportedOperationException();
            }

            com.sleepycat.db.Cursor clone = null;

            try
            {
                clone = _cursor.dup(true);

                //
                // Not interested in data
                //
                com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry();
                dbValue.setPartial(true);
                
                com.sleepycat.db.OperationStatus rc = clone.getSearchKey(_lastReturned.getDbKey(), dbValue, null);

                if(rc == com.sleepycat.db.OperationStatus.NOTFOUND)
                {
                  throw new IllegalStateException();
                }
                if(clone.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY)
                {
                  throw new IllegalStateException();
                }
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                dead();
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "EntryIterator.remove: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            { 
                DatabaseException ex = new DatabaseException();
                ex.initCause(e);
                ex.message = _errorPrefix + "EntryIterator.remove: " + e.getMessage();
                throw ex;
            }
            finally
            {
                if(clone != null)
                {
                  closeCursor(clone);
                }
            }
          }
        }

        //
        // Extra operations.
        //
        public void
        close()
        {
          close(false);
      }

      //
      // The synchronized is needed because this method can be called 
      // concurrently by Connection, Map and Map.EntryIterator finalizers.
      //
      synchronized void
      close(boolean finalizing)
      {
          if(finalizing && (_cursor != null || _txn != null) && _connection.closeInFinalizeWarning())
          {
            _connection.communicator().getLogger().warning(
                "finalize() closing a live iterator on Map \"" + _db.dbName() + "\"; the application " +
                 "should have closed it earlier by calling Map.EntryIterator.close(), " +
                 "Map.closeAllIterators(), Map.close(), Connection.close(), or (if also " +
                 "leaking a transaction) Transaction.commit() or Transaction.rollback()");
          }
       
          if(_iteratorListToken != null)
          {
            synchronized(_iteratorList)
            {
                _iteratorListToken.remove();
                _iteratorListToken = null;
            }
          }
   
          if(_cursor != null) 
          {
            com.sleepycat.db.Cursor cursor = _cursor;
            _cursor = null;
            closeCursor(cursor);
          }
          
          if(_txn != null)
          {
            String txnId = null;

            try
            {
                if(_connection.txTrace() >= 1)
                {
                  txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); 
                }

                _txn.commit();

                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "committed transaction " + txnId);
                }
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "failed to commit transaction " + txnId + ": " +
                                                     e.getMessage());
                }

                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "DbTxn.commit: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            {
                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "failed to commit transaction " + txnId + ": " +
                                                     e.getMessage());
                }

                DatabaseException ex = new DatabaseException();
                ex.initCause(e);
                ex.message = _errorPrefix + "DbTxn.commit: " + e.getMessage();
                throw ex;
            }
            finally
            {
                _txn = null;
            }
          }   
      }
      
      //
      // An alias for close()
      //
      public void
      destroy()
      {
          close();
      }

      protected void
        finalize()
        {
            close(true);
        }

      void
      setValue(Map.Entry entry, Object value)
      {
          if(_index != null)
          {
            throw new UnsupportedOperationException(
                _errorPrefix + "Cannot set an iterator retrieved through an index");
          }

          if(_txn != null)
          {
            closeAllIteratorsExcept(this, false);
          }

          //
          // Are we trying to update the current value?
          //
          if(_current == entry)
          {
            //
            // Yes, update it directly
            //
            byte[] v = encodeValue(value, _connection.communicator());
            com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v);
            
            try
            {
                _cursor.putCurrent(dbValue);
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                dead();
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "Dbc.put: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            { 
                DatabaseException ex = new DatabaseException();
                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.Cursor clone = null;

            try
            {
                clone = _cursor.dup(true);

                //
                // Not interested in data
                //
                com.sleepycat.db.DatabaseEntry dummy = new com.sleepycat.db.DatabaseEntry();
                dummy.setPartial(true);
                
                com.sleepycat.db.OperationStatus rc = clone.getSearchKey(entry.getDbKey(), dummy, null);

                if(rc == com.sleepycat.db.OperationStatus.NOTFOUND)
                {
                  NotFoundException ex = new NotFoundException();
                  ex.message = _errorPrefix + "Dbc.get: DB_NOTFOUND";
                  throw ex;
                }
               
                byte[] v = encodeValue(value, _connection.communicator());
                com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v);
                clone.putCurrent(dbValue);
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                dead();
                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "EntryIterator.setValue: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            { 
                DatabaseException ex = new DatabaseException();
                ex.initCause(e);
                ex.message = _errorPrefix + "EntryIterator.setValue: " + e.getMessage();
                throw ex;
            }
            finally
            {
                if(clone != null)
                {
                  closeCursor(clone);
                }
            }
          }
      }

      private void
      closeCursor(com.sleepycat.db.Cursor cursor)
      {
          try
          {
            cursor.close();
          }
          catch(com.sleepycat.db.DeadlockException e)
          {
            dead();
            DeadlockException ex = new DeadlockException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Dbc.close: " + e.getMessage();
            throw ex;
          }
          catch(com.sleepycat.db.DatabaseException e)
          { 
            DatabaseException ex = new DatabaseException();
            ex.initCause(e);
            ex.message = _errorPrefix + "Dbc.close: " + e.getMessage();
            throw ex;
          }
      }

      private void
      dead()
      {
          if(_cursor != null) 
          {
            com.sleepycat.db.Cursor cursor = _cursor;
            _cursor = null;
            closeCursor(cursor);
          }

          if(_txn != null)
          {
            String txnId = null;

            try
            {
                if(_connection.txTrace() >= 1)
                {
                  txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); 
                }

                _txn.abort();

                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "rolled back transaction " + txnId);
                }
            }
            catch(com.sleepycat.db.DeadlockException e)
            {
                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "failed to roll back transaction " + txnId +
                                                     ": " + e.getMessage());
                }

                DeadlockException ex = new DeadlockException();
                ex.initCause(e);
                ex.message = _errorPrefix + "DbTxn.abort: " + e.getMessage();
                throw ex;
            }
            catch(com.sleepycat.db.DatabaseException e)
            {
                if(_connection.txTrace() >= 1)
                {
                  _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix +
                                                     "failed to roll back transaction " +
                                                     txnId + ": " + e.getMessage());
                }

                DatabaseException ex = new DatabaseException();
                ex.initCause(e);
                ex.message = _errorPrefix + "DbTxn.abort: " + e.getMessage();
                throw ex;
            }
            finally
            {
                _txn = null;
            }
          }
      }

      private com.sleepycat.db.Transaction _txn;
        private com.sleepycat.db.Cursor _cursor;
        private Entry _current;
        private Entry _lastReturned;
      private java.util.Iterator _iteratorListToken;
      
      private final Index _index;
      private final byte[] _fromKey;
      private final byte[] _toKey;
      private final boolean _onlyFromKeyDups;
      private final boolean _skipDups;
    }

    static class Entry implements java.util.Map.Entry 
    {
        public
        Entry(EntryIteratorImpl iterator, Map map, Ice.Communicator communicator, 
            com.sleepycat.db.DatabaseEntry dbKey, byte[] valueBytes, byte[] indexBytes)
        {
            _iterator = iterator;
          _map = map;
          _communicator = communicator;
            _dbKey = dbKey;
          _valueBytes = valueBytes;
          _indexBytes = indexBytes;
        }

      public Object
      getKey()
      {
            if(!_haveKey)
            {
                assert(_dbKey != null);
                _key = _map.decodeKey(_dbKey.getData(), _communicator);
                _haveKey = true;
            }
          return _key;
      }

      public Object
      getValue()
      {
            if(!_haveValue)
            {
                assert(_valueBytes != null);
                _value = _map.decodeValue(_valueBytes, _communicator);
                _haveValue = true;
            //
            // Not needed anymore
            //
            _valueBytes = null;
            }
          return _value;
      }

      public byte[]
      getIndexBytes()
      {
          return _indexBytes;
      }

      public Object
      setValue(Object value)
      {
          Object old = getValue();
          _iterator.setValue(this, value);
          _value = value;
            _haveValue = true;
          return old;
      }

      public boolean
      equals(Object o)
      {
          if(!(o instanceof Map.Entry))
          {
            return false;
          }
          Map.Entry e = (Map.Entry)o;
          return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue());
      }

      public int
      hashCode()
      {
          return ((getKey()   == null) ? 0 : getKey().hashCode()) ^
                 ((getValue() == null) ? 0 : getValue().hashCode());
      }

      public String
      toString()
      {
          return getKey() + "=" + getValue();
      }

      com.sleepycat.db.DatabaseEntry
        getDbKey()
      {
          return _dbKey;
      }

      private /*static*/ boolean
      eq(Object o1, Object o2)
      {
          return (o1 == null ? o2 == null : o1.equals(o2));
      }

      private EntryIteratorImpl _iterator;
      private Map _map;
      private Ice.Communicator _communicator;
      private com.sleepycat.db.DatabaseEntry _dbKey;
      private byte[] _valueBytes;
      private byte[] _indexBytes;
      private Object _key;
        private boolean _haveKey = false;
      private Object _value;
        private boolean _haveValue = false;
    }

    public static class Patcher implements IceInternal.Patcher
    {
        public
        Patcher(String type)
        {
            this.type = type;
        }

        public void
        patch(Ice.Object v)
        {
            value = v;
        }

        public String
        type()
        {
            return this.type;
        }

        public Ice.Object
        value()
        {
            return this.value;
        }

        public String type;
        public Ice.Object value;
    }
    
    protected ConnectionI _connection;
    private final Comparator _comparator;

    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 java.util.Map _indexMap = new java.util.HashMap();
}

Generated by  Doxygen 1.6.0   Back to index