Mercurial > hg > RemoteEditor > REPSessionManager
changeset 387:6f356d160e58
IPv6 any address
author | one@firefly.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Mon, 10 Nov 2008 22:21:52 +0900 |
parents | bba62c4ac323 |
children | 4ec3b70f8f09 |
files | Todo rep/SessionManager.java rep/SessionManagerList.java rep/gui/RPanel.java rep/handler/Dispatcher.java rep/handler/Editor.java rep/handler/FirstConnector.java rep/handler/Forwarder.java rep/handler/NullForwarder.java rep/handler/REPNode.java rep/xml/SessionXMLDecoder.java test/RepCommandOptimizeTest.java test/Text.java test/XMLTest.java test/sematest/TestEditor.java |
diffstat | 15 files changed, 201 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/Todo Mon Nov 10 22:19:34 2008 +0900 +++ b/Todo Mon Nov 10 22:21:52 2008 +0900 @@ -1,4 +1,33 @@ +Sun Oct 26 17:36:40 JST 2008 +Todo: (kono) +GUI のEditorの方が、どれがどれだか、さっぱりわからない。 +せめて、sessionを持っているかとか出ないとだめっぽい。 +なんか、NO_NAMEってのが最初に出るらしい。なんだ? + +Sun Oct 26 14:33:51 JST 2008 +Todo: (kono) +quit/close 処理が間違っているらしい。 + +Sat Oct 25 10:52:05 JST 2008 +Todo: (kono) +Editorからのmutli-sessoin の扱い、TestEditor でのmulti-session +の実装。REPNode.handle の中でreadしちゃうと、handle 間での処理 +の引き渡しが出来ない。handlerの切替えにkeyは必要。 + +一つのeditorの中で、同じsessionに複数selectすると、コマンドを +判定出来なくなる。今でも、新しくchannelを開けるなら複数セッション +をselectすることは可能。channelで識別しているので。 +新しいeditorが作られてしまうので、ダメなケースの判定は、直接接続し +ているSMでしか出来ない。と言うことは、selectのcancelのprotocolが +必要らしい。それは、結構、面倒。command に source editor id を +付けてやれば良いのだが... + +Todo: (kono) +text editor のバッファが増えるバグがあるらしい。 + Done: たぶん、quit/quit2が動いてない。close の処理のがまずいせい。 + Fri Oct 24 19:00:50 JST 2008 +Note: XML に editor がselectされているかどうかのflagがあった方が良い。 現状では、update はなんにも役に立たない。 @@ -12,7 +41,9 @@ Todo: (kono) やっぱり、END_MERGEが繰り返し出るバグがあるらしい。 - Done: Thu Oct 23 10:12:27 JST 2008 merge confilict 時にmode setを忘れてました。 + Done: Thu Oct 23 10:12:27 JST 2008 merge confilict 時にmode setを + 忘れてました。 + 結局、flag を入れて対症療法しました。 Wed Oct 22 02:31:27 JST 2008 @@ -22,12 +53,13 @@ だが... やっぱり、dummy editor ではなくて、専用のものを作らないと だめ? Done: Wed Oct 22 02:56:30 JST 2008 - ちょっとあれだが、next がdirecgtでない場合を判断して、向こうのforwarder側で - 処理するのが簡単らしい。 + ちょっとあれだが、next がdirecgtでない場合を判断して、向こうの + forwarder側で処理するのが簡単らしい。 Todo: (kono) Select後のupdateを流してないので、他の人が、そのsessionがselectされたのを 知り得ない。なので、複数のjoin_ackがありえる。 + Done: Sun Oct 26 17:39:05 JST 2008 Mon Oct 20 16:38:39 JST 2008
--- a/rep/SessionManager.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/SessionManager.java Mon Nov 10 22:21:52 2008 +0900 @@ -51,7 +51,7 @@ // Session Manager Channel may have dummy editors. EditorList editorList = new EditorList(); // Queue limit for debugging purpose. - static final int packetLimit = 200; + static final int packetLimit = 400; // globalSessionID = SessionManagerID * MAXID + localSessionID private static final int MAXID = 10000; @@ -118,7 +118,7 @@ REPSocketChannel<REPCommand> sessionchannel = REPSocketChannel.<REPCommand>create(new REPCommandPacker()); sessionchannel.connect(addr); while(!sessionchannel.finishConnect()); - REPNode sm = new FirstConnector(this); + REPNode sm = new FirstConnector(this,sessionchannel); registerChannel(sessionchannel, sm); sm_join(sm); }catch (IOException e) { @@ -208,9 +208,9 @@ } private REPNode createSessionForwarder(int sid, REPNode editor) { - REPNode f = new Forwarder(this); + REPNode f = new Forwarder(this,editor.channel); f.setEID(makeID(editorList.newEid())); - f.setChannel(editor.channel); // incoming channel + // f.setChannel(editor.channel); // incoming channel f.setHost(myHost); f.setSID(sid); return f; @@ -237,7 +237,7 @@ */ public REPNode newEditor(REPSocketChannel<REPCommand> channel) { int eid = makeID(editorList.newEid()); - REPNode editor = new Editor(this, eid, channel); + REPNode editor = new Editor(eid, this, channel); editorList.add(editor); return editor; } @@ -448,7 +448,7 @@ // すでに channelはSessionManager Idを持っていて、 // direct link ではないので、 // channel を持たないForwarderとして登録する - sm = new Forwarder(this); + sm = new Forwarder(this,null); } else { sm = forwarder; } @@ -547,7 +547,7 @@ } else return; } else { - editor = new Editor(this, command.eid); + editor = new Editor(manager, command.eid); } editor.setName(command.string); editor.setSID(command.sid);
--- a/rep/SessionManagerList.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/SessionManagerList.java Mon Nov 10 22:21:52 2008 +0900 @@ -13,7 +13,7 @@ private static final long serialVersionUID = 1L; private int mySMID=0; private int smid_root=0; - private REPNode parent=new NullForwarder(null); + private REPNode parent=new NullForwarder(null,null); private LinkedList<REPNode> waiting= new LinkedList<REPNode>();
--- a/rep/gui/RPanel.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/gui/RPanel.java Mon Nov 10 22:21:52 2008 +0900 @@ -106,9 +106,12 @@ }else if(event.getSource() == selectButton){ //System.out.println("RPanel.actionPerformed() : editorSelectedRow = " + editor_table.getSelectedRow()); + int selectedSession = session_table.getSelectedRow(); + if (selectedSession<0) return; // no sessin is selected + int selectedEditor = editor_table.getSelectedRow(); listener.buttonPressed( - new SelectButtonEvent(editorList.get(editor_table.getSelectedRow()), - sessionList.get(session_table.getSelectedRow()))); + new SelectButtonEvent(editorList.get(selectedEditor), + sessionList.get(selectedSession))); }else if(event.getSource() == closeButton){ listener.buttonPressed(new CloseButtonEvent(sessionList.get(session_table.getSelectedRow()), listener)); }
--- a/rep/handler/Dispatcher.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/Dispatcher.java Mon Nov 10 22:21:52 2008 +0900 @@ -17,8 +17,10 @@ */ public class Dispatcher extends Forwarder { - public Dispatcher(SessionManager manager) { - super(manager); + + public Dispatcher(SessionManager manager, + REPSocketChannel<REPCommand> channel) { + super(manager, channel); } public void setQuit2(REPCommand cmd) { @@ -35,14 +37,13 @@ } - public void handle(REPSelectionKey<REPCommand> key) throws IOException { + @Override + public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { /* * SessionManagerから来たコマンドは、Editor関係のコマンドは、 * sessionとeidを判定して、そのeditorにforwardしてやれば良い。 * 残りは、manager.manage() で処理する。 */ - REPSocketChannel<REPCommand> channel = key.channel1(); - REPCommand command = channel.read(); ServerMainLoop.logger.writeLog("REPHandlerImpl.handle() : command = " + command); if (manager.sessionManage(this, command)) return;
--- a/rep/handler/Editor.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/Editor.java Mon Nov 10 22:21:52 2008 +0900 @@ -16,28 +16,26 @@ public class Editor extends Forwarder { private Translator translator; + // REPCommands we are going to send to the next editor private List<REPCommand> sentList = new LinkedList<REPCommand>(); - // REPCommands we are going to send to the next editor - //private REPCommand quit2 = null; - private SessionManager manager; private REPCommand quit2=null; + private boolean merging; static final boolean doOptimize = true; public Editor(SessionManager manager,int editorNo){ - super(manager); - this.manager = manager; + // no translator case + super(manager, null); + } + + public Editor(int editorNo, SessionManager manager,REPSocketChannel<REPCommand> channel){ + super(editorNo,manager,channel); eid = editorNo; REPCommandOptimizer optimizer; if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ else optimizer = new NullOptimizer(); //なにもしないけどOptimizer. translator = new Translator(eid,optimizer); - } - - public Editor(SessionManager manager,int editorNo, REPSocketChannel<REPCommand> channel){ - this(manager,editorNo); - this.channel = channel; - } + public void translate(REPCommand command){ @@ -99,6 +97,7 @@ // 送らないで良い場合もある? REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,""); send(cmd); + merging = true; // Session Manager 側で、このeditorへの他のeditorからの // 入力を止めて、merge にそなえる。merge は、eidtor 側から // ACKが来てから始まる。 @@ -117,7 +116,8 @@ @Override public void setEID(int eid) { this.eid = eid; - translator.setEid(eid); + if (translator!=null) + translator.setEid(eid); } public String toString(){ @@ -131,9 +131,12 @@ void checkEndMerge() { - if(translator.isMerging()) return; - REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,""); - send(mergeEnd); + if (merging) { + if(translator.isMerging()) return; + REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,""); + send(mergeEnd); + merging = false; + } if (quit2!=null) checkQuit(); } @@ -147,17 +150,17 @@ } @Override - public boolean manage(REPCommand receivedCommand) { + public boolean manage(REPCommand command) { - switch(receivedCommand.cmd){ + switch(command.cmd){ // Editor Command case REPCMD_DELETE: case REPCMD_INSERT: case REPCMD_NOP: { - translate(receivedCommand); + translate(command); break; } @@ -165,7 +168,7 @@ { // マージの処理と次のエディタへコマンドを送信する処理 translator.mergeAck(); - if (!merge(receivedCommand)) { + if (!merge(command)) { // nothing to do, send END_MERGE checkEndMerge(); } @@ -174,19 +177,19 @@ case SMCMD_SYNC: if (isMaster()) - send(receivedCommand); + send(command); else - next.send(receivedCommand); + next.send(command); case SMCMD_QUIT: { - next.send(receivedCommand); + next.send(command); break; } case SMCMD_QUIT_2: { // QUIT_2 is returned. - if (receivedCommand.eid!=eid) { + if (command.eid!=eid) { // stop this editor unless this is the start, starter will stopped // by QUIT_2_ACK manager.remove(this); @@ -195,9 +198,9 @@ // merge is processed. // this does not work in distributed case. if (next.isDirect()) - next.setQuit2(receivedCommand); + next.setQuit2(command); else - next.send(receivedCommand); + next.send(command); break; } case SMCMD_QUIT_2_ACK: @@ -213,10 +216,17 @@ @Override - public void handle(REPSelectionKey<REPCommand> key) throws IOException { - REPSocketChannel<REPCommand> channel = key.channel1(); - REPCommand command = channel.read(); + public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { ServerMainLoop.logger.writeLog("REPHandlerImpl.handle() read : command = " + command +" from "+channel); + if (command.cmd==REP.SMCMD_JOIN||command.cmd==REP.SMCMD_PUT) { + assert false; + // 若干問題があるらしい + next = new Forwarder(manager,next.channel); + REPNode first = new FirstConnector(manager,channel); + first.handle(command, key); + key.attach(new Dispatcher(manager,channel)); + return; + } if (manager.sessionManage(this, command)) return; manage(command); }
--- a/rep/handler/FirstConnector.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/FirstConnector.java Mon Nov 10 22:21:52 2008 +0900 @@ -13,15 +13,19 @@ public class FirstConnector extends Forwarder { - public FirstConnector(SessionManager manager) { - super(manager); + + + public FirstConnector(SessionManager manager, + REPSocketChannel<REPCommand> channel) { + super(manager,channel); } - + public void cancel(REPSocketChannel<REPCommand> socketChannel) { manager.remove(socketChannel); } - public void handle(REPSelectionKey<REPCommand> key) throws IOException { + @Override + public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { /* * 接続要求は、EditorかSlave Editorで、 * join, put, sm_join @@ -29,8 +33,6 @@ * sm_join_ack */ REPNode fw; - REPSocketChannel<REPCommand> channel = key.channel1(); - REPCommand command = channel.read(); ServerMainLoop.logger.writeLog("FirstConnector: command = " + command); switch(command.cmd) { case SMCMD_JOIN: @@ -63,14 +65,14 @@ } case SMCMD_SM_JOIN: { - fw = new Dispatcher(manager); // FirstConnector? + fw = new Dispatcher(manager,channel); // FirstConnector? manager.addWaitingSessionManager(fw, command); break; } case SMCMD_SM_JOIN_ACK: manager.setSessionManagerID(command.sid); manager.afterConnect(); - fw = new Dispatcher(manager); + fw = new Dispatcher(manager,channel); manager.setParent(fw); break; default: throw new IOException();
--- a/rep/handler/Forwarder.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/Forwarder.java Mon Nov 10 22:21:52 2008 +0900 @@ -21,11 +21,15 @@ // REPCommands we sent to the next editor final int limit=100; // debugging purpose, assert check only final REPLogger ns = REPLogger.singleton(); - SessionManager manager; - public REP mode = null; - - public Forwarder(SessionManager manager) { - this.manager = manager; + + public Forwarder(SessionManager manager, + REPSocketChannel<REPCommand> channel) { + super(manager,channel); + } + + public Forwarder(int editorNo, SessionManager manager, + REPSocketChannel<REPCommand> channel) { + super(editorNo,manager,channel); } public int seq() { @@ -81,11 +85,13 @@ return channel.getLocalHostName(); } + @Override public void cancel(REPSocketChannel<REPCommand> socketChannel) { manager.remove(socketChannel); } - public void handle(REPSelectionKey<REPCommand> key) throws IOException { + @Override + public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { assert false; }
--- a/rep/handler/NullForwarder.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/NullForwarder.java Mon Nov 10 22:21:52 2008 +0900 @@ -14,33 +14,43 @@ */ public class NullForwarder extends Forwarder { - public NullForwarder(SessionManager manager) { - super(manager); + + public NullForwarder(SessionManager manager, + REPSocketChannel<REPCommand> channel) { + super(manager, channel); } - + + @Override public void send(REPCommand command) { } + + @Override public void cancel(REPSocketChannel<REPCommand> socketChannel) { } - public void handle(REPSelectionKey<REPCommand> key) throws IOException { + @Override + public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { } + @Override public boolean manage(REPCommand command) { return true; } + @Override public boolean isEditor() { return false; } + @Override public boolean isForwarder() { return false; } + @Override public boolean isDirect() { return false; }
--- a/rep/handler/REPNode.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/handler/REPNode.java Mon Nov 10 22:21:52 2008 +0900 @@ -5,6 +5,7 @@ import rep.REP; import rep.REPCommand; import rep.Session; +import rep.SessionManager; import rep.channel.REPSelectionKey; import rep.channel.REPSocketChannel; @@ -28,14 +29,21 @@ public REP mode; public REPSocketChannel<REPCommand> channel; public REPNode next; + public SessionManager manager; public REPNode() { } - - public REPNode(int eid, REPSocketChannel<REPCommand> channel) { + + public REPNode(int eid, SessionManager manager, REPSocketChannel<REPCommand> channel) { this.eid = eid; this.channel = channel; + this.manager = manager; + } + + public REPNode(SessionManager manager, REPSocketChannel<REPCommand> channel) { + this.channel = channel; + this.manager = manager; } public String getName() { @@ -94,7 +102,7 @@ if (host==null) host = editor.host; } - public abstract void handle(REPSelectionKey<REPCommand> key) throws IOException; + public abstract void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException; public abstract void cancel(REPSocketChannel<REPCommand> channel1) ;
--- a/rep/xml/SessionXMLDecoder.java Mon Nov 10 22:19:34 2008 +0900 +++ b/rep/xml/SessionXMLDecoder.java Mon Nov 10 22:21:52 2008 +0900 @@ -84,15 +84,17 @@ Element elementFile = (Element) nodelistEditorFile.item(0); String file = elementFile.getFirstChild().getNodeValue(); - Editor editor = new Editor(null, 0); - editor.setHost(host);/* editor.setPort(port)*/; editor.setName(file); editor.setEID(Integer.parseInt(eid)); + int id = Integer.parseInt(eid); + Editor editor = new Editor(null, id); + editor.setHost(host);/* editor.setPort(port)*/; editor.setName(file); session = new Session(sid, editor); session.addEditor(editor); sessionlist.put(sid,session); }else { - Editor editor = new Editor(null, 0); - editor.setHost(host);/* editor.setPort(port)*/; editor.setName(null); editor.setEID(Integer.parseInt(eid)); + int id = Integer.parseInt(eid); + Editor editor = new Editor(null, id); + editor.setHost(host);/* editor.setPort(port)*/; editor.setName(null); if(session != null){ session.addEditor(editor); }
--- a/test/RepCommandOptimizeTest.java Mon Nov 10 22:19:34 2008 +0900 +++ b/test/RepCommandOptimizeTest.java Mon Nov 10 22:21:52 2008 +0900 @@ -1,8 +1,12 @@ package test; +import static org.junit.Assert.*; + import java.util.LinkedList; import java.util.List; +import org.junit.Test; + import rep.REPCommand; import rep.REP; import rep.optimizers.NullOptimizer; @@ -85,7 +89,15 @@ text.printAllText(); } + public static void main(String[] s){ + RepCommandOptimizeTest t = new RepCommandOptimizeTest(); + t.main0(); + } + + @Test + public void main0(){ + REPCommandOptimizer rco; if (true) rco = new DeleteInsertOptimizer(); // @@ -107,7 +119,6 @@ } - private static void test(REPCommandOptimizer rco, List<REPCommand> cmdlist, Text text1, Text text2) { List<REPCommand> result; // optimize @@ -117,6 +128,7 @@ // this command list applied to other text, and print it. text2.edit(result); // check two texts. + assertEquals(text1.equals(text2),true); if(!text1.equals(text2)){ System.out.println("two texts not match"); print(cmdlist, result, text1, text2);
--- a/test/Text.java Mon Nov 10 22:19:34 2008 +0900 +++ b/test/Text.java Mon Nov 10 22:21:52 2008 +0900 @@ -7,36 +7,46 @@ import rep.REPCommand; import rep.REP; -public class Text { +public class Text extends LinkedList<String> { + - List<String> strList; - + /** + * + */ + private static final long serialVersionUID = 1L; + public Text(String[] _strings){ - strList = new LinkedList<String>(Arrays.asList(_strings)); + super(Arrays.asList(_strings)); } + public Text(List<String> _strings){ - strList = new LinkedList<String>(_strings); + super(_strings); } public String insert(int i, String str){ - assert 0<=i && i<=strList.size(); - strList.add(i, str); + assert 0<=i && i<=size(); + add(i, str); return null; } + public String delete(int i){ - assert 0<=i && i<strList.size(); - return strList.remove(i); + if (i>=size()) return ""; + // assert 0<=i && i<size(); + return remove(i); } + public String replace(int i, String str){ - assert 0<=i && i<strList.size(); - String replaced = strList.get(i); - strList.set(i, str); + //assert 0<=i && i<size(); + String replaced ; + if (i<size()) { + replaced = get(i); + } else { + replaced = ""; + } + set(i, str); return replaced; } - public String get(int i){ - assert 0<=i && i<strList.size(); - return strList.get(i); - } + 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); @@ -44,21 +54,16 @@ //else assert false; return null; } + public void edit(List<REPCommand> cmdlist){ for (REPCommand cmd: cmdlist){ edit(cmd); } } - public int size(){ - return strList.size(); - } public void printAllText(){ - for( String str: strList){ + for( String str: this){ System.out.println(str); } } - public boolean equals(Text _target){ - return strList.equals(_target.strList); - } }
--- a/test/XMLTest.java Mon Nov 10 22:19:34 2008 +0900 +++ b/test/XMLTest.java Mon Nov 10 22:21:52 2008 +0900 @@ -14,13 +14,13 @@ public static void main(String[] args){ - Editor editor = new Editor(null,0, null); + Editor editor = new Editor(0,null,null); editor.setEID(1); editor.setHost("firefly.cr.ie.u-ryukyu.ac.jp"); //editor.setPort("56789"); editor.setName("Test.java"); - Editor editor2 = new Editor(null,1, null); + Editor editor2 = new Editor(1,null,null); editor2.setEID(2); editor2.setHost("teto.cr.ie.u-ryukyu.ac.jp"); //editor2.setPort("45678");
--- a/test/sematest/TestEditor.java Mon Nov 10 22:19:34 2008 +0900 +++ b/test/sematest/TestEditor.java Mon Nov 10 22:21:52 2008 +0900 @@ -39,6 +39,7 @@ private boolean inputLock=false; public boolean detached=false; public boolean master=false; + REPCommand quit=null; private int syncCounter=0; private boolean hasInputLock=false; private int port; @@ -62,7 +63,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)); @@ -182,7 +183,7 @@ * clients simply disconnect from the session manager. */ cmds.clear(); - sendCommand(cmd); + quit = cmd; break; case SMCMD_JOIN: case SMCMD_PUT: @@ -197,9 +198,14 @@ assert(false); } } else { - if(syncCounter==0) + if(syncCounter==0) { // no more command to send, and we don't have syncCounter timeout = 0; + if (quit!=null) { + sendCommand(quit); + quit=null; + } + } } } @@ -229,9 +235,6 @@ addNop(); forwardCommand(cmd); break; - case REPCMD_INSERT_ACK : - assert(false); - break; case REPCMD_DELETE : String del=""; if(cmd.lineno>text.size()) { @@ -242,14 +245,12 @@ cmd.setString(del); forwardCommand(cmd); break; - case REPCMD_DELETE_ACK : - assert(false); - break; case REPCMD_NOP : if (cmd.eid!=REP.MERGE_EID.id) addNop(); forwardCommand(cmd); - break; case REPCMD_CLOSE : + break; + case REPCMD_CLOSE : case REPCMD_CLOSE_2 : assert(false); break; @@ -275,20 +276,15 @@ // stop input processing after this command cmds.clear(); break; - case SMCMD_QUIT_ACK : - assert(false); - break; case SMCMD_START_MERGE : // lock user input during merge (optional) inputLock = hasInputLock; cmd.cmd = REP.SMCMD_START_MERGE_ACK; sendCommand(cmd); break; - case SMCMD_START_MERGE_ACK : - assert(false); - break; case SMCMD_END_MERGE : inputLock = false; + prevSeq = seq; break; case SMCMD_QUIT_2 : if (cmd.eid!=eid) { @@ -318,8 +314,8 @@ private void addNop() { if (seq!=prevSeq) return; // We haven't send any command, add nop before retransmition. + prevSeq = seq; sendCommand(nop); - prevSeq = seq; } public int getPort() {