Mercurial > hg > RemoteEditor > REPSessionManager
view rep/Session.java @ 452:d0d2449000f5
checkAck
author | one |
---|---|
date | Thu, 23 Sep 2010 21:19:28 +0900 |
parents | 795ef563f2a0 |
children | 7420dea70dd7 |
line wrap: on
line source
package rep; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import rep.channel.REPSocketChannel; import rep.handler.Editor; import rep.handler.REPNode; import rep.handler.Forwarder; public class Session extends HashMap<Integer,REPNode> { /** * Editor Session * contains interacting editors * accessed by eid. There is one masterEditor which * has a file name (is a sessionName). * * maintain connection among handlers (Dispatcher, * Forwarder, Editor). * first->editor->editor...->last * first may equal to the last. When a session is * created, first equals the last. */ private static final long serialVersionUID = 1L; private REPNode masterEditor; private int sessionID; private String sessionName; // isOnwer means this session is owner of an active channels(forwarders). private boolean isOwner = false; private REPNode first; private REPNode last; public Session(int sid, String name, REPNode editor) { this(sid, editor); sessionName = name; } public Session(int sid, REPNode master) { sessionID = sid; if (master!=null) { // we have a master masterEditor = last = master; master.setSID(sid); put(master.eid,master); if(master.channel!=null) { // master is a real connected editor first = master; masterEditor.setNext(masterEditor); isOwner = true; } } } /* * どこにlocal editorを入れても良いのだが、まとめた方が良いか? */ public void addForwarder(REPNode editor) { // add a forwarder and connect this to the session editor.setSID(sessionID); editor.setNext(last.getNextForwarder()); last.setNext(editor); last = editor; put(editor.eid,editor); isOwner = true; if(first==null) first = editor; // printSessionDetail(); } public void addEditor(Editor editor) { // add a not-connected editor in a sassion // the editor is in the outside of this manager editor.setSID(sessionID); put(editor.eid,editor); } public Collection<REPNode> getEditorList() { return values(); } public int getSID() { return sessionID; } public REPNode getOwner() { return masterEditor; } public String getName() { return sessionName; } /* * Remove and disconnect a forwarder from the session */ public boolean deleteEditor(REPSocketChannel<REPCommand> channel) { // this is fanatic, one channel may have multiple sessions, but // a session should have only one channel that is one editor. // REPNode e = getEditor(channel); // if (e!=null) { unconnect((Forwarder)e); remove(e); } is Ok. LinkedList<REPNode> toBeRemoved = new LinkedList<REPNode>(); for (REPNode e:values() ) { if (e.getChannel()==channel) { unconnect((Forwarder)e); // we cannot directly remove this because of the concurrent access toBeRemoved.add(e); } } for(REPNode e:toBeRemoved) { remove(e); } return !toBeRemoved.isEmpty(); } public boolean deleteForwarder(Forwarder editor) { unconnect(editor); return remove(editor)!=null; } /* * Clear connection of a forwarder. The rest of the forwarders in this * session have to be connected properly. */ private void unconnect(Forwarder e) { boolean hasOwner = false; for(REPNode e1:values()) { Forwarder f = (Forwarder)e1; if(f.next==e) { f.next=e.next; } else { if (f.channel!=null) hasOwner=true; } } if(first==e) first=null; if(masterEditor==e) masterEditor=null; isOwner = hasOwner; } public void setSID(int sid) { sessionID = sid; } public boolean hasOwner() { return isOwner; } public Editor getEditor(REPSocketChannel<REPCommand> channel) { for(REPNode editor : values()){ if(editor.getChannel() == channel) { return (Editor)editor; } } return null; } /** * Start closing protocol * not yet implemented. Use quit instead. */ public void closeSession() { REPNode f = first; if (f!=null) { REPCommand command = new REPCommand(REP.REPCMD_CLOSE, sessionID, REP.SM_EID.id, 0, 0, ""); f.send(command); } } public REPNode getForwarder(REPSocketChannel<REPCommand> channel) { REPNode f = first; while(f.channel!=channel) f = f.next; ServerMainLoop.logger.writeLog("getFirstForwarder="+f.next+"=>"+f.next.channel); return f.next; } /** * @param manager * * remove all editors in this session from our manager. */ public void remove(SessionManager manager) { for(REPNode editor : values()){ if(editor.getChannel() !=null) unconnect((Forwarder)editor); manager.editorList.remove(editor); } } /** * @param s * * Merge editors from UPDATED session. Only dummy editors * outside of this manager to be add. */ public void merge(Session s) { for(REPNode editor : s.values()){ REPNode mine = get(editor.eid); if (mine==null) { put(editor.eid,editor); } else { // update editor status mine.merge(editor); } } } @Override public String toString() { String s = super.toString(); return s+" sid="+sessionID+" "+sessionName+" master="+ ((masterEditor==null)?"null":masterEditor.toString()); } public void setName(String string) { sessionName = string; } public void setFirstForwarder(REPNode f) { f.setSID(sessionID); put(f.eid,f); f.setNext(f); first = last = f; } public void printSessionDetail() { REPNode f = first; if (f==null) return; String log = "Session Detail "; while (f!=null) { log += ","+f+"="+f.channel+"->"+f.next; f = f.next; if (f==first) { log += "*"; break; } } ServerMainLoop.logger.writeLog(log); } }