public void doReclaim()

in environment/src/main/java/jetbrains/exodus/tree/btree/LeafNodeDup.java [103:184]


    public void doReclaim(@NotNull final BTreeReclaimTraverser context, final int leafIndex) {
        final long keyAddress = context.currentNode.getKeyAddress(leafIndex);
        final BTreeDupMutable tree;
        final BaseLeafNodeMutable mutable;
        final BTreeMutable mainTree = context.mainTree;
        if (keyAddress < 0) {
            mutable = ((BasePageMutable) context.currentNode).keys[leafIndex];
            if (mutable.isDup()) {
                tree = ((LeafNodeDupMutable) mutable).tree;
            } else {
                return; // current node is duplicate no more
            }
        } else if (keyAddress == getAddress()) {
            final BasePageMutable node = context.currentNode.getMutableCopy(mainTree);
            final LeafNodeDupMutable converted = LeafNodeDupMutable.convert(this, mainTree);
            mainTree.addExpiredLoggable(keyAddress);
            tree = converted.tree;
            mutable = converted;
            node.set(leafIndex, mutable, null);
            context.wasReclaim = true;
            context.setPage(node);
        } else {
            final RandomAccessLoggable upToDate = mainTree.getLoggable(keyAddress);
            switch (upToDate.getType()) {
                case BTreeBase.LEAF_DUP_BOTTOM_ROOT:
                case BTreeBase.LEAF_DUP_INTERNAL_ROOT:
                    mutable = null; // indicates that loggable was not updated
                    tree = new LeafNodeDup(mainTree, upToDate).getTreeCopyMutable();
                    tree.mainTree = mainTree;
                    break;
                case BTreeBase.LEAF:
                    return; // current node is duplicate no more
                default:
                    throw new ExodusException("Unexpected loggable type " + upToDate.getType());
            }
        }
        // TODO: implement mutable lower bound to avoid allocations (yapavel knows how)
        final BTreeReclaimTraverser dupStack = new BTreeReclaimTraverser(tree);
        for (final RandomAccessLoggable loggable : context.dupLeafsLo) {
            switch (loggable.getType()) {
                case BTreeBase.DUP_LEAF:
                    new LeafNode(log, loggable).reclaim(dupStack);
                    break;
                case BTreeBase.DUP_BOTTOM:
                    tree.reclaimBottom(loggable, dupStack);
                    break;
                case BTreeBase.DUP_INTERNAL:
                    tree.reclaimInternal(loggable, dupStack);
                    break;
                default:
                    throw new ExodusException("Unexpected loggable type " + loggable.getType());
            }
        }
        // TODO: less copy-paste
        for (final RandomAccessLoggable loggable : context.dupLeafsHi) {
            switch (loggable.getType()) {
                case BTreeBase.DUP_LEAF:
                    new LeafNode(log, loggable).reclaim(dupStack);
                    break;
                case BTreeBase.DUP_BOTTOM:
                    tree.reclaimBottom(loggable, dupStack);
                    break;
                case BTreeBase.DUP_INTERNAL:
                    tree.reclaimInternal(loggable, dupStack);
                    break;
                default:
                    throw new ExodusException("Unexpected loggable type " + loggable.getType());
            }
        }
        while (dupStack.canMoveUp()) {
            // wire up mutated stuff
            dupStack.popAndMutate();
        }
        if (dupStack.wasReclaim && mutable == null) { // was reclaim in sub-tree
            mainTree.addExpiredLoggable(keyAddress);
            final BasePageMutable node = context.currentNode.getMutableCopy(mainTree);
            node.set(leafIndex, new LeafNodeDupMutable(tree), null);
            context.wasReclaim = true;
            context.setPage(node);
        }
        //TODO: remove? dupStack.clear();
    }