changeset 153:6326e5ea4595

*** empty log message ***
author pin
date Sat, 23 Aug 2008 11:28:16 +0900
parents 09ad66f62f4a
children 6a3c982bd72a
files bin/remoteeditor/network/REP.class src/pathfinder/mergetest/ChannelSimulator.java src/pathfinder/mergetest/EditorSimulator.java src/pathfinder/mergetest/EditorSimulatorAsync.java src/pathfinder/mergetest/EditorSimulatorWithoutMerger.java src/pathfinder/mergetest/SelectionKeySimulator.java src/pathfinder/mergetest/SelectorSimulator.java src/pathfinder/mergetest/SessionManagerSimulatorWithMerger.java src/pathfinder/mergetest/TestMerger.java src/pathfinder/mergetest/TestMerger2.java src/pathfinder/mergetest/Text.java src/pathfinder/mergetest/UsersSimulator.java src/remoteeditor/network/REP.java src/sample/merge/Merger.java src/sample/merge/Translater.java src/sample/merge/TranslaterImp1.java
diffstat 16 files changed, 246 insertions(+), 390 deletions(-) [+]
line wrap: on
line diff
Binary file bin/remoteeditor/network/REP.class has changed
--- a/src/pathfinder/mergetest/ChannelSimulator.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/ChannelSimulator.java	Sat Aug 23 11:28:16 2008 +0900
@@ -1,11 +1,14 @@
 package pathfinder.mergetest;
 
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
 
 public class ChannelSimulator<P> {
 	private BlockingQueue<P> qread;
 	private BlockingQueue<P> qwrite;
 	private NetworkSimulator<P> ns;
+	private BlockingQueue<ChannelSimulator<P>> connectQueue = 
+		new LinkedBlockingQueue<ChannelSimulator<P>>();
 
 	public ChannelSimulator(NetworkSimulator<P> _ns, BlockingQueue<P> _a, BlockingQueue<P> _b){
 		ns = _ns;
@@ -68,6 +71,25 @@
 	public ChannelSimulator<P> getServerChannel() {
 		return new ChannelSimulator<P>(ns, qwrite, qread);
 	}
+	
+	public void connect(ChannelSimulator<P> c){
+		synchronized(ns){
+			connectQueue.add(c);
+			ns.notifyAll();
+		}
+	}
+
+	public ChannelSimulator<P> accept() {
+		return connectQueue.remove();
+	}
+
+	public boolean isAcceptable() {
+		return !connectQueue.isEmpty();
+	}
+
+	public boolean isReadable() {
+		return !qread.isEmpty();
+	}
 
 
 }
--- a/src/pathfinder/mergetest/EditorSimulator.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/EditorSimulator.java	Sat Aug 23 11:28:16 2008 +0900
@@ -12,18 +12,18 @@
 	//private boolean isOwner;
 	protected NetworkSimulator<REPCommand> ns;
 	protected ChannelSimulator<REPCommand> cs;
-	protected Queue<REPCommand> CmdList;
+	//protected Queue<REPCommand> CmdList;
 	private TranslaterImp1 translater;
 	protected Text text;
 	protected boolean running=true;
 
-	public EditorSimulator(int _eid, NetworkSimulator<REPCommand> _ns, Queue<REPCommand> q, String _name) {
+	public EditorSimulator(int _eid, NetworkSimulator<REPCommand> _ns, String[] strings, String _name) {
 		super(_name);
 		eid = _eid;
 		ns = _ns;
-		CmdList = q;
+		
 		translater = new TranslaterImp1(_eid);
-		text = new Text();
+		text = new Text(strings);
 		cs = ns.connect();
 	}
 
@@ -83,8 +83,8 @@
 	}
 
 	protected void sendOneCommand(REPCommand cmd) {
-		REPCommand[] cmds;
-		if (cmd==null) cmd = CmdList.poll();
+		REPCommand cmds;
+		//if (cmd==null) cmd = CmdList.poll();
 		if (cmd==null) return;
 
 		//cmd.eid = eid;
@@ -92,34 +92,25 @@
 		cmd.setString("inserted by Editor"+cmd.eid+":"+cmd.seq);
 
 		//if (isOwner) cmd.setThroughMaster(true);
-		for (int i=0; i<cmds.length; i++){
-			text.edit(cmds[i]);
-			cs.write(new REPCommand(cmds[i]));
-		}
+//		for (int i=0; i<cmds.length; i++){
+//			text.edit(cmds[i]);
+//			cs.write(new REPCommand(cmds[i]));
+//		}
+		text.edit(cmds);
+		cs.write(cmds);
 		Thread.yield();
 	}
-	private void sendAllCommand() {
-		REPCommand[] cmds;
-		for (REPCommand cmd: CmdList){
-			cmd.seq = seq;
-			cmd.eid = eid;
-			cmds = translater.transSendCmd(cmd);
-			cmd.setString("this is inserted or replaced by Editor"+cmd.eid+":"+cmd.seq);
-			//if (isOwner) cmd.setThroughMaster(true);
-			for (int i=0; i<cmds.length; i++){
-				text.edit(cmds[i]);
-				cs.write(new REPCommand(cmds[i]));
-			}
-		}
-
-		// Send Quit Command
-		cmds = translater.transSendCmd( new REPCommand(REP.SMCMD_QUIT, 0, eid, seq++, 0, 0, "QUIT by Editor"+eid));
-		for (int i=0; i<cmds.length; i++){
-			text.edit(cmds[i]);
-			cs.write(new REPCommand(cmds[i]));
-		}
-
-	}
+//	private void sendAllCommand() {
+//		REPCommand[] cmds;
+//
+//		// Send Quit Command
+//		cmds = translater.transSendCmd( new REPCommand(REP.SMCMD_QUIT, 0, eid, seq++, 0, 0, "QUIT by Editor"+eid));
+//		for (int i=0; i<cmds.length; i++){
+//			text.edit(cmds[i]);
+//			cs.write(new REPCommand(cmds[i]));
+//		}
+//
+//	}
 /*
 	private boolean checkQuit(REPCommand cmd) {
 		// 最初に全部のコマンドを送信するから、自分のQUITが来るのは最後
--- a/src/pathfinder/mergetest/EditorSimulatorAsync.java	Fri Aug 22 15:48:52 2008 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-package pathfinder.mergetest;
-
-import java.util.Queue;
-
-import remoteeditor.command.REPCommand;
-import remoteeditor.network.REP;
-import sample.merge.TranslaterImp1;
-
-public class EditorSimulatorAsync extends EditorSimulator{
-	private int eid;
-	private boolean isOwner;
-	private NetworkSimulator<REPCommand> ns;
-	private ChannelSimulator<REPCommand> cs;
-	private TranslaterImp1 translater;
-	private Text text;
-	private boolean running=true;
-	private User user;
-
-	public EditorSimulatorAsync(int _eid, NetworkSimulator<REPCommand> _ns, Queue<REPCommand> q, String _name) {
-		super(_eid, _ns, q, _name);
-		eid = _eid;
-		ns = _ns;
-		cs = ns.connect();
-		translater = new TranslaterImp1(_eid);
-		text = new Text();
-		user = new User(translater, text, q, cs);
-	}
-
-	public void run(){
-		System.out.println("Editor"+eid+" start.");
-		user.start();
-
-		// MainLoop, 
-		while(running){
-			REPCommand cmd = cs.read();
-			REPCommand[] cmds;
-
-			//終了条件
-			if (cmd.eid==eid && cmd.cmd==REP.SMCMD_QUIT){
-				System.out.println("\tEditor"+eid+" catch QUIT command emited by itself.");
-				cmds = translater.catchOwnCommand(cmd);
-				for (int i=0; i<cmds.length; i++){
-					cmd = cmds[i];
-					System.out.println("\t\tEditor"+eid+" edit text. ");
-					text.edit(cmd);
-				}
-				running=false; break;
-			}
-			System.out.println("\tEditor"+eid+" catch command from "+cmd.eid+" NO."+cmd.seq);
-			
-			if (cmd.eid==eid){
-				cmds = translater.catchOwnCommand(cmd);
-				for (int i=0; i<cmds.length; i++){
-					cmd = cmds[i];
-					System.out.println("\t\tEditor"+eid+" edit text. ");
-					text.edit(cmd);
-				}
-			} else {
-				cmds = translater.transReceiveCmd(cmd);
-				for (int i=0; i<cmds.length; i++){
-					cmd = cmds[i];
-					System.out.println("\t\tEditor"+eid+" edit text and pass Cmd. ");
-					text.edit(cmd);
-					cs.write(cmd);
-				}
-			}
-		}
-
-		try { user.join();
-		} catch (InterruptedException e) { e.printStackTrace(); }
-		
-		System.out.println("Editor"+eid+" finish.");
-	}
-
-/*
-	private boolean checkQuit(REPCommand cmd) {
-		// 最初に全部のコマンドを送信するから、自分のQUITが来るのは最後
-		return (cmd.eid==eid && cmd.cmd==REP.SMCMD_QUIT);
-	}
-*/
-	public Text getText(){
-		return text;
-	}
-	
-	
-	
-	public class User extends Thread{
-		private Queue<REPCommand> CmdList;
-		private TranslaterImp1 translater;
-		private Text text;
-		private ChannelSimulator<REPCommand> cs;
-
-		public User(TranslaterImp1 _translater, Text _text, Queue<REPCommand> q, ChannelSimulator<REPCommand> _cs){
-			translater = _translater;
-			text = _text;
-			CmdList = q;
-			cs = _cs;
-		}
-		
-		public void run(){
-			System.out.println("Editor"+eid+"'s writer thread start.");
-			while ( !CmdList.isEmpty() ){
-				sendOneCommand();
-			}
-			sendQuitCommand();
-			System.out.println("Editor"+eid+"'s writer thread finish.");
-		}
-
-		private void sendOneCommand() {
-			REPCommand[] cmds;
-			REPCommand cmd = CmdList.poll();
-			cmd.eid = eid;
-			cmds = translater.transSendCmd(cmd);
-			cmd.setString("this is inserted or replaced by Editor"+cmd.eid+":"+cmd.seq);
-
-			if (isOwner) cmd.setThroughMaster(true);
-			for (int i=0; i<cmds.length; i++){
-				text.edit(cmds[i]);
-				cs.write(cmds[i]);
-			}
-		}
-
-		private void sendQuitCommand(){
-			REPCommand[] cmds;
-			cmds = translater.transSendCmd( new REPCommand(REP.SMCMD_QUIT, 0, eid, 0, 0, 0, "QUIT by Editor"+eid));
-			for (int i=0; i<cmds.length; i++){
-				text.edit(cmds[i]);
-				cs.write(cmds[i]);
-			}
-		}
-/*
-		private void sendAllCommand() {
-			REPCommand[] cmds;
-			for (REPCommand cmd: CmdList){
-				cmd.seq = seq;
-				cmd.eid = eid;
-				cmds = translater.transSendCmd(cmd);
-				cmd.setString("this is inserted or replaced by Editor"+cmd.eid+":"+cmd.seq);
-				//if (isOwner) cmd.setThroughMaster(true);
-				for (int i=0; i<cmds.length; i++){
-					text.edit(cmds[i]);
-					cs.write(cmds[i]);
-				}
-			}
-
-		}
-*/
-	}
-	
-	
-	
-	
-	
-	
-}
\ No newline at end of file
--- a/src/pathfinder/mergetest/EditorSimulatorWithoutMerger.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/EditorSimulatorWithoutMerger.java	Sat Aug 23 11:28:16 2008 +0900
@@ -9,8 +9,8 @@
 
 	private boolean lock;
 
