@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; }