Mercurial > hg > RemoteEditor > REPSessionManager
annotate rep/handler/Editor.java @ 460:ef70109af810
self writeQueue and waitingQueue
author | one |
---|---|
date | Fri, 24 Sep 2010 17:05:19 +0900 |
parents | 66c4f6b29baf |
children | e7eeb8be0de1 |
rev | line source |
---|---|
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
1 package rep.handler; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
2 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
3 import java.io.IOException; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
4 import java.util.LinkedList; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
5 import java.util.List; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
6 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
7 import rep.PacketSet; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
8 import rep.REP; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
9 import rep.REPCommand; |
384 | 10 import rep.ServerMainLoop; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
11 import rep.SessionManager; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
12 import rep.channel.REPSelectionKey; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
13 import rep.channel.REPSocketChannel; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
14 import rep.optimizers.*; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
15 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
16 public class Editor extends Forwarder { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
17 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
18 private Translator translator; |
387 | 19 // REPCommands we are going to send to the next editor |
439 | 20 private LinkedList<REPCommand> sentList = new LinkedList<REPCommand>(); |
460 | 21 public LinkedList<REPCommand> waitingCommandInMerge= new LinkedList<REPCommand>(); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
22 private REPCommand quit2=null; |
442 | 23 private REPCommand preMergeCommand; |
387 | 24 private boolean merging; |
449 | 25 private REPCommand mergeMark = new REPCommand(REP.SMCMD_START_MERGE, 0,0, 0, 0, ""); |
391 | 26 public static boolean noMergeMode=false; |
445 | 27 static final boolean doOptimize = false; |
460 | 28 private Forwarder toEditor; |
29 private LinkedList<REPCommand> writeQueue = new LinkedList<REPCommand>(); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
30 |
385 | 31 public Editor(SessionManager manager,int editorNo){ |
387 | 32 // no translator case |
33 super(manager, null); | |
34 } | |
35 | |
36 public Editor(int editorNo, SessionManager manager,REPSocketChannel<REPCommand> channel){ | |
37 super(editorNo,manager,channel); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
38 eid = editorNo; |
449 | 39 sentList.add(mergeMark); // merge mark |
453 | 40 toEditor = new Forwarder(eid, manager, channel); // no wait forwarder for my editor |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
41 REPCommandOptimizer optimizer; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
42 if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
43 else optimizer = new NullOptimizer(); //なにもしないけどOptimizer. |
383 | 44 translator = new Translator(eid,optimizer); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
45 } |
387 | 46 |
427 | 47 /* |
48 * Merge Protocol | |
445 | 49 (0) Editor へのコマンドは、ack 以外は直接 Editor へ送られてしまう。(next.send(cmd)) |
50 Editor から返ってくるコマンドをtranslatorが処理する。 | |
427 | 51 (1) Editor CommandをSession Ring 上に流し、それが戻って来るまでに、他のEditorから |
52 受け取った Editor Command をキューに入れておく。 | |
53 (2) 戻って来たタイミングで、キュー上のEditor Commandを、eid とCommandの | |
54 順序を基にソートする。(self merge) | |
55 (3) 他のEditorにソートのタイミングを与えるために、Editor Command の | |
56 ack を、もう一周させる。 | |
57 (4) 他のEditorのCommandを受け取ってから、ack が来るまでのCommandをキューに | |
58 入れておき、ack が来たら、eid とCommandの順序を基にソートする。(other merge) | |
59 | |
60 Editor には、ソートした編集結果になるように、それまで行なった編集をUndo | |
61 して、ソートした編集結果を適用する。Undo が無駄な動作をしないように最適化する。 | |
62 | |
63 handle() | |
64 セッションの処理 | |
65 manage() | |
66 編集コマンドは translate() へ | |
67 一周して来た編集コマンドのACKは廃棄 (merge queue から削除) | |
68 一周して来た自分のコマンドならself merge | |
69 他のエディタの編集コマンドのACK->other merge | |
70 それ以外は、そのまま実行、merge queue へ格納 | |
71 merge は checkReturnedCommand() から | |
72 startMerge() へ | |
73 まず、接続されている Editor に START_MERGE を送る | |
74 邪魔されないように、他のcommand は block する | |
75 manager() | |
76 START_MERGE_ACK が来たら、translator.mergeAck() で教えて、 | |
77 merge()-> | |
78 translator.checkOwnCommand() へ | |
79 ここで、sort されて、Merge Command をEditorへ送信 | |
80 checkEndMerge()から | |
81 endMerge() が呼ばれる。 | |
82 自分のエディタにEND_MERGE で Merge終了を通知 | |
83 自分のコマンドは、ACKに変えて送信 (3) | |
84 それ以外は、そのまま送信 (一周させる) | |
85 | |
86 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
87 |
397 | 88 public void translate(REPCommand command){ |
89 switch(command.cmd) { | |
90 case REPCMD_INSERT_ACK: | |
91 case REPCMD_DELETE_ACK: | |
92 if (command.eid==eid) { | |
93 // Second Phase が終わって同期が終了。 | |
442 | 94 // SessionManager.logger.writeLog("Complete "+command); |
452 | 95 checkAck(command); |
410 | 96 checkQuit(); |
397 | 97 return; |
98 } | |
99 checkReturnedCommand(command); | |
100 return; | |
400 | 101 case REPCMD_INSERT_USER: |
102 command.cmd = REP.REPCMD_INSERT; | |
103 userEditorCommand(command); | |
104 return; | |
105 case REPCMD_DELETE_USER: | |
406 | 106 command.cmd = REP.REPCMD_DELETE; |
400 | 107 userEditorCommand(command); |
108 return; | |
401 | 109 case REPCMD_INSERT: |
110 case REPCMD_DELETE: | |
111 if (command.eid == REP.MERGE_EID.id){ | |
112 //マージコマンドが返ってきた | |
113 if(translator.checkMergeConflict(command)){ | |
114 //マージ中にエディタからの割り込みがあった場合 | |
115 translator.getMergeAgain(this); | |
116 } | |
117 checkEndMerge(); | |
118 return; | |
457 | 119 } |
120 if (command.eid == eid){ | |
401 | 121 // 編集コマンドが一周して来た |
122 checkReturnedCommand(command); | |
400 | 123 return; |
124 } | |
401 | 125 |
126 //他のエディタからの編集コマンド | |
127 translator.transReceiveCmd(next,command); | |
431 | 128 |
401 | 129 sendEditorCommand(command); |
400 | 130 return; |
401 | 131 default: |
132 assert(false); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
133 } |
400 | 134 } |
135 | |
136 private void userEditorCommand(REPCommand command) { | |
137 //エディタからの新たな編集コマンド | |
138 if (next==this) return; // singleton case | |
139 translator.transSendCmd(command); | |
140 sendEditorCommand(command); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
141 return; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
142 } |
398 | 143 |
404 | 144 // private void checkDouble(List<REPCommand> sentList) { |
145 // if (sentList.size()==0) return; | |
146 // int count = 0; | |
147 // REPCommand f = sentList.get(0); | |
148 // for(REPCommand c:sentList) { | |
149 // if (c.eid==f.eid&&c.seq==f.seq) { | |
150 // count++; | |
151 // } | |
152 // } | |
153 // assert(count==1); | |
154 // if (true) return; | |
155 // count = 0; | |
156 // for(PacketSet c:waitingCommandInMerge) { | |
157 // for(REPCommand g:sentList) { | |
158 // if (c.command.eid==g.eid&&c.command.seq==g.seq) { | |
159 // count++; | |
160 // } | |
161 // } | |
162 // } | |
163 // assert(count==0); | |
164 // } | |
399 | 165 |
460 | 166 /** |
167 * Sending to Editor and waiting Queue | |
168 * +--------+ | |
169 * send() --> write() -> | Editor | -> handle() -> manager() | |
170 * +--------+ | |
171 * waitingQueue | |
172 * writeQueue | |
173 * | |
174 * send() は、他のEditor Node から呼ばれる | |
175 * write() は、内部で優先的に送信するのに用いる | |
176 * writeQueue は、waitingQueue よりも常に先に実行される必要がある | |
177 | |
178 * Manageの送信キューはここでは使わない | |
179 * send() manage | |
180 */ | |
181 @Override | |
182 public void send(REPCommand command) { | |
183 if (merging || isMerging() || waitingCommandInMerge.size()>0) { | |
184 waitingCommandInMerge.addLast(command); | |
185 ServerMainLoop.logger.writeLog("Editor eid:"+eid+" waitingCommandInMerge = "+waitingCommandInMerge); | |
186 return; | |
187 } | |
188 if (isMergeCommand(command)) { | |
189 merging = true; | |
190 ServerMainLoop.logger.writeLog("Editor"+eid+": merging=true (send)"+command); | |
191 } | |
192 writeQueue.add(command); | |
398 | 193 } |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
194 |
460 | 195 /** |
196 * Check waiting command in merge | |
197 * periodically called from manager | |
198 */ | |
199 public void checkWaitingCommandInMerge() { | |
200 if (writeQueue.size()>0) { | |
201 REPCommand command =writeQueue.pollFirst(); | |
202 ServerMainLoop.logger.writeLog("Editor"+eid+": write comand="+command); | |
203 super.write(command); | |
204 return; | |
205 } | |
206 if (translator==null || merging || isMerging()) return; | |
207 if (waitingCommandInMerge.size()>0) { | |
208 REPCommand command = waitingCommandInMerge.pollFirst(); | |
209 ServerMainLoop.logger.writeLog("Editor"+eid+": send waiting comand="+command); | |
210 super.write(command); | |
211 if (isMergeCommand(command)) { | |
212 merging = true; | |
213 } | |
214 } | |
399 | 215 } |
431 | 216 /** |
217 * 他のエディタへのコマンドの送信 | |
218 * @param command | |
219 * | |
220 * sendList にキープする必要がある。 | |
221 */ | |
397 | 222 private void sendEditorCommand(REPCommand command) { |
223 REPCommand keep = new REPCommand(command); | |
224 sentList.add(keep); | |
407 | 225 //ServerMainLoop.logger.writeLog("Editor eid:"+eid+" sentList = "+sentList); |
397 | 226 assert(sentList.size()<limit); |
431 | 227 if (command.cmd==REP.REPCMD_DELETE) { |
228 // delete のundo用の文字列は、外に出す意味はない | |
229 command.string=null; | |
230 } | |
397 | 231 next.send(command); |
232 } | |
233 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
234 boolean merge(REPCommand command) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
235 //マージして送信 |
435 | 236 return translator.catchOwnCommand(this, command); |
431 | 237 } |
238 | |
239 @Override | |
240 public List<REPCommand> getSentList() { | |
241 return sentList; | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
242 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
243 |
391 | 244 /** |
245 * 一周して来たcommandの処理。 | |
404 | 246 * |
247 * INSERT/DELETEを受け取った時に、sentListに登録 | |
248 * INSERT_ACK/DELETE_ACKが来たら一周。そこで、Mergeする。 | |
249 * | |
250 * 自分が出したINSERT/DELETEが戻って来たら、ACKに変更して、Merge。 | |
251 * | |
252 * 途中から参加した場合、自分が受けとってないcommandのACKが先に来ることが | |
253 * ある。それは、無視して良い。 | |
391 | 254 * @param command |
255 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
256 void checkReturnedCommand(REPCommand command) { |
439 | 257 startMerge(command); |
406 | 258 return; |
259 } | |
260 | |
395 | 261 private void startMerge(REPCommand command) { |
451 | 262 ServerMainLoop.logger.writeLog("Editor"+eid+": startMerge "+command); |
397 | 263 preMergeCommand = new REPCommand(command); |
391 | 264 // merge は必須だが、EditorのCommand実装をテストするには邪魔なので、off に出来るようにする。 |
265 if (noMergeMode) { | |
410 | 266 checkQuit(); |
396 | 267 endMerge(); |
391 | 268 return; |
269 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
270 // START_MERGE を送る |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
271 // 送らないで良い場合もある? |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
272 REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,""); |
450 | 273 sendToEditor(cmd); |
387 | 274 merging = true; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
275 // Session Manager 側で、このeditorへの他のeditorからの |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
276 // 入力を止めて、merge にそなえる。merge は、eidtor 側から |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
277 // ACKが来てから始まる。 |
427 | 278 translator.startMerge(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
279 } |
457 | 280 |
281 private boolean checkAck(REPCommand command) { | |
282 assert(!isMerging()); | |
283 REPCommand prev; | |
284 if (sentList.getFirst()==mergeMark) prev=sentList.remove(1); else prev=sentList.remove(0); | |
285 if (prev==null || prev.seq != command.seq || prev.eid!=command.eid) { | |
286 // should be more robust to allow communication failure | |
287 String err = "Editor eid="+eid+" checkReturnedCommand() : command = " + command + " prev="+ | |
288 (prev==null?"null":prev)+" sentList="; | |
289 err += sentList; | |
290 ServerMainLoop.logger.writeLog(err); | |
291 assert(false); | |
292 } | |
293 return true; | |
294 } | |
295 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
296 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
297 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
298 public void setQuit2(REPCommand cmd) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
299 quit2 = cmd; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
300 checkQuit(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
301 // do not send quit2 until we received all pending |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
302 // command |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
303 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
304 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
305 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
306 public void setEID(int eid) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
307 this.eid = eid; |
387 | 308 if (translator!=null) |
309 translator.setEid(eid); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
310 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
311 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
312 public String toString(){ |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
313 return ("Editor eid="+eid+" sid="+sid+" " + host + ":" + file); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
314 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
315 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
316 public boolean isMerging() { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
317 return translator.isMerging(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
318 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
319 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
320 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
321 void checkEndMerge() { |
387 | 322 if (merging) { |
434 | 323 if (translator.isMerging()) return; |
396 | 324 endMerge(); |
387 | 325 merging = false; |
326 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
327 if (quit2!=null) checkQuit(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
328 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
329 |
442 | 330 |
396 | 331 private void endMerge() { |
445 | 332 translator.endMerge(); |
396 | 333 REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,sid,eid,seq(),0,""); |
450 | 334 sendToEditor(mergeEnd); |
452 | 335 checkAck(preMergeCommand); |
397 | 336 if (preMergeCommand.eid==eid) { |
337 // First Phase End, send ACK | |
338 REPCommand keep = new REPCommand(preMergeCommand); | |
339 switch(keep.cmd) { | |
398 | 340 case REPCMD_INSERT: keep.cmd = REP.REPCMD_INSERT_ACK;break; |
341 case REPCMD_DELETE: keep.cmd = REP.REPCMD_DELETE_ACK;break; | |
406 | 342 default: assert(false); |
397 | 343 } |
449 | 344 sentList.addLast(preMergeCommand); |
407 | 345 //ServerMainLoop.logger.writeLog("Editor eid:"+eid+" sentList = "+sentList); |
397 | 346 assert(sentList.size()<limit); |
347 next.send(keep); | |
348 } else { | |
349 next.send(preMergeCommand); | |
350 } | |
449 | 351 sentList.remove(mergeMark); |
352 sentList.addLast(mergeMark); | |
397 | 353 preMergeCommand = null; |
396 | 354 } |
355 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
356 private boolean checkQuit() { |
460 | 357 if (quit2!=null && sentList.size()==1&&!isMerging() && waitingCommandInMerge.size()==0) { |
450 | 358 sendToEditor(quit2); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
359 quit2 = null; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
360 return true; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
361 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
362 return false; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
363 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
364 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
365 @Override |
387 | 366 public boolean manage(REPCommand command) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
367 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
368 |
387 | 369 switch(command.cmd){ |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
370 // Editor Command |
396 | 371 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
372 case REPCMD_DELETE: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
373 case REPCMD_INSERT: |
400 | 374 case REPCMD_DELETE_USER: |
375 case REPCMD_INSERT_USER: | |
396 | 376 case REPCMD_DELETE_ACK: |
377 case REPCMD_INSERT_ACK: | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
378 { |
387 | 379 translate(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
380 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
381 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
382 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
383 case SMCMD_START_MERGE_ACK: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
384 { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
385 // マージの処理と次のエディタへコマンドを送信する処理 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
386 translator.mergeAck(); |
434 | 387 if (!merge(preMergeCommand)) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
388 // nothing to do, send END_MERGE |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
389 checkEndMerge(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
390 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
391 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
392 } |
386 | 393 |
394 case SMCMD_SYNC: | |
395 if (isMaster()) | |
450 | 396 sendToEditor(command); |
386 | 397 else |
387 | 398 next.send(command); |
386 | 399 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
400 case SMCMD_QUIT: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
401 { |
387 | 402 next.send(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
403 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
404 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
405 case SMCMD_QUIT_2: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
406 { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
407 // QUIT_2 is returned. |
387 | 408 if (command.eid!=eid) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
409 // stop this editor unless this is the start, starter will stopped |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
410 // by QUIT_2_ACK |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
411 manager.remove(this); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
412 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
413 // don't send quit_2 directly to the editor until all pending |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
414 // merge is processed. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
415 // this does not work in distributed case. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
416 if (next.isDirect()) |
387 | 417 next.setQuit2(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
418 else |
387 | 419 next.send(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
420 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
421 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
422 case SMCMD_QUIT_2_ACK: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
423 { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
424 manager.remove(this); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
425 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
426 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
427 default: |
396 | 428 assert false; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
429 return false; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
430 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
431 return true; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
432 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
433 |
442 | 434 |
450 | 435 private boolean isMergeCommand(REPCommand command) { |
436 switch(command.cmd) { | |
437 case REPCMD_INSERT: case REPCMD_DELETE: | |
438 return command.eid==eid; | |
439 case REPCMD_INSERT_ACK: case REPCMD_DELETE_ACK: | |
440 return command.eid!=eid; | |
441 } | |
442 return false; | |
443 } | |
444 | |
445 public void sendToEditor(REPCommand command) { | |
460 | 446 writeQueue.add(command); |
450 | 447 } |
448 | |
442 | 449 @Override |
387 | 450 public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { |
442 | 451 //ServerMainLoop.logger.writeLog("Manager "+manager.getId()+" read : command = " + command |
452 // +" from "+manager.editorList.editorByChannel(channel)); | |
387 | 453 if (command.cmd==REP.SMCMD_JOIN||command.cmd==REP.SMCMD_PUT) { |
404 | 454 // assert false; |
427 | 455 // 一つのエディタ上に複数のセッションが作られた場合。 |
387 | 456 // 若干問題があるらしい |
457 next = new Forwarder(manager,next.channel); | |
458 REPNode first = new FirstConnector(manager,channel); | |
459 first.handle(command, key); | |
460 key.attach(new Dispatcher(manager,channel)); | |
461 return; | |
462 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
463 if (manager.sessionManage(this, command)) return; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
464 manage(command); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
465 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
466 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
467 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
468 public void cancel(REPSocketChannel<REPCommand> socketChannel) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
469 manager.remove(socketChannel); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
470 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
471 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
472 public boolean isMaster() { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
473 return mode==REP.SMCMD_PUT; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
474 } |
386 | 475 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
476 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
477 /* Handle special case first, usually these cases |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
478 * are handled in the next Editor in a session manager, but |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
479 * it is forwarded here. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
480 */ |
385 | 481 public void forwardedCommandManage(REPCommand command) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
482 if (command.cmd==REP.SMCMD_QUIT_2) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
483 // we have to wait next editor's finishing before sending this. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
484 // this is odd, but the editor itself does not know it's merging |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
485 // state. Only this session manager knows it. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
486 setQuit2(command); |
401 | 487 return; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
488 } |
385 | 489 send(command); |
490 } | |
491 | |
399 | 492 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
493 } |