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