view src/pathfinder/mergetest/SessionManagerSimulatorWithMerger.java @ 156:7ebd30e5e385 simulator-2008-8-26

*** empty log message ***
author pin
date Mon, 25 Aug 2008 15:53:03 +0900
parents 0dfb6413a31e
children 1a2269c820df
line wrap: on
line source

package pathfinder.mergetest;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import remoteeditor.command.REPCommand;
import remoteeditor.network.REP;
import sample.merge.TranslaterImp1;

public class SessionManagerSimulatorWithMerger<P extends REPCommand> extends SeMaSimulator<P> {

	private List<TranslaterImp1> editorList;
	private SelectorSimulator<P> selector;
	private List<EditorObject<P>> editorList2;
	private int startQuit2;

	public SessionManagerSimulatorWithMerger(NetworkSimulator<P> _ns) {
		super(_ns);
	}

	public SessionManagerSimulatorWithMerger(NetworkSimulator<P> ns, int ne) {
		super(ns, ne);
	}
	
	public SessionManagerSimulatorWithMerger(NetworkSimulator<P> _ns, int max_client, int max_packet) {
		super(_ns, max_client, max_packet);
		editorList = new ArrayList<TranslaterImp1>();
		selector = new SelectorSimulator<P>(_ns);
		editorList2 = new ArrayList<EditorObject<P>>();
	}
	
	protected void checkAccept(){
		ChannelSimulator<P> cs;
		while((cs=ns.accept())!=null){
			csList.add(cs);
			editorList.add(new TranslaterImp1(editorList.size()));
			editorList2.add(new EditorObject<P>(editorList2.size(), cs, new TranslaterImp1(editorList2.size())));
			registerChannel (selector, cs, SelectionKeySimulator.OP_READ);
		}
	}
	
	private void registerChannel(SelectorSimulator selector2, ChannelSimulator<P> cs, int key) {
		selector.register(cs);
	}

	public void run(){

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

		/* Main Loop */
		while(running){

			selector.select();
			for(SelectionKeySimulator<P> key : selector.selectedKeys()){
				
				if(key.isAcceptable()){
					ChannelSimulator<P> channel = key.channel();
					channel = channel.accept();
					selector.register(channel);
					
				}else if(key.isReadable()){
					ChannelSimulator<P> channel = key.channel();
					P packet = channel.read();
					REPCommand command = unpack(packet);
					manage(channel, command);
				}
			}
		}
		
		ns.writeLog("SessionManager finish.", 1);
	}

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

		int eid = getEID(channel);
		int neid = getNextEID(eid);
		
		ns.writeLog("SessionManager received from " + ":" + eid + ": " + command, 3);
		
		EditorObject editor = getEditor(eid);
		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)%editorList2.size();
	}


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

	private void translate(int eid, int neid, REPCommand command) {

		ChannelSimulator<P> channel = getChannel(eid);
		ChannelSimulator<P> nextChannel = getChannel(neid);

		EditorObject editor = getEditor(eid);

		if(command.eid == eid){
			if(checkOwnCommand(command)){
				//エディタからの編集コマンドが戻ってきた場合、マージしてエディタへ反映
				if(eid == 2)System.out.println("returned Editor Command : " + command);
				REPCommand[] cmds = editorList.get(eid).catchOwnCommand(command);
				for(REPCommand cmd : cmds){
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					REPCommand tmp2 = new REPCommand(cmd);
					tmp2.eid = REP.MERGE_EID;
					channel.write(pack(tmp2));
				}

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

		}
	}

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

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

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

	private P pack(REPCommand command) {
		P cmd = (P) new REPCommand(command);
		return cmd;
	}

	private REPCommand unpack(P packet) {
		REPCommand cmd = null;
		if(packet instanceof REPCommand){
			cmd = (REPCommand) packet;
		}else{
			ns.writeLog("Error!! :Packet type is NOT REPCommand!", 1);
		}
		return new REPCommand(cmd);
	}
	
}