view src/pathfinder/mergetest/SessionManagerSimulatorWithMerger.java @ 164:5c458f1a7679

*** empty log message ***
author tkaito
date Thu, 28 Aug 2008 22:18:28 +0900
parents e9047957acc2
children
line wrap: on
line source

package pathfinder.mergetest;

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

import pathfinder.mergetest.channels.*;

import remoteeditor.command.REPCommand;
import remoteeditor.network.REP;
import sample.merge.TranslaterImp1;

public class SessionManagerSimulatorWithMerger extends Thread{
	protected boolean running=true;
	protected List<ChannelSimulator<REPCommand>> csList;

	private List<TranslaterImp1> transList;
	private SelectorSimulator<REPCommand> selector;
	private List<EditorObject> editorList;
	private int startQuit2;
	//private List<LinkedList<REPCommand>> sendList;
	private List<PacketSet> waitingList;
	protected NetworkSimulator<REPCommand> ns;
	protected ServerChannelSimulator<REPCommand> scs;
	protected int IP;


	public SessionManagerSimulatorWithMerger(NetworkSimulator<REPCommand> _ns, int ip) {
		IP = ip;
		ns = _ns;
		transList = new ArrayList<TranslaterImp1>();
		editorList = new ArrayList<EditorObject>();
		waitingList = new LinkedList<PacketSet>();
		selector = new SelectorSimulator<REPCommand>();
		scs = new ServerChannelSimulator<REPCommand>(ns, selector);
		scs.bind(IP);
		selector.register(scs, SelectionKeySimulator.OP_ACCEPT);
	}

	/*
	protected void checkAccept(){
		ChannelSimulator<REPCommand> cs;
		while((cs=ns.accept())!=null){
			csList.add(cs);
			transList.add(new TranslaterImp1(transList.size()));
			editorList.add(new EditorObject<REPCommand>(editorList.size(), cs, new TranslaterImp1(editorList.size())));
			//sendList.add(new LinkedList<REPCommand>());
			registerChannel (selector, cs, SelectionKeySimulator.OP_READ);
		}
	}*/
	
	private void registChannel(SelectorSimulator<REPCommand> selector2, ChannelSimulator<REPCommand> cs, int key) {
		csList.add(cs);
		transList.add(new TranslaterImp1(transList.size()));
		editorList.add(new EditorObject(editorList.size(), cs, new TranslaterImp1(editorList.size())));
		REPHandler handler = new REPHandlerImpl(this);
		selector.register(cs, SelectionKeySimulator.OP_READ, handler);
	}
	
	public void init(){
	}
	
