Mercurial > hg > RemoteEditor > REPSessionManager
annotate rep/handler/Editor.java @ 448:ed97273477a0
fix sentList
author | one |
---|---|
date | Wed, 22 Sep 2010 17:42:47 +0900 |
parents | 22a741c1fa2d |
children | 89a326696c54 |
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); |
391 | 246 // merge は必須だが、EditorのCommand実装をテストするには邪魔なので、off に出来るようにする。 |
247 if (noMergeMode) { | |
410 | 248 checkQuit(); |
396 | 249 endMerge(); |
391 | 250 return; |
251 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
252 // START_MERGE を送る |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
253 // 送らないで良い場合もある? |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
254 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
|
255 send(cmd); |
387 | 256 merging = true; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
257 // Session Manager 側で、このeditorへの他のeditorからの |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
258 // 入力を止めて、merge にそなえる。merge は、eidtor 側から |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
259 // ACKが来てから始まる。 |
427 | 260 translator.startMerge(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
261 } |
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 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
264 public void setQuit2(REPCommand cmd) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
265 quit2 = cmd; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
266 checkQuit(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
267 // 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
|
268 // command |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
269 } |
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 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
272 public void setEID(int eid) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
273 this.eid = eid; |
387 | 274 if (translator!=null) |
275 translator.setEid(eid); | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
276 } |
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 public String toString(){ |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
279 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
|
280 } |
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 public boolean isMerging() { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
283 return translator.isMerging(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
284 } |
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 void checkEndMerge() { |
387 | 288 if (merging) { |
434 | 289 if (translator.isMerging()) return; |
396 | 290 endMerge(); |
387 | 291 merging = false; |
292 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
293 if (quit2!=null) checkQuit(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
294 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
295 |
442 | 296 |
396 | 297 private void endMerge() { |
445 | 298 translator.endMerge(); |
396 | 299 REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,sid,eid,seq(),0,""); |
300 send(mergeEnd); | |
436 | 301 sentList.remove(0); |
397 | 302 if (preMergeCommand.eid==eid) { |
303 // First Phase End, send ACK | |
304 REPCommand keep = new REPCommand(preMergeCommand); | |
305 switch(keep.cmd) { | |
398 | 306 case REPCMD_INSERT: keep.cmd = REP.REPCMD_INSERT_ACK;break; |
307 case REPCMD_DELETE: keep.cmd = REP.REPCMD_DELETE_ACK;break; | |
406 | 308 default: assert(false); |
397 | 309 } |
448 | 310 sentList.add(preMergeCommand); |
407 | 311 //ServerMainLoop.logger.writeLog("Editor eid:"+eid+" sentList = "+sentList); |
397 | 312 assert(sentList.size()<limit); |
313 next.send(keep); | |
314 } else { | |
315 next.send(preMergeCommand); | |
316 } | |
317 preMergeCommand = null; | |
396 | 318 } |
319 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
320 private boolean checkQuit() { |
410 | 321 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
|
322 send(quit2); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
323 quit2 = null; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
324 return true; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
325 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
326 return false; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
327 } |
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 @Override |
387 | 330 public boolean manage(REPCommand command) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
331 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
332 |
387 | 333 switch(command.cmd){ |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
334 // Editor Command |
396 | 335 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
336 case REPCMD_DELETE: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
337 case REPCMD_INSERT: |
400 | 338 case REPCMD_DELETE_USER: |
339 case REPCMD_INSERT_USER: | |
396 | 340 case REPCMD_DELETE_ACK: |
341 case REPCMD_INSERT_ACK: | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
342 { |
387 | 343 translate(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
344 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
345 } |
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 case SMCMD_START_MERGE_ACK: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
348 { |
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 translator.mergeAck(); |
434 | 351 if (!merge(preMergeCommand)) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
352 // nothing to do, send END_MERGE |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
353 checkEndMerge(); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
354 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
355 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
356 } |
386 | 357 |
358 case SMCMD_SYNC: | |
359 if (isMaster()) | |
387 | 360 send(command); |
386 | 361 else |
387 | 362 next.send(command); |
386 | 363 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
364 case SMCMD_QUIT: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
365 { |
387 | 366 next.send(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
367 break; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
368 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
369 case SMCMD_QUIT_2: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
370 { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
371 // QUIT_2 is returned. |
387 | 372 if (command.eid!=eid) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
373 // 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
|
374 // by QUIT_2_ACK |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
375 manager.remove(this); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
376 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
377 // 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
|
378 // merge is processed. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
379 // this does not work in distributed case. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
380 if (next.isDirect()) |
387 | 381 next.setQuit2(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
382 else |
387 | 383 next.send(command); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
384 break; |
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 case SMCMD_QUIT_2_ACK: |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
387 { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
388 manager.remove(this); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
389 break; |
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 default: |
396 | 392 assert false; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
393 return false; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
394 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
395 return true; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
396 } |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
397 |
443 | 398 /** |
399 * send command to the editor | |
400 * called from another Editor instance such as next.send(command) | |
401 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
402 @Override |
442 | 403 public void send(REPCommand command) { |
404 if (command.eid == REP.MERGE_EID.id || | |
405 command.cmd==REP.SMCMD_END_MERGE || | |
444 | 406 !waitingRequired(command,channel)) { |
442 | 407 super.send(command); |
408 } | |
409 } | |
410 | |
411 @Override | |
387 | 412 public void handle(REPCommand command, REPSelectionKey<REPCommand> key) throws IOException { |
442 | 413 //ServerMainLoop.logger.writeLog("Manager "+manager.getId()+" read : command = " + command |
414 // +" from "+manager.editorList.editorByChannel(channel)); | |
387 | 415 if (command.cmd==REP.SMCMD_JOIN||command.cmd==REP.SMCMD_PUT) { |
404 | 416 // assert false; |
427 | 417 // 一つのエディタ上に複数のセッションが作られた場合。 |
387 | 418 // 若干問題があるらしい |
419 next = new Forwarder(manager,next.channel); | |
420 REPNode first = new FirstConnector(manager,channel); | |
421 first.handle(command, key); | |
422 key.attach(new Dispatcher(manager,channel)); | |
423 return; | |
424 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
425 if (manager.sessionManage(this, command)) return; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
426 manage(command); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
427 } |
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 @Override |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
430 public void cancel(REPSocketChannel<REPCommand> socketChannel) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
431 manager.remove(socketChannel); |
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 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
434 public boolean isMaster() { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
435 return mode==REP.SMCMD_PUT; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
436 } |
386 | 437 |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
438 |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
439 /* Handle special case first, usually these cases |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
440 * 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
|
441 * it is forwarded here. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
442 */ |
385 | 443 public void forwardedCommandManage(REPCommand command) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
444 if (command.cmd==REP.SMCMD_QUIT_2) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
445 // 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
|
446 // 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
|
447 // state. Only this session manager knows it. |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
448 setQuit2(command); |
401 | 449 return; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
450 } |
385 | 451 send(command); |
452 } | |
453 | |
399 | 454 /** |
455 * Check waiting command in merge | |
456 * @return true if there is a processed waiting command | |
457 * @throws IOException | |
458 */ | |
459 public void checkWaitingCommandInMerge() { | |
406 | 460 if (translator==null||isMerging()) return; |
461 LinkedList<PacketSet> w = waitingCommandInMerge; | |
462 waitingCommandInMerge = new LinkedList<PacketSet>(); | |
463 while(w.size()>0) { | |
464 if (isMerging()) { | |
465 w.addAll(waitingCommandInMerge); | |
466 waitingCommandInMerge = w; | |
467 return; | |
468 } | |
469 PacketSet p = w.remove(0); | |
399 | 470 try { |
444 | 471 if (p.channel!=null) |
472 send(p.command); | |
473 else | |
474 manage(p.command); | |
399 | 475 } catch (Exception e1) { |
406 | 476 assert false; |
399 | 477 manager.close(p.channel); |
406 | 478 return; |
399 | 479 } |
480 } | |
481 } | |
482 | |
483 | |
484 public boolean hasWaitingCommand() { | |
485 return waitingCommandInMerge.size()>0; | |
486 } | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
diff
changeset
|
487 } |