view src/main/java/jp/ac/u_ryukyu/ie/cr/jungleNetwork/persistent/TransactionManager/PersistentDifferenceTransactionManager.java @ 329:2a0cb1f0ba4e

rename Error package
author kono
date Sat, 08 Jul 2017 21:05:55 +0900
parents d6b81870216b
children
line wrap: on
line source

package jp.ac.u_ryukyu.ie.cr.jungleNetwork.persistent.TransactionManager;

import jp.ac.u_ryukyu.ie.cr.jungle.data.list.List;
import jp.ac.u_ryukyu.ie.cr.jungle.persistent.ChangeListWriter;
import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.DifferentialInterfaceTraverser;
import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.InterfaceTraverser;
import jp.ac.u_ryukyu.ie.cr.jungle.store.TreeContext;
import jp.ac.u_ryukyu.ie.cr.jungle.store.index.Index;
import jp.ac.u_ryukyu.ie.cr.jungle.store.index.ParentIndex;
import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.DefaultTreeOperationLog;
import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.TreeOperationLog;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.context.DifferenceTreeContext;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.manager.TransactionManager;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNodeChildren;
import jp.ac.u_ryukyu.ie.cr.jungle.tree.TreeType;
import jp.ac.u_ryukyu.ie.cr.jungle.util.DefaultEither;
import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
import jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.Error;
import jp.ac.u_ryukyu.ie.cr.jungleNetwork.persistent.PersistentChangeList;

import java.util.concurrent.atomic.AtomicReference;

import static jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.TransactionError.APPEND_FAILD;
import static jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.TreeEditorError.CAS_MISS;


public class PersistentDifferenceTransactionManager implements TransactionManager {
    private final AtomicReference<TreeContext> repository;
    private final TreeContext tip;
    private final ChangeListWriter writer;
    private final String uuid;
    private final int bufferSize;

    public PersistentDifferenceTransactionManager(ChangeListWriter writer, TreeContext tip, AtomicReference<TreeContext> repository, String uuid, int bufferSize) {
        this.repository = repository;
        this.tip = tip;
        this.writer = writer;
        this.uuid = uuid;
        this.bufferSize = bufferSize;
    }

    /**
     * DifferentialTreeではIndexの更新時
     * delete処理を行う必要が無いので
     * editNodeListは使用しない
     * commitの第三引数のeditNodeListは使用しない
     * しかし、末尾のノード情報をrepositoryに入れる必要があるため
     * editNodeListを使ってここに持って来ている
     * 昔はJungleTreeEditorで後からsetしていたが、
     * DifferentialInterfaceTraverserに末尾ノードを入れる必要が出てきたので
     * この実装になった
     */
    @Override
    public Either<Error, TransactionManager> commit(TreeNode subTreeRoot, TreeOperationLog log, List<TreeNode> editNodeList) {
        long currentRevision = tip.revision();
        long nextRevision = currentRevision + 1;
        //NodeOperation commitOperation = new Commit();
        //TreeOperationLog newLog = log.add(new DefaultNodePath(), commitOperation);
        final String treeName = tip.getTreeName();

        PersistentChangeList list;
        if (log.length() > bufferSize)
            list = new PersistentChangeList(uuid, treeName, TreeType.DIFFERENCE, new DefaultTreeOperationLog());
        else
            list = new PersistentChangeList(uuid, treeName, TreeType.DIFFERENCE, log);

        TreeNode root = tip.getRoot();
        Index index = tip.getIndex();
        ParentIndex parentIndex = tip.getParentIndex();
        TreeNode endNode = editNodeList.get(0);
        InterfaceTraverser traverser = new DifferentialInterfaceTraverser(root, endNode, index, parentIndex, true);
        TreeContext newTreeContext = new DifferenceTreeContext(root, endNode, tip, list, uuid, treeName, nextRevision, traverser);
        if (repository.compareAndSet(newTreeContext.prev(), newTreeContext)) {
            Either<Error, TreeNode> either = appendSubTree(subTreeRoot);
            if (either.isA())
                return DefaultEither.newA(either.a());
            traverser.updateIndex(tip.getEndNode());
            if (log.length() > bufferSize) {
                PersistentChangeList writeList = new PersistentChangeList(uuid, treeName, TreeType.DIFFERENCE, log);
                writer.write(writeList);
            }
            TransactionManager txManager = new PersistentDifferenceTransactionManager(writer, newTreeContext, repository, uuid, bufferSize);
            return DefaultEither.newB(txManager);
        }

        return DefaultEither.newA(CAS_MISS);
    }

    private Either<Error, TreeNode> appendSubTree(TreeNode subTreeRoot) {
        TreeNode appendedNode = tip.getEndNode();
        TreeNodeChildren children = appendedNode.getChildren();
        if (children.size() != 0)
            return DefaultEither.newA(APPEND_FAILD); //append Nodeが1つ以上子を持つ場合過去の木であるため、変更させない。そうすることで整合性を保証する
        return children.addNewChildAt(0, subTreeRoot);
    }


    @Override
    public Either<Error, TransactionManager> flashCommit(TreeNode _newRoot, TreeOperationLog _log) {
        return null;//commit(_newRoot, _log);
    }

    @Override
    public String getUUID() {
        return uuid;
    }

    @Override
    public long getRevision() {
        return tip.revision();
    }

}