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