Mercurial > hg > RemoteEditor > REPSessionManager
annotate rep/SessionManager.java @ 389:4b535bef903a
23
author | one@firefly.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Mon, 10 Nov 2008 22:24:21 +0900 |
parents | 6f356d160e58 |
children | 3b0a5a55e3ee |
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. |
387 | 54 static final int packetLimit = 400; |
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()); |
387 | 121 REPNode sm = new FirstConnector(this,sessionchannel); |
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) { |
389 | 173 logger.writeLog("Select sid="+sid+" and "+editor); |
372 | 174 if (editor.isDirect()&&editor.getEID()==eid) { |
386 | 175 REPCommand command = new REPCommand(); |
176 command.setSID(sid); | |
177 command.setEID(eid); | |
178 command.setString(session.getName()); | |
389 | 179 if(session.hasOwner()){ |
180 editor.selectSession(command,session); | |
181 }else { | |
182 forwardSelect(sid, session, eid, editor); | |
183 } | |
372 | 184 } else { |
185 // 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
|
186 REPNode next = routingTable.toSessionManager(getSMID(eid)); |
372 | 187 // pass the select command to the next path. |
188 REPCommand command = new REPCommand(); | |
189 command.setCMD(REP.SMCMD_SELECT0); | |
190 command.setSID(sid); | |
191 command.setEID(eid); | |
192 command.setString(editor.getHost()); | |
193 next.send(command); | |
194 } | |
358 | 195 } |
196 | |
386 | 197 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
|
198 REPNode editor) { |
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
199 REPNode next; |
372 | 200 // session searching continue... |
201 next = routingTable.toSessionManager(getSMID(sid)); | |
202 // make a forwarding channel here | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
203 REPNode f = createSessionForwarder(sid, next); |
372 | 204 session.setFirstForwarder(f); |
205 session.addForwarder(editor); | |
206 // pass the select command to the next path. | |
207 REPCommand command = new REPCommand(); | |
208 command.setCMD(REP.SMCMD_SELECT); | |
209 command.setSID(sid); | |
210 command.setEID(eid); | |
211 command.setString(editor.getHost()); | |
212 next.send(command); | |
213 } | |
214 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
215 private REPNode createSessionForwarder(int sid, REPNode editor) { |
387 | 216 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
|
217 f.setEID(makeID(editorList.newEid())); |
387 | 218 // f.setChannel(editor.channel); // incoming channel |
372 | 219 f.setHost(myHost); |
220 f.setSID(sid); | |
221 return f; | |
222 } | |
223 | |
363 | 224 /* |
225 * Create and send UPDATE command. | |
226 */ | |
386 | 227 public void sendUpdate(int sid) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
228 REPCommand command = makeREPCommandWithSessionList(REP.SMCMD_UPDATE); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
229 command.setSID(sid); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
230 command.setEID(REP.SM_EID.id); |
386 | 231 if (isMaster()) { |
232 command.setCMD(REP.SMCMD_UPDATE_ACK); | |
233 smList.sendToSlaves(command); | |
234 } else { | |
235 smList.sendToMaster(command); | |
236 } | |
358 | 237 } |
238 | |
363 | 239 /* |
240 * Create new editor in this sessin manager. A dummy editor | |
241 * is created also. | |
242 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
243 public REPNode newEditor(REPSocketChannel<REPCommand> channel) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
244 int eid = makeID(editorList.newEid()); |
387 | 245 REPNode editor = new Editor(eid, this, channel); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
246 editorList.add(editor); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
247 return editor; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
248 } |
363 | 249 |
250 /* | |
251 * Create new session. | |
252 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
253 public Session newSession(REPNode master) { |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
254 int sid= makeID(sessionList.newSessionID()); |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
255 Session session = new Session(sid, master); |
360 | 256 sessionList.put(sid, session); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
257 return session; |
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
258 } |
358 | 259 |
363 | 260 /* |
261 * GUI command interface for close session. | |
262 */ | |
259 | 263 public void closeSession(SessionManagerEvent event) { |
264 Session session = ((CloseButtonEvent) event).getSession(); | |
265 session.closeSession(); | |
266 sessionList.remove(session); | |
267 updateGUI(); | |
268 } | |
269 | |
363 | 270 /* |
271 * Remove editors which has the cannel. | |
272 */ | |
274 | 273 public void remove(REPSocketChannel<REPCommand> channel) { |
358 | 274 int i = 0; |
275 for(Session s:sessionList.values()) { | |
274 | 276 if (s.deleteEditor(channel)) { |
358 | 277 i++; |
274 | 278 } |
279 } | |
358 | 280 assert(i==1); |
274 | 281 // can be other session manager? what should I do? |
282 } | |
283 | |
317 | 284 |
318 | 285 public void remove(Editor editor) { |
358 | 286 Session s = sessionList.get(editor.getSID()); |
362 | 287 if (s==null) { |
288 assert(false); | |
289 editorList.remove(editor); | |
290 } else if (editor.isMaster()) { | |
358 | 291 removeSession(s); |
292 } else { | |
293 s.deleteForwarder(editor); | |
294 editorList.remove(editor); | |
318 | 295 } |
341 | 296 updateGUI(); |
297 } | |
298 | |
299 private void removeSession(Session s0) { | |
358 | 300 s0.remove(this); |
341 | 301 sessionList.remove(s0); |
359
fa041bae35f1
all code written for distributed session except gather.
kono
parents:
358
diff
changeset
|
302 sendUpdate(s0.getSID()); |
318 | 303 } |
304 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
305 public boolean sessionManage(REPNode forwarder, REPCommand command) throws ClosedChannelException, |
358 | 306 IOException { |
355 | 307 switch(command.cmd){ |
353 | 308 |
309 // Session Manager Command | |
310 | |
311 case SMCMD_JOIN: | |
312 { | |
358 | 313 // first connection or forwarded command |
367 | 314 routingTable.add(forwarder,getSMID(command.eid)); |
358 | 315 if(isMaster()) { |
316 REPCommand ackCommand = new REPCommand(); | |
317 ackCommand.setCMD(REP.SMCMD_JOIN_ACK); | |
318 ackCommand.setEID(command.eid); | |
360 | 319 ackCommand.setSID(command.sid); |
358 | 320 ackCommand.string = command.string; |
321 smList.sendToSlaves(ackCommand); | |
322 registEditor(forwarder,ackCommand); | |
323 } else { | |
324 smList.sendToMaster(command); | |
325 } | |
360 | 326 updateGUI(); |
353 | 327 } |
328 | |
329 break; | |
330 | |
361 | 331 case SMCMD_PUT_ACK: |
366 | 332 if (forwarder.isDirect()) { |
333 // send put_ack to the editor now. | |
334 command.setCMD(REP.SMCMD_PUT_ACK); | |
335 command.string = command.string; | |
336 command.setEID(command.eid); | |
337 command.setSID(command.sid); | |
338 forwarder.send(command); | |
339 } | |
353 | 340 case SMCMD_JOIN_ACK: |
358 | 341 registEditor(forwarder,command); |
360 | 342 updateGUI(); |
353 | 343 break; |
344 | |
345 case SMCMD_PUT: | |
346 { | |
358 | 347 // first connection or forwarded command |
367 | 348 routingTable.add(forwarder,getSMID(command.eid)); |
370 | 349 REPCommand ack = new REPCommand(command); ack.setCMD(REP.SMCMD_PUT_ACK); |
350 if(isMaster()) { | |
371 | 351 // Reached to the top of the tree, multicast the ack. |
370 | 352 smList.sendToSlaves(ack); |
353 registEditor(forwarder,ack); | |
371 | 354 if (forwarder.isDirect()) { |
355 // If put editor on the master, no SMCMD_PUT_ACK is | |
356 // generated. Send ack to the editor now. | |
357 forwarder.send(ack); | |
358 } | |
358 | 359 } else { |
371 | 360 // Pass this to the master. |
358 | 361 smList.sendToMaster(command); |
361 | 362 // registEditor will be done by SMCMD_PUT_ACK |
363 } | |
360 | 364 updateGUI(); |
353 | 365 |
366 } | |
367 break; | |
358 | 368 |
372 | 369 case SMCMD_SELECT0: |
370 /* | |
371 * finding joining editor, do not make the path. | |
372 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
373 REPNode editor = editorList.get(command.eid); |
372 | 374 if (editor==null|| !editor.isDirect()) { |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
375 REPNode next = routingTable.toSessionManager(getSMID(command.eid)); |
372 | 376 next.send(command); |
377 break; | |
378 } | |
379 // we've found the editor, fall thru. | |
353 | 380 case SMCMD_SELECT: |
361 | 381 { |
372 | 382 /* |
383 * finding active session ring from joined editor. | |
384 */ | |
361 | 385 Session session = sessionList.get(command.sid); |
386 if (session==null) { | |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
387 session = new Session(command.sid, command.string,null); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
388 sessionList.put(command.sid,session); |
361 | 389 } |
372 | 390 // Do not directly addForwarder(forwarder). It may be |
391 // shared among sessions. | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
392 REPNode f = createSessionForwarder(command.sid, forwarder); |
372 | 393 session.addForwarder(f); // f.next is set up here. |
389 | 394 if(session.hasOwner()){ |
395 forwarder.selectSession(command,session); | |
396 }else { | |
397 forwardSelect(command.sid, session, command.eid, forwarder); | |
398 } | |
361 | 399 } |
400 break; | |
353 | 401 case SMCMD_SELECT_ACK: |
402 { | |
369 | 403 // Sessionが見つかったので、select したeditorに教える。 |
358 | 404 Session session = sessionList.get(command.sid); |
376 | 405 searchSelectedEditor(command,session.getForwarder(forwarder.channel)); |
353 | 406 } |
358 | 407 break; |
408 | |
353 | 409 case SMCMD_SM_JOIN: |
410 { | |
355 | 411 // SM_JOIN中にSMCMD_SM_JOINが来たら、これはループなので、 |
412 ///自分のSM_JOINを取り消す。 | |
413 if (sm_join_channel!=null) cancel_sm_join(); | |
353 | 414 // SMCMD_SM_JOIN は、master まで上昇する。 |
415 // masterでなければ、自分のparentに転送する。 | |
355 | 416 if(isMaster()) { |
353 | 417 // master であれば、SessionManager IDを決めて、 |
418 // 自分のsmList に登録 | |
377 | 419 registSessionManager(forwarder, command); |
355 | 420 } else { |
421 if (forwarder.sid==-1) { | |
422 // direct link の場合は、識別のために、EIDに直上の | |
423 // smid を入れておく。 | |
424 command.setEID(smList.sessionManagerID()); | |
425 } | |
426 smList.sendToMaster(command); | |
353 | 427 } |
428 } | |
429 break; | |
386 | 430 |
431 case SMCMD_SYNC_ACK: | |
432 break; | |
433 | |
355 | 434 case SMCMD_SM_JOIN_ACK: |
435 send_sm_join_ack(command.eid, command.sid, command); | |
353 | 436 break; |
437 | |
438 case SMCMD_UPDATE: | |
386 | 439 sendUpdate(command.sid); |
440 break; | |
353 | 441 case SMCMD_UPDATE_ACK: |
358 | 442 command.setString(mergeUpdate(command)); |
443 // 下に知らせる | |
355 | 444 smList.sendToSlaves(command); |
358 | 445 updateGUI(); |
353 | 446 break; |
447 default: | |
448 return false; | |
449 } | |
450 return true; | |
451 } | |
452 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
453 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
|
454 REPNode sm; |
377 | 455 int psid = command.eid; |
456 if (forwarder.sid!=-1) { | |
457 // すでに channelはSessionManager Idを持っていて、 | |
458 // direct link ではないので、 | |
459 // channel を持たないForwarderとして登録する | |
387 | 460 sm = new Forwarder(this,null); |
377 | 461 } else { |
462 sm = forwarder; | |
463 } | |
464 int sid = smList.addNewSessionManager(sm,command); | |
465 routingTable.add(forwarder,sid); | |
466 | |
467 REPCommand sendCommand = makeREPCommandWithSessionList(REP.SMCMD_SM_JOIN_ACK); | |
468 // command.eid==smList.sesionManagerID() の場合は、 | |
469 // 待っている自分の下のsessionManagerにsidをassignする必要がある。 | |
470 sendCommand.setSID(sid); // new Session manager ID | |
471 // 複数のSM_JOIN_ACKを識別するには、最初にSM_JOINを受け付けた | |
472 // Session manager IDを使う。 | |
473 sendCommand.setEID(psid); | |
474 send_sm_join_ack(psid, sid, sendCommand); | |
475 } | |
476 | |
477 | |
478 void send_sm_join_ack(int psid, int sid,REPCommand sendCommand) { | |
479 if (psid==smList.sessionManagerID()) { | |
480 // 直下のsessionManagerにIDを割り振る必要がある。 | |
481 smList.assignSessionManagerIDtoWaitingSM(sid); | |
482 // ここで smList に一つだけ追加されるので | |
483 // 待っている最初のsm一つにだけ、sm_join_ackが新たに送られる。 | |
484 } | |
485 smList.sendToSlaves(sendCommand); | |
486 } | |
487 | |
372 | 488 /* |
489 * 指定されたeditorがlocalにあるかどうかを調べる。なければ、他に送る。戻って何回も探すことが | |
490 * あり得るので、よろしくない。 | |
491 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
492 private void searchSelectedEditor(REPCommand command, REPNode editor) { |
372 | 493 for(;editor.isDirect();editor = editor.getNextForwarder()) { |
494 if (editor.getEID()==command.eid) { | |
495 // select したeditor を見つけた | |
389 | 496 editor.joinAck(command,command.sid); |
372 | 497 return; |
498 } | |
499 } | |
500 // ここにはありませんでした。 | |
501 editor.send(command); | |
502 } | |
503 | |
355 | 504 |
363 | 505 /** |
506 * UPDATE/UPDATE_ACKにより送られてきたSessionの情報を追加する | |
507 * @param command | |
508 * @return | |
509 * @throws IOException | |
510 */ | |
358 | 511 private String mergeUpdate(REPCommand command) throws IOException { |
512 SessionList receivedSessionList; | |
513 try { | |
514 receivedSessionList = decoder.decode(command.string); | |
515 } catch (SAXException e) { | |
516 throw new IOException(); | |
517 } | |
363 | 518 // 受け取った情報と自分の情報を混ぜる。 |
519 sessionList.merge(receivedSessionList); | |
358 | 520 //XMLを生成。送信コマンドにセット。 |
521 return encoder.sessionListToXML(sessionList); | |
522 | |
523 } | |
524 | |
525 /* | |
526 * id has SessionManager ID part | |
527 */ | |
528 private int makeID(int newid) { | |
529 return newid+smList.sessionManagerID()*MAXID; | |
530 } | |
531 | |
384 | 532 int getSMID(int id) { |
358 | 533 return id/MAXID; |
534 } | |
535 | |
536 | |
361 | 537 /** |
538 * Register Editor to our editorList. No connection is made. | |
539 * @param forwarder Editor to be add | |
540 * @param command | |
541 */ | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
542 public void registEditor(REPNode forwarder,REPCommand command) { |
358 | 543 // make ack for PUT/JOIN. Do not send this to the editor, |
544 // 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
|
545 REPNode editor; |
367 | 546 if (getSMID(command.eid)==smList.sessionManagerID()) { |
547 if (forwarder.isDirect()) { | |
548 editor = (Editor)forwarder; | |
549 } else | |
550 return; | |
358 | 551 } else { |
387 | 552 editor = new Editor(manager, command.eid); |
358 | 553 } |
554 editor.setName(command.string); | |
555 editor.setSID(command.sid); | |
556 if (!editorList.hasEid(command.eid)) { | |
557 editorList.add(editor); | |
558 } | |
367 | 559 if (command.cmd==REP.SMCMD_PUT_ACK) { |
560 Session session = new Session(command.sid, command.string, editor); | |
561 sessionList.put(command.sid, session); | |
562 } | |
358 | 563 // we don't join ack to the direct linked editor. We |
564 // have to wait select command | |
565 } | |
566 | |
567 | |
355 | 568 private REPCommand makeREPCommandWithSessionList(REP cmd) { |
569 //SessionListからXMLを生成。 | |
570 //joinしてきたSessionManagerに対してACKを送信。 | |
571 REPCommand sendCommand = new REPCommand(); | |
572 sendCommand.setCMD(cmd); | |
358 | 573 sendCommand.setString(encoder.sessionListToXML(sessionList)); |
355 | 574 return sendCommand; |
575 } | |
576 | |
577 | |
578 public boolean isMaster() { | |
579 return smList.isMaster(); | |
580 } | |
581 | |
582 | |
583 public void setSessionManagerID(int sid) { | |
584 smList.setSessionManagerID(sid); | |
585 } | |
586 | |
358 | 587 |
588 public Session getSession(int sid) { | |
589 return sessionList.get(sid); | |
590 } | |
591 | |
382
4b87f89b3afd
REP Session Manager (Java version)
one@firefly.cr.ie.u-ryukyu.ac.jp
parents:
378
diff
changeset
|
592 public void setParent(REPNode fw) { |
365
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
593 smList.setParent(fw); |
c432755c3555
distributed session debug continue... SELECT/SELECT_ACK loop
kono
parents:
364
diff
changeset
|
594 } |
367 | 595 |
596 public String toString() { | |
597 int myId = 0; | |
598 if (smList!=null) myId = smList.sessionManagerID(); | |
384 | 599 return "rep.SessionManager-"+myId+"@"+super.toString(); |
367 | 600 } |
385 | 601 |
602 public void addWaitingSessionManager(REPNode fw, REPCommand command) { | |
603 smList.addWaitingSessionManager(fw, command); | |
604 } | |
389 | 605 |
0 | 606 } |