Пример #1
0
  /**
   * Remove an entry with the given key from the BTree.
   *
   * @param key Removal key
   * @return Value associated with the key, or null if no entry with given key existed in the BTree.
   */
  public synchronized Object remove(Object key) throws IOException {
    if (key == null) {
      throw new IllegalArgumentException("Argument 'key' is null");
    }

    BPage rootPage = getRoot();
    if (rootPage == null) {
      return null;
    }
    boolean dirty = false;
    BPage.RemoveResult remove = rootPage.remove(_height, key);
    if (remove._underflow && rootPage.isEmpty()) {
      _height -= 1;
      dirty = true;

      // TODO:  check contract for BPages to be removed from recman.
      if (_height == 0) {
        _root = 0;
      } else {
        _root = rootPage.childBPage(_pageSize - 1)._recid;
      }
    }
    if (remove._value != null) {
      _entries--;
      dirty = true;
    }
    if (dirty) {
      _recman.update(_recid, this);
    }
    return remove._value;
  }
Пример #2
0
 /**
  * Load a persistent BTree.
  *
  * @param recman RecordManager used to store the persistent btree
  * @param recid Record id of the BTree
  */
 public static BTree load(RecordManager recman, long recid) throws IOException {
   BTree btree = (BTree) recman.fetch(recid);
   btree._recid = recid;
   btree._recman = recman;
   btree._bpageSerializer = new BPage();
   btree._bpageSerializer._btree = btree;
   return btree;
 }
Пример #3
0
  /**
   * Insert an entry in the BTree.
   *
   * <p>The BTree cannot store duplicate entries. An existing entry can be replaced using the <code>
   * replace</code> flag. If an entry with the same key already exists in the BTree, its value is
   * returned.
   *
   * @param key Insert key
   * @param value Insert value
   * @param replace Set to true to replace an existing key-value pair.
   * @return Existing value, if any.
   */
  public synchronized Object insert(Object key, Object value, boolean replace) throws IOException {
    if (key == null) {
      throw new IllegalArgumentException("Argument 'key' is null");
    }
    if (value == null) {
      throw new IllegalArgumentException("Argument 'value' is null");
    }

    BPage rootPage = getRoot();

    if (rootPage == null) {
      // BTree is currently empty, create a new root BPage
      if (DEBUG) {
        System.out.println("BTree.insert() new root BPage");
      }
      rootPage = new BPage(this, key, value);
      _root = rootPage._recid;
      _height = 1;
      _entries = 1;
      _recman.update(_recid, this);
      return null;
    } else {
      BPage.InsertResult insert = rootPage.insert(_height, key, value, replace);
      boolean dirty = false;
      if (insert._overflow != null) {
        // current root page overflowed, we replace with a new root page
        if (DEBUG) {
          System.out.println("BTree.insert() replace root BPage due to overflow");
        }
        rootPage = new BPage(this, rootPage, insert._overflow);
        _root = rootPage._recid;
        _height += 1;
        dirty = true;
      }
      if (insert._existing == null) {
        _entries++;
        dirty = true;
      }
      if (dirty) {
        _recman.update(_recid, this);
      }
      // insert might have returned an existing value
      return insert._existing;
    }
  }
Пример #4
0
 /** Return the root BPage, or null if it doesn't exist. */
 private BPage getRoot() throws IOException {
   if (_root == 0) {
     return null;
   }
   BPage root = (BPage) _recman.fetch(_root, _bpageSerializer);
   root._recid = _root;
   root._btree = this;
   return root;
 }
Пример #5
0
  /**
   * Create a new persistent BTree with the given number of entries per node.
   *
   * @param recman Record manager used for persistence.
   * @param comparator Comparator used to order index entries
   * @param keySerializer Serializer used to serialize index keys (optional)
   * @param valueSerializer Serializer used to serialize index values (optional)
   * @param pageSize Number of entries per page (must be even).
   */
  public static BTree createInstance(
      RecordManager recman,
      Comparator comparator,
      Serializer keySerializer,
      Serializer valueSerializer,
      int pageSize)
      throws IOException {
    BTree btree;

    if (recman == null) {
      throw new IllegalArgumentException("Argument 'recman' is null");
    }

    if (comparator == null) {
      throw new IllegalArgumentException("Argument 'comparator' is null");
    }

    if (!(comparator instanceof Serializable)) {
      throw new IllegalArgumentException("Argument 'comparator' must be serializable");
    }

    if (keySerializer != null && !(keySerializer instanceof Serializable)) {
      throw new IllegalArgumentException("Argument 'keySerializer' must be serializable");
    }

    if (valueSerializer != null && !(valueSerializer instanceof Serializable)) {
      throw new IllegalArgumentException("Argument 'valueSerializer' must be serializable");
    }

    // make sure there's an even number of entries per BPage
    if ((pageSize & 1) != 0) {
      throw new IllegalArgumentException("Argument 'pageSize' must be even");
    }

    btree = new BTree();
    btree._recman = recman;
    btree._comparator = comparator;
    btree._keySerializer = keySerializer;
    btree._valueSerializer = valueSerializer;
    btree._pageSize = pageSize;
    btree._bpageSerializer = new BPage();
    btree._bpageSerializer._btree = btree;
    btree._recid = recman.insert(btree);
    return btree;
  }