Package org.apache.jackrabbit.oak.kernel

Source Code of org.apache.jackrabbit.oak.kernel.KernelNodeStoreBranch

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.kernel;

import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.mk.api.MicroKernelException;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStoreBranch;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;

/**
* {@code NodeStoreBranch} based on {@link MicroKernel} branching and merging.
* This implementation keeps changes in memory up to a certain limit and writes
* them back when the to the Microkernel branch when the limit is exceeded.
*/
class KernelNodeStoreBranch implements NodeStoreBranch {

    /** The underlying store to which this branch belongs */
    private final KernelNodeStore store;

    /** Root state of the base revision of this branch */
    private final NodeState base;

    /** Revision of the base state of this branch*/
    private final String baseRevision;

    /** Root state of the head revision of this branch*/
    private NodeState head;

    /** Head revision of this branch, null if not yet branched*/
    private String headRevision;

    KernelNodeStoreBranch(KernelNodeStore store, KernelNodeState root) {
        this.store = store;
        this.base = root;
        this.baseRevision = root.getRevision();
        this.head = root;
    }

    @Override
    public NodeState getBase() {
        return base;
    }

    @Override
    public NodeState getRoot() {
        checkNotMerged();
        return head;
    }

    @Override
    public void setRoot(NodeState newRoot) {
        checkNotMerged();
        if (!head.equals(newRoot)) {
            JsopDiff diff = new JsopDiff(store.getKernel());
            newRoot.compareAgainstBaseState(head, diff);
            commit(diff.toString());
        }
    }

    @Override
    public boolean move(String source, String target) {
        checkNotMerged();
        if (getNode(source) == null) {
            // source does not exist
            return false;
        }
        NodeState destParent = getNode(getParentPath(target));
        if (destParent == null) {
            // parent of destination does not exist
            return false;
        }
        if (destParent.getChildNode(getName(target)) != null) {
            // destination exists already
            return false;
        }

        commit(">\"" + source + "\":\"" + target + '"');
        return true;
    }

    @Override
    public boolean copy(String source, String target) {
        checkNotMerged();
        if (getNode(source) == null) {
            // source does not exist
            return false;
        }
        NodeState destParent = getNode(getParentPath(target));
        if (destParent == null) {
            // parent of destination does not exist
            return false;
        }
        if (destParent.getChildNode(getName(target)) != null) {
            // destination exists already
            return false;
        }

        commit("*\"" + source + "\":\"" + target + '"');
        return true;
    }

    @Override
    public NodeState merge() throws CommitFailedException {
        checkNotMerged();
        CommitHook commitHook = store.getHook();
        NodeState toCommit = commitHook.processCommit(base, head);
        NodeState oldRoot = head;
        setRoot(toCommit);

        try {
            if (headRevision == null) {
                // Nothing was written to this branch: return base state
                head = null// Mark as merged
                return base;
            }
            else {
                MicroKernel kernel = store.getKernel();
                String mergedRevision = kernel.merge(headRevision, null);
                headRevision = null;
                head = null// Mark as merged
                return store.getRootState(mergedRevision);
            }
        }
        catch (MicroKernelException e) {
            setRoot(oldRoot);
            throw new CommitFailedException(e);
        }
    }

    //------------------------------------------------------------< private >---

    private void checkNotMerged() {
        checkState(head != null, "Branch has already been merged");
    }

    private NodeState getNode(String path) {
        checkArgument(path.startsWith("/"));
        NodeState node = getRoot();
        for (String name : elements(path)) {
            node = node.getChildNode(name);
            if (node == null) {
                break;
            }
        }

        return node;
    }

    private void commit(String jsop) {
        MicroKernel kernel = store.getKernel();
        if (headRevision == null) {
            // create the branch if this is the first commit
            headRevision = kernel.branch(baseRevision);
        }

        headRevision = kernel.commit("", jsop, headRevision, null);
        head = store.getRootState(headRevision);
    }
}
TOP

Related Classes of org.apache.jackrabbit.oak.kernel.KernelNodeStoreBranch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.