view src/main/java/jp/ac/u_ryukyu/treevnc/server/TreeManagement.java @ 188:f176bffcdc4a

add showTreeNode option.
author oc
date Tue, 24 Jun 2014 16:49:29 +0900
parents 34b7558aeffa
children a204b53a30c7
line wrap: on
line source

package jp.ac.u_ryukyu.treevnc.server;


import java.io.IOException;
import java.util.LinkedList;

import jp.ac.u_ryukyu.treevnc.client.TreeVncProtocol;

public class TreeManagement {

	private LinkedList<TreeVNCNode> nodeList = new LinkedList<TreeVNCNode>();
	boolean runflag = false;
	private final int treebranch = 2;
	private boolean showTreeNode = false;

	public TreeManagement(String hostName, int vncport, boolean showTree) {
		TreeVNCNode me = new TreeVNCNode(hostName, vncport,"localhost");
		showTreeNode = showTree;
		me.setTreeNum(0);
		nodeList.add(me);
	}
	
//
//	private boolean checkAddress(String line) {
//		String test[] = line.split("\\.");
//		int a = Integer.parseInt(test[0]);
//		int b = Integer.parseInt(test[1]);
//		if ((192 == a && b == 168) || (172 == a && (b > 15 || b < 32))
//				|| 10 == a) {
//			return true;
//		} else {
//			return false;
//		}
//	}


	/**
	 * a parent is lost, remove from the list and move last one into here
	 * @param nodeNum
	 *            parent value
	 */
	private void moveLastNodeToLostNodePosition(int nodeNum) {
		nodeList.remove(nodeNum);
		TreeVNCNode node = nodeList.removeLast();
		node.setTreeNum(nodeNum);
		nodeList.add(nodeNum, node) ; 
	}

	private void checkParameter(int parent, int counter, int leaderflag2) {
		System.out.println("number p =" + parent);
		System.out.println("number i =" + counter);
		System.out.println("leaderflag=" + leaderflag2 + "\n");
	}

	private TreeVNCNode getParentNode(int nodeNum) {
		int parentnum = (nodeNum - 1) / treebranch;
        return  nodeList.get(parentnum);
	}
	
	
	public TreeVNCNode getChildNode(TreeVNCNode newparent, int i) {
		int child = newparent.getTreeNum() * treebranch + i + 1;
		if (child >= nodeList.size()) {
			return(null);
		} else {
			return(nodeList.get(child));
		}
		
	}	
	
	/**
	 * A parent is lost, move last node which has no child to the position 
	 * @param hostname
	 * @param port
	 */
    public void fixLostParent(String hostname, int port) {
        TreeVNCNode lostParentNode = lookup(nodeList,hostname,port);
        if (lostParentNode == null ) return;   // some thing wrong
        int treeNumber = lostParentNode.getTreeNum();
        TreeVNCNode deadParent = getParentNode(treeNumber);
        if (deadParent.getTreeNum() == 0) {
        	// if dead root, connect me.
        	connectTo(nodeList.getFirst(), lostParentNode);
        	return;
        }
        if (getChildNode(deadParent, 0) == null) return;
        moveLastNodeToLostNodePosition(deadParent.getTreeNum());
        lostNodeConnection(deadParent);
        // if lostParentNode is the last one, we don't need reconnection
        // Thread.sleep(intv_time);
    }

    /**
     * send reconnect to all children
     * @param newparent
     */
    private void lostNodeConnection(TreeVNCNode oldParent) {
    	TreeVNCNode newparent = nodeList.get(oldParent.getTreeNum());
    	TreeVNCNode grandfather = getParentNode(newparent.getTreeNum());
    	
    	connectTo(grandfather, newparent);
    	
        for(int i=0; i < treebranch; i++) {
        	TreeVNCNode child = getChildNode(newparent, i);
            if (child != null) {
                connectTo(newparent, child);
            }
        }
        
        if (showTreeNode) {
        	showTreeNode();
        }
    }



	public void connectTo(TreeVNCNode newparent, TreeVNCNode n) {
		TreeVncProtocol vc1 = new TreeVncProtocol(n.getHostname(),n.getPort());
		try {
		    short nodeId = (short) n.getTreeNum();
			vc1.connectTo(newparent.getHostname(), newparent.getPort(), isLeader(n), nodeId);
		} catch (IOException e) {
		    // log
		}
	}

    private int isLeader(TreeVNCNode n) {
        return ( n.getTreeNum() % treebranch == 1) ? 1 : 0;
    }

    private TreeVNCNode lookup(LinkedList<TreeVNCNode> list, String hostname, int port) {
	    for (TreeVNCNode r : list) {
	        if (r.getHostname().equals(hostname) && r.getPort() == port )
	                return r;
	    }
	    return null;
    }

	/**
	 * Determine tree topology and send CONNECT_TO command
	 * @param hostname
	 * @param port
	 */
	public void decideWhereToConnect(String hostname, int port, String localhostname) {
        TreeVNCNode node = new TreeVNCNode(hostname,port,localhostname);
        node.setTreeNum(nodeList.size());
        nodeList.add(node);
	    if (nodeList.size() >= treebranch + 1) {
		    TreeVNCNode parent = getParentNode(node.getTreeNum());
		    checkParameter(parent.getTreeNum(), nodeList.size(), isLeader(node));
		    connectTo(parent, node);
		} else {
		    // connect to me
			connectTo(nodeList.getFirst(), node);
		}
	    if (showTreeNode) {
	    	showTreeNode();
	    }
	}
	
	/**
	 * show Tree Node.
	 */
	public void showTreeNode() {
		int nl = 0, pow = 2;
        for (int i=0; i<nodeList.size(); i++) {
          	TreeVNCNode treeNode = nodeList.get(i);
        	System.out.print(treeNode.getTreeNum() + ":" + treeNode.getPort() + ":" + treeNode.getHostname());
        	if (i==nl) {
        		System.out.println();
        		nl = nl + pow;
        		pow = pow * pow;
        	} else {
        		System.out.print(" ");
        	}

        }
        System.out.println();
	}

	public LinkedList<TreeVNCNode> getList() {
		return nodeList;
	}

	public void setList(LinkedList<TreeVNCNode> _ls) {
		nodeList = _ls;
	}

	public int getTreeBranch() {
		return treebranch;
	}

}