Mercurial > hg > RemoteEditor > REPSessionManager
comparison rep/SessionManager.java @ 363:1a8856580d38
*** empty log message ***
author | kono |
---|---|
date | Mon, 20 Oct 2008 03:03:28 +0900 |
parents | f0bd158dace6 |
children | c965ef2b5fd6 |
comparison
equal
deleted
inserted
replaced
362:f0bd158dace6 | 363:1a8856580d38 |
---|---|
44 */ | 44 */ |
45 | 45 |
46 public class SessionManager implements SessionManagerEventListener{ | 46 public class SessionManager implements SessionManagerEventListener{ |
47 static public REPLogger logger = REPLogger.singleton(); | 47 static public REPLogger logger = REPLogger.singleton(); |
48 | 48 |
49 SessionList sessionList; | 49 SessionList sessionList; |
50 private SessionManagerGUI gui; | 50 private SessionManagerGUI gui; |
51 // Main nio.Selector of this server | |
51 private REPSelector<REPCommand> selector; | 52 private REPSelector<REPCommand> selector; |
53 // Known Session Manager List, At most one parent. No parent means master. | |
52 SessionManagerList smList; | 54 SessionManagerList smList; |
55 // Known Editor list. Connected Editor has a channel. | |
56 // Session Manager Channel may have dummy editors. | |
53 EditorList editorList; | 57 EditorList editorList; |
54 // editorList は、sessionList に入っているeditorとは別なeditorのlistらしい。 | 58 // Commands for busy editor are kept in this queue. |
55 // private String maxHost; | |
56 private List<PacketSet> waitingCommandInMerge; | 59 private List<PacketSet> waitingCommandInMerge; |
57 private BlockingQueue<SessionManagerEvent> waitingEventQueue = new LinkedBlockingQueue<SessionManagerEvent>();; | 60 // Command from gui. Synchronization is required. |
61 private BlockingQueue<SessionManagerEvent> waitingEventQueue | |
62 = new LinkedBlockingQueue<SessionManagerEvent>();; | |
63 // host name of this server. One of connecting SocketChannel's hostname | |
58 String myHost; | 64 String myHost; |
65 // Single threaded write queueu. To avoid dead lock with too many writes. | |
59 private LinkedList<PacketSet> writeQueue = new LinkedList<PacketSet>(); | 66 private LinkedList<PacketSet> writeQueue = new LinkedList<PacketSet>(); |
60 private int receive_port; | 67 private int receive_port; |
61 private int parent_port; | 68 private int parent_port; |
62 static final int DEFAULT_PORT = 8766; | 69 static final int DEFAULT_PORT = 8766; |
70 // Queue limit for debugging purpose. | |
63 private static final int packetLimit = 200; | 71 private static final int packetLimit = 200; |
64 | 72 |
73 // globalSessionID = SessionManagerID * MAXID + localSessionID | |
65 private static final int MAXID = 10000; | 74 private static final int MAXID = 10000; |
66 SessionXMLDecoder decoder = new SessionXMLDecoder(); | 75 SessionXMLDecoder decoder = new SessionXMLDecoder(); |
67 SessionXMLEncoder encoder = new SessionXMLEncoder(); | 76 SessionXMLEncoder encoder = new SessionXMLEncoder(); |
77 // SocketChannel for our parent. At most one parent is allowed. | |
68 private Forwarder sm_join_channel; | 78 private Forwarder sm_join_channel; |
69 | 79 // Routing table for session and session manager. |
70 private RoutingTable routingTable = new RoutingTable(); | 80 private RoutingTable routingTable = new RoutingTable(); |
71 | 81 |
72 public static void main(String[] args) throws InterruptedException, IOException { | 82 public static void main(String[] args) throws InterruptedException, IOException { |
73 | 83 |
74 int port = DEFAULT_PORT; | 84 int port = DEFAULT_PORT; |
75 int port_s = DEFAULT_PORT; | 85 int port_s = DEFAULT_PORT; |
76 //System.setProperty("file.encoding", "UTF-8"); | 86 //System.setProperty("file.encoding", "UTF-8"); |
77 if(args.length > 0){ | 87 if(args.length > 0){ |
88 if (args.length!=2) { | |
89 logger.writeLog("Usage: sessionManager our_port parent_port"); | |
90 return; | |
91 } | |
78 port = Integer.parseInt(args[0]); | 92 port = Integer.parseInt(args[0]); |
79 port_s = Integer.parseInt(args[1]); | 93 port_s = Integer.parseInt(args[1]); |
80 } | 94 } |
81 SessionManager sm = new SessionManager(); | 95 SessionManager sm = new SessionManager(); |
82 sm.setReceivePort(port); | 96 sm.setReceivePort(port); |
83 sm.setParentPort(port_s); | 97 sm.setParentPort(port_s); |
98 // Ok start main loop | |
84 sm.init(port,new SessionManagerGUIimpl(sm)); | 99 sm.init(port,new SessionManagerGUIimpl(sm)); |
85 | 100 } |
86 | 101 |
87 } | |
88 | |
89 | |
90 public void setReceivePort(int port) { | 102 public void setReceivePort(int port) { |
91 receive_port = port; | 103 receive_port = port; |
92 } | 104 } |
93 | 105 |
94 | |
95 public void openSelector() throws IOException{ | |
96 selector = REPSelector.<REPCommand>create(); | |
97 } | |
98 | |
99 public void init(int port, SessionManagerGUI gui) throws IOException, InterruptedException { | 106 public void init(int port, SessionManagerGUI gui) throws IOException, InterruptedException { |
100 this.gui = gui; | 107 this.gui = gui; |
101 openSelector(); | |
102 init(port); | 108 init(port); |
103 mainLoop(); | 109 mainLoop(); |
104 } | 110 } |
105 | 111 |
106 | |
107 private void init(int port) throws InterruptedException, IOException { | 112 private void init(int port) throws InterruptedException, IOException { |
108 | 113 selector = REPSelector.<REPCommand>create(); |
109 REPServerSocketChannel<REPCommand> ssc = REPServerSocketChannel.<REPCommand>open(new REPCommandPacker()); | 114 REPServerSocketChannel<REPCommand> ssc = REPServerSocketChannel.<REPCommand>open(new REPCommandPacker()); |
110 ssc.configureBlocking(false); //reuse address 必須 | 115 ssc.configureBlocking(false); // Selector requires this |
111 ssc.socket().setReuseAddress(true); | 116 ssc.socket().setReuseAddress(true); //reuse address 必須 |
112 //getAllByNameで取れた全てのアドレスに対してbindする | 117 //getAllByNameで取れた全てのアドレスに対してbindする |
113 ssc.socket().bind(new InetSocketAddress(port)); | 118 ssc.socket().bind(new InetSocketAddress(port)); |
114 ssc.register(selector, SelectionKey.OP_ACCEPT, | 119 ssc.register(selector, SelectionKey.OP_ACCEPT, |
115 new Forwarder(this)); | 120 new Forwarder(this)); |
116 | 121 |
121 | 126 |
122 | 127 |
123 } | 128 } |
124 | 129 |
125 /* | 130 /* |
131 * The main loop. | |
132 * Check incoming events and waiting writes. | |
133 * Do select and call select() to check in coming packets. | |
126 * We wrote everything in one thread, but we can assign | 134 * We wrote everything in one thread, but we can assign |
127 * one thread for each communication channel and GUI event. | 135 * one thread for each communication channel and GUI event. |
128 */ | 136 */ |
129 | |
130 public void mainLoop() throws IOException { | 137 public void mainLoop() throws IOException { |
131 while(true){ | 138 while(true){ |
132 checkWaitingCommandInMerge(); | 139 checkWaitingCommandInMerge(); |
133 if (checkInputEvent() || | 140 if (checkInputEvent() || |
134 checkWaitingWrite()) { | 141 checkWaitingWrite()) { |
140 selector.select(); | 147 selector.select(); |
141 select(); | 148 select(); |
142 } | 149 } |
143 } | 150 } |
144 | 151 |
152 /* | |
153 * Synchronize GUI event in the main loop. | |
154 */ | |
145 private boolean checkInputEvent() { | 155 private boolean checkInputEvent() { |
146 SessionManagerEvent e; | 156 SessionManagerEvent e; |
147 if((e = waitingEventQueue.poll())!=null){ | 157 if((e = waitingEventQueue.poll())!=null){ |
148 e.exec(this); | 158 e.exec(this); |
149 return true; | 159 return true; |
150 } | 160 } |
151 return false; | 161 return false; |
152 } | 162 } |
153 | 163 |
164 /* | |
165 * Write a packet during the main loop. | |
166 */ | |
154 private boolean checkWaitingWrite() throws IOException { | 167 private boolean checkWaitingWrite() throws IOException { |
155 PacketSet p = writeQueue.poll(); | 168 PacketSet p = writeQueue.poll(); |
156 if (p!=null) { | 169 if (p!=null) { |
157 p.channel.write(p.command); | 170 p.channel.write(p.command); |
158 return true; | 171 return true; |
184 close(p.channel); | 197 close(p.channel); |
185 } | 198 } |
186 } | 199 } |
187 } | 200 } |
188 } | 201 } |
189 | 202 |
203 /* | |
204 * If we have waiting write commands, further sent commands also | |
205 * wait to avoid out of order packet sending. | |
206 */ | |
207 public boolean hasWaitingCommand(REPSocketChannel<REPCommand>c) { | |
208 for(PacketSet p:waitingCommandInMerge) { | |
209 if (p.channel==c) { | |
210 return true; | |
211 } | |
212 } | |
213 return false; | |
214 } | |
215 | |
216 /* | |
217 * Close a channel in case of exception or close. | |
218 */ | |
190 private void close(REPSocketChannel<REPCommand> channel) { | 219 private void close(REPSocketChannel<REPCommand> channel) { |
191 REPSelectionKey<REPCommand>key = channel.keyFor1(selector); | 220 REPSelectionKey<REPCommand>key = channel.keyFor1(selector); |
192 REPHandler handler = (REPHandler)key.attachment(); | 221 REPHandler handler = (REPHandler)key.attachment(); |
193 key.cancel(); | 222 key.cancel(); |
194 handler.cancel(channel); | 223 handler.cancel(channel); |
195 // we have to remove session/enditor | 224 // we have to remove session/enditor |
196 } | 225 } |
197 | 226 |
198 | 227 |
199 public boolean hasWaitingCommand(REPSocketChannel<REPCommand>c) { | 228 /* |
200 for(PacketSet p:waitingCommandInMerge) { | 229 * Do select operation on the Selector. Each key has a forwarder. |
201 if (p.channel==c) { | 230 * A forwarder can be a firstConnector, a forwarder for Session Manager |
202 return true; | 231 * or an Editor. |
203 } | 232 */ |
204 } | |
205 return false; | |
206 } | |
207 | |
208 private void select() throws IOException { | 233 private void select() throws IOException { |
209 | 234 |
210 Set<REPSelectionKey<REPCommand>> keys = selector.selectedKeys1(); | 235 Set<REPSelectionKey<REPCommand>> keys = selector.selectedKeys1(); |
211 for(REPSelectionKey<REPCommand> key : keys){ | 236 for(REPSelectionKey<REPCommand> key : keys){ |
212 if(key.isAcceptable()){ | 237 if(key.isAcceptable()){ |
238 /* | |
239 * Incoming connection. We don't know which, editor or | |
240 * session manager. Assign FirstConnector to distinguish. | |
241 */ | |
213 REPSocketChannel<REPCommand> channel = key.accept(new REPCommandPacker()); | 242 REPSocketChannel<REPCommand> channel = key.accept(new REPCommandPacker()); |
214 logger.writeLog("SessionManager.select() : key.isAcceptable : channel = " + channel); | 243 logger.writeLog("SessionManager.select() : key.isAcceptable : channel = " + channel); |
215 registerChannel (channel, new FirstConnector(this)); | 244 registerChannel(channel, new FirstConnector(this)); |
216 channel = null; | 245 channel = null; |
217 | |
218 }else if(key.isReadable()){ | 246 }else if(key.isReadable()){ |
247 /* | |
248 * Incoming packets are handled by a various forwarder. | |
249 * A hadler throw IOException() in case of a trouble to | |
250 * close the channel. | |
251 */ | |
219 REPHandler handler = (REPHandler)(key.attachment()); | 252 REPHandler handler = (REPHandler)(key.attachment()); |
220 try { | 253 try { |
221 handler.handle(key); | 254 handler.handle(key); |
222 } catch (IOException e) { | 255 } catch (IOException e) { |
223 key.cancel(); | 256 key.cancel(); |
234 handler.setChannel(channel); | 267 handler.setChannel(channel); |
235 channel.configureBlocking(false); | 268 channel.configureBlocking(false); |
236 channel.register(selector, SelectionKey.OP_READ, handler); | 269 channel.register(selector, SelectionKey.OP_READ, handler); |
237 } | 270 } |
238 | 271 |
239 | 272 /* |
240 void cancel_sm_join() { | 273 * After loop detection, we give up session manager join. |
274 */ | |
275 private void cancel_sm_join() { | |
241 removeChannel(sm_join_channel); | 276 removeChannel(sm_join_channel); |
242 sm_join_channel=null; | 277 sm_join_channel=null; |
243 } | 278 } |
244 | 279 |
245 | 280 |
246 private void removeChannel(Forwarder sm_join_channel) { | 281 private void removeChannel(Forwarder channel) { |
247 REPSelectionKey<REPCommand> key = sm_join_channel.channel.keyFor1(selector); | 282 REPSelectionKey<REPCommand> key = channel.channel.keyFor1(selector); |
248 key.cancel(); | 283 key.cancel(); |
249 try { | 284 try { |
250 sm_join_channel.channel.close(); | 285 channel.channel.close(); |
251 } catch (IOException e) { | 286 } catch (IOException e) { |
252 } | 287 } |
253 } | 288 } |
254 | 289 |
255 | 290 |
264 | 299 |
265 | 300 |
266 | 301 |
267 void setMyHostName(String localHostName) { | 302 void setMyHostName(String localHostName) { |
268 myHost = localHostName + receive_port; | 303 myHost = localHostName + receive_port; |
269 // if(maxHost == null) { | |
270 // maxHost = myHost; | |
271 // } | |
272 setHostToEditor(myHost); | 304 setHostToEditor(myHost); |
273 } | 305 } |
274 | 306 |
275 private void setHostToEditor(String myHost2) { | 307 private void setHostToEditor(String myHost2) { |
276 for(Editor editor : editorList.values()){ | 308 for(Editor editor : editorList.values()){ |
279 } | 311 } |
280 } | 312 } |
281 | 313 |
282 | 314 |
283 /** | 315 /** |
316 * GUI から、呼ばれて、Session Managerに接続する。 | |
284 * Host 名のSession Manager に SM_JOIN する。自分は、Session を持っていては | 317 * Host 名のSession Manager に SM_JOIN する。自分は、Session を持っていては |
285 * ならない。複数のSession Managerにjoinすることは出来ない。(NATを実装するまでは)。 | 318 * ならない。複数のSession Managerにjoinすることは出来ない。(NATを実装するまでは)。 |
286 * @param host | 319 * @param host |
287 */ | 320 */ |
288 public void connectSession(String host) { | 321 public void connectSession(String host) { |
289 if (sm_join_channel!=null) return; | 322 if (sm_join_channel!=null) return; |
290 if (!sessionList.isEmpty()) return; | 323 if (!sessionList.isEmpty()) return; |
291 if (!smList.isMaster()) return; | 324 if (!smList.isMaster()) return; |
292 int port = parent_port; | 325 int port = parent_port; |
326 /* | |
327 * IPv6 対応では、複数のアドレスを取って、それのすべてに接続を試す必要が | |
328 * ある。 | |
329 */ | |
293 InetSocketAddress addr = new InetSocketAddress(host, port); | 330 InetSocketAddress addr = new InetSocketAddress(host, port); |
294 try { | 331 try { |
295 REPSocketChannel<REPCommand> sessionchannel = REPSocketChannel.<REPCommand>create(new REPCommandPacker()); | 332 REPSocketChannel<REPCommand> sessionchannel = REPSocketChannel.<REPCommand>create(new REPCommandPacker()); |
296 | |
297 sessionchannel.connect(addr); | 333 sessionchannel.connect(addr); |
298 while(!sessionchannel.finishConnect()); | 334 while(!sessionchannel.finishConnect()); |
299 Forwarder sm = new Forwarder(this); | 335 Forwarder sm = new Forwarder(this); |
300 registerChannel(sessionchannel, sm); | 336 registerChannel(sessionchannel, sm); |
301 sm_join(sm); | 337 sm_join(sm); |
302 }catch (IOException e) { | 338 }catch (IOException e) { |
303 } | 339 } |
304 } | 340 } |
305 | 341 |
342 /** | |
343 * channel に SMCMD_SM_JOIN command を送る。 | |
344 * @param channel | |
345 */ | |
306 private void sm_join(Forwarder channel){ | 346 private void sm_join(Forwarder channel){ |
307 sm_join_channel = channel; | 347 sm_join_channel = channel; |
308 //SM_JOINコマンドを生成。 | 348 //SM_JOINコマンドを生成。 |
309 REPCommand command = new REPCommand(); | 349 REPCommand command = new REPCommand(); |
310 command.setCMD(REP.SMCMD_SM_JOIN); | 350 command.setCMD(REP.SMCMD_SM_JOIN); |
317 String string = myHost; | 357 String string = myHost; |
318 command.setString(string); | 358 command.setString(string); |
319 | 359 |
320 //SM_JOINコマンドを送信。 | 360 //SM_JOINコマンドを送信。 |
321 channel.send(command); | 361 channel.send(command); |
322 //SessionManagerのListに追加。 | 362 // ack を受け取ったら、SessionManagerのListに追加。ここではやらない。 |
323 | |
324 } | 363 } |
325 | 364 |
326 /* | 365 /* |
327 * Select Session from Manager button | 366 * Select Session from Manager button |
328 * selected editor is joined editor directly connected to this session | 367 * selected editor is joined editor directly connected to this session |
332 int sid = event.getSID(); | 371 int sid = event.getSID(); |
333 Session session = sessionList.get(sid); | 372 Session session = sessionList.get(sid); |
334 | 373 |
335 Editor editor = (Editor)event.getEditor(); | 374 Editor editor = (Editor)event.getEditor(); |
336 if(editor == null){ | 375 if(editor == null){ |
337 logger.writeLog("SessionManager.selectSession():editor = " + editor); | 376 logger.writeLog("Error SessionManager.selectSession(): editor = " + editor); |
338 return; | 377 return; |
339 } | 378 } |
340 if (editor.hasSession()) return; | 379 if (editor.hasSession()) return; |
341 | 380 |
342 selectSession(sid, session, editor.getEID(), editor); | 381 selectSession(sid, session, editor.getEID(), editor); |
343 } | 382 } |
344 | 383 |
345 /* | 384 /* |
346 * Select Session Protocol handler | 385 * Select Session Protocol handler |
386 * called from GUI or incoming SMCMD_SELECT command. | |
347 */ | 387 */ |
348 private void selectSession(int sid, Session session, int eid, Forwarder editor) { | 388 private void selectSession(int sid, Session session, int eid, Forwarder editor) { |
349 if(session.hasOwner()){ | 389 if(session.hasOwner()){ |
390 // we have selected session. | |
350 REPCommand sendCommand = new REPCommand(); | 391 REPCommand sendCommand = new REPCommand(); |
351 if (editor.isDirect()&&editor.getEID()==eid) { | 392 if (editor.isDirect()&&editor.getEID()==eid) { |
393 // Found directly connected joined editor. Send join_ack(). | |
352 session.addForwarder(editor); | 394 session.addForwarder(editor); |
353 sendUpdate(session.getSID()); | 395 sendUpdate(session.getSID()); |
354 sendCommand.setCMD(REP.SMCMD_JOIN_ACK); | 396 sendCommand.setCMD(REP.SMCMD_JOIN_ACK); |
355 } else { | 397 } else { |
398 // We have a session, but joined editor is on the other sm. | |
356 // SELECT_ACK is sent to the session ring to | 399 // SELECT_ACK is sent to the session ring to |
357 // find out joined editor | 400 // find out the joined editor. |
358 sendCommand.setCMD(REP.SMCMD_SELECT_ACK); | 401 sendCommand.setCMD(REP.SMCMD_SELECT_ACK); |
359 // Do not directly addForwarder(forwarder). It may be | 402 // Do not directly addForwarder(forwarder). It may be |
360 // shared among sessions. | 403 // shared among sessions. |
361 Forwarder f = new Editor(this, false, makeID(editorList.newEid())); | 404 Forwarder f = new Editor(this, false, makeID(editorList.newEid())); |
362 f.setChannel(editor.channel); // incoming channel | 405 f.setChannel(editor.channel); // incoming channel |
363 f.setHost(myHost); | 406 f.setHost(myHost); |
364 f.setSID(sid); | 407 f.setSID(sid); |
365 session.addForwarder(f); | 408 session.addForwarder(f); // f.next is set up here. |
366 } | 409 } |
367 sendCommand.setEID(editor.getEID()); | 410 sendCommand.setEID(editor.getEID()); |
368 sendCommand.setSID(sid); | 411 sendCommand.setSID(sid); |
369 sendCommand.string = session.getName(); | 412 sendCommand.string = session.getName(); |
370 editor.send(sendCommand); | 413 editor.send(sendCommand); |
371 }else { | 414 }else { |
372 // session searching | 415 // session searching continue... |
373 Forwarder next = routingTable.toSession(sid); | 416 Forwarder next = routingTable.toSession(sid); |
374 | 417 |
418 // create dummy editor for this session | |
375 Forwarder f = new Editor(this, false, makeID(editorList.newEid())); | 419 Forwarder f = new Editor(this, false, makeID(editorList.newEid())); |
376 f.setChannel(editor.channel); // incoming channel | 420 f.setChannel(editor.channel); // incoming channel |
377 f.setNext(next); | 421 f.setNext(next); |
378 f.setHost(myHost); | 422 f.setHost(myHost); |
379 f.setSID(sid); | 423 f.setSID(sid); |
380 session.setFirstForwarder(f); | 424 session.setFirstForwarder(f); |
381 | 425 |
426 // pass the select command to the next path. | |
382 REPCommand command = new REPCommand(); | 427 REPCommand command = new REPCommand(); |
383 command.setCMD(REP.SMCMD_SELECT); | 428 command.setCMD(REP.SMCMD_SELECT); |
384 command.setSID(sid); | 429 command.setSID(sid); |
385 command.setEID(eid); | 430 command.setEID(eid); |
386 command.setString(editor.getHost()); | 431 command.setString(editor.getHost()); |
387 next.send(command); | 432 next.send(command); |
388 } | 433 } |
389 } | 434 } |
390 | 435 |
436 /* | |
437 * Create and send UPDATE command. | |
438 */ | |
391 private void sendUpdate(int sid) { | 439 private void sendUpdate(int sid) { |
392 REPCommand command = makeREPCommandWithSessionList(REP.SMCMD_UPDATE); | 440 REPCommand command = makeREPCommandWithSessionList(REP.SMCMD_UPDATE); |
393 command.setSID(sid); | 441 command.setSID(sid); |
394 command.setEID(REP.SM_EID.id); | 442 command.setEID(REP.SM_EID.id); |
395 smList.sendToMaster(command); | 443 smList.sendToMaster(command); |
396 } | 444 } |
397 | 445 |
446 /* | |
447 * Create new editor in this sessin manager. A dummy editor | |
448 * is created also. | |
449 */ | |
398 public Editor newEditor(REPSocketChannel<REPCommand> channel) { | 450 public Editor newEditor(REPSocketChannel<REPCommand> channel) { |
399 int eid = makeID(editorList.newEid()); | 451 int eid = makeID(editorList.newEid()); |
400 Editor editor = new Editor(this, eid, channel); | 452 Editor editor = new Editor(this, eid, channel); |
401 editorList.add(editor); | 453 editorList.add(editor); |
402 return editor; | 454 return editor; |
403 } | 455 } |
404 | 456 |
405 | 457 /* |
458 * Create new session. | |
459 */ | |
406 public Session newSession(Forwarder master) { | 460 public Session newSession(Forwarder master) { |
407 int sid= makeID(sessionList.newSessionID()); | 461 int sid= makeID(sessionList.newSessionID()); |
408 Session session = new Session(sid, master); | 462 Session session = new Session(sid, master); |
409 sessionList.put(sid, session); | 463 sessionList.put(sid, session); |
410 return session; | 464 return session; |
412 | 466 |
413 public void addWaitingCommand(PacketSet set) { | 467 public void addWaitingCommand(PacketSet set) { |
414 waitingCommandInMerge.add(set); | 468 waitingCommandInMerge.add(set); |
415 } | 469 } |
416 | 470 |
471 /* | |
472 * Synchronize GUI command in this session manager. | |
473 */ | |
417 public void buttonPressed(SessionManagerEvent event) { | 474 public void buttonPressed(SessionManagerEvent event) { |
418 try { | 475 try { |
419 waitingEventQueue.put(event); | 476 waitingEventQueue.put(event); |
420 } catch (InterruptedException e) {} | 477 } catch (InterruptedException e) {} |
421 selector.wakeup(); | 478 selector.wakeup(); |
422 } | 479 } |
423 | 480 |
481 /* | |
482 * Execute incoming event during the initialization for | |
483 * testing purpose. | |
484 */ | |
424 public void syncExec(SessionManagerEvent event) { | 485 public void syncExec(SessionManagerEvent event) { |
425 try { | 486 try { |
426 waitingEventQueue.put(event); | 487 waitingEventQueue.put(event); |
427 } catch (InterruptedException e) { | 488 } catch (InterruptedException e) { |
428 } | 489 } |
429 } | 490 } |
430 | 491 |
492 /* | |
493 * GUI command interface for close session. | |
494 */ | |
431 public void closeSession(SessionManagerEvent event) { | 495 public void closeSession(SessionManagerEvent event) { |
432 Session session = ((CloseButtonEvent) event).getSession(); | 496 Session session = ((CloseButtonEvent) event).getSession(); |
433 session.closeSession(); | 497 session.closeSession(); |
434 sessionList.remove(session); | 498 sessionList.remove(session); |
435 updateGUI(); | 499 updateGUI(); |
436 } | 500 } |
437 | 501 |
502 /* | |
503 * Remove editors which has the cannel. | |
504 */ | |
438 public void remove(REPSocketChannel<REPCommand> channel) { | 505 public void remove(REPSocketChannel<REPCommand> channel) { |
439 int i = 0; | 506 int i = 0; |
440 for(Session s:sessionList.values()) { | 507 for(Session s:sessionList.values()) { |
441 if (s.deleteEditor(channel)) { | 508 if (s.deleteEditor(channel)) { |
442 i++; | 509 i++; |
627 } | 694 } |
628 return true; | 695 return true; |
629 } | 696 } |
630 | 697 |
631 | 698 |
699 /** | |
700 * UPDATE/UPDATE_ACKにより送られてきたSessionの情報を追加する | |
701 * @param command | |
702 * @return | |
703 * @throws IOException | |
704 */ | |
632 private String mergeUpdate(REPCommand command) throws IOException { | 705 private String mergeUpdate(REPCommand command) throws IOException { |
633 SessionList receivedSessionList; | 706 SessionList receivedSessionList; |
634 try { | 707 try { |
635 receivedSessionList = decoder.decode(command.string); | 708 receivedSessionList = decoder.decode(command.string); |
636 } catch (SAXException e) { | 709 } catch (SAXException e) { |
637 throw new IOException(); | 710 throw new IOException(); |
638 } | 711 } |
639 // UPDATE/UPDATE_ACKにより送られてきたSessionの情報を追加する | 712 // 受け取った情報と自分の情報を混ぜる。 |
713 sessionList.merge(receivedSessionList); | |
640 //XMLを生成。送信コマンドにセット。 | 714 //XMLを生成。送信コマンドにセット。 |
641 sessionList.merge(receivedSessionList); | |
642 return encoder.sessionListToXML(sessionList); | 715 return encoder.sessionListToXML(sessionList); |
643 | 716 |
644 } | 717 } |
645 | 718 |
646 /* | 719 /* |
647 * id has SessionManager ID part | 720 * id has SessionManager ID part |
648 */ | 721 */ |
649 | |
650 private int makeID(int newid) { | 722 private int makeID(int newid) { |
651 return newid+smList.sessionManagerID()*MAXID; | 723 return newid+smList.sessionManagerID()*MAXID; |
652 } | 724 } |
653 | |
654 | 725 |
655 private int getSMID(int id) { | 726 private int getSMID(int id) { |
656 return id/MAXID; | 727 return id/MAXID; |
657 } | 728 } |
658 | 729 |