예제 #1
0
  @Override
  @Nullable
  public BasePageMutable put(
      @NotNull ByteIterable key, @NotNull ByteIterable value, boolean overwrite, boolean[] result) {
    final SearchRes res = binarySearch(key);

    final BTreeMutable tree = (BTreeMutable) getTree();

    int pos = res.index;
    if (pos >= 0) {
      if (overwrite) {
        // key found
        final ILeafNode ln = res.key;
        if (ln == null) {
          throw new IllegalStateException("Leaf is expected to be found");
        }
        if (tree.allowsDuplicates) {
          // overwrite for tree with duplicates means add new value to existing key
          // manage sub-tree of duplicates
          // ln may be mutable or immutable, with dups or without
          LeafNodeDupMutable lnm = LeafNodeDupMutable.convert(ln, tree);
          if (lnm.put(value)) {
            tree.addExpiredLoggable(ln.getAddress());
            set(pos, lnm, null);
            result[0] = true;
          }
          // main tree size will be auto-incremented with some help from duplicates tree
        } else {
          if (!ln.isDupLeaf()) {
            // TODO: remove this forced update when we no longer need meta tree cloning
            tree.addExpiredLoggable(keysAddresses[pos]);
            set(pos, tree.createMutableLeaf(key, value), null);
            // this should be always true in order to keep up with keysAddresses[pos] expiration
            result[0] = true;
          }
        }
      }
      return null;
    }

    // if found - insert at this position, else insert after found
    if (pos < 0) pos = -pos - 1;
    else pos++;

    final BasePageMutable page = insertAt(pos, tree.createMutableLeaf(key, value), null);
    result[0] = true;
    tree.incrementSize();
    return page;
  }
예제 #2
0
  @Override
  public boolean delete(@NotNull ByteIterable key, @Nullable ByteIterable value) {
    final SearchRes sp = binarySearch(key);
    final int pos = sp.index;
    if (pos < 0) return false;

    final BTreeMutable tree = (BTreeMutable) getTree();

    if (tree.allowsDuplicates) {
      final ILeafNode ln = sp.key;
      if (value == null) { // size will be decreased dramatically, all dup sub-tree will expire
        tree.addExpiredLoggable(keysAddresses[pos]);
        LongIterator it = ln.addressIterator();
        while (it.hasNext()) tree.addExpiredLoggable(it.next());
        copyChildren(pos + 1, pos);
        tree.decrementSize(ln.getDupCount());
        decrementSize(1);
        return true;
      }
      if (ln.isDup()) {
        LeafNodeDupMutable lnm;
        boolean res;
        if (ln.isMutable()) {
          lnm = (LeafNodeDupMutable) ln;
          res = lnm.delete(value);
        } else {
          LeafNodeDup lnd = (LeafNodeDup) ln;

          final BTreeDupMutable dupTree = lnd.getTreeCopyMutable();
          dupTree.mainTree = tree;

          if (res = dupTree.delete(value)) {
            tree.addExpiredLoggable(ln.getAddress());
            lnm = LeafNodeDupMutable.convert(ln, tree, dupTree);
            // remember in page
            set(pos, lnm, null);
          } else {
            return false;
          }
        }

        if (res) {
          // if only one node left
          if (lnm.getRootPage().isBottom() && lnm.getRootPage().getSize() == 1) {
            // expire previous address
            tree.addExpiredLoggable(keysAddresses[pos]);
            // expire single duplicate from sub-tree
            LongIterator it = ln.addressIterator();
            tree.addExpiredLoggable(it.next());
            // convert back to leaf without duplicates
            set(pos, tree.createMutableLeaf(lnm.getKey(), lnm.getValue()), null);
          }
          return true;
        }
        return false;
      }
    }

    tree.addExpiredLoggable(keysAddresses[pos]);
    copyChildren(pos + 1, pos);
    tree.decrementSize(1);
    decrementSize(1);

    return true;
  }