changeset 319:dfed28488274

*** empty log message ***
author kono
date Thu, 09 Oct 2008 17:26:55 +0900
parents dc57e24ea3df
children 83790b8b8174
files rep/Editor.java rep/EditorPlus.java rep/Forwarder.java rep/RPanel.java rep/Session.java rep/SessionList.java rep/SessionManager.java rep/handler/REPSessionManagerHandler.java rep/xml/SessionXMLEncoder.java test/sematest/TestSessionManager.java
diffstat 10 files changed, 256 insertions(+), 270 deletions(-) [+]
line wrap: on
line diff
--- a/rep/Editor.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/Editor.java	Thu Oct 09 17:26:55 2008 +0900
@@ -2,19 +2,13 @@
 
 import java.util.LinkedList;
 import java.util.List;
-
 import rep.channel.REPSocketChannel;
 import rep.handler.PacketSet;
 import rep.optimizers.*;
 import rep.translater.TranslaterImp1;
 
 public class Editor extends Forwarder {
-	private int sid = -1 ;      // globally unique session id
-	private int seq = 0;
 
-	//private Forwarder next;
-	private String host;
-	private String file;
 	private TranslaterImp1 translater;
 	private List<REPCommand> sentList = new LinkedList<REPCommand>();
 	// REPCommands we are going to send to the next editor
@@ -35,8 +29,8 @@
 
 	public Editor(SessionManager manager,int editorNo, REPSocketChannel<REPCommand> channel){
 		this(manager,false,editorNo);
-		myChannel = channel;
-		setHostAndPort(myChannel);
+		this.channel = channel;
+		setHostAndPort(channel);
 	}
 
 	public void translate(Forwarder nextEditor, REPCommand command){
@@ -105,6 +99,7 @@
 		return false;
 	}
 
+	@Override
 	public void setQuit2(REPCommand cmd) {
 		if (sentList.size()==0) {
 			send(cmd);
@@ -120,14 +115,6 @@
 		
 	}
 
-	public void setHost(String host){
-		this.host = host;
-	}
-
-	
-	public String getHost(){
-		return host;
-	}
 
 
 
@@ -141,15 +128,6 @@
 		return ("Editor eid="+eid+" sid="+sid+" " + host  + ":" + file);
 	}
 
-	public String getName() {
-		return file;
-	}
-
-	public void setName(String string) {
-		file = string;
-	}
-
-
 	public boolean isMerging() {
 		return translater.isMerging();
 	}
@@ -159,9 +137,6 @@
 	public void setSID(int sessionID) {
 		sid   = sessionID;
 	}
-	public int seq() {
-		return seq++;
-	}
 	
 	/**
 	 * Sent optimized merged command list
@@ -185,4 +160,38 @@
 		send(mergeEnd);
 	}
 
+	@Override
+	public boolean manage(REPCommand receivedCommand) {
+	
+		switch(receivedCommand.cmd){
+		// Editor Command
+		
+		case REPCMD_DELETE:
+		case REPCMD_INSERT:
+		case REPCMD_NOP:
+		{
+			translate(next, receivedCommand);
+			break;
+		}
+		
+		case SMCMD_QUIT:
+		{
+			next.send(receivedCommand);
+			break;
+		}
+		case SMCMD_QUIT_2:
+		{
+			Forwarder editor1 = getNextForwarder();
+			// don't send quit2 to the editor until all pending
+			// merge is processed.
+			editor1.setQuit2(receivedCommand);
+			break;
+		}
+		default:
+			return false;
+		}
+		return true;
+	}
+	
+	
 }
--- a/rep/EditorPlus.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/EditorPlus.java	Thu Oct 09 17:26:55 2008 +0900
@@ -2,22 +2,65 @@
 
 import rep.channel.REPSocketChannel;
 
-public class EditorPlus<P> {
+public class EditorPlus {
 
-	private int eid;
-	private REPSocketChannel<P> channel;
-	public EditorPlus(int eid, REPSocketChannel<P> channel) {
+	public int eid; // unique in a session, eid==0 master
+	public int sid=-1; // globally unique
+	public String host;
+	public String file;
+	public REPSocketChannel<REPCommand> channel;
+	
+	public EditorPlus() {
+		
+	}
+	
+	public EditorPlus(int eid, REPSocketChannel<REPCommand> channel) {
 		this.eid = eid;
 		this.channel = channel;
 	}
+
+	public String getName() {
+		return file;
+	}
+
+	public void setName(String string) {
+		file = string;
+	}
+
+
+	public void setSID(int sid) {
+		this.sid = sid;
+	}
+	
+	public int getSID() {
+		return sid;
+	}
+	
 	public String toString(){
 		return ("Editor:" + eid);
 	}
+
+	public void setEID(int eid) {
+		this.eid = eid;
+	}
+	
 	public int getEID(){
 		return eid;
 	}
-	public REPSocketChannel<P> getChannel(){
+
+	public void setHost(String host){
+		this.host = host;
+	}
+
+	
+	public String getHost(){
+		return host;
+	}
+	public REPSocketChannel<REPCommand> getChannel(){
 		return channel;
 		
 	}
+	public void setChannel(REPSocketChannel<REPCommand> channel) {
+		this.channel = channel;		
+	}
 }
--- a/rep/Forwarder.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/Forwarder.java	Thu Oct 09 17:26:55 2008 +0900
@@ -4,9 +4,9 @@
 import rep.channel.REPSocketChannel;
 import rep.handler.PacketSet;
 
-public class Forwarder {
-	int eid;            // unique id in a session
-	REPSocketChannel<REPCommand> myChannel;
+public class Forwarder extends EditorPlus {
+	int seq = 0;
+	Forwarder next;
 	// REPCommands we sent to the next editor
 	final int limit=100;
 	REPLogger ns = REPLogger.singleton();
@@ -16,29 +16,38 @@
 		this.manager = manager;
 	}
 
-	public int getEID() {
-		return eid;
-	}
-
-	public void setEID(int eid) {
-		this.eid = eid;
+	public int seq() {
+		return seq++;
 	}
 	
 	public void send(REPCommand command) {
 		assert(command!=null);
-		manager.addWriteQueue(new PacketSet(myChannel, null, command));
+		manager.addWriteQueue(new PacketSet(channel, null, command));
 	}
 	
 	public REPSocketChannel<REPCommand> getChannel() {
-		return myChannel;
+		return channel;
 	}
 	
 	public void setChannel(REPSocketChannel<REPCommand> channel) {
-		myChannel = channel;
+		this.channel = channel;
 	}
 
 	public void setQuit2(REPCommand cmd) {
 		send(cmd);
 	}
 
+	public void setNext(Forwarder next) {
+		this.next = next;
+	}
+	
+	public Forwarder getNextForwarder() {
+		return next;
+	}
+
+	public boolean manage(REPCommand command) {
+		send(command);
+		return true;
+	}
+
 }
\ No newline at end of file
--- a/rep/RPanel.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/RPanel.java	Thu Oct 09 17:26:55 2008 +0900
@@ -40,7 +40,7 @@
 	private DefaultTableModel s_tableModel = new DefaultTableModel(session_column, 0);
 	private DefaultTableModel e_tableModel = new DefaultTableModel(editor_column, 0);
 	//LinkedList<SessionPlus> s_list = new LinkedList<SessionPlus>();
-	LinkedList<EditorPlus<REPCommand>> e_list = new LinkedList<EditorPlus<REPCommand>>();
+	LinkedList<EditorPlus> e_list = new LinkedList<EditorPlus>();
 	private String s_host;
 	private String s_port;
 	private String s_file;
--- a/rep/Session.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/Session.java	Thu Oct 09 17:26:55 2008 +0900
@@ -6,13 +6,14 @@
 
 public class Session {
 	private Forwarder masterEditor;
-	private Forwarder next;
 	private int sessionID;
 	private String sessionName;
-	private LinkedList<Editor> editorList = new LinkedList<Editor>();
+	private LinkedList<EditorPlus> editorList = new LinkedList<EditorPlus>();
 	private boolean isOwner = false;
+	private int eidSeed = 0;
+	private Forwarder firstForwarder;
 	
-	public Session(int sid, String name, Editor editor) {
+	public Session(int sid, String name, Forwarder editor) {
 		this(sid, editor);
 		sessionName = name;
 	}
@@ -20,20 +21,33 @@
 		masterEditor = editor;
 		this.sessionID = 0;
 		this.sessionName = editor.getName();
+		if(editor.channel!=null) firstForwarder = editor;
 	}
 
-	public Session(int sid, Editor editor) {
+	public Session(int sid, Forwarder editor) {
 		sessionID = sid;
 		masterEditor = editor;
 		editorList.add(editor);
+		if(editor.channel!=null) firstForwarder = editor;
 	}
+	
 	public void addEditor(SessionManager manager,int editorID, REPSocketChannel<REPCommand> channel) {
-		editorList.add(new Editor(manager,editorID, channel));
+		Editor editor =new Editor(manager,editorID, channel);
+		addForwarder(editor);
 	}
-	public LinkedList<Editor> getEditorList() {
-		if(editorList == null) System.out.println("null!");  
+	
+	public void addForwarder(Forwarder forwarder) {
+		Forwarder last = (Forwarder)editorList.getLast();
+		forwarder.setNext(last.getNextForwarder());
+		last.setNext(forwarder);
+		editorList.add(forwarder);
+		if(firstForwarder==null) firstForwarder = forwarder;
+	}
+	
+	public LinkedList<EditorPlus> getEditorList() {
 		return editorList;
 	}
+	
 	public String toString(){
 		return sessionName;
 	}
@@ -46,19 +60,26 @@
 	public String getName() {
 		return sessionName;
 	}
-	public void addEditor(Editor editor) {
-		int eid = editorList.size();
-		editor.setEID(eid);
-		editor.setSID(sessionID);
-		editorList.add(editor);
+	
+	public int newEid() {
+		int eid=0;
+		boolean flag = true;
+		while(flag) {
+			eid=eidSeed++;
+			for(EditorPlus e:editorList) {
+				if(!(flag = (eid!=e.eid))) break;
+			}
+		}
+		return eid;
 	}
 	
 	public boolean deleteEditor(REPSocketChannel<REPCommand> channel) {
 		boolean flag = false;
 
-	    for (Iterator<Editor> it = editorList.iterator();it.hasNext(); ) {
-	        Forwarder e = it.next();
+	    for (Iterator<EditorPlus> it = editorList.iterator();it.hasNext(); ) {
+	        Forwarder e = (Forwarder)it.next();
 			if (e.getChannel()==channel) {
+				unconnect(e);
 				it.remove(); // to avoid concurrent modification
 				flag = true;
 			}
@@ -66,6 +87,17 @@
 		return flag;
 	}
 	
+	private void unconnect(Forwarder e) {
+		for(EditorPlus e1:editorList) {
+			Forwarder f = (Forwarder)e1;
+			if(f.next==e) 
+				f.next=e.next;
+		}
+		if(firstForwarder==e) firstForwarder=null;
+		if(masterEditor==e) masterEditor=null;
+		// if no masterEditor we should delete session also...
+	}
+	
 	public void setSID(int sid) {
 		sessionID = sid;
 	}
@@ -73,62 +105,44 @@
 	public boolean hasOwner() {
 		return isOwner;
 	}
+	
 	public void hasOwner(boolean b) {
 		isOwner = true;
 	}
-	public void sendToEditor(REPCommand repCmd) {
-		for(Forwarder editor : editorList){
-			editor.getChannel().write(repCmd);
-		}
-	}
+	
 	public Editor getEditor(REPSocketChannel<REPCommand> channel) {
-		for(Editor editor : editorList){
-			if(editor.getChannel() == channel) return editor;
+		for(EditorPlus editor : editorList){
+			if(editor.getChannel() == channel) {
+				return (Editor)editor;
+			}
 		}
 		return null;
 	}
 
 	
 	Forwarder getNextEditor(Forwarder editor) {
-		int eid = editor.getEID();
-		int neid = (eid+1)%editorList.size();
-		Forwarder nextEditor = editorList.get(neid);
-		return nextEditor;
-	}
-	public Forwarder getPrevEditor(Forwarder editor) {
-		int eid = editor.getEID();
-		int peid = (eid + editorList.size() - 1)%editorList.size();
-		Forwarder prevEditor = editorList.get(peid);
-		return prevEditor;		
+		return editor.getNextForwarder();
 	}
+	
 	public void closeSession() {
-		REPCommand command = new REPCommand();
-		command.setCMD(REP.REPCMD_CLOSE);
-		for(Forwarder editor : editorList){
-			command.setEID(editor.getEID());
-			editor.send(command);
-		}
-	}
-	public void sendToNextEditor(REPSocketChannel<REPCommand>channel,REPCommand command) {
-		Forwarder next = getNextEditor(getEditor(channel));
-		next.send(command);
+		EditorPlus e = editorList.getFirst();
+		Forwarder first = (Forwarder)e;
+		REPCommand command = new REPCommand(REP.REPCMD_CLOSE, sessionID, REP.SM_EID.id, 0, 0, "");
+		if (first!=null)
+			first.send(command);
 	}
 	
-	public void setForwarder(Forwarder next) {
-		this.next = next;
+
+	public boolean deleteForwarder(Forwarder editor) {
+		unconnect(editor);
+		return editorList.remove(editor);
 	}
 	
-	/**
-	 * Dispatch REPCommand in this session
-	 * @param eid
-	 * @return
-	 */
-	public Forwarder getForwarder(int eid) {
-		Forwarder f = editorList.get(eid);
-		if (f==null) return next;
-		return f;
+	public Forwarder getFirstForwarder() {
+		return firstForwarder;
 	}
-	public boolean deleteForwarder(Forwarder editor) {
-		return editorList.remove(editor);
+	
+	public void addEditor(Editor editor) {
+		editorList.add(editor);
 	}
 }
--- a/rep/SessionList.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/SessionList.java	Thu Oct 09 17:26:55 2008 +0900
@@ -8,15 +8,11 @@
 
 public class SessionList {
 	
-//	Hashtable<Integer, Session> session3 = new Hashtable<Integer, Session>();
 	LinkedList<Session> sessionLinkedList = new LinkedList<Session>();
 	LinkedList<String> stringlist = new LinkedList<String>();
 	private int sessionID = 0;
 	private int editorCount = 0;
-
-	private boolean channelequals = false;
 	private String maxHost;
-	//private TranslaterImp1 translater;
 	
 	public SessionList(){
 		makeDefaultSession();
@@ -27,8 +23,6 @@
 	}
 	
 	public void makeDefaultSession(){
-//		session3.put(0, new Session(0, null, null));
-//		session4.add(0, new Session(0, null, null));
 	}
 
 	public int getEditorNumber() {
@@ -42,69 +36,26 @@
 
 	public int addSession(REPSocketChannel<REPCommand> channel, String string) {
 		sessionID++;
-//		session3.put(sessionID, new Session(sessionID, string, channel));
-//		sessionLinkedList.add(new Session(sessionID, string, channel));
 		return sessionID; 
 		
 	}
 
 	public void addEditor(SessionManager manager,REPSocketChannel<REPCommand> channel, int sid, REPCommand repCmd) {
 		int editorID = repCmd.eid;
-//		if(session3.get(sid) == null) System.out.println("ぬるぽ!");
-//		session3.get(sid).addEditor(editorID, channel);
 		sessionLinkedList.get(sid-1).addEditor(manager,editorID, channel);		//本当はforループで検索しないといけないよ。
 	}
 
-//	public int getSessionID(SocketChannel channel) {
-//		return 0;
-//	}
-
 	public int getNumberOfEditor() {
 		editorCount++;
 		return editorCount;
 	}
 
-	public void sendCmd(REPSocketChannel<REPCommand> channel2, REPCommand repCmd) {
-//		LinkedList <Editor> editorList = session3.get(repCmd.sid).getEditorList();
-		LinkedList <Editor> editorList = sessionLinkedList.get(repCmd.sid).getEditorList();	//ここもforループで検索しないといけないよ。
-		for(Forwarder editor : editorList){
-			REPSocketChannel<REPCommand> channel = editor.getChannel();
-			if(channel.equals(channel2)) {
-				System.out.println("equals");
-				continue;
-			}
-			channel.write(repCmd);
-		}
-	}
-	
-	public void sendCmd(REPSocketChannel<REPCommand> channel, REPCommand repCmd, boolean ring){
-//		LinkedList <Editor> editorList = session3.get(repCmd.sid).getEditorList();
-		LinkedList <Editor> editorList = sessionLinkedList.get(repCmd.sid).getEditorList();	//ここもforループで検索しないといけないよ。
-		for(Forwarder editor : editorList){
-			REPSocketChannel<REPCommand> channel2 = editor.getChannel();
-			if(channel.equals(channel2)){
-				System.out.println("equals");
-				channelequals = true;
-			}else if(channelequals){
-				channel2.write(repCmd);
-			}
-		}
-	}
 
 	public void addSessionManager(SocketChannel channel, REPCommand repCmd) {
 		
 	}
 
-//	public void sendAddedSession(REPCommand repCmd) {
-//		repCmd.setCMD(REP.SMCMD_SM_JOIN);
-//		REPPacketSend repSend = new REPPacketSend(smchannel);
-//	}
-
 	public String getSessionList() {
-//		if (session3 != null) {
-//			System.out.println(session3.toString());
-//			return session3.toString();
-//		}
 		if (sessionLinkedList != null) {
 			System.out.println(sessionLinkedList.toString());
 			return sessionLinkedList.toString();
@@ -114,20 +65,14 @@
 
 
 	public void addEditor(SessionManager manager,REPSocketChannel<REPCommand> editorChannel, int sid, int eid) {
-//		session3.get(sid).addEditor(eid, editorChannel);
 		sessionLinkedList.get(sid-1).addEditor(manager,eid, editorChannel);
 	}
 
 	public void sendSelect(int sid) {
-//		SocketChannel channel = session3.get(sid).getMaster().getChannel();
 		REPSocketChannel<REPCommand> channel = sessionLinkedList.get(sid-1).getOwner().getChannel();
 		channel.write(new REPCommand(REP.SMCMD_SELECT, sid, 0, 0, 0, ""));
 	}
 
-	public void addSession(REPSocketChannel<REPCommand> channel, String string, int i) {
-//		tmpSessionList.add(new Session(0, string, channel));
-	}
-
 //	public String getXML() {
 ///* SessionListをXMLに書き出す。ときの形式
 // * 	<Session>
@@ -206,7 +151,6 @@
 
 	public int addSession(Session session) {
 		sessionID++;
-//		session3.put(sessionID, session);
 		session.setSID(sessionID);
 		sessionLinkedList.add(session);
 		return sessionID;
@@ -226,17 +170,14 @@
 	}
 
 	public void setMaxHost(String myHost) {
-		// TODO Auto-generated method stub
 		maxHost = myHost;
 	}
 
 	public String getMaxHost() {
-		// TODO Auto-generated method stub
 		return maxHost;
 	}
 
 	public void setList(LinkedList<Session> list) {
-		// TODO Auto-generated method stub
 		sessionLinkedList = list;
 	}
 
@@ -246,13 +187,6 @@
 		for(Session session : list){
 			session.getEditorList().get(0).setChannel(channel);
 			++i;
-			int sid = addSession(session);
-			setTranslationTable(channel, i, sid);
 		}
 	}
-
-	private void setTranslationTable(REPSocketChannel<REPCommand> channel, int i, int sid) {
-		
-	}
-
 }
--- a/rep/SessionManager.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/SessionManager.java	Thu Oct 09 17:26:55 2008 +0900
@@ -44,17 +44,17 @@
 
 public class SessionManager implements SessionManagerEventListener{
 	
-	private LinkedList<Session> sessionList;
+	LinkedList<Session> sessionList;
 	private SessionManagerGUI gui;
 	private REPSelector<REPCommand> selector;
-	private SessionManagerList smList;
-	private List<Editor> editorList;
+	SessionManagerList smList;
+	List<Editor> editorList;
 	// editorList は、sessionList に入っているeditorとは別なeditorのlistらしい。
 	private String maxHost;
 	private List<PacketSet> waitingCommandInMerge;
 	REPHandler normalHandler = new REPEditorHandler(this);
 	private BlockingQueue<SessionManagerEvent> waitingEventQueue = new LinkedBlockingQueue<SessionManagerEvent>();;
-	private String myHost;
+	String myHost;
 	private LinkedList<PacketSet> writeQueue = new LinkedList<PacketSet>();
 	private static int receive_port;
 	private static int parent_port;
@@ -201,70 +201,60 @@
 	}
 
 	public void manage(REPSocketChannel<REPCommand> channel, REPCommand receivedCommand) throws IOException {
-		if(receivedCommand == null) return;
-		//Session session;
-		REPSocketChannel<REPCommand> send = channel;
+		if (sessionManagerCommand(channel, receivedCommand)) return;
+		Session s = getSession(receivedCommand.sid);
+		Editor e = s.getEditor(channel);
+		e.manage(receivedCommand);
+	}
 
+
+	private boolean sessionManagerCommand(REPSocketChannel<REPCommand> channel,
+			REPCommand receivedCommand) throws ClosedChannelException,
+			IOException {
 		switch(receivedCommand.cmd){
 
-		// Editor Command
-		
-		case REPCMD_DELETE:
-		case REPCMD_INSERT:
-		case REPCMD_NOP:
-		{
-			// sid から Session を取得
-			Session session = getSession(receivedCommand.sid);
-			if (session==null) throw new IOException();
-			// 次のエディタへコマンドを送信する処理
-			Editor editor = session.getEditor(channel);
-			editor.translate(session.getNextEditor(editor), receivedCommand);
-			break;
-		}
-		
+		// Session Manager Command
+
 		case SMCMD_JOIN:
 		{
 			//どのSessionにも属さないエディタをリストに追加
 			//エディタとchannelは1対1 (ではない)
 			//エディタが新しくputする場合は新しくソケットを作る
 			// ここのeditorList はsessionのとは別物
-			Editor editor = new Editor(this,editorList.size(),channel);
-			editor.setHost(myHost);
-			editorList.add(editor);
-
+			Editor editor1 = new Editor(this,editorList.size(),channel);
+			editor1.setHost(myHost);
+			editorList.add(editor1);
+	
 			updateGUI();
-
+	
 		}
-
+	
 		break;
-
+	
 		case SMCMD_JOIN_ACK:
 			assert (false);
 			break;
-
+	
 		case SMCMD_PUT:
 		{
-			//エディタのリストに追加
-			Editor editor = new Editor(this,editorList.size(), channel);
-			//editorList.add(editor);
-
 			//Sessionを生成
 			int sid = sessionList.size();
-			editor = new Editor(this,0, channel);
-			editor.setHost(myHost);
-			Session session = new Session(sid, receivedCommand.string, editor);
+			Editor editor2 = new Editor(this,0, channel);
+			editorList.add(editor2);
+			editor2.setHost(myHost);
+			Session session = new Session(sid, receivedCommand.string, editor2);
 			session.hasOwner(true);
 			sessionList.add(session);
-
+	
 			updateGUI();
-
+	
 			//エディタにAckを送信
 			REPCommand sendCommand = new REPCommand(receivedCommand);
 			sendCommand.setCMD(REP.SMCMD_PUT_ACK);
-			sendCommand.setEID(editor.getEID());
+			sendCommand.setEID(editor2.getEID());
 			sendCommand.setSID(session.getSID());
-			editor.send(sendCommand);
-
+			editor2.send(sendCommand);
+	
 			//他のSessionManagerへSessionの追加を報告
 			//親に送って、親から子へ
 			SessionXMLEncoder sessionEncoder = new SessionXMLEncoder(session);
@@ -273,58 +263,56 @@
 			command.setString(sessionEncoder.sessionListToXML());
 			command.setCMD(REP.SMCMD_UPDATE);
 			smList.sendExcept(channel, command);
-
+	
 		}
-
+	
 		break;
-
+	
 		// SELECT is no longer used in a editor. Select
 		// operation is handled in Session Manager Only
 		case SMCMD_SELECT:
 		{
 			//他のSessionManagerをエディタとしてSessionに追加
-			Editor editor = new Editor(this,0,channel);
+			Forwarder next = new Forwarder(this);
+			next.setChannel(channel);
 			Session session = getSession(receivedCommand.sid);
-			session.addEditor(editor);
-
+			session.addForwarder(next);
+	
 			if(session.hasOwner()){
 				//このSessionManagerがオーナーを持っている場合、Sessionにエディタを追加し、エディタへAckを返す
 				REPCommand sendCommand = new REPCommand(receivedCommand);
 				sendCommand.setCMD(REP.SMCMD_SELECT_ACK);
-				sendCommand.setEID(editor.getEID());
-				editor.send(sendCommand);
+				sendCommand.setEID(next.getEID());
+				next.send(sendCommand);
 			}else{
 				//オーナーを持ってない場合は、オーナーを持っているSessionManagerへSELECTコマンドを中継する
 				Forwarder owner = session.getOwner();
 				owner.send(receivedCommand);
 			}
 		}
-
+	
 		break;
-
+	
 		case SMCMD_SELECT_ACK:
 		{
 			String hostport = receivedCommand.string;
-			Forwarder editor = getEditor(hostport);
-
-			if(editor != null) {
+			Forwarder editor1 = getEditor(hostport);
+	
+			if(editor1 != null) {
 				//host, port を見て、このコマンドが自分が送信したSelectコマンドのAckかどうかを判断する
 				REPCommand command = new REPCommand();
 				command.setCMD(REP.SMCMD_JOIN_ACK);
 				command.setSID(receivedCommand.sid);
 				command.setEID(receivedCommand.eid);
-				editor.send(command);
-
+				editor1.send(command);
+	
 			}else{
 				//自分が送信したコマンドでなければ、次のSessionManagerへ中継する
 				smList.sendExcept(channel, receivedCommand);
 			}
 		}
-
+	
 		break;
-
-		// Session Manager Command
-		
 		case SMCMD_SM_JOIN:
 
 		{
@@ -358,7 +346,7 @@
 			REPCommand sendCommand = new REPCommand();
 			sendCommand.setCMD(REP.SMCMD_SM_JOIN_ACK);
 			sendCommand.setString(sessionlistEncoder.sessionListToXML());
-			send.write(sendCommand);
+			channel.write(sendCommand);
 
 			//その他の SessionManager に対して SMCMD_UPDATEを 送信。
 			sendCommand = new REPCommand();
@@ -411,12 +399,13 @@
 
 		case SMCMD_UPDATE_ACK:
 		{
-			if(receivedCommand.sid > sessionList.size()){
-				Editor editor = new Editor(this,0,channel);
-				editor.setName(receivedCommand.string);
+			if(!hasSession(receivedCommand.sid)) {
+				// accept new Session
+				Forwarder editor = new Forwarder(this);
+				editor.setChannel(channel);
 
-				Session session = new Session(editor);
-				session.addEditor(editor);
+				Session session = new Session(receivedCommand.sid,receivedCommand.string,editor);
+				session.addEditor(this, session.newEid(), channel);
 
 				sessionList.add(session);
 				
@@ -447,7 +436,6 @@
 		{
 			// sid から Session を取得
 			Session session = getSession(receivedCommand.sid);
-			if (session==null) throw new IOException();
 			// マージの処理と次のエディタへコマンドを送信する処理
 			Editor editor = session.getEditor(channel);
 			if (!editor.merge(editor,receivedCommand)) {
@@ -456,33 +444,22 @@
 			}
 			break;
 		}
-		case SMCMD_QUIT:
-		{
-			Session session = getSession(receivedCommand.sid);
-			if (session==null) throw new IOException();
-			session.sendToNextEditor(channel,receivedCommand);
-			break;
+
+		default:
+			return false;
 		}
-		case SMCMD_QUIT_2:
-		{
-			Session session = getSession(receivedCommand.sid);
-			if (session==null) throw new IOException();
-			Forwarder me = session.getEditor(channel);
-			if (me==null) break; // already removed.
-			Forwarder editor = session.getNextEditor(me);
-			// don't send quit2 to the editor until all pending
-			// merge is processed.
-			editor.setQuit2(receivedCommand);
-			break;
-		}
-		default:
-			assert(false);
-			break;
-			
-		}
+		return true;
 	}
 
-	private void updateGUI() {
+	private boolean hasSession(int sid) {
+		for(Session s:sessionList) {
+			if (s.getSID()==sid) return true;
+		}
+		return false;
+	}
+
+
+	void updateGUI() {
 		//リストのコピーをGUIに渡す
 		LinkedList<Session> sList = new LinkedList<Session>(sessionList);
 		LinkedList<Editor> eList = new LinkedList<Editor>(editorList);
@@ -491,7 +468,7 @@
 		gui.invokeLater(doRun);
 	}
 
-	private Forwarder getEditor(String hostport) {
+	Forwarder getEditor(String hostport) {
 		for(Editor editor : editorList){
 			if(editor.getHost() == hostport){
 				return editor;
@@ -589,10 +566,11 @@
 			return;
 		}
 
-		session.addEditor(editor);
+
 		
 		System.out.println("SessionManager.session.hasOnwer="+session.hasOwner());
 		if(session.hasOwner()){
+			session.addForwarder(editor);
 			REPCommand sendCommand = new REPCommand();
 			sendCommand.setCMD(REP.SMCMD_JOIN_ACK);
 			sendCommand.setEID(editor.getEID());
@@ -604,8 +582,7 @@
 			editor = new Editor(this,0,channel);
 			editor.setHost(myHost);
 			session = getSession(sid);
-			session.addEditor(editor);
-			
+			session.addEditor(this,0,channel);
 			Forwarder owner = session.getOwner();
 			
 			REPCommand command = new REPCommand();
--- a/rep/handler/REPSessionManagerHandler.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/handler/REPSessionManagerHandler.java	Thu Oct 09 17:26:55 2008 +0900
@@ -31,9 +31,9 @@
 		REPCommand command = channel.read();
 		System.out.println("REPHandlerImpl.handle() : command = " + command);
 		Session s = manager.getSession(command.sid);
-		Forwarder next = s.getForwarder(command.eid);
-		if (next!=null) {
-			next.send(command);
+		Forwarder editor = s.getFirstForwarder();
+		if (editor!=null) {
+			editor.manage(command);
 		} else {
 			manager.manage(channel, command);
 		}
--- a/rep/xml/SessionXMLEncoder.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/rep/xml/SessionXMLEncoder.java	Thu Oct 09 17:26:55 2008 +0900
@@ -13,7 +13,7 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import rep.Editor;
+import rep.EditorPlus;
 import rep.Session;
 import rep.SessionList;
 
@@ -76,8 +76,8 @@
 						Element elementSession = doc.createElement("Session");
 						root.appendChild(elementSession);
 
-						LinkedList <Editor> editorlist = session.getEditorList();
-						for(Editor editor : editorlist){
+						LinkedList <EditorPlus> editorlist = session.getEditorList();
+						for(EditorPlus editor : editorlist){
 							Element elementEditor = doc.createElement("Editor");
 							elementEditor.setAttribute("eid", Integer.toString(editor.getEID()));
 							elementSession.appendChild(elementEditor);
--- a/test/sematest/TestSessionManager.java	Wed Oct 08 10:09:02 2008 +0900
+++ b/test/sematest/TestSessionManager.java	Thu Oct 09 17:26:55 2008 +0900
@@ -30,7 +30,7 @@
 	 *      master session managers using syncExec.
 	 */
 	int editorPort[] = {masterPort,masterPort};
-	boolean editorMaster[] = {true,false};
+	boolean editorMaster[] = {true,false,false};
 	SessionManagerEvent ev1[] = {
 			new SessionManagerEvent() {
 				// executed before first select();
@@ -107,7 +107,7 @@
 		 *    isSimulation=false    socket based communication mode
 		 */
 		REPServerSocketChannel.isSimulation = true;
-		TestSessionManager test = new TestSessionManager(1, 0, 2);
+		TestSessionManager test = new TestSessionManager(1, 0, 3);
 		logger.setLogLevel(5);
 		test.startTest();
 	}