	public void run(){

		ns.writeLog("SessionManager start.", 1);

		try {
			mainLoop();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		ns.writeLog("SessionManager finish.", 1);
	}

	private void mainLoop() throws IOException {
		/* Main Loop */
		while(running){

			selector.select();
			select();
		}
	}

	private void select() {
		for(SelectionKeySimulator<REPCommand> key : selector.selectedKeys()){
			
			if(key.isAcceptable()){
				ChannelSimulator<REPCommand> channel = (ChannelSimulator<REPCommand>)key.channel();
				channel = channel.accept();
				//REPHandler handler = new REPHandlerImpl(this);
				//selector.register(channel, SelectionKeySimulator.OP_READ, handler);
				registChannel(selector, channel, SelectionKeySimulator.OP_READ);
				
			}else if(key.isReadable()){

				REPHandler handler = (REPHandler)key.attachment();
				handler.handle(key);

			}
		}
	}

	void manage(ChannelSimulator<REPCommand> channel, REPCommand command) {
		// コマンドの処理

		int eid = getEID(channel);
		int neid = getNextEID(eid);
		
		ns.writeLog("SessionManager received from " + ":" + eid + ": " + command, 3);
		
		EditorObject nextEditor = getEditor(neid);
		//editor.receive(command);
		
		switch(command.cmd){
		case REP.SMCMD_QUIT_2:
			quit2(nextEditor, command, 0);
			break;
			
		case REP.SMCMD_QUIT:
			quit(nextEditor, command);
			break;
					
		default:
			translate(eid, neid, command);
			//REPCommand sendCommand = editor.receive(command);
			//nextEditor.send(command);
		}
		
	}

	private int getNextEID(int eid) {
		return (eid+1)%editorList.size();
	}


	private void quit(EditorObject nextEditor, REPCommand command) {
		nextEditor.send(command);
		if(command.eid == nextEditor.eid){
			//quitコマンドが一周してきた
			if(transList.get(nextEditor.eid).isFinished()) {
				command.setCMD(REP.SMCMD_QUIT_2);
			}else{
				System.out.println("has Unmerged Commands.");
			}
		}
	}
	
	private void quit2(EditorObject nextEditor, REPCommand command, int fromPort) {
		nextEditor.send(command);
		if(startQuit2 == -1) startQuit2 = fromPort;
		else if(startQuit2 == nextEditor.eid) ;//finish();
	}

	private void translate(int eid, int neid, REPCommand command) {
		
		ChannelSimulator<REPCommand> channel = getChannel(eid);

		EditorObject editor = getEditor(eid);
		EditorObject nextEditor = getEditor(neid);

		if(command.eid == eid){
			if(checkOwnCommand(command)){
				//エディタからの編集コマンドが戻ってきた場合、マージしてエディタへ反映
				//Hndlerを切り替える
				setMergeState(channel, selector);
				if(eid == 0)System.out.println("returned Editor Command : " + command);
				REPCommand[] cmds = transList.get(eid).catchOwnCommand(command);
				for(REPCommand cmd : cmds){
					REPCommand tmp2 = new REPCommand(cmd);
					tmp2.eid = REP.MERGE_EID;
					channel.write(pack(tmp2));
				}

			}else{
				//エディタからの新たな編集コマンド
				if(eid == 0)System.out.println("new Editor Command : " + command);
				transList.get(eid).transSendCmd(command);
				nextEditor.send(command);
			}
			
		}else if(command.eid == REP.MERGE_EID){
			//マージのときにエディタからの割り込みがないか確認
			if(eid == 0)System.out.println("	Merged Command : " + command);
			if(transList.get(eid).checkMergeConflict(command)){
				LinkedList<REPCommand> againList = transList.get(eid).getMergeAgain();
				for(REPCommand againCommand : againList){
					channel.write(pack(againCommand));
					if(false)System.out.println("		reMerge : " + againCommand);
				}
			}else{
				//マージが終了
				//Handlerを元に戻す
				if(!editor.isMerging()) setNormalState(channel, selector);
			}
			
		}else{
			//他のエディタからのコマンドはマージャへ追加し次のエディタへ送信する
			REPCommand[] cmds = transList.get(eid).transReceiveCmd(command);
			for(REPCommand cmd : cmds){
				nextEditor.send(cmd);
			}
		}
	}

	private void setMergeState(ChannelSimulator<REPCommand> channel, SelectorSimulator<REPCommand> selector2) {
		SelectionKeySimulator<REPCommand> key = channel.keyFor(selector2);
		key.attach(new REPHandlerInMerge(this));
	}

	private void setNormalState(ChannelSimulator<REPCommand> channel, SelectorSimulator<REPCommand> selector2) {
		SelectionKeySimulator<REPCommand> key = channel.keyFor(selector2);
		key.attach(new REPHandlerImpl(this));
	}

	private EditorObject getEditor(int eid) {
		for(EditorObject editor : editorList){
			if(editor.getEID() == eid) {
				return editor;
			}
		}
		return null;
	}
	
	private int getEID(ChannelSimulator<REPCommand> channel) {
		int eid = 0;
		for(EditorObject editor : editorList){
			if(editor.getChannel() == channel){
				eid = editor.getEID();
			}
		}
		return eid;
	}

	private ChannelSimulator<REPCommand> getChannel(int eid) {
		ChannelSimulator<REPCommand> channel = null;
		for(EditorObject editor : editorList){
			if(editor.getEID() == eid){
				channel = editor.getChannel();
			}
		}
		return channel;
	}

	private boolean checkOwnCommand(REPCommand command) {
		boolean ownCommand = false;
		LinkedList<REPCommand> sentCommands = transList.get(command.eid).getSentCmds();
		if(sentCommands.size() > 0){
			if(sentCommands.get(0).seq == command.seq){
				ownCommand = true;
			}
		}
		return ownCommand;
	}

	private REPCommand pack(REPCommand command) {
		return new REPCommand(command);
	}

	REPCommand unpack(REPCommand packet) {
		return new REPCommand(packet);
	}

	public void addWaitingCommand(PacketSet set) {
		// TODO Auto-generated method stub
		waitingList.add(set);
	}

	public void doWaiting() {
		
	}
	
	synchronized public void finish(){
		synchronized(ns){
			running = false;
			ns.notify();
		}
	}
	
}