Mercurial > hg > Members > shoshi > TreeCMSv2
view src/treecms/memory/OnMemoryMonotonicTree.java @ 27:aecc55e87143 default tip
test commit
author | Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 18 Aug 2011 17:37:03 +0900 |
parents | 9cb971a68cc5 |
children |
line wrap: on
line source
package treecms.memory; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import treecms.api.MonotonicTree; import treecms.api.MonotonicTreeNode; import treecms.api.Node; import treecms.api.NodeID; import treecms.merger.Merger; import treecms.tree.id.NodeIDProvider; /** * provides monotonic tree modification method in local (== not thread-safe) */ public class OnMemoryMonotonicTree implements MonotonicTree { private final Merger<OnMemoryNode> m_merger; private final OnMemoryMonotonicTree m_tree; private final AtomicReference<OnMemoryNode> m_tip; private final AtomicReference<OnMemoryNode> m_snapshot; private final OnMemoryMonotonicTreeNode m_editing; private OnMemoryMonotonicTree(NodeIDProvider _provider,OnMemoryMonotonicTree _tree,Merger<OnMemoryNode> _merger) { m_merger = _merger; m_tree = _tree; m_tip = new AtomicReference<OnMemoryNode>(); m_snapshot = new AtomicReference<OnMemoryNode>(); //if remote tree (target tree) is exist , then import root node form remote tree. if(m_tree != null){ m_tip.set(m_tree.m_tip.get()); }else{ m_tip.set(new OnMemoryNode(_provider.create(),null)); } m_snapshot.set(m_tip.get()); //create editing node. m_editing = new OnMemoryMonotonicTreeNode(m_snapshot.get(),null); } public static OnMemoryMonotonicTree createInstance(NodeIDProvider _provider,OnMemoryMonotonicTree _tree,Merger<OnMemoryNode> _merger) { OnMemoryMonotonicTree tree = new OnMemoryMonotonicTree(_provider,_tree,_merger); return tree; } public OnMemoryNode get(String _fid) { if(_fid == null){ throw new NullPointerException("the parameter _fid must not be null."); } OnMemoryNode root = (OnMemoryNode)m_editing.getNode(); return (OnMemoryNode)search(_fid,root); } private Node search(String _fid,Node _node) { if(_node.getID().getFamilyID().equals(_fid)){ return _node; } for(Node child : _node.getList()){ Node ret = search(_fid,child); if(ret != null){ return ret; } } return null; } @Override public boolean commit(boolean _doForceCommit) { //if commit target is exist. if(m_tree != null){ //if force commit is enabled. if(_doForceCommit){ //force commit is just replace the target root to own root. return true; //always returns true. } //trying to compare and swap tip to editing root. (trying to commit) OnMemoryNode root = (OnMemoryNode)m_editing.getNode(); if(m_tip.compareAndSet(m_snapshot.get(),root)){ return true; } //failed to CAS modified tree } return false; } /** * this method may fail when failed to commit tree. */ public boolean push() { //pushing local root node to remote tree. OnMemoryNode local = (OnMemoryNode)this.m_editing.getNode(); OnMemoryNode snapshot = this.m_snapshot.get(); //compare remote tip and own snapshot boolean ret = m_tree.m_tip.compareAndSet(snapshot,local); //if that is false , that means need to merge. return ret; } @Override public boolean pull() { //need to compare and swap here? or just replace OnMemoryNode newRoot = m_tree.m_tip.get(); m_tip.set(newRoot); m_editing. return true; } @Override public boolean check() { if(m_tree == null){ return false; } OnMemoryNode root = m_root.get(); return m_tree.m_root.get().equals(root); } @Override public void merge() { OnMemoryNode tree1 = m_root.get(); OnMemoryNode tree2 = (OnMemoryNode)m_editing.get().getNode(); OnMemoryNode merged = m_merger.merge(tree1,tree2); m_editing.set(new OnMemoryMonotonicTreeNode(merged,null)); } @Override public MonotonicTreeNode getRoot() { return m_editing.get(); } }