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