-	public EditorSimulatorWithoutMerger(int _eid, NetworkSimulator<REPCommand> _ns, Queue<REPCommand> q, String _name) {
-		super(_eid, _ns, q, _name);
+	public EditorSimulatorWithoutMerger(int _eid, NetworkSimulator<REPCommand> _ns, String[] strings, String _name) {
+		super(_eid, _ns, strings, _name);
 	}
 	
 	public void run(){
@@ -43,12 +43,14 @@
 						continue;
 					}
 					
-					if(lock) continue;
-					sendOneCommand(cmd);
+					//if(lock) continue;
+					String replacedText = text.edit(cmd);
+					sendOneCommand(cmd, replacedText);
 					
 				}else if(cmd.eid == -2){
 					// Merged Commands.
-					text.edit(cmd);
+					String replacedText = text.edit(cmd);
+					sendOneCommand(cmd, replacedText);
 					
 					/* 終了条件  */
 					if (cmd.cmd==REP.SMCMD_QUIT){
@@ -88,40 +90,42 @@
 		lock = b;
 	}
 
-	protected void sendOneCommand(REPCommand cmd){
-
-		if (cmd==null) cmd = CmdList.poll();
+	protected void sendOneCommand(REPCommand cmd, String replacedText){
+		
 		if (cmd==null) return;
 		
 		cmd.eid = eid;
 		cmd.seq = seq++;
 		
 		if(cmd.cmd == REP.REPCMD_INSERT){
-			cmd.setString("inserted by Editor"+cmd.eid+":"+cmd.seq);
+			//cmd.setString("inserted by Editor"+cmd.eid+":"+cmd.seq);
 			cs.write(cmd);
 			
 		}else if(cmd.cmd == REP.REPCMD_DELETE){
-			String line = text.get(cmd.lineno);
-			cmd.setString(line);
+			///String line = text.get(cmd.lineno);
+			//cmd.setString(line);
+			cmd.setString(replacedText);
 			cs.write(cmd);
 			
 		}else if(cmd.cmd ==  REP.REPCMD_REPLACE){
 
-			REPCommand undoCmd = new REPCommand(REP.SMCMD_UNDO_REPLACE, 0, eid, seq-1, cmd.lineno, 0, "");
-			undoCmd.setString(text.get(cmd.lineno));
-			cs.write(undoCmd);
+			REPCommand deleteCmd = new REPCommand(REP.REPCMD_DELETE, 0, eid, seq-1, cmd.lineno, 0, "");
+			//undoCmd.setString(text.get(cmd.lineno));
+			deleteCmd.setString(replacedText);
+			cs.write(deleteCmd);
 			
-			cmd.setString("replaced by Editor"+cmd.eid+":"+cmd.seq);
+			//cmd.setString("replaced by Editor"+cmd.eid+":"+cmd.seq);
+			cmd.setCMD(REP.REPCMD_INSERT);
 			cs.write(cmd);
 			
 		}else if(cmd.cmd == REP.SMCMD_QUIT){
-			cmd.setString("sent by Editor"+cmd.eid+":"+cmd.seq);
+			//cmd.setString("sent by Editor"+cmd.eid+":"+cmd.seq);
 			cs.write(cmd);
 		}
 
-		text.edit(cmd);
+		//text.edit(cmd);
 
-		Thread.yield();
+		//Thread.yield();
 	}
 	
 }
--- a/src/pathfinder/mergetest/SelectionKeySimulator.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/SelectionKeySimulator.java	Sat Aug 23 11:28:16 2008 +0900
@@ -11,13 +11,12 @@
 	}
 
 	public boolean isAcceptable() {
-		// TODO Auto-generated method stub
-		return false;
+		
+		return channel.isAcceptable();
 	}
 
 	public boolean isReadable() {
-		// TODO Auto-generated method stub
-		return true;
+		return channel.isReadable();
 	}
 
 	public ChannelSimulator<P> channel() {
--- a/src/pathfinder/mergetest/SelectorSimulator.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/SelectorSimulator.java	Sat Aug 23 11:28:16 2008 +0900
@@ -20,23 +20,25 @@
 		
 		synchronized(ns){
 			boolean empty = false;
-			for(SelectionKeySimulator<P> key : keyList){
-				ChannelSimulator<P> channel = key.channel();
-				if(channel.readQisEmpty()){
-					empty = true;
-				}else{
-					empty = false;
-					//selectedKeys = key;
-					selectedKeys.add(key);
-					break;
+			while(empty){
+				for(SelectionKeySimulator<P> key : keyList){
+					ChannelSimulator<P> channel = key.channel();
+					if(channel.readQisEmpty()){
+						empty = true;
+					}else{
+						empty = false;
+						//selectedKeys = key;
+						selectedKeys.add(key);
+						break;
+					}
 				}
-			}
-			
-			try {
-				if(empty) ns.wait();
-			} catch (InterruptedException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
+
+				try {
+					if(empty) ns.wait();
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					//e.printStackTrace();
+				}
 			}
 		}
 		return selectedKeys.size();
--- a/src/pathfinder/mergetest/SessionManagerSimulatorWithMerger.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/SessionManagerSimulatorWithMerger.java	Sat Aug 23 11:28:16 2008 +0900
@@ -1,6 +1,7 @@
 package pathfinder.mergetest;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import remoteeditor.command.REPCommand;
 import remoteeditor.network.REP;
@@ -10,9 +11,10 @@
 
 	private List<TranslaterImp1> editorList;
 	private SelectorSimulator<P> selector;
-	private List<ArrayList<REPCommand>> sentList;
+	//private List<ArrayList<REPCommand>> sentList;
 	private List<EditorObject<P>> editorList2;
 	private int countQuit;
+	private int startQuit2;
 
 	public SessionManagerSimulatorWithMerger(NetworkSimulator<P> _ns) {
 		super(_ns);
@@ -25,7 +27,6 @@
 	public SessionManagerSimulatorWithMerger(NetworkSimulator<P> _ns, int max_client, int max_packet) {
 		super(_ns, max_client, max_packet);
 		editorList = new ArrayList<TranslaterImp1>();
-		sentList = new ArrayList<ArrayList<REPCommand>>();
 		selector = new SelectorSimulator<P>(_ns);
 		editorList2 = new ArrayList<EditorObject<P>>();
 	}
@@ -35,7 +36,6 @@
 		while((cs=ns.accept())!=null){
 			csList.add(cs);
 			editorList.add(new TranslaterImp1(editorList.size()));
-			sentList.add(new ArrayList<REPCommand>());
 			editorList2.add(new EditorObject<P>(editorList2.size(), cs, new TranslaterImp1(editorList2.size())));
 			registerChannel (selector, cs, SelectionKeySimulator.OP_READ);
 		}
@@ -60,8 +60,8 @@
 				
 				if(key.isAcceptable()){
 					ChannelSimulator<P> channel = key.channel();
+					channel = channel.accept();
 					selector.register(channel);
-					channel = null;
 					
 				}else if(key.isReadable()){
 					ChannelSimulator<P> channel = key.channel();
@@ -80,24 +80,21 @@
 		// コマンドの処理
 
 		int eid = getEID(channel);
-		int neid = (eid+1)%editorList2.size();
+		int neid = getNextEID(eid);
 		
 		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;
-		
-		case REP.SMCMD_UNDO_REPLACE:
-			for(TranslaterImp1 trans : editorList){
-				trans.setUndoCommand(command);
-			}
-			break;
-			
+					
 		default:
 			translate(eid, neid, command);
 			//REPCommand sendCommand = editor.receive(command);
@@ -106,22 +103,32 @@
 		
 	}
 
+	private int getNextEID(int eid) {
+		return (eid+1)%editorList2.size();
+	}
+
 
 	private void quit(EditorObject nextEditor, REPCommand command) {
-		if(countQuit > editorList2.size()*2){
-			REPCommand quitCommand = new REPCommand(command);
-			quitCommand.eid = -2;
-			for(EditorObject editor : editorList2){
-				editor.send(quitCommand);
-			}
-		}else{
-			nextEditor.send(command);
+		if(command.eid == nextEditor.eid){
+			//quitコマンドが一周してきた
+			command.setCMD(REP.SMCMD_QUIT_2);
 		}
-		countQuit++;
+		nextEditor.send(command);
+	}
+	
+	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) quitSessionManager();
 	}
 
-	private void checkQuit(ChannelSimulator<P> channel, REPCommand command) {
-		
+	private void quitSessionManager() {
+		running = false;
 	}
 
 	private void translate(int eid, int neid, REPCommand command) {
@@ -136,50 +143,32 @@
 		
 		if(command.eid == eid){
 			if(checkOwnCommand(command)){
-				//エディタからの編集コマンドが他の全てのエディタを通って戻ってきた場合
-				if(command.cmd == REP.SMCMD_QUIT){
-					//QUITコマンドの場合
-					REPCommand tmp = new REPCommand(command);
-					tmp.eid = -2;
-					//quitCommand = tmp;
-					channel.write(pack(tmp));
-				}else{
 					//エディタからの編集コマンドが戻ってきた場合、マージしてエディタへ反映
-					REPCommand[] cmds = editorList.get(eid).catchOwnCommand(command);
-					for(REPCommand cmd : cmds){
-						REPCommand tmp2 = new REPCommand(cmd);
-						tmp2.eid = -2;
-						channel.write(pack(tmp2));
-					}
+				REPCommand[] cmds = editorList.get(eid).catchOwnCommand(command);
+				for(REPCommand cmd : cmds){
+					REPCommand tmp2 = new REPCommand(cmd);
+					tmp2.eid = REP.SMCMD_MERGE_EID;
+					channel.write(pack(tmp2));
 				}
 				
 			}else{
-				if(command.cmd == REP.SMCMD_QUIT){
-					//エディタからのQUITコマンド
-					sentList.get(eid).add(command);
-					nextChannel.write(pack(command));
-				}else{
+
 					//エディタからの新たな編集コマンド
-					sentList.get(eid).add(command);
 					editorList.get(eid).transSendCmd(command);
 					nextChannel.write(pack(command));
-				}
+
 			}
-		}else if(command.eid == -2){
-//			if(mergedList.get(eid).size() == 0){
-//				if(quitCommand != null) channel.write(pack(quitCommand));
-//			}
+		}else if(command.eid == REP.SMCMD_MERGE_EID){
+			 //マージのときにエディタとの間に衝突がないか確認
+			editorList.get(eid).checkMergeConflict();
 		}else{
-			if(command.cmd == REP.SMCMD_QUIT){
-				//QUITコマンドはマージャへ追加せずそのまま次のエディタへ送信する
-				nextChannel.write(pack(command));
-			}else{
+
 				//他のエディタからのコマンドはマージャへ追加しを次のエディタへ送信する
-				REPCommand[] cmds = editorList.get(eid).transReceiveCmd(command);
-				for(REPCommand cmd : cmds){
-					nextChannel.write(pack(cmd));
-				}
+			REPCommand[] cmds = editorList.get(eid).transReceiveCmd(command);
+			for(REPCommand cmd : cmds){
+				nextChannel.write(pack(cmd));
 			}
+			
 		}
 	}
 
@@ -193,12 +182,6 @@
 		return null;
 	}
 	
-	private EditorObject getEditor(ChannelSimulator<P> channel){
-		int eid = getEID(channel);
-		EditorObject editor = getEditor(eid);
-		return editor;
-	}
-
 	private int getEID(ChannelSimulator<P> channel) {
 		int eid = 0;
 		for(EditorObject editor : editorList2){
@@ -210,9 +193,8 @@
 	}
 
 	private ChannelSimulator<P> getChannel(int eid) {
-		// TODO Auto-generated method stub
 		ChannelSimulator<P> channel = null;
-		for(EditorObject editor : editorList2){
+		for(EditorObject<P> editor : editorList2){
 			if(editor.getEID() == eid){
 				channel = editor.getChannel();
 			}
@@ -223,10 +205,10 @@
 	private boolean checkOwnCommand(REPCommand command) {
 		// TODO Auto-generated method stub
 		boolean ownCommand = false;
-		if(sentList.get(command.eid).size() > 0){
-			if(sentList.get(command.eid).get(0).seq == command.seq){
+		LinkedList<REPCommand> sentCommand = editorList.get(command.eid).getSentCmds();
+		if(sentCommand.size() > 0){
+			if(sentCommand.get(0).seq == command.seq){
 				ownCommand = true;
-				sentList.get(command.eid).remove(0);
 			}
 		}
 		return ownCommand;
--- a/src/pathfinder/mergetest/TestMerger.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/TestMerger.java	Sat Aug 23 11:28:16 2008 +0900
@@ -73,7 +73,7 @@
 		ns.setLogLevel(ll);
 
 		/* create UsersSimulator.  */
-		users = new UsersSimulator(ns, ne, np*ne);
+		//users = new UsersSimulator(ns, ne, np*ne);
 
 		/* create ne Editors and np commands.  */
 		for (int i=0; i<ne; i++){
@@ -93,7 +93,7 @@
 			*/
 
 			/* create a Editor, and pass command list to it.  */
-			EditorSimulator ee = new EditorSimulator(i, ns, cmds, "Editor"+i);
+			EditorSimulator ee = null; //new EditorSimulator(i, ns, cmds, "Editor"+i);
 			if(i==0) ee.setOwner(true);
 			editors.add(ee);
 		}
--- a/src/pathfinder/mergetest/TestMerger2.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/TestMerger2.java	Sat Aug 23 11:28:16 2008 +0900
@@ -9,7 +9,15 @@
 	protected NetworkSimulator<REPCommand> ns=null;
 	protected LinkedList<EditorSimulatorWithoutMerger> editors;
 	protected SessionManagerSimulatorWithMerger<REPCommand> sema;
-	protected UsersSimulator users;
+	protected LinkedList<UsersSimulator> users = new LinkedList<UsersSimulator>();
+	
+	static private String[] text0 = {
+		"aaa", "bbb", "ccc", "ddd", "eee",
+		"fff", "ggg", "hhh", "iii", "jjj",
+		"kkk", "lll", "mmm", "nnn", "ooo",
+		"ppp", "qqq", "rrr", "sss", "ttt",
+		"uuu", "vvv", "www", "xxx", "yyy", "zzz"
+	};
 
 	public TestMerger2(){
 		editors = new LinkedList<EditorSimulatorWithoutMerger>();
@@ -46,8 +54,16 @@
 		/* start SessionManager if it exist.  */
 		if (sema!=null) sema.init();
 		if (sema!=null) sema.start();
-		users.init();
-		users.start();
+		
+		for(UsersSimulator u: users){
+			u.start();
+		}
+		for(UsersSimulator u: users){
+			try {
+				u.join();
+			} catch (InterruptedException e) { }
+		}
+
 
 		/* wait Editors finish.  */
 		for (EditorSimulatorWithoutMerger ee: editors){
@@ -58,9 +74,26 @@
 			}
 		}
 		/* inform SessionManager to finish.  */
-		if (sema!=null) sema.finish();
+		if (sema!=null) {
+			sema.finish();
+			try {
+				sema.join();
+			} catch (InterruptedException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
 	}
 
+	 LinkedList<REPCommand> userCommand(int eid){
+		LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
+		cmds .add(new REPCommand(REP.REPCMD_REPLACE, 0, eid, 1, 0, 0, "replaced by editor:" + eid + ":1"));
+		cmds .add(new REPCommand(REP.REPCMD_REPLACE, 0, eid, 2, 0, 0, "replaced by editor:" + eid + ":2"));
+		cmds .add(new REPCommand(REP.REPCMD_REPLACE, 0, eid, 3, 0, 0, "replaced by editor:" + eid + ":3"));
+		if(eid == 0) cmds .add(new REPCommand(REP.SMCMD_QUIT, 0, eid, 4, 0, 0, "replaced by editor:" + eid + ":4"));
+		return cmds;
+	}
+	
 	protected void init(boolean sm, int ne, int np, int ll){
 		/* create NetworkSimulator, and SessionManager if it's required.   */
 		if (sm){
@@ -73,11 +106,14 @@
 		ns.setLogLevel(ll);
 
 		/* create UsersSimulator.  */
-		users = new UsersSimulator(ns, ne, np*ne);
+		for(int i = 0; i < ne; i++){
+			ChannelSimulator<REPCommand> channel = ns.getAcceptedSession(i);
+			users.add(new UsersSimulator(channel, userCommand(i)));	
+		}
 
 		/* create ne Editors and np commands.  */
 		for (int i=0; i<ne; i++){
-			LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
+			//LinkedList<REPCommand> cmds = new LinkedList<REPCommand>();
 			// 各エディタが送信するコマンド列を生成
 
 			/* create command list.  */
@@ -93,7 +129,7 @@
 			*/
 
 			/* create a Editor, and pass command list to it.  */
-			EditorSimulatorWithoutMerger ee = new EditorSimulatorWithoutMerger(i, ns, cmds, "Editor"+i);
+			EditorSimulatorWithoutMerger ee = new EditorSimulatorWithoutMerger(i, ns, i==0?text0:null, "Editor"+i);
 			if(i==0) ee.setOwner(true);
 			editors.add(ee);
 		}
--- a/src/pathfinder/mergetest/Text.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/Text.java	Sat Aug 23 11:28:16 2008 +0900
@@ -7,43 +7,38 @@
 import remoteeditor.network.REP;
 
 public class Text {
-	static private String[] text0 = {
-		"aaa", "bbb", "ccc", "ddd", "eee",
-		"fff", "ggg", "hhh", "iii", "jjj",
-		"kkk", "lll", "mmm", "nnn", "ooo",
-		"ppp", "qqq", "rrr", "sss", "ttt",
-		"uuu", "vvv", "www", "xxx", "yyy", "zzz"
-	};
+
 	LinkedList<String> strList;
 
-	public Text(){
-		this(Text.text0);
-	}
 	public Text(String[] _strings){
 		strList = new LinkedList<String>(Arrays.asList(_strings));
 	}
 
-	synchronized public void insert(int i, String str){
+	public String insert(int i, String str){
 		assert 0<i && i<strList.size();
 		strList.add(i, str);
+		return null;
 	}
-	synchronized public void delete(int i){
+	public String delete(int i){
 		assert 0<i && i<strList.size();
-		strList.remove(i);
+		return strList.remove(i);
 	}
-	synchronized public void replace(int i, String str){
+	public String replace(int i, String str){
 		assert 0<i && i<strList.size();
+		String replaced = strList.get(i);
 		strList.set(i, str);
+		return replaced;
 	}
 	public String get(int i){
 		assert 0<i && i<strList.size();
 		return strList.get(i);
 	}
-	public void edit(REPCommand cmd){
-		if (cmd.cmd==REP.REPCMD_INSERT)        insert(cmd.lineno, cmd.string);
-		else if (cmd.cmd==REP.REPCMD_REPLACE)  replace(cmd.lineno, cmd.string);
-		else if (cmd.cmd==REP.REPCMD_DELETE)   delete(cmd.lineno);
+	public String edit(REPCommand cmd){
+		if (cmd.cmd==REP.REPCMD_INSERT)        return insert(cmd.lineno, cmd.string);
+		else if (cmd.cmd==REP.REPCMD_REPLACE)  return replace(cmd.lineno, cmd.string);
+		else if (cmd.cmd==REP.REPCMD_DELETE)   return delete(cmd.lineno);
 		//else assert false;
+		return null;
 	}
 
 	public int size(){
--- a/src/pathfinder/mergetest/UsersSimulator.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/pathfinder/mergetest/UsersSimulator.java	Sat Aug 23 11:28:16 2008 +0900
@@ -1,76 +1,35 @@
 package pathfinder.mergetest;
 
-import java.util.ArrayList;
+import java.util.LinkedList;
 
 import remoteeditor.command.REPCommand;
-import remoteeditor.network.REP;
 
 public class UsersSimulator extends Thread {
 	private NetworkSimulator<REPCommand> ns;
-	private int N_client;
-	private int N_packet;
-	private ArrayList<ChannelSimulator<REPCommand>> channelList;
-	private int nextChannelIndex;
+	private ChannelSimulator<REPCommand> cs;
+	private LinkedList<REPCommand> cmds;
 
-	public UsersSimulator(NetworkSimulator<REPCommand> _ns, int max_client, int max_packet){
-		ns = _ns;
-		N_client = max_client;
-		N_packet = max_packet;
-		channelList = new ArrayList<ChannelSimulator<REPCommand>>();
+	public UsersSimulator(ChannelSimulator<REPCommand> _cs, LinkedList<REPCommand> _cmds){
+		cs = _cs;
+		cmds = _cmds;
 	}
 
 	public void run(){
-		int i=0;
-
 		ns.writeLog("UsersSimulator start.", 1);
-		while( i++<N_packet ){
+		while(cmds.size()>0){
 			REPCommand cmd0 = createCmd();
-			ChannelSimulator<REPCommand> cs = channelList.get(nextChannelIndex);
 			cs.write(cmd0);
-	
-			nextChannelIndex++;
-			if (nextChannelIndex>=channelList.size()) nextChannelIndex=0;
-		}
-		
-		// Quitコマンドを送るエディタはeid=0のエディタのみ
-//		ChannelSimulator<REPCommand> channel = channelList.get(0);
-//		REPCommand qCommand = createQuitCmd();
-//		channel.write(qCommand);
-
-		/* send quitPacket to all editors.  */
-		synchronized (ns){
-		//	for ( ChannelSimulator<REPCommand> cs : channelList){
-			ChannelSimulator<REPCommand> cs = channelList.get(0);
-			REPCommand cmd0 = createQuitCmd();
-			cs.write(cmd0);
-		//	}
 		}
 
 		ns.writeLog("UsersSimulator finish.", 1);
 	}
 
 	private REPCommand createCmd(){
-		String str = new String("this text was created by Control thread.");
-		//REPCommand cmd = new REPCommand(REP.REPCMD_INSERT, 0, -1, 0, 10, str.length(), str);
-		REPCommand cmd = new REPCommand(REP.REPCMD_REPLACE, 0, -1, 0, 10, str.length(), str);
+		REPCommand cmd = cmds.remove(0);
 		return cmd;
 	}
-	private REPCommand createQuitCmd(){
-		String str = new String("this text was created by Control thread.");
-		REPCommand cmd = new REPCommand(REP.SMCMD_QUIT, 0, -1, 0, 10, str.length(), str);
-		return cmd;
-	}
+
 	
 	public void init(){
-		getAllChannelSimulators();
-	}
-
-	private void getAllChannelSimulators(){
-		while (channelList.size()<N_client){
-			ChannelSimulator<REPCommand> cs;
-			cs = ns.getAcceptedSession( channelList.size() );
-			if (cs==null) continue;
-			channelList.add( cs );
-		}
 	}
 }
--- a/src/remoteeditor/network/REP.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/remoteeditor/network/REP.java	Sat Aug 23 11:28:16 2008 +0900
@@ -41,6 +41,8 @@
 	public static final int SMCMD_START_MERGE = 75;
 	public static final int SMCMD_START_MERGE_ACK = 76;
 	public static final int SMCMD_END_MERGE = 77;
+	public static final int SMCMD_QUIT_2 = 78;
+	public static final int SMCMD_MERGE_EID = -2;
 	
 	//public static final int SMCMD_START_MERGE = 73;
 	//public static final int SMCMD_START_MERGE_ACK = 74;
--- a/src/sample/merge/Merger.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/sample/merge/Merger.java	Sat Aug 23 11:28:16 2008 +0900
@@ -47,13 +47,13 @@
 	}
 
 	public void CommandSend(REPCommand cmd){
-		REPCommand[] cmds;
+		REPCommand cmds;
 		cmd.eid = eid;
 		cmds = translater.transSendCmd(cmd);
 
-		for (int i=0; i<cmds.length; i++){
-			sender.send(cmds[i]);
-		}
+//		for (int i=0; i<cmds.length; i++){
+//			sender.send(cmds[i]);
+//		}
 	}
 
 	/*   */
--- a/src/sample/merge/Translater.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/sample/merge/Translater.java	Sat Aug 23 11:28:16 2008 +0900
@@ -9,7 +9,7 @@
 	 * @param command which the editor want to send.
 	 * @return translated command which should be sent by the editor.
 	 */
-	abstract public REPCommand[] transSendCmd(REPCommand cmd);
+	abstract public REPCommand transSendCmd(REPCommand cmd);
 
 	/**
 	 * Inform translater about that the editor receive own command which it sent.
--- a/src/sample/merge/TranslaterImp1.java	Fri Aug 22 15:48:52 2008 +0900
+++ b/src/sample/merge/TranslaterImp1.java	Sat Aug 23 11:28:16 2008 +0900
@@ -1,8 +1,11 @@
 package sample.merge;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.Stack;
+import java.util.TreeSet;
 
 import remoteeditor.command.REPCommand;
 import remoteeditor.network.REP;
@@ -30,13 +33,11 @@
 	 * @param cmd
 	 * @return translated command.
 	 */
-	synchronized public REPCommand[] transSendCmd(REPCommand cmd){
-		REPCommand[] cmds = new REPCommand[1];
+	public REPCommand transSendCmd(REPCommand cmd){
 		setCmdState(cmd);
-		cmds[0] = cmd;
 		sentCmds.add(cmd);
 		unMergedCmds.push(cmd);
-		return cmds;
+		return cmd;
 	}
 	/**
 	 * Dequeue command cmd that was returned.
@@ -50,8 +51,7 @@
 		assert tmp.seq==cmd.seq;
 		assert cmd.eid==eid;
 
-		/* スタックから全部取り出してマージする まだマージできないやつはまたスタックへ戻す  */
-		/* スタックから全部取り出す  */
+				//スタック上にあるコマンドを全部undoコマンドにする
 		while ( !unMergedCmds.isEmpty() ){
 			REPCommand cmd0 = unMergedCmds.pop();
 			returnCmds.add( createUndo(cmd0) );
@@ -96,24 +96,37 @@
 		System.out.println();
 		return null;	
 	}
+	
+	class REPCommandComparator implements Comparator<REPCommand>{
 
-	private ArrayList<REPCommand> sortCmds(ArrayList<REPCommand> cmds) {
-		ArrayList<REPCommand> sortedCmds = new ArrayList<REPCommand>();
+		public int compare(REPCommand o1, REPCommand o2) {
+			
+			if ( o2.lineno > o1.lineno ) return 1;
+			else if ( o2.lineno < o1.lineno 
+					|| o2.eid > o1.eid )
+				/* deleteとinsertの場合などはeidによらず、順序を強制する必要があるかも  */
+				return -1;
+
+			return 1;
+		}
+		
+	}
+	
+	private Collection<REPCommand> sortCmds(ArrayList<REPCommand> cmds) {
+		TreeSet<REPCommand> sortedCmds1 = new TreeSet<REPCommand>(new REPCommandComparator());
 		int top;
 		int prevEid=-1;
 		int i,j;
 
-		/*  
-		 * EID,SEQの低い順に、各EID毎に1個だけ選択しsortedCmdsに格納
-		 * cmdsにはまだデータが残る     
-		 */
 		while ( -1 != (top=getPrecedence(cmds, prevEid+1)) ){
 		//while ( -1 != (top=getPrecedence(cmds, prevEid)) ){
 			REPCommand tmp = cmds.remove(top); 
-			sortedCmds.add(tmp);
+			sortedCmds1.add(tmp);
 			prevEid = tmp.eid;
 		}
-
+		
+		if(false){
+			ArrayList<REPCommand> sortedCmds = new ArrayList<REPCommand>();
 		/* lineno の大きい順にソート  */
 		for (i=0; i<sortedCmds.size(); i++){
 			int k=i;
@@ -128,7 +141,8 @@
 			sortedCmds.set(i, sortedCmds.get(k));
 			sortedCmds.set(k, tmp);
 		}
-		return sortedCmds;
+		}
+		return sortedCmds1;
 	}
 
 	/* search cmd. ordering by  min EID that is lower lowEid and min SEQ.  */
@@ -213,4 +227,9 @@
 		// TODO Auto-generated method stub
 		undoReplaceList.add(command);
 	}
+
+	public void checkMergeConflict() {
+		// TODO Auto-generated method stub
+		
+	}
 }