# HG changeset patch # User kono # Date 1224402877 -32400 # Node ID 034acadc0cdc7088b29f6f33fb58f56d45fae35d # Parent 6ae9dcb30a12fd088de956099d83d286a008f75a *** empty log message *** diff -r 6ae9dcb30a12 -r 034acadc0cdc Todo --- a/Todo Sat Oct 18 21:28:17 2008 +0900 +++ b/Todo Sun Oct 19 16:54:37 2008 +0900 @@ -1,3 +1,69 @@ +Sat Oct 18 20:03:10 JST 2008 + +Note: Routing Table (kono) + +Routing Table (Session, Editor)を作るには、上下双方向の通信が必要。 +SessionID を master が作ると、一旦、multi cast した後、もう一度、 +上に上げる必要がある。Select の時には、editor から上に上がるので、 +その時に構築すれば良い。SessionManagerIDと組み合わせれば、eid/sid +ともに、下から構築出来る。 + +自分が出したjoin/put/sm_joinに対するackかどうかを見るために、 +SessionManagerID は、どうせ必要。この方法だと、routing table +もSessionManagerIDに対してだけ構築すれば良い。とは、ならない。 +Session は、複数のSessionManagerにまたがるので。 + +join_ack が来た時には、そのeditorのrouting tableは完成している、 +あるいは、select が完成させるjoin_ackに追い付くことはない。 +put_ack も同様。 + +select は、editorへのpathを探しながら、session routing table +を構築する。もっとも高位のsession managerへのrouting table +は、これで作成される。ここからjoinしたeditorまでのpathは、 +そのeditor単一のpathだが、routing table に登録される。 +select は、session ringに到達した時点で update を流す。 +update は、木をさかのぼりrouting tableを構築する。 +これで上方向のroutingは確定する。update_ackにより、 +下方向のsesionn routing tableが確定する。 + +Wed Oct 15 13:33:58 JST 2008 + +Note: (kono) + +Session List を渡すタイミング + + SM_JOIN_ACK (必須...) + SM_JOIN では、Session List は0なはず。 + JOIN,PUT は、multi-cast されるので、その時に登録すれば良い。 + その時に、Session List を送っても良いが... + SELECTは、joinするeditorからしか出ない。Session List は必要ない。 + SELECT_ACK は、UPDATEが出るので必要ない + UPDATE,UPDATE_ACK には、Session List が付く + GATHER,GATHER_ACK には、Session List が付く + +Session List では、editor,session に対するroutingも作成する、必要 +な情報を含む必要がある。 + eid, EditorName, FileName, sid, SessionManagerName +SessionManagerName が入っていれば、editor, session が +Session Listが来た方向にいるということになる。 + +SessionManagerName は、network 上でuniqueな必要がある。 +sm_join した時に、そのchannelの名前が大域的に確定する。 +sm_join は複数行なわれないから、名前が変わることはない。 +sm_join された側の名前も、接続されて初めて確定する。 +複数 sm_join されることはあるが、その場合は最初のもの +を使う。ということは、localにsm_join された後、大域的 +に接続される場合があるってことか。ってことは、やっぱり、 +session manager id を配布するべきだってことね。で、 +SMの名前はあくまでも補助的に使う。 + +UPDATEの情報によって削除も行なう。delete entry が必要。 + +Routing Table + + +null は、local。channel==parent なら、自分の下にはいない。 + Tue Oct 14 06:02:37 JST 2008 Todo: (kono) diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/Editor.java --- a/rep/Editor.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/Editor.java Sun Oct 19 16:54:37 2008 +0900 @@ -1,5 +1,6 @@ package rep; +import java.io.IOException; import java.util.LinkedList; import java.util.List; @@ -192,7 +193,7 @@ @Override - public void handle(REPSelectionKey key) throws Exception { + public void handle(REPSelectionKey key) throws IOException { REPSocketChannel channel = key.channel1(); REPCommand command = channel.read(); SessionManager.logger.writeLog("REPHandlerImpl.handle() read : command = " + command +" from "+channel); @@ -204,4 +205,8 @@ public void cancel(REPSocketChannel socketChannel) { manager.remove(socketChannel); } + + public boolean isMaster() { + return mode==REP.SMCMD_PUT; + } } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/EditorList.java --- a/rep/EditorList.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/EditorList.java Sun Oct 19 16:54:37 2008 +0900 @@ -1,30 +1,32 @@ package rep; -import java.util.LinkedList; +import java.util.HashMap; -public class EditorList extends LinkedList { +public class EditorList extends HashMap { /** * */ private static final long serialVersionUID = 1L; private int eid_root=0; - private LinkedList waiting= new LinkedList(); + private HashMap waiting= new HashMap(); public void addWaitingEditor(Editor fw) { - waiting.add(fw); + waiting.put(fw.getEID(),fw); + } + + public void add(Editor fw) { + put(fw.getEID(),fw); } - public void assignSessionManagerIDtoWaitingSM(int eid) { - // 待っていたEditorにEditor IDを登録し,Session Manager List + // 待っていたEditorを登録する。 // に登録する。この後、EditorのPUT/JOINに従って、ACKを送り、EID // を確定する。 Editor waiter; - if ((waiter=waiting.poll())!=null) { - waiter.setEID(eid); - add(waiter); + if ((waiter=waiting.remove(eid))!=null) { + put(eid,waiter); return; } assert false; @@ -37,7 +39,12 @@ public boolean waiting(Editor editor) { - return waiting.contains(editor); + return waiting.containsKey(editor.getEID()); + } + + + public boolean hasEid(int eid) { + return containsKey(eid); } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/FirstConnector.java --- a/rep/FirstConnector.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/FirstConnector.java Sun Oct 19 16:54:37 2008 +0900 @@ -15,7 +15,7 @@ manager.remove(socketChannel); } - public void handle(REPSelectionKey key) throws Exception { + public void handle(REPSelectionKey key) throws IOException { /* * 接続要求は、EditorかSlave Editorで、 *    join, put, sm_join @@ -37,6 +37,7 @@ Editor editor = new Editor(manager,-1,channel); editor.setHost(manager.myHost); manager.editorList.add(editor); + manager.updateGUI(); fw = editor; break; } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/Forwarder.java --- a/rep/Forwarder.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/Forwarder.java Sun Oct 19 16:54:37 2008 +0900 @@ -1,8 +1,6 @@ package rep; import java.io.IOException; - - import rep.channel.REPLogger; import rep.channel.REPSelectionKey; import rep.channel.REPSocketChannel; @@ -69,7 +67,7 @@ manager.remove(socketChannel); } - public void handle(REPSelectionKey key) throws Exception { + public void handle(REPSelectionKey key) throws IOException { /* * SessionManagerから来たコマンドは、Editor関係のコマンドは、 * sessionとeidを判定して、そのeditorにforwardしてやれば良い。 @@ -98,5 +96,9 @@ return mode==REP.SMCMD_SM_JOIN||mode==REP.SMCMD_SM_JOIN_ACK; } + public boolean isDirect() { + return isEditor(); + } + } \ No newline at end of file diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/RoutingTable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rep/RoutingTable.java Sun Oct 19 16:54:37 2008 +0900 @@ -0,0 +1,46 @@ +package rep; + +import java.util.HashMap; +import java.util.Map.Entry; + +public class RoutingTable { + + HashMap sessionManagers =new HashMap(); + // we don't need this, but we keep it because it is easy. + // editor can be reached using this routing table. + HashMap sessionTable =new HashMap(); + // session may have multiple forward, if so we have a session + // here. So we don't have to keep multiple session, just keep + // one. + + public void add(Forwarder forwarder, int smid, int sid) { + if (smid>0) sessionManagers.put(smid, forwarder) ; + if (sid>0) sessionTable.put(sid, forwarder) ; + } + + public void remove(Forwarder f) { + for(Entry entry:sessionManagers.entrySet()) { + if (entry.getValue()==f) sessionManagers.remove(entry.getKey()); + } + for(Entry entry:sessionTable.entrySet()) { + if (entry.getValue()==f) sessionTable.remove(entry.getKey()); + } + } + + public void removeSession(int sid) { + sessionTable.remove(sid); + } + + public void removeManager(int smid) { + sessionManagers.remove(smid); + } + + public Forwarder toSession(int sid) { + return sessionTable.get(sid); + } + + public Forwarder toSessionManager(int eid) { + return sessionManagers.get(eid); + } + +} diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/Session.java --- a/rep/Session.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/Session.java Sun Oct 19 16:54:37 2008 +0900 @@ -79,6 +79,11 @@ return flag; } + public boolean deleteForwarder(Forwarder editor) { + unconnect(editor); + return editorList.remove(editor); + } + private void unconnect(Forwarder e) { for(EditorPlus e1:editorList) { Forwarder f = (Forwarder)e1; @@ -125,14 +130,19 @@ } - public boolean deleteForwarder(Forwarder editor) { - unconnect(editor); - return editorList.remove(editor); - } public Forwarder getFirstForwarder() { return firstForwarder; } + + + public void remove(SessionManager manager) { + for(EditorPlus editor : editorList){ + if(editor.getChannel() !=null) + unconnect((Forwarder)editor); + manager.editorList.remove(editor); + } + } } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/SessionList.java --- a/rep/SessionList.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/SessionList.java Sun Oct 19 16:54:37 2008 +0900 @@ -1,21 +1,16 @@ package rep; -import java.util.LinkedList; + +import java.util.HashMap; import rep.channel.REPSocketChannel; -import rep.xml.SessionXMLEncoder; -public class SessionList extends LinkedList{ - +public class SessionList extends HashMap{ /** * */ private static final long serialVersionUID = 1L; - LinkedList stringlist = new LinkedList(); - private String maxHost; private int sid_root = 0; - - public void sendSelect(int sid) { REPSocketChannel channel = get(sid-1).getOwner().getChannel(); @@ -88,43 +83,26 @@ // return str.toString(); // }*/ - public LinkedList getList() { - return new LinkedList(this); - } - - public String toXML() { - SessionXMLEncoder encoder = new SessionXMLEncoder(this); - encoder.sessionListToXML(); - return null; - } public int addSession(Session session) { int sid; session.setSID(sid=newSessionID()); - add(session); + put(sid,session); return sid; } - + public Session getSession(int sid) { - for(Session session : this){ - if(session.getSID() == sid){ - return session; - } - } - return get(sid - 1); + return get(sid); } - public void setMaxHost(String myHost) { - maxHost = myHost; - } - - public String getMaxHost() { - return maxHost; - } - - public int newSessionID() { return ++sid_root ; } + public void merge(SessionList receivedSessionList) { + // TODO Auto-generated method stub + + } + + } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/SessionManager.java --- a/rep/SessionManager.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/SessionManager.java Sun Oct 19 16:54:37 2008 +0900 @@ -46,7 +46,7 @@ public class SessionManager implements SessionManagerEventListener{ static public REPLogger logger = REPLogger.singleton(); - LinkedList sessionList; + SessionList sessionList; private SessionManagerGUI gui; private REPSelector selector; SessionManagerList smList; @@ -61,9 +61,14 @@ private int parent_port; static final int DEFAULT_PORT = 8766; private static final int packetLimit = 200; + + private static final int MAXID = 10000; SessionXMLDecoder decoder = new SessionXMLDecoder(); + SessionXMLEncoder encoder = new SessionXMLEncoder(); private Forwarder sm_join_channel; + private RoutingTable routingTable = new RoutingTable(); + public static void main(String[] args) throws InterruptedException, IOException { int port = DEFAULT_PORT; @@ -109,7 +114,7 @@ ssc.register(selector, SelectionKey.OP_ACCEPT, new Forwarder(this)); - sessionList = new LinkedList(); + sessionList = new SessionList(); smList = new SessionManagerList(); editorList = new EditorList(); waitingCommandInMerge = new LinkedList(); @@ -214,7 +219,7 @@ REPHandler handler = (REPHandler)(key.attachment()); try { handler.handle(key); - } catch (Exception x) { + } catch (IOException e) { key.cancel(); handler.cancel(key.channel1()); } @@ -248,47 +253,16 @@ } - boolean hasSession(int sid) { - for(Session s:sessionList) { - if (s.getSID()==sid) return true; - } - return false; - } - - void updateGUI() { //リストのコピーをGUIに渡す - LinkedList sList = new LinkedList(sessionList); - LinkedList eList = new LinkedList(editorList); + LinkedList sList = new LinkedList(sessionList.values()); + LinkedList eList = new LinkedList(editorList.values()); //GUIに反映 Runnable doRun = new DoGUIUpdate(sList, eList, gui); gui.invokeLater(doRun); } - Forwarder getEditor(String hostport) { - for(Editor editor : editorList){ - if(editor.getHost() == hostport){ - return editor; - } - } - return null; - } - - public Session getSession(int sid) throws IOException { - for(Session session : sessionList){ - if(session.getSID() == sid) return session; - } - throw new IOException(); - } -// private boolean setMaxHost(REPSocketChannel channel, String maxHost2) { -// if(maxHost.compareTo(maxHost2) > 0){ -// return false; -// }else{ -// maxHost = maxHost2; -// return true; -// } -// } void setMyHostName(String localHostName) { myHost = localHostName + receive_port; @@ -299,8 +273,9 @@ } private void setHostToEditor(String myHost2) { - for(Editor editor : editorList){ - editor.setHost(myHost2); + for(Editor editor : editorList.values()){ + if (editor.channel!=null) + editor.setHost(myHost2); } } @@ -339,9 +314,6 @@ //hostnameをセット。 setMyHostName(channel.getLocalHostName()); - //XMLを生成。送信コマンドにセット。 - //SessionXMLEncoder encoder = new SessionXMLEncoder(sessionList); - //String string = encoder.sessionListToXML(); String string = myHost; command.setString(string); @@ -353,7 +325,7 @@ public void selectSession(SelectButtonEvent event) throws IOException { int sid = event.getSID(); - Session session = getSession(sid); + Session session = sessionList.get(sid); Editor editor = (Editor)event.getEditor(); if(editor == null){ @@ -361,32 +333,48 @@ return; } if (editor.hasSession()) return; - if (editorList.waiting(editor)) return; + selectSession(sid, session, editor.getEID(), editor); + } + + + private void selectSession(int sid, Session session, int eid, Forwarder editor) { if(session.hasOwner()){ - editor.setEID(editorList.newEid()); - editor.setSID(sid); session.addForwarder(editor); REPCommand sendCommand = new REPCommand(); - sendCommand.setCMD(REP.SMCMD_JOIN_ACK); + if (editor.isDirect()&&editor.getEID()==eid) { + sendUpdate(); + sendCommand.setCMD(REP.SMCMD_JOIN_ACK); + } else { + // SELECT_ACK is sent to the session ring to + // find out joined editor + sendCommand.setCMD(REP.SMCMD_SELECT_ACK); + } sendCommand.setEID(editor.getEID()); sendCommand.setSID(sid); sendCommand.string = ""; editor.send(sendCommand); }else { + session.addForwarder(editor); editor.setHost(myHost); editor.setSID(sid); - session.addEditor(editor); - Forwarder owner = session.getOwner(); + Forwarder next = routingTable.toSession(sid); REPCommand command = new REPCommand(); command.setCMD(REP.SMCMD_SELECT); command.setSID(sid); + command.setEID(eid); command.setString(editor.getHost()); - owner.send(command); + next.send(command); } } + private void sendUpdate() { + // TODO Auto-generated method stub + + } + + public void addWaitingCommand(PacketSet set) { waitingCommandInMerge.add(set); } @@ -413,12 +401,13 @@ } public void remove(REPSocketChannel channel) { - for(Session s:sessionList) { + int i = 0; + for(Session s:sessionList.values()) { if (s.deleteEditor(channel)) { - return ; + i++; } } - assert(false); + assert(i==1); // can be other session manager? what should I do? } @@ -430,20 +419,20 @@ public void remove(Editor editor) { - Session s0 = null; - editorList.remove(editor); - for(Session s:sessionList) { - if (s.deleteForwarder(editor)) { - if (editor.getEID()==0) s0=s; - } + Session s = sessionList.get(editor.getSID()); + if (editor.isMaster()) { + removeSession(s); + } else { + s.deleteForwarder(editor); + editorList.remove(editor); } - if (s0!=null) removeSession(s0); updateGUI(); } private void removeSession(Session s0) { + s0.remove(this); sessionList.remove(s0); - // send UPDATE to all the session manager + sendUpdate(); } public void setParentPort(int port) { @@ -459,103 +448,73 @@ boolean sessionManage(Forwarder forwarder, REPCommand command) throws ClosedChannelException, - IOException, SAXException { + IOException { switch(command.cmd){ // Session Manager Command case SMCMD_JOIN: { - updateGUI(); + // first connection or forwarded command + if (forwarder.isDirect()) { + // direct linked editor なので、ここでIDを作成する + command.setEID(makeID(editorList.newEid())); + } + if(isMaster()) { + REPCommand ackCommand = new REPCommand(); + ackCommand.setCMD(REP.SMCMD_JOIN_ACK); + ackCommand.setEID(command.eid); + ackCommand.string = command.string; + smList.sendToSlaves(ackCommand); + registEditor(forwarder,ackCommand); + } else { + routingTable.add(forwarder,getSMID(command.eid),command.sid); + smList.sendToMaster(command); + } + } break; case SMCMD_JOIN_ACK: - assert (false); + case SMCMD_PUT_ACK: + registEditor(forwarder,command); break; case SMCMD_PUT: { - //Sessionを生成 - // sessionIDってglobaly uniqueだから、本来は、 - // 自分の親に作ってもらう必要がある。自分が親なら自分で作って良い。 - - int sid = sessionList.size(); - Editor editor = (Editor) forwarder; - Session session = new Session(sid, command.string, (Editor)forwarder); - session.hasOwner(true); - sessionList.add(session); - - updateGUI(); - - //エディタにAckを送信 - REPCommand sendCommand = new REPCommand(command); - sendCommand.setCMD(REP.SMCMD_PUT_ACK); - sendCommand.setEID(editor.getEID()); - sendCommand.setSID(session.getSID()); - editor.send(sendCommand); - - //他のSessionManagerへSessionの追加を報告 - //親に送って、親から子へ - SessionXMLEncoder sessionEncoder = new SessionXMLEncoder(session); - REPCommand command1 = new REPCommand(); - command1.setSID(session.getSID()); - command1.setString(sessionEncoder.sessionListToXML()); - command1.setCMD(REP.SMCMD_UPDATE); - smList.sendToSlaves( command); + // first connection or forwarded command + if (forwarder.isDirect()) { + // direct link, make new ID + int eid = makeID(editorList.newEid()); + int sid = makeID(sessionList.newSessionID()); + command.setEID(eid); + command.setSID(sid); + } + if(isMaster()) { + command.setCMD(REP.SMCMD_PUT_ACK); + command.string = command.string; + command.setEID(command.eid); + command.setSID(command.sid); + smList.sendToSlaves(command); + registEditor(forwarder,command); + } else { + routingTable.add(forwarder,getSMID(command.eid),command.sid); + smList.sendToMaster(command); + } } - break; - - // SELECT is no longer used in a editor. Select - // operation is handled in Session Manager Only + case SMCMD_SELECT: - { - //他のSessionManagerをエディタとしてSessionに追加 - Forwarder next = new Forwarder(this); - next.setChannel(forwarder.channel); - Session session = getSession(command.sid); - session.addForwarder(next); - - if(session.hasOwner()){ - //このSessionManagerがオーナーを持っている場合、Sessionにエディタを追加し、エディタへAckを返す - REPCommand sendCommand = new REPCommand(command); - sendCommand.setCMD(REP.SMCMD_SELECT_ACK); - sendCommand.setEID(next.getEID()); - next.send(sendCommand); - }else{ - //オーナーを持ってない場合は、オーナーを持っているSessionManagerへSELECTコマンドを中継する - Forwarder owner = session.getOwner(); - owner.send(command); - } - } - - break; - case SMCMD_SELECT_ACK: { - String hostport = command.string; - Forwarder editor1 = getEditor(hostport); - - if(editor1 != null) { - //host, port を見て、このコマンドが自分が送信したSelectコマンドのAckかどうかを判断する - REPCommand command1 = new REPCommand(); - command1.setCMD(REP.SMCMD_JOIN_ACK); - command1.setSID(command.sid); - command1.setEID(command.eid); - editor1.send(command); - - }else{ - //自分が送信したコマンドでなければ、次のSessionManagerへ中継する - smList.sendToSlaves(command); - } + Session session = sessionList.get(command.sid); + selectSession(command.sid, session, command.eid, forwarder); } - - break; + break; + case SMCMD_SM_JOIN: - { // SM_JOIN中にSMCMD_SM_JOINが来たら、これはループなので、 ///自分のSM_JOINを取り消す。 @@ -600,55 +559,17 @@ break; case SMCMD_UPDATE: - { - SessionList receivedSessionList3 = decoder.decode(command.string); - - //UPDATEコマンドにより送られてきたSessionの情報を追加する - LinkedList list = receivedSessionList3.getList(); - for(Session session : list){ - session.getEditorList().get(0).setChannel(forwarder.channel); - sessionList.add(session); - } - - //他のSessionManagerへ中継する - smList.sendToSlaves(command); - - updateGUI(); - } + command.setString(mergeUpdate(command)); + // 上に知らせる + smList.sendToMaster(command); break; case SMCMD_UPDATE_ACK: - { - if(!hasSession(command.sid)) { - // accept new Session - // ここで初めてsession id が決まる。 - // このコマンドは、master session manager が出すはず - Forwarder sm = new Forwarder(this); - sm.setChannel(forwarder.channel); - Session session = new Session(command.sid,command.string,null); - session.addForwarder(sm); - - sessionList.add(session); - - updateGUI(); - } + command.setString(mergeUpdate(command)); + // 下に知らせる smList.sendToSlaves(command); - } + updateGUI(); break; - - // case SMCMD_CH_MASTER: - // { - // //maxHost を設定。 - // if(setMaxHost(channel, receivedCommand.string)){ - // REPCommand sendCommand = new REPCommand(); - // sendCommand.setCMD(REP.SMCMD_CH_MASTER); - // sendCommand.setString(maxHost); - // smList.sendExcept(channel, sendCommand); - // } - // } - // break; - - default: return false; } @@ -656,12 +577,66 @@ } + private String mergeUpdate(REPCommand command) throws IOException { + SessionList receivedSessionList; + try { + receivedSessionList = decoder.decode(command.string); + } catch (SAXException e) { + throw new IOException(); + } + // UPDATE/UPDATE_ACKにより送られてきたSessionの情報を追加する + //XMLを生成。送信コマンドにセット。 + sessionList.merge(receivedSessionList); + return encoder.sessionListToXML(sessionList); + + } + + /* + * id has SessionManager ID part + */ + + private int makeID(int newid) { + return newid+smList.sessionManagerID()*MAXID; + } + + private int getSessionID(int id) { + return id%MAXID; + } + + private int getSMID(int id) { + return id/MAXID; + } + + + private void registEditor(Forwarder forwarder,REPCommand command) { + // make ack for PUT/JOIN. Do not send this to the editor, + // before select. After select, ack is sent to the editor. + routingTable.add(forwarder,getSMID(command.eid),command.sid); + Editor editor; + if (getSessionID(command.sid)==smList.sessionManagerID() + && forwarder.isDirect()) { + // direct link だった + editor = (Editor)forwarder; + } else { + editor = new Editor(this, command.cmd==REP.SMCMD_PUT_ACK, command.eid); + } + editor.setName(command.string); + editor.setSID(command.sid); + if (!editorList.hasEid(command.eid)) { + editorList.add(editor); + updateGUI(); + } + // we don't join ack to the direct linked editor. We + // have to wait select command + } + + void send_sm_join_ack(int psid, int sid,REPCommand sendCommand) { if (psid==smList.sessionManagerID()) { // 直下のsessionManagerにIDを割り振る必要がある。 smList.assignSessionManagerIDtoWaitingSM(sid); // ここで smList に一つだけ追加されるので - // 待っている最初のsm一つにだけ、sm_joinが新たに送られる。 + // 待っている最初のsm一つにだけ、sm_join_ackが新たに送られる。 } smList.sendToSlaves(sendCommand); } @@ -670,10 +645,9 @@ private REPCommand makeREPCommandWithSessionList(REP cmd) { //SessionListからXMLを生成。 //joinしてきたSessionManagerに対してACKを送信。 - SessionXMLEncoder sessionlistEncoder = new SessionXMLEncoder(sessionList); REPCommand sendCommand = new REPCommand(); sendCommand.setCMD(cmd); - sendCommand.setString(sessionlistEncoder.sessionListToXML()); + sendCommand.setString(encoder.sessionListToXML(sessionList)); return sendCommand; } @@ -687,4 +661,9 @@ smList.setSessionManagerID(sid); } + + public Session getSession(int sid) { + return sessionList.get(sid); + } + } diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/handler/REPHandler.java --- a/rep/handler/REPHandler.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/handler/REPHandler.java Sun Oct 19 16:54:37 2008 +0900 @@ -1,11 +1,13 @@ package rep.handler; +import java.io.IOException; + import rep.REPCommand; import rep.channel.REPSelectionKey; import rep.channel.REPSocketChannel; public interface REPHandler { - void handle(REPSelectionKey key)throws Exception; + void handle(REPSelectionKey key) throws IOException; void cancel(REPSocketChannel socketChannel); diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/xml/SessionXMLDecoder.java --- a/rep/xml/SessionXMLDecoder.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/xml/SessionXMLDecoder.java Sun Oct 19 16:54:37 2008 +0900 @@ -44,22 +44,22 @@ //sessionlist = createSessionList(root); sessionlist = generateSessionList(root); - sessionlist.setMaxHost(getSessionManagerHost(root)); + //sessionlist.setMaxHost(getSessionManagerHost(root)); return sessionlist; } - private String getSessionManagerHost(Element root) { - NodeList nodelist = root.getChildNodes(); - String host = null; - for(int i = 0; i < nodelist.getLength(); i++){ - if(nodelist.item(i).getNodeName().equals("host")){ - host = nodelist.item(i).getTextContent(); - } - } - return host; - } +// private String getSessionManagerHost(Element root) { +// NodeList nodelist = root.getChildNodes(); +// String host = null; +// for(int i = 0; i < nodelist.getLength(); i++){ +// if(nodelist.item(i).getNodeName().equals("host")){ +// host = nodelist.item(i).getTextContent(); +// } +// } +// return host; +// } private SessionList generateSessionList(Element element){ SessionList sessionlist = new SessionList(); diff -r 6ae9dcb30a12 -r 034acadc0cdc rep/xml/SessionXMLEncoder.java --- a/rep/xml/SessionXMLEncoder.java Sat Oct 18 21:28:17 2008 +0900 +++ b/rep/xml/SessionXMLEncoder.java Sun Oct 19 16:54:37 2008 +0900 @@ -5,7 +5,10 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; @@ -18,26 +21,10 @@ import rep.SessionList; public class SessionXMLEncoder { - private LinkedList list = new LinkedList(); - private String sessionmanagerHost; - - public SessionXMLEncoder(SessionList sessionlist) { - sessionmanagerHost = sessionlist.getMaxHost(); - this.list = sessionlist.getList(); - } + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + TransformerFactory tfactory = TransformerFactory.newInstance(); - public SessionXMLEncoder(LinkedList sessionList) { - this.list = sessionList; - } - - public SessionXMLEncoder() { - } - - public SessionXMLEncoder(Session session) { - list.add(session); - } - - public String sessionListToXML() { + public String sessionListToXML(SessionList list) { /* SessionListをXMLに書き出す。ときの形式 * * naha.ie.u-ryukyu.ac.jp @@ -59,57 +46,62 @@ * * */ - StringWriter str = null; - try { - str = new StringWriter(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.newDocument(); - Element root = doc.getDocumentElement(); - root = doc.createElement("SessionList"); - - Element elementSeMaHost = doc.createElement("host"); - if(sessionmanagerHost != null) elementSeMaHost.setTextContent(sessionmanagerHost); - root.appendChild(elementSeMaHost); + StringWriter str = new StringWriter(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + return ""; + } + Document doc = builder.newDocument(); + Element root = doc.getDocumentElement(); + root = doc.createElement("SessionList"); + // + // Element elementSeMaHost = doc.createElement("host"); + // if(sessionmanagerHost != null) elementSeMaHost.setTextContent(sessionmanagerHost); + // root.appendChild(elementSeMaHost); - for(Session session : list){ - Element elementSession = doc.createElement("Session"); - root.appendChild(elementSession); - elementSession.setAttribute("sid", Integer.toString(session.getSID())); + for(Session session : list.values()){ + Element elementSession = doc.createElement("Session"); + root.appendChild(elementSession); + elementSession.setAttribute("sid", Integer.toString(session.getSID())); + + LinkedList editorlist = session.getEditorList(); + for(EditorPlus editor : editorlist){ + Element elementEditor = doc.createElement("Editor"); + elementEditor.setAttribute("eid", Integer.toString(editor.getEID())); + elementSession.appendChild(elementEditor); + + Element elementHost = doc.createElement("host"); + elementEditor.appendChild(elementHost); + elementHost.setTextContent(editor.getHost()); - LinkedList editorlist = session.getEditorList(); - for(EditorPlus editor : editorlist){ - Element elementEditor = doc.createElement("Editor"); - elementEditor.setAttribute("eid", Integer.toString(editor.getEID())); - elementSession.appendChild(elementEditor); - - Element elementHost = doc.createElement("host"); - elementEditor.appendChild(elementHost); - elementHost.setTextContent(editor.getHost()); - - Element elementPort = doc.createElement("port"); - elementEditor.appendChild(elementPort); - //elementPort.setTextContent(editor.getPort()); - - if(editor.getName() != null){ - Element elementName = doc.createElement("file"); - elementEditor.appendChild(elementName); - elementName.setTextContent(editor.getName()); - //System.out.println(editor.getName()); - } - } - } - doc.appendChild(root); - - TransformerFactory tfactory = TransformerFactory.newInstance(); - Transformer transformer = tfactory.newTransformer(); - StreamResult result = new StreamResult(str); - transformer.transform(new DOMSource(doc), result); + Element elementPort = doc.createElement("port"); + elementEditor.appendChild(elementPort); + //elementPort.setTextContent(editor.getPort()); + + if(editor.getName() != null){ + Element elementName = doc.createElement("file"); + elementEditor.appendChild(elementName); + elementName.setTextContent(editor.getName()); + //System.out.println(editor.getName()); + } + } + } + doc.appendChild(root); - }catch (Exception e){ - - } - //System.out.println(str.toString()); - return str.toString(); - } + Transformer transformer; + StreamResult result = new StreamResult(str); + try { + transformer = tfactory.newTransformer(); + transformer.transform(new DOMSource(doc), result); + } catch (TransformerConfigurationException e1) { + return ""; + } catch (TransformerException e) { + return ""; + } + + //System.out.println(str.toString()); + return str.toString(); + } } diff -r 6ae9dcb30a12 -r 034acadc0cdc test/XMLTest.java --- a/test/XMLTest.java Sat Oct 18 21:28:17 2008 +0900 +++ b/test/XMLTest.java Sun Oct 19 16:54:37 2008 +0900 @@ -26,19 +26,19 @@ session.addEditor(editor2); SessionList sessionlist = new SessionList(); - sessionlist.setMaxHost("naha.ie.u-ryukyu.ac.jp"); + //sessionlist.setMaxHost("naha.ie.u-ryukyu.ac.jp"); sessionlist.addSession(session); /*** SessionList から XML へ ***/ //SessionXMLEncoder encoder = new SessionXMLEncoder(sessionlist.getList()); - SessionXMLEncoder encoder = new SessionXMLEncoder(sessionlist); - System.out.println(encoder.sessionListToXML()); + SessionXMLEncoder encoder = new SessionXMLEncoder(); + System.out.println(encoder.sessionListToXML(sessionlist)); /*** XML から SessionList へ ***/ - SessionXMLDecoder decoder = new SessionXMLDecoder(); - String t1 = encoder.sessionListToXML(); + String t1 = encoder.sessionListToXML(sessionlist); System.out.println(t1); SessionList sessionlist2; + SessionXMLDecoder decoder = new SessionXMLDecoder(); try { sessionlist2 = decoder.decode(t1); } catch (Exception e) { @@ -47,11 +47,10 @@ /*** SessionList から XML へ ***/ //SessionXMLEncoder encoder2 = new SessionXMLEncoder(sessionlist2.getList()); - SessionXMLEncoder encoder2 = new SessionXMLEncoder(sessionlist2); - System.out.println(encoder2.sessionListToXML()); + System.out.println(encoder.sessionListToXML(sessionlist2)); /*** TestSAX ***/ - String[] string = {encoder2.sessionListToXML(),}; + String[] string = {encoder.sessionListToXML(sessionlist2),}; TestSax.main(string); } }