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();
	}
}