# HG changeset patch # User kono # Date 1223287129 -32400 # Node ID 20fb70068089dc22a1c81965cd77576ddc4ff5ff # Parent edb373aa421ec20ea89bfefb8888ea8a52c1b65b *** empty log message *** diff -r edb373aa421e -r 20fb70068089 Todo --- a/Todo Mon Oct 06 10:34:37 2008 +0900 +++ b/Todo Mon Oct 06 18:58:49 2008 +0900 @@ -1,26 +1,40 @@ +Mon Oct 6 16:39:57 JST 2008 + +Todo: translator にある5つのqueueが、Editor にもある。merge のアルゴリズムの +実装を見直す必要がある。(kono) + +Todo: +SessionManager の向うにあるeditorにREPCommandを送るコードがない。Editor 扱いしても良いが、Editor が複雑すぎるので、それは好ましくない。Editor に nextChannelを持たせるのが良いか? (kono) + +Todo: +SessionManger のeditor がmerge 中のeditor commandをblockするのは良いが、 +sessionManger コマンドをblockされるのは困る。(kono) Wed Oct 1 20:58:51 JST 2008 Todo: Session ring 廻るcommand packetは、基本的に書き換えられるべきではない   eid, seq の組でuniqueになる。現状では、そここで書き換えが起きているらしい。 eid = -1 (Session Manager), eid = -2 (MergeCommand) あたりが - 特殊らしい。 でも、実際には生成されてないっぽい。 + 特殊らしい。 でも、実際には生成されてないっぽい。(kono) + Done: Mon Oct 6 16:40:14 JST 2008 (kono) Todo: SessionManagerのprotocolのswitch文で、そこら中でgetEditor/getSessionが -  呼ばれている。これらは、for loopで探しているので、繰り返し行うのは変。 +  呼ばれている。これらは、for loopで探しているので、繰り返し行うのは変。(kono) -Todo: REPCMD_INSERTが止まらない... +Todo: REPCMD_INSERTが止まらない... (kono) + Done: Mon Oct 6 16:40:38 JST 2008 (kono) -Todo: SessionMnager のmessageをREPLogger baseに書き換える。 +Todo: SessionMnager のmessageをREPLogger baseに書き換える。 (kono) Wed Oct 1 15:35:44 JST 2008 -Todo: SessionManager 複数のコマンドをまとめてeditorに送るとdead lockする可能性がある。 -  送信キューを作り、select loop しながら、ひとつずつコマンドを送信する - Done: +Todo: SessionManager 複数のコマンドをまとめてeditorに送るとdead lockする + 可能性がある。送信キューを作り、select loop しながら、ひとつずつコマンドを + 送信する (kono) + Done: (kono) Todo: Editor quit, quit2 の実装   quit2 では、自分の送信したコマンドが戻ってくるまで待つ必要がある。 -  editor 毎の状態となる。 - Done: - \ No newline at end of file +  editor 毎の状態となる。(kono) + Done: (kono) + diff -r edb373aa421e -r 20fb70068089 rep/Editor.java --- a/rep/Editor.java Mon Oct 06 10:34:37 2008 +0900 +++ b/rep/Editor.java Mon Oct 06 18:58:49 2008 +0900 @@ -1,6 +1,5 @@ package rep; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -18,9 +17,10 @@ private String file; private TranslaterImp1 translater; private List sentList; - private List sentMergedList; + // REPCommands we sent to the next editor + private List writeQueue; + // REPCommands we are going to send to the next editor private REPCommandOptimizer optimizer; - private List writeQueue; private REPCommand quit2 = null; private REPLogger ns = REPLogger.singleton(); private final int limit=100; @@ -32,7 +32,6 @@ setHostAndPort(myChannel); translater = new TranslaterImp1(eid); sentList = new LinkedList(); - sentMergedList = new LinkedList(); writeQueue = new LinkedList(); if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ @@ -45,7 +44,6 @@ this.myChannel = channel; translater = new TranslaterImp1(eid); sentList = new LinkedList(); - sentMergedList = new LinkedList(); writeQueue = new LinkedList(); setHostAndPort(myChannel); } @@ -58,64 +56,50 @@ writeQueue = new LinkedList(); } - public List translate(REPCommand command){ - List list = new LinkedList(); - if(command.eid == eid){ + enum TranslatorResult { + START_MERGE, NEW_COMMAND, MERGE_RETURN, MERGE_AGAIN, INCOMMING_COMMAND, MERGE_END + } + + public TranslatorResult translate(Editor nextEditor, REPCommand command){ + if(command.eid == nextEditor.getEID()){ if(checkReturnedCommand(command)){ //エディタからのコマンドが元のエディタに戻ってきた // START_MERGE を送る REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,""); - list.add(cmd); - return list; - }else{ + nextEditor.send(cmd); + return TranslatorResult.START_MERGE; + } else assert(false); + } else if(command.eid == eid){ //エディタからの新たな編集コマンド sentList.add(command); assert(sentList.size() mergeAgainList = translater.getMergeAgain(); - - mergeAgainList = optimizer.optimize(mergeAgainList); - writeQueue.addAll(mergeAgainList); - assert(writeQueue.size() cmds = translater.catchOwnCommand(); - //optimizer - if (cmds.size()==0) - return false; // no merge phase is necessary - //マージ中のエディタからの割り込み検知に使う - sentMergedList.addAll(cmds); - sendMergedCommand(cmds); - return true; - } - - private void sendMergedCommand(ArrayList cmds) { - for(REPCommand mergeCommand : cmds){ - mergeCommand.setEID(REP.MERGE_EID.id); - mergeCommand.setSEQID(seq()); - writeQueue.add(mergeCommand); - assert(writeQueue.size() sList = new LinkedList(sessionList); diff -r edb373aa421e -r 20fb70068089 rep/translater/Translater.java --- a/rep/translater/Translater.java Mon Oct 06 10:34:37 2008 +0900 +++ b/rep/translater/Translater.java Mon Oct 06 18:58:49 2008 +0900 @@ -1,7 +1,6 @@ package rep.translater; -import java.util.ArrayList; - +import rep.Editor; import rep.REPCommand; public interface Translater { @@ -18,14 +17,14 @@ * but in this case, you can use also transReceiveCmd() * @param command which the editor sent. */ - abstract public ArrayList catchOwnCommand(); + abstract public boolean catchOwnCommand(Editor editor); /** * Translate Command cmd that was received from SeMa. * @param cmd the command to be translated. * @return translated command. */ - abstract public REPCommand[] transReceiveCmd(REPCommand cmd); + abstract public void transReceiveCmd(Editor nextEditor,REPCommand cmd); /** * set the editor's id. diff -r edb373aa421e -r 20fb70068089 rep/translater/TranslaterImp1.java --- a/rep/translater/TranslaterImp1.java Mon Oct 06 10:34:37 2008 +0900 +++ b/rep/translater/TranslaterImp1.java Mon Oct 06 18:58:49 2008 +0900 @@ -1,23 +1,23 @@ package rep.translater; -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 rep.Editor; import rep.REPCommand; import rep.REP; public class TranslaterImp1 implements Translater{ - //List userList; - //List tokenList; - private LinkedList sentCmds; - //private LinkedList unMergedCmds; - private Stack unMergedCmds; public int eid; private int seq; + /* + * queue が5つもいるって、あまりに馬鹿げてる。 + */ + private LinkedList sentCmds; + private Stack unMergedCmds; private LinkedList undoReplaceList; private LinkedList sentMergedList; private LinkedList mergeAgainList; @@ -32,13 +32,12 @@ } /** - * Translate cmd When the editor send REPCommand. - * but now, Only adding cmd to the queue is available. + * New command from an editor + * The command is sent to the next editor * @param cmd * @return translated command. */ public REPCommand transSendCmd(REPCommand cmd){ - //setCmdState(cmd); sentCmds.add(cmd); unMergedCmds.push(cmd); @@ -50,31 +49,30 @@ return cmd; } /** - * Dequeue command cmd that was returned. + * My command is returned from the session ring. * @param cmd */ - public ArrayList catchOwnCommand(){ - ArrayList returnCmds = new ArrayList(); - ArrayList cmds = new ArrayList(); + public boolean catchOwnCommand(Editor editor){ + LinkedList output = new LinkedList(); + LinkedList cmds = new LinkedList(); prev(); //スタック上にあるコマンドを全部undoコマンドにする while ( !unMergedCmds.isEmpty() ){ REPCommand cmd0 = unMergedCmds.pop(); - returnCmds.add( createUndo(cmd0) ); + output.add( createUndo(cmd0) ); cmds.add(cmd0); } /* 必要な分だけソートして返却用のリストに追加 */ - //if (cmds.size()==0) return null; - returnCmds.addAll( sortCmds(cmds) ); + output.addAll( sortCmds(cmds) ); /* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる */ - for(int i=0; i sortCmds(ArrayList cmds) { + private Collection sortCmds(LinkedList cmds) { TreeSet sortedCmds1 = new TreeSet(new REPCommandComparator()); int top; int prevEid=-1; @@ -120,21 +114,21 @@ } /* search cmd. ordering by min EID that is lower lowEid and min SEQ. */ - private int getPrecedence(ArrayList cmds, int lowEid) { + private int getPrecedence(LinkedList cmds, int lowEid) { int cEid, cSeq; cEid=cSeq=Integer.MAX_VALUE; int ret=-1; for (int i=0; icEid ) continue; - else if ( tmp.eid==cEid ) { - if ( tmp.seq>cSeq ) continue; - cSeq=tmp.seq; + REPCommand c = cmds.get(i); + if ( c.eidcEid ) continue; + else if ( c.eid==cEid ) { + if ( c.seq>cSeq ) continue; + cSeq=c.seq; ret = i; } else { /* tmp.eid channel; + REPCommand nop = new REPCommand(REP.REPCMD_NOP, 0, 0, 0, 0, ""); boolean running = true; long timeout = 1; private String name; @@ -58,7 +59,7 @@ cmds.add(new REPCommand(REP.SMCMD_PUT,0,0,0,0,name+"-file")); cmds.add(new REPCommand(REP.REPCMD_INSERT,0,0,0,0,"m0")); //cmds.add(new REPCommand(REP.REPCMD_DELETE,0,0,0,0,"m0")); - //cmds.add(new REPCommand(REP.SMCMD_QUIT,0,0,0,0,"")); + cmds.add(new REPCommand(REP.SMCMD_QUIT,0,0,0,0,"")); } else { text = new Text(new String[0]); cmds.add(new REPCommand(REP.SMCMD_JOIN,0,0,0,0,name)); @@ -145,8 +146,8 @@ 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,seq++); - sendCommand(ins,seq++); + sendCommand(del); + sendCommand(ins); syncCounter++; } } @@ -160,12 +161,12 @@ switch(cmd.cmd) { case REPCMD_INSERT: text.insert(cmd.lineno, cmd.string); - sendCommand(cmd,seq++); + sendCommand(cmd); break; case REPCMD_DELETE: String del = text.delete(cmd.lineno); cmd.setString(del); - sendCommand(cmd,seq++); + sendCommand(cmd); break; case SMCMD_QUIT: /* @@ -174,11 +175,11 @@ * clients simply disconnect from the session manager. */ cmds.clear(); - sendCommand(cmd,seq++); + sendCommand(cmd); break; case SMCMD_JOIN: case SMCMD_PUT: - sendCommand(cmd,seq++); + sendCommand(cmd); prevSeq = seq; /* * To prevent confusion, stop user input until the ack @@ -195,42 +196,48 @@ } - private void sendCommand(REPCommand cmd1,int seq) { + private void sendCommand(REPCommand cmd1) { REPCommand cmd = new REPCommand(cmd1); - cmd.setSEQID(seq); + cmd.setSEQID(seq++); cmd.setEID(eid); cmd.setSID(sid); ns.writeLog(name +" send "+cmd); channel.write(cmd); } + private void forwardCommand(REPCommand cmd1) { + REPCommand cmd = new REPCommand(cmd1); + ns.writeLog(name +" forward "+cmd); + channel.write(cmd); + } + private void handle(REPCommand cmd) { if (cmd==null) return; ns.writeLog(name +": read "+cmd); switch(cmd.cmd) { case REPCMD_INSERT : text.insert(cmd.lineno, cmd.string); - if (cmd.eid==REP.MERGE_EID.id) break; - addNop(); - sendCommand(cmd,cmd.seq); + if (cmd.eid!=REP.MERGE_EID.id) + addNop(); + forwardCommand(cmd); break; case REPCMD_INSERT_ACK : assert(false); break; case REPCMD_DELETE : String del = text.delete(cmd.lineno); - if (cmd.eid==REP.MERGE_EID.id) break; - addNop(); + if (cmd.eid!=REP.MERGE_EID.id) + addNop(); cmd.setString(del); - sendCommand(cmd,cmd.seq); + forwardCommand(cmd); break; case REPCMD_DELETE_ACK : assert(false); break; case REPCMD_NOP : - if (cmd.eid==REP.MERGE_EID.id) break; - addNop(); - sendCommand(cmd,cmd.seq); + if (cmd.eid!=REP.MERGE_EID.id) + addNop(); + forwardCommand(cmd); break; case REPCMD_CLOSE : case REPCMD_CLOSE_2 : assert(false); @@ -247,13 +254,12 @@ inputLock = false; break; case SMCMD_QUIT : - if (false) { + if(true) return; if (cmd.eid!=eid) - sendCommand(cmd,cmd.seq); + forwardCommand(cmd); else sendCommand(new REPCommand(REP.SMCMD_QUIT_2, - sid, eid, seq, 0, ""),seq++); - } + sid, eid, seq, 0, "")); cmds.clear(); break; case SMCMD_QUIT_ACK : @@ -263,7 +269,7 @@ // lock user input during merge (optional) inputLock = hasInputLock; cmd.cmd = REP.SMCMD_START_MERGE_ACK; - sendCommand(cmd,seq++); + sendCommand(cmd); break; case SMCMD_START_MERGE_ACK : assert(false); @@ -273,13 +279,14 @@ break; case SMCMD_QUIT_2 : if (cmd.eid!=eid) { - sendCommand(cmd,cmd.seq); + forwardCommand(cmd); } running = false; break; case SMCMD_SYNC: // start contents sync with newly joined editor - cmd.cmd = REP.SMCMD_SYNC_ACK; sendCommand(cmd,cmd.seq); + cmd.cmd = REP.SMCMD_SYNC_ACK; + forwardCommand(cmd); if (cmd.eid==eid) syncCounter = 1; break; @@ -292,8 +299,7 @@ private void addNop() { if (seq!=prevSeq) return; // We haven't send any command, add nop before retransmition. - REPCommand nop = new REPCommand(REP.REPCMD_NOP, sid, eid, seq, 0, ""); - sendCommand(nop,seq++); + sendCommand(nop); prevSeq = seq; } }