Mercurial > hg > RemoteEditor > REPSessionManager
annotate rep/SessionManager.java @ 386:bba62c4ac323
sync-option
author | one@firefly.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Mon, 10 Nov 2008 22:19:34 +0900 |
parents | 1fca50ce3508 |
children | 6f356d160e58 |
rev | line source |
---|---|
266 | 1 |
0 | 2 package rep; |
3 | |
4 import java.io.IOException; | |
5 import java.net.InetSocketAddress; | |
267 | 6 import java.nio.channels.ClosedChannelException; |
0 | 7 |
346 | 8 import org.xml.sax.SAXException; |
9 | |
198 | 10 |
353 | 11 |
337 | 12 import rep.channel.REPLogger; |
133 | 13 import rep.channel.REPSocketChannel; |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
14 import rep.gui.CloseButtonEvent; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
15 import rep.gui.SelectButtonEvent; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
16 import rep.gui.SessionManagerEvent; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
17 import rep.gui.SessionManagerEventListener; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
18 import rep.gui.SessionManagerGUI; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
19 import rep.gui.SessionManagerGUIimpl; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
20 import rep.handler.Editor; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
21 import rep.handler.REPNode; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
22 import rep.handler.FirstConnector; |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
23 import rep.handler.Forwarder; |
56 | 24 import rep.xml.SessionXMLDecoder; |
45 | 25 import rep.xml.SessionXMLEncoder; |
264 | 26 |
198 | 27 /* |
264 | 28 +-------+--------+--------+-------+--------+---------+------+ |
29 | cmd | session| editor | seqid | lineno | textsiz | text | | |
30 | | id | id | | | | | | |
31 +-------+--------+--------+-------+--------+---------+------+ | |
32 o---------- header section (network order) ----------o | |
33 | |
34 int cmd; kind of command | |
35 int sid; session ID : uniqu to editing file | |
36 int eid; editor ID : owner editor ID = 1。Session に対して unique | |
308 | 37 -1 session manager command |
38 -2 merge command | |
264 | 39 int seqno; Sequence number : sequence number はエディタごとに管理 |
40 int lineno; line number | |
41 int textsize; textsize : bytesize | |
42 byte[] text; | |
198 | 43 */ |
1 | 44 |
384 | 45 public class SessionManager extends ServerMainLoop |
46 implements SessionManagerEventListener { | |
47 SessionList sessionList = new SessionList(); | |
363 | 48 // Known Session Manager List, At most one parent. No parent means master. |
384 | 49 SessionManagerList smList = new SessionManagerList(); |
363 | 50 // Known Editor list. Connected Editor has a channel. |
51 // Session Manager Channel may have dummy editors. | |
384 | 52 EditorList editorList = new EditorList(); |
363 | 53 // Queue limit for debugging purpose. |
384 | 54 static final int packetLimit = 200; |
358 | 55 |
363 | 56 // globalSessionID = SessionManagerID * MAXID + localSessionID |
358 | 57 private static final int MAXID = 10000; |
353 | 58 SessionXMLDecoder decoder = new SessionXMLDecoder(); |
358 | 59 SessionXMLEncoder encoder = new SessionXMLEncoder(); |
363 | 60 // SocketChannel for our parent. At most one parent is allowed. |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
61 private REPNode sm_join_channel; |
363 | 62 // Routing table for session and session manager. |
369 | 63 private RoutingTable routingTable = new RoutingTable(this); |
386 | 64 // sync option |
65 public boolean sync = true; | |
384 | 66 |
67 static public REPLogger logger = REPLogger.singleton(); | |
68 | |
316 | 69 public static void main(String[] args) throws InterruptedException, IOException { |
384 | 70 int port =ServerMainLoop.DEFAULT_PORT; |
71 int port_s = ServerMainLoop.DEFAULT_PORT; | |
316 | 72 //System.setProperty("file.encoding", "UTF-8"); |
73 if(args.length > 0){ | |
363 | 74 if (args.length!=2) { |
75 logger.writeLog("Usage: sessionManager our_port parent_port"); | |
76 return; | |
77 } | |
316 | 78 port = Integer.parseInt(args[0]); |
79 port_s = Integer.parseInt(args[1]); | |
80 } | |
81 SessionManager sm = new SessionManager(); | |
336 | 82 sm.setReceivePort(port); |
83 sm.setParentPort(port_s); | |
363 | 84 // Ok start main loop |
316 | 85 sm.init(port,new SessionManagerGUIimpl(sm)); |
86 } | |
87 | |
280 | 88 public void init(int port, SessionManagerGUI gui) throws IOException, InterruptedException { |
384 | 89 mainLoop(this, port, gui); |
2 | 90 } |
91 | |
363 | 92 /* |
93 * After loop detection, we give up session manager join. | |
94 */ | |
95 private void cancel_sm_join() { | |
364 | 96 logger.writeLog("Loop detected "+this); |
384 | 97 removeChannel(this, sm_join_channel); |
355 | 98 sm_join_channel=null; |
99 } | |
100 | |
101 | |
102 /** | |
363 | 103 * GUI から、呼ばれて、Session Managerに接続する。 |
355 | 104 * Host 名のSession Manager に SM_JOIN する。自分は、Session を持っていては |
105 * ならない。複数のSession Managerにjoinすることは出来ない。(NATを実装するまでは)。 | |
106 * @param host | |
107 */ | |
378 | 108 public void connectSessionManager(String host, int port) { |
355 | 109 if (sm_join_channel!=null) return; |
110 if (!sessionList.isEmpty()) return; | |
111 if (!smList.isMaster()) return; | |
363 | 112 /* |
113 * IPv6 対応では、複数のアドレスを取って、それのすべてに接続を試す必要が | |
114 * ある。 | |
115 */ | |
1 | 116 InetSocketAddress addr = new InetSocketAddress(host, port); |
117 try { | |
186 | 118 REPSocketChannel<REPCommand> sessionchannel = REPSocketChannel.<REPCommand>create(new REPCommandPacker()); |
1 | 119 sessionchannel.connect(addr); |
337 | 120 while(!sessionchannel.finishConnect()); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
121 REPNode sm = new FirstConnector(this); |
355 | 122 registerChannel(sessionchannel, sm); |
349 | 123 sm_join(sm); |
1 | 124 }catch (IOException e) { |
125 } | |
126 } | |
364 | 127 |
378 | 128 public void connectSessionManager(String host) { |
129 connectSessionManager(host,parent_port); | |
364 | 130 } |
77 | 131 |
363 | 132 /** |
133 * channel に SMCMD_SM_JOIN command を送る。 | |
134 * @param channel | |
135 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
136 private void sm_join(REPNode channel){ |
355 | 137 sm_join_channel = channel; |
122 | 138 //SM_JOINコマンドを生成。 |
77 | 139 REPCommand command = new REPCommand(); |
140 command.setCMD(REP.SMCMD_SM_JOIN); | |
349 | 141 command.setEID(-1); // request Parent SessionManagerID |
142 command.setSID(-1); // request SessionManagerID | |
79 | 143 |
122 | 144 //hostnameをセット。 |
349 | 145 setMyHostName(channel.getLocalHostName()); |
82 | 146 |
355 | 147 String string = myHost; |
77 | 148 command.setString(string); |
149 | |
122 | 150 //SM_JOINコマンドを送信。 |
349 | 151 channel.send(command); |
363 | 152 // ack を受け取ったら、SessionManagerのListに追加。ここではやらない。 |
77 | 153 } |
349 | 154 |
361 | 155 /* |
156 * Select Session from Manager button | |
157 * selected editor is joined editor directly connected to this session | |
158 * manager. | |
159 */ | |
316 | 160 public void selectSession(SelectButtonEvent event) throws IOException { |
250 | 161 int sid = event.getSID(); |
358 | 162 Session session = sessionList.get(sid); |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
163 if (session==null) throw new IOException(); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
164 REPNode editor = event.getEditor(); |
324 | 165 if (editor.hasSession()) return; |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
166 // assert(getSMID(editor.eid)==smList.sessionManagerID()); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
167 // assert(editor.channel!=null); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
168 editor.setSID(sid); // mark as selected |
372 | 169 selectSession0(sid, session, editor.getEID(), editor); |
170 } | |
171 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
172 private void selectSession0(int sid, Session session, int eid, REPNode editor) { |
372 | 173 if (editor.isDirect()&&editor.getEID()==eid) { |
386 | 174 REPCommand command = new REPCommand(); |
175 command.setSID(sid); | |
176 command.setEID(eid); | |
177 command.setString(session.getName()); | |
178 editor.selectSession(command, session); | |
372 | 179 } else { |
180 // we don't have this editor, search the editor first. | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
181 REPNode next = routingTable.toSessionManager(getSMID(eid)); |
372 | 182 // pass the select command to the next path. |
183 REPCommand command = new REPCommand(); | |
184 command.setCMD(REP.SMCMD_SELECT0); | |
185 command.setSID(sid); | |
186 command.setEID(eid); | |
187 command.setString(editor.getHost()); | |
188 next.send(command); | |
189 } | |
358 | 190 } |
191 | |
386 | 192 public void forwardSelect(int sid, Session session, int eid, |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
193 REPNode editor) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
194 REPNode next; |
372 | 195 // session searching continue... |
196 next = routingTable.toSessionManager(getSMID(sid)); | |
197 // make a forwarding channel here | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
198 REPNode f = createSessionForwarder(sid, next); |
372 | 199 session.setFirstForwarder(f); |
200 session.addForwarder(editor); | |
201 // pass the select command to the next path. | |
202 REPCommand command = new REPCommand(); | |
203 command.setCMD(REP.SMCMD_SELECT); | |
204 command.setSID(sid); | |
205 command.setEID(eid); | |
206 command.setString(editor.getHost()); | |
207 next.send(command); | |
208 } | |
209 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
210 private REPNode createSessionForwarder(int sid, REPNode editor) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
211 REPNode f = new Forwarder(this); |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
212 f.setEID(makeID(editorList.newEid())); |
372 | 213 f.setChannel(editor.channel); // incoming channel |
214 f.setHost(myHost); | |
215 f.setSID(sid); | |
216 return f; | |
217 } | |
218 | |
363 | 219 /* |
220 * Create and send UPDATE command. | |
221 */ | |
386 | 222 public void sendUpdate(int sid) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
223 REPCommand command = makeREPCommandWithSessionList(REP.SMCMD_UPDATE); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
224 command.setSID(sid); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
225 command.setEID(REP.SM_EID.id); |
386 | 226 if (isMaster()) { |
227 command.setCMD(REP.SMCMD_UPDATE_ACK); | |
228 smList.sendToSlaves(command); | |
229 } else { | |
230 smList.sendToMaster(command); | |
231 } | |
358 | 232 } |
233 | |
363 | 234 /* |
235 * Create new editor in this sessin manager. A dummy editor | |
236 * is created also. | |
237 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
238 public REPNode newEditor(REPSocketChannel<REPCommand> channel) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
239 int eid = makeID(editorList.newEid()); |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
240 REPNode editor = new Editor(this, eid, channel); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
241 editorList.add(editor); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
242 return editor; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
243 } |
363 | 244 |
245 /* | |
246 * Create new session. | |
247 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
248 public Session newSession(REPNode master) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
249 int sid= makeID(sessionList.newSessionID()); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
250 Session session = new Session(sid, master); |
360 | 251 sessionList.put(sid, session); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
252 return session; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
253 } |
358 | 254 |
363 | 255 /* |
256 * GUI command interface for close session. | |
257 */ | |
259 | 258 public void closeSession(SessionManagerEvent event) { |
259 Session session = ((CloseButtonEvent) event).getSession(); | |
260 session.closeSession(); | |
261 sessionList.remove(session); | |
262 updateGUI(); | |
263 } | |
264 | |
363 | 265 /* |
266 * Remove editors which has the cannel. | |
267 */ | |
274 | 268 public void remove(REPSocketChannel<REPCommand> channel) { |
358 | 269 int i = 0; |
270 for(Session s:sessionList.values()) { | |
274 | 271 if (s.deleteEditor(channel)) { |
358 | 272 i++; |
274 | 273 } |
274 } | |
358 | 275 assert(i==1); |
274 | 276 // can be other session manager? what should I do? |
277 } | |
278 | |
317 | 279 |
318 | 280 public void remove(Editor editor) { |
358 | 281 Session s = sessionList.get(editor.getSID()); |
362 | 282 if (s==null) { |
283 assert(false); | |
284 editorList.remove(editor); | |
285 } else if (editor.isMaster()) { | |
358 | 286 removeSession(s); |
287 } else { | |
288 s.deleteForwarder(editor); | |
289 editorList.remove(editor); | |
318 | 290 } |
341 | 291 updateGUI(); |
292 } | |
293 | |
294 private void removeSession(Session s0) { | |
358 | 295 s0.remove(this); |
341 | 296 sessionList.remove(s0); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
297 sendUpdate(s0.getSID()); |
318 | 298 } |
299 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
300 public boolean sessionManage(REPNode forwarder, REPCommand command) throws ClosedChannelException, |
358 | 301 IOException { |
355 | 302 switch(command.cmd){ |
353 | 303 |
304 // Session Manager Command | |
305 | |
306 case SMCMD_JOIN: | |
307 { | |
358 | 308 // first connection or forwarded command |
367 | 309 routingTable.add(forwarder,getSMID(command.eid)); |
358 | 310 if(isMaster()) { |
311 REPCommand ackCommand = new REPCommand(); | |
312 ackCommand.setCMD(REP.SMCMD_JOIN_ACK); | |
313 ackCommand.setEID(command.eid); | |
360 | 314 ackCommand.setSID(command.sid); |
358 | 315 ackCommand.string = command.string; |
316 smList.sendToSlaves(ackCommand); | |
317 registEditor(forwarder,ackCommand); | |
318 } else { | |
319 smList.sendToMaster(command); | |
320 } | |
360 | 321 updateGUI(); |
353 | 322 } |
323 | |
324 break; | |
325 | |
361 | 326 case SMCMD_PUT_ACK: |
366 | 327 if (forwarder.isDirect()) { |
328 // send put_ack to the editor now. | |
329 command.setCMD(REP.SMCMD_PUT_ACK); | |
330 command.string = command.string; | |
331 command.setEID(command.eid); | |
332 command.setSID(command.sid); | |
333 forwarder.send(command); | |
334 } | |
353 | 335 case SMCMD_JOIN_ACK: |
358 | 336 registEditor(forwarder,command); |
360 | 337 updateGUI(); |
353 | 338 break; |
339 | |
340 case SMCMD_PUT: | |
341 { | |
358 | 342 // first connection or forwarded command |
367 | 343 routingTable.add(forwarder,getSMID(command.eid)); |
370 | 344 REPCommand ack = new REPCommand(command); ack.setCMD(REP.SMCMD_PUT_ACK); |
345 if(isMaster()) { | |
371 | 346 // Reached to the top of the tree, multicast the ack. |
370 | 347 smList.sendToSlaves(ack); |
348 registEditor(forwarder,ack); | |
371 | 349 if (forwarder.isDirect()) { |
350 // If put editor on the master, no SMCMD_PUT_ACK is | |
351 // generated. Send ack to the editor now. | |
352 forwarder.send(ack); | |
353 } | |
358 | 354 } else { |
371 | 355 // Pass this to the master. |
358 | 356 smList.sendToMaster(command); |
361 | 357 // registEditor will be done by SMCMD_PUT_ACK |
358 } | |
360 | 359 updateGUI(); |
353 | 360 |
361 } | |
362 break; | |
358 | 363 |
372 | 364 case SMCMD_SELECT0: |
365 /* | |
366 * finding joining editor, do not make the path. | |
367 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
368 REPNode editor = editorList.get(command.eid); |
372 | 369 if (editor==null|| !editor.isDirect()) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
370 REPNode next = routingTable.toSessionManager(getSMID(command.eid)); |
372 | 371 next.send(command); |
372 break; | |
373 } | |
374 // we've found the editor, fall thru. | |
353 | 375 case SMCMD_SELECT: |
361 | 376 { |
372 | 377 /* |
378 * finding active session ring from joined editor. | |
379 */ | |
361 | 380 Session session = sessionList.get(command.sid); |
381 if (session==null) { | |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
382 session = new Session(command.sid, command.string,null); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
383 sessionList.put(command.sid,session); |
361 | 384 } |
372 | 385 // Do not directly addForwarder(forwarder). It may be |
386 // shared among sessions. | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
387 REPNode f = createSessionForwarder(command.sid, forwarder); |
372 | 388 session.addForwarder(f); // f.next is set up here. |
386 | 389 forwarder.selectSession(command,session); |
361 | 390 } |
391 break; | |
353 | 392 case SMCMD_SELECT_ACK: |
393 { | |
369 | 394 // Sessionが見つかったので、select したeditorに教える。 |
358 | 395 Session session = sessionList.get(command.sid); |
376 | 396 searchSelectedEditor(command,session.getForwarder(forwarder.channel)); |
353 | 397 } |
358 | 398 break; |
399 | |
353 | 400 case SMCMD_SM_JOIN: |
401 { | |
355 | 402 // SM_JOIN中にSMCMD_SM_JOINが来たら、これはループなので、 |
403 ///自分のSM_JOINを取り消す。 | |
404 if (sm_join_channel!=null) cancel_sm_join(); | |
353 | 405 // SMCMD_SM_JOIN は、master まで上昇する。 |
406 // masterでなければ、自分のparentに転送する。 | |
355 | 407 if(isMaster()) { |
353 | 408 // master であれば、SessionManager IDを決めて、 |
409 // 自分のsmList に登録 | |
377 | 410 registSessionManager(forwarder, command); |
355 | 411 } else { |
412 if (forwarder.sid==-1) { | |
413 // direct link の場合は、識別のために、EIDに直上の | |
414 // smid を入れておく。 | |
415 command.setEID(smList.sessionManagerID()); | |
416 } | |
417 smList.sendToMaster(command); | |
353 | 418 } |
419 } | |
420 break; | |
386 | 421 |
422 case SMCMD_SYNC_ACK: | |
423 break; | |
424 | |
355 | 425 case SMCMD_SM_JOIN_ACK: |
426 send_sm_join_ack(command.eid, command.sid, command); | |
353 | 427 break; |
428 | |
429 case SMCMD_UPDATE: | |
386 | 430 sendUpdate(command.sid); |
431 break; | |
353 | 432 case SMCMD_UPDATE_ACK: |
358 | 433 command.setString(mergeUpdate(command)); |
434 // 下に知らせる | |
355 | 435 smList.sendToSlaves(command); |
358 | 436 updateGUI(); |
353 | 437 break; |
438 default: | |
439 return false; | |
440 } | |
441 return true; | |
442 } | |
443 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
444 private void registSessionManager(REPNode forwarder, REPCommand command) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
445 REPNode sm; |
377 | 446 int psid = command.eid; |
447 if (forwarder.sid!=-1) { | |
448 // すでに channelはSessionManager Idを持っていて、 | |
449 // direct link ではないので、 | |
450 // channel を持たないForwarderとして登録する | |
451 sm = new Forwarder(this); | |
452 } else { | |
453 sm = forwarder; | |
454 } | |
455 int sid = smList.addNewSessionManager(sm,command); | |
456 routingTable.add(forwarder,sid); | |
457 | |
458 REPCommand sendCommand = makeREPCommandWithSessionList(REP.SMCMD_SM_JOIN_ACK); | |
459 // command.eid==smList.sesionManagerID() の場合は、 | |
460 // 待っている自分の下のsessionManagerにsidをassignする必要がある。 | |
461 sendCommand.setSID(sid); // new Session manager ID | |
462 // 複数のSM_JOIN_ACKを識別するには、最初にSM_JOINを受け付けた | |
463 // Session manager IDを使う。 | |
464 sendCommand.setEID(psid); | |
465 send_sm_join_ack(psid, sid, sendCommand); | |
466 } | |
467 | |
468 | |
469 void send_sm_join_ack(int psid, int sid,REPCommand sendCommand) { | |
470 if (psid==smList.sessionManagerID()) { | |
471 // 直下のsessionManagerにIDを割り振る必要がある。 | |
472 smList.assignSessionManagerIDtoWaitingSM(sid); | |
473 // ここで smList に一つだけ追加されるので | |
474 // 待っている最初のsm一つにだけ、sm_join_ackが新たに送られる。 | |
475 } | |
476 smList.sendToSlaves(sendCommand); | |
477 } | |
478 | |
372 | 479 /* |
480 * 指定されたeditorがlocalにあるかどうかを調べる。なければ、他に送る。戻って何回も探すことが | |
481 * あり得るので、よろしくない。 | |
482 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
483 private void searchSelectedEditor(REPCommand command, REPNode editor) { |
372 | 484 for(;editor.isDirect();editor = editor.getNextForwarder()) { |
485 if (editor.getEID()==command.eid) { | |
486 // select したeditor を見つけた | |
487 command.cmd=REP.SMCMD_JOIN_ACK; | |
488 editor.send(command); | |
386 | 489 sendUpdate(command.sid); |
490 if (sync) { | |
491 REPCommand sync = new REPCommand(command); | |
492 sync.setCMD(REP.SMCMD_SYNC); | |
493 editor.sendSync(sync); | |
494 } | |
372 | 495 return; |
496 } | |
497 } | |
498 // ここにはありませんでした。 | |
499 editor.send(command); | |
500 } | |
501 | |
355 | 502 |
363 | 503 /** |
504 * UPDATE/UPDATE_ACKにより送られてきたSessionの情報を追加する | |
505 * @param command | |
506 * @return | |
507 * @throws IOException | |
508 */ | |
358 | 509 private String mergeUpdate(REPCommand command) throws IOException { |
510 SessionList receivedSessionList; | |
511 try { | |
512 receivedSessionList = decoder.decode(command.string); | |
513 } catch (SAXException e) { | |
514 throw new IOException(); | |
515 } | |
363 | 516 // 受け取った情報と自分の情報を混ぜる。 |
517 sessionList.merge(receivedSessionList); | |
358 | 518 //XMLを生成。送信コマンドにセット。 |
519 return encoder.sessionListToXML(sessionList); | |
520 | |
521 } | |
522 | |
523 /* | |
524 * id has SessionManager ID part | |
525 */ | |
526 private int makeID(int newid) { | |
527 return newid+smList.sessionManagerID()*MAXID; | |
528 } | |
529 | |
384 | 530 int getSMID(int id) { |
358 | 531 return id/MAXID; |
532 } | |
533 | |
534 | |
361 | 535 /** |
536 * Register Editor to our editorList. No connection is made. | |
537 * @param forwarder Editor to be add | |
538 * @param command | |
539 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
540 public void registEditor(REPNode forwarder,REPCommand command) { |
358 | 541 // make ack for PUT/JOIN. Do not send this to the editor, |
542 // before select. After select, ack is sent to the editor. | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
543 REPNode editor; |
367 | 544 if (getSMID(command.eid)==smList.sessionManagerID()) { |
545 if (forwarder.isDirect()) { | |
546 editor = (Editor)forwarder; | |
547 } else | |
548 return; | |
358 | 549 } else { |
385 | 550 editor = new Editor(this, command.eid); |
358 | 551 } |
552 editor.setName(command.string); | |
553 editor.setSID(command.sid); | |
554 if (!editorList.hasEid(command.eid)) { | |
555 editorList.add(editor); | |
556 } | |
367 | 557 if (command.cmd==REP.SMCMD_PUT_ACK) { |
558 Session session = new Session(command.sid, command.string, editor); | |
559 sessionList.put(command.sid, session); | |
560 } | |
358 | 561 // we don't join ack to the direct linked editor. We |
562 // have to wait select command | |
563 } | |
564 | |
565 | |
355 | 566 private REPCommand makeREPCommandWithSessionList(REP cmd) { |
567 //SessionListからXMLを生成。 | |
568 //joinしてきたSessionManagerに対してACKを送信。 | |
569 REPCommand sendCommand = new REPCommand(); | |
570 sendCommand.setCMD(cmd); | |
358 | 571 sendCommand.setString(encoder.sessionListToXML(sessionList)); |
355 | 572 return sendCommand; |
573 } | |
574 | |
575 | |
576 public boolean isMaster() { | |
577 return smList.isMaster(); | |
578 } | |
579 | |
580 | |
581 public void setSessionManagerID(int sid) { | |
582 smList.setSessionManagerID(sid); | |
583 } | |
584 | |
358 | 585 |
586 public Session getSession(int sid) { | |
587 return sessionList.get(sid); | |
588 } | |
589 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
590 public void setParent(REPNode fw) { |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
591 smList.setParent(fw); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
592 } |
367 | 593 |
594 public String toString() { | |
595 int myId = 0; | |
596 if (smList!=null) myId = smList.sessionManagerID(); | |
384 | 597 return "rep.SessionManager-"+myId+"@"+super.toString(); |
367 | 598 } |
385 | 599 |
600 public void addWaitingSessionManager(REPNode fw, REPCommand command) { | |
601 smList.addWaitingSessionManager(fw, command); | |
602 } | |
0 | 603 } |