# HG changeset patch # User kono # Date 1222845604 -32400 # Node ID 8f6b7a1890b23f42e6ac0d10c3e5bb33001f6970 # Parent d13dad30fd247ef8625c08b33107b92b20a3db8f *** empty log message *** diff -r d13dad30fd24 -r 8f6b7a1890b2 Todo --- /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 diff -r d13dad30fd24 -r 8f6b7a1890b2 rep/Editor.java --- 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 sentList; private List sentMergedList; private REPCommandOptimizer optimizer; + private List writeQueue; + private REPCommand quit2 = null; public Editor(){ this(true); @@ -27,6 +29,7 @@ translater = new TranslaterImp1(eid); sentList = new LinkedList(); sentMergedList = new LinkedList(); + writeQueue = new LinkedList(); if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ else optimizer = new NullOptimizer(); //なにもしないけどOptimizer. @@ -39,6 +42,7 @@ translater = new TranslaterImp1(eid); sentList = new LinkedList(); sentMergedList = new LinkedList(); + writeQueue = new LinkedList(); setHostAndPort(myChannel); } @@ -47,6 +51,7 @@ setHostAndPort(myChannel); translater = new TranslaterImp1(eid); sentList = new LinkedList(); + writeQueue = new LinkedList(); } public List translate(REPCommand command){ @@ -74,9 +79,7 @@ List 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 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 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); diff -r d13dad30fd24 -r 8f6b7a1890b2 rep/Session.java --- 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(REPSocketChannelchannel,REPCommand command) { + Editor next = getNextEditor(getEditor(channel)); + next.send(command); + } } diff -r d13dad30fd24 -r 8f6b7a1890b2 rep/SessionManager.java --- 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 key : keys){ if(key.isAcceptable()){ REPSocketChannel 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 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]); diff -r d13dad30fd24 -r 8f6b7a1890b2 test/sematest/TestEditor.java --- 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);