Esempio n. 1
0
  /**
   * Associates the specified value with the specified key.
   *
   * @param key key with which the specified value is to be assocated.
   * @param value value to be associated with the specified key.
   * @return object which was previously associated with the given key, or <code>null</code> if no
   *     association existed.
   */
  Object put(Object key, Object value) throws IOException {
    if (value == null) {
      return remove(key);
    }
    int hash = hashCode(key);
    long child_recid = _children[hash];
    if (child_recid == 0) {
      // no bucket/page here yet, let's create a bucket
      HashBucket bucket = new HashBucket(tree, _depth + 1);

      // insert (key,value) pair in bucket
      Object existing = bucket.addElement(key, value);

      long b_recid = _recman.insert(bucket, tree.SERIALIZER);
      _children[hash] = b_recid;

      _recman.update(_recid, this, tree.SERIALIZER);

      // System.out.println("Added: "+bucket);
      return existing;
    } else {
      HashNode node = (HashNode) _recman.fetch(child_recid, tree.SERIALIZER);

      if (node instanceof HashDirectory) {
        // recursive insert in next directory level
        HashDirectory dir = (HashDirectory) node;
        dir.setPersistenceContext(_recman, child_recid);
        return dir.put(key, value);
      } else {
        // node is a bucket
        HashBucket bucket = (HashBucket) node;
        if (bucket.hasRoom()) {
          Object existing = bucket.addElement(key, value);
          _recman.update(child_recid, bucket, tree.SERIALIZER);
          // System.out.println("Added: "+bucket);
          return existing;
        } else {
          // overflow, so create a new directory
          if (_depth == MAX_DEPTH) {
            throw new RuntimeException("Cannot create deeper directory. " + "Depth=" + _depth);
          }
          HashDirectory dir = new HashDirectory(tree, (byte) (_depth + 1));
          long dir_recid = _recman.insert(dir, tree.SERIALIZER);
          dir.setPersistenceContext(_recman, dir_recid);

          _children[hash] = dir_recid;
          _recman.update(_recid, this, tree.SERIALIZER);

          // discard overflown bucket
          _recman.delete(child_recid);

          // migrate existing bucket elements
          ArrayList keys = bucket.getKeys();
          ArrayList values = bucket.getValues();
          int entries = keys.size();
          for (int i = 0; i < entries; i++) {
            dir.put(keys.get(i), values.get(i));
          }

          // (finally!) insert new element
          return dir.put(key, value);
        }
      }
    }
  }