changeset 300:8f6b7a1890b2

*** empty log message ***
author kono
date Wed, 01 Oct 2008 16:20:04 +0900
parents d13dad30fd24
children d12aac5ab798
files Todo rep/Editor.java rep/Session.java rep/SessionManager.java test/sematest/TestEditor.java
diffstat 5 files changed, 86 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Todo	Wed Oct 01 16:20:04 2008 +0900
@@ -0,0 +1,10 @@
+Wed Oct  1 15:35:44 JST 2008
+
+Todo: SessionManager 複数のコマンドをまとめてeditorに送るとdead lockする可能性がある。
+  送信キューを作り、select loop しながら、ひとつずつコマンドを送信する
+	Done:
+
+Todo: Editor quit, quit2 の実装
+  quit2 では、自分の送信したコマンドが戻ってくるまで待つ必要がある。
+  editor 毎の状態となる。
+	Done:
\ No newline at end of file
--- a/rep/Editor.java	Wed Oct 01 03:21:48 2008 +0900
+++ b/rep/Editor.java	Wed Oct 01 16:20:04 2008 +0900
@@ -18,6 +18,8 @@
 	private List<REPCommand> sentList;
 	private List<REPCommand> sentMergedList;
 	private REPCommandOptimizer optimizer;
+	private List<REPCommand> writeQueue;
+	private REPCommand quit2 = null;
 	
 	public Editor(){
 		this(true);
@@ -27,6 +29,7 @@
 		translater = new TranslaterImp1(eid);
 		sentList = new LinkedList<REPCommand>();
 		sentMergedList = new LinkedList<REPCommand>();
+		writeQueue = new LinkedList<REPCommand>();
 
 		if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ
 		else            optimizer = new NullOptimizer();         //なにもしないけどOptimizer.
@@ -39,6 +42,7 @@
 		translater = new TranslaterImp1(eid);
 		sentList = new LinkedList<REPCommand>();
 		sentMergedList = new LinkedList<REPCommand>();
+		writeQueue = new LinkedList<REPCommand>();
 		setHostAndPort(myChannel);
 	}
 	
@@ -47,6 +51,7 @@
 		setHostAndPort(myChannel);
 		translater = new TranslaterImp1(eid);
 		sentList = new LinkedList<REPCommand>();
+		writeQueue = new LinkedList<REPCommand>();
 	}
 	
 	public List<REPCommand> translate(REPCommand command){
@@ -74,9 +79,7 @@
 				List<REPCommand> mergeAgainList = translater.getMergeAgain();
 
 				mergeAgainList = optimizer.optimize(mergeAgainList);
-				for(REPCommand againCommand: mergeAgainList){
-					myChannel.write(againCommand);
-				}
+				writeQueue.addAll(mergeAgainList);
 			}
 		}else{
 			//他のエディタからの編集コマンド
@@ -89,14 +92,9 @@
 	}
 	
 	private void sendMergedCommand(ArrayList<REPCommand> cmds) {
-		//  一気に送ると、向こう側(Editor)で、dead lock する可能性がある。
-		//  select loop の中で一つ一つ送るしかない。Editor側から割り込まれる可能性も
-		//  ある。その時に複数のコマンドを送っていると、どこに割り込まれたかを判断する
-		// ことが出来ない。そこで、一つ一つReturnを確認する必要がある。つまり、
-		// select loop で送るしかない。
 		for(REPCommand mergeCommand : cmds){
 			mergeCommand.setEID(REP.MERGE_EID.id);
-			myChannel.write(mergeCommand);
+			writeQueue.add(mergeCommand);
 		}
 	}
 
@@ -107,11 +105,35 @@
 				return true;
 			}else{
 				System.err.println("Editor.checkReturnedCommand() : command = " + command);
+				assert(false);
 			}
 		}
 		return false;
 	}
 
+	
+	public boolean doWaitingWrite() {
+		//  一気に送ると、向こう側(Editor)で、dead lock する可能性がある。
+		//  select loop の中で一つ一つ送るしかない。Editor側から割り込まれる可能性も
+		//  ある。その時に複数のコマンドを送っていると、どこに割り込まれたかを判断する
+		// ことが出来ない。そこで、一つ一つReturnを確認する必要がある。つまり、
+		// select loop で送るしかない。
+		REPCommand cmd;
+		if (writeQueue.size()>0) {
+			cmd = writeQueue.remove(0);
+			myChannel.write(cmd);
+			return true;
+		} else if (quit2!=null && sentList.size()==0) {
+			myChannel.write(quit2);
+			return true;
+		}
+		return false;
+	}
+	
+	public void setQuit2(REPCommand cmd) {
+		quit2 = cmd;
+	}
+	
 	private void setHostAndPort(REPSocketChannel<REPCommand> myChannel2) {
 		//host = myChannel2.socket().getRemoteSocketAddress().toString();
 		
@@ -137,6 +159,7 @@
 
 	public void setEID(int eid) {
 		this.eid = eid;
+		translater.setEid(eid);
 	}
 	public String toString(){
 		return (host  + ":" + file);
--- a/rep/Session.java	Wed Oct 01 03:21:48 2008 +0900
+++ b/rep/Session.java	Wed Oct 01 16:20:04 2008 +0900
@@ -116,4 +116,8 @@
 			editor.send(command);
 		}
 	}
+	public void sendToNextEditor(REPSocketChannel<REPCommand>channel,REPCommand command) {
+		Editor next = getNextEditor(getEditor(channel));
+		next.send(command);
+	}
 }
--- a/rep/SessionManager.java	Wed Oct 01 03:21:48 2008 +0900
+++ b/rep/SessionManager.java	Wed Oct 01 16:20:04 2008 +0900
@@ -91,11 +91,13 @@
 
 	public void mainLoop() throws IOException {
 		while(true){
-			System.out.println();
 			SessionManagerEvent e;
 			while((e = waitingQueue.poll())!=null){
 				e.exec();
 			}
+			for(Editor editor:editorList) {
+				if (editor.doWaitingWrite()) break;
+			}
 			if(checkSend()){
 				if(selector.selectNow() > 0){
 					select();
@@ -128,7 +130,7 @@
 		for(REPSelectionKey<REPCommand> key : keys){
 			if(key.isAcceptable()){
 				REPSocketChannel<REPCommand> channel = key.accept(new REPCommandPacker());
-				//System.out.println("SessionManager.select() : key.isAcceptable : channel = " + channel);
+				System.out.println("SessionManager.select() : key.isAcceptable : channel = " + channel);
 				registerChannel (channel, SelectionKey.OP_READ);
 				channel = null;
 
@@ -157,7 +159,6 @@
 	}
 
 	public void manage(REPSocketChannel<REPCommand> channel, REPCommand receivedCommand) throws IOException {
-		System.out.println("SessionManager.manage() : receivedCommand = " + receivedCommand);
 		if(receivedCommand == null) return;
 		//Session session;
 		REPCommand sendCommand = new REPCommand(receivedCommand);
@@ -376,6 +377,7 @@
 
 		case REPCMD_DELETE:
 		case REPCMD_INSERT:
+		case REPCMD_NOP:
 		{
 			//sid から Session を取得
 			Session session = getSession(receivedCommand.sid);
@@ -396,7 +398,21 @@
 			}
 		}
 		break;
-		
+		case SMCMD_QUIT:
+		{
+			Session session = getSession(receivedCommand.sid);
+			if (session==null) throw new IOException();
+			session.sendToNextEditor(channel,receivedCommand);
+			break;
+		}
+		case SMCMD_QUIT_2:
+		{
+			Session session = getSession(receivedCommand.sid);
+			if (session==null) throw new IOException();
+			Editor editor = session.getEditor(channel);
+			editor.setQuit2(receivedCommand);
+			break;
+		}
 		default:
 			assert(false);
 			break;
@@ -475,7 +491,7 @@
 		
 		int port = DEFAULT_PORT;
 		int port_s = DEFAULT_PORT;
-
+		//System.setProperty("file.encoding", "UTF-8");
 		if(args.length > 0){
 			port = Integer.parseInt(args[0]);
 			port_s = Integer.parseInt(args[1]);
--- a/test/sematest/TestEditor.java	Wed Oct 01 03:21:48 2008 +0900
+++ b/test/sematest/TestEditor.java	Wed Oct 01 16:20:04 2008 +0900
@@ -101,16 +101,7 @@
 				continue;
 			} else if (selector.select(timeout)<=0) {
 				if (syncCounter>0) {
-					if (syncCounter>text.size()) {
-						syncCounter=0;
-					} else {
-						int i=syncCounter-1;
-						REPCommand del = new REPCommand(REP.REPCMD_DELETE,sid,eid,0,i, text.get(i));
-						REPCommand ins = new REPCommand(REP.REPCMD_INSERT,sid,eid,0,i, text.get(i));
-						sendCommand(del);
-						sendCommand(ins);
-						syncCounter++;
-					}
+					syncText();
 				}
 				userInput();
 			} else {
@@ -119,6 +110,19 @@
 		}
 	}
 
+	private void syncText() {
+		if (syncCounter>text.size()) {
+			syncCounter=0;
+		} else {
+			int i=syncCounter-1;
+			REPCommand del = new REPCommand(REP.REPCMD_DELETE,sid,eid,0,i, text.get(i));
+			REPCommand ins = new REPCommand(REP.REPCMD_INSERT,sid,eid,0,i, text.get(i));
+			sendCommand(del);
+			sendCommand(ins);
+			syncCounter++;
+		}
+	}
+
 	private void userInput() {
 		REPCommand cmd = cmds.poll();
 		if (cmd!=null) {
@@ -139,6 +143,7 @@
 			case SMCMD_JOIN:
 			case SMCMD_PUT:
 				sendCommand(cmd);
+				inputLock = true; // wait until ACK
 				break;
 			default:
 				assert(false);
@@ -164,7 +169,7 @@
 		case REPCMD_INSERT	:
 			text.insert(cmd.lineno, cmd.string);
 			sendCommand(cmd);
-			sendCommand(nop);
+			// sendCommand(nop); session manager do this for me
 			break;
 		case REPCMD_INSERT_ACK	:
 			assert(false);
@@ -173,7 +178,7 @@
 			String del = text.delete(cmd.lineno);
 			cmd.setString(del);
 			sendCommand(cmd);
-			sendCommand(nop);
+			// sendCommand(nop); session manager do this for me
 			break;
 		 case REPCMD_DELETE_ACK	:
 				assert(false);
@@ -189,10 +194,12 @@
 		 case SMCMD_JOIN_ACK	:
 			 sid = cmd.sid;
 			 eid = cmd.eid;
+			 inputLock = false;
 			 break;
 		 case SMCMD_PUT_ACK	:
 			 sid = cmd.sid;
 			 eid = cmd.eid;
+			 inputLock = false;
 			 break;
 		 case SMCMD_QUIT		:
 			 sendCommand(cmd);