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