changeset 386:bba62c4ac323

sync-option
author one@firefly.cr.ie.u-ryukyu.ac.jp
date Mon, 10 Nov 2008 22:19:34 +0900
parents 1fca50ce3508
children 6f356d160e58
files Todo rep/SessionManager.java rep/handler/Dispatcher.java rep/handler/Editor.java rep/handler/Forwarder.java rep/handler/REPNode.java rep/xml/SessionXMLDecoder.java test/Text.java test/XMLTest.java test/sematest/TestEditor.java
diffstat 10 files changed, 136 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/Todo	Mon Nov 10 22:18:14 2008 +0900
+++ b/Todo	Mon Nov 10 22:19:34 2008 +0900
@@ -1,7 +1,18 @@
+Fri Oct 24 19:00:50 JST 2008
+	XML に editor がselectされているかどうかのflagがあった方が良い。
+	現状では、update はなんにも役に立たない。
+	
+Thu Oct 23 10:31:58 JST 2008
+
+Todo: (kono)
+UPDATE/UPDATE_ACKが出ない。
+	Done: Fri Oct 24 19:00:50 JST 2008
+	
 Wed Oct 22 19:53:59 JST 2008
 
 Todo: (kono)
 やっぱり、END_MERGEが繰り返し出るバグがあるらしい。
+    Done: Thu Oct 23 10:12:27 JST 2008 merge confilict 時にmode setを忘れてました。
 
 Wed Oct 22 02:31:27 JST 2008
 
@@ -261,6 +272,8 @@
 Todo:
 Optimizerを使った場合のテスト (kono)
 行番号0があるとだめらしい。
+	Done: (takano) Thu Oct 23 13:05:52 JST 2008
+	
 
 Todo:
 manager.remove(editor) の動作のタイミング、 channel closeの扱い
@@ -282,7 +295,8 @@
 	Done:Sat Oct 11 22:28:49 JST 2008
 
 Todo:
-SessionManager の向うにあるeditorにREPCommandを送るコードがない。Editor 扱いしても良いが、Editor が複雑すぎるので、それは好ましくない。Editor に nextChannelを持たせるのが良いか? (kono)
+SessionManager の向うにあるeditorにREPCommandを送るコードがない。Editor 扱いしても良いが、
+Editor が複雑すぎるので、それは好ましくない。Editor に nextChannelを持たせるのが良いか? (kono)
     Done: Forwarder を作った
 
 Todo:
@@ -305,7 +319,8 @@
       Done: Mon Oct  6 16:40:38 JST 2008 (kono)
 
 Todo: SessionMnager のmessageをREPLogger baseに書き換える。 (kono)
-
+	  Done: Thu Oct 23 13:05:52 JST 2008
+	  
 Wed Oct  1 15:35:44 JST 2008
 
 Todo: SessionManager 複数のコマンドをまとめてeditorに送るとdead lockする
--- a/rep/SessionManager.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/SessionManager.java	Mon Nov 10 22:19:34 2008 +0900
@@ -61,6 +61,8 @@
 	private REPNode sm_join_channel;
 	// Routing table for session and session manager.
 	private RoutingTable routingTable = new RoutingTable(this);
+	// sync option
+	public boolean sync = true;
 	
 	static public REPLogger logger = REPLogger.singleton();
 	
@@ -169,7 +171,11 @@
 
 	private void selectSession0(int sid, Session session, int eid, REPNode editor) {
 		if (editor.isDirect()&&editor.getEID()==eid) {
-			selectSession(sid, session, editor.getEID(), editor);
+			REPCommand command = new REPCommand();
+			command.setSID(sid);
+			command.setEID(eid);
+			command.setString(session.getName());
+			editor.selectSession(command, session);
 		} else {
 			// we don't have this editor, search the editor first.
 			REPNode next = routingTable.toSessionManager(getSMID(eid));
@@ -183,35 +189,7 @@
 		}
 	}
 
-	/*
-	 * Select Session Protocol handler
-	 *    called from GUI or incoming SMCMD_SELECT command.
-	 */
-	private void selectSession(int sid, Session session, int eid, REPNode editor) {
-		if(session.hasOwner()){
-			// we have selected session.
-			REPCommand sendCommand = new REPCommand();
-			if (editor.isDirect()&&editor.getEID()==eid) {
-				// Found directly connected joined editor. Send join_ack().
-				session.addForwarder(editor);
-				sendUpdate(session.getSID());
-				sendCommand.setCMD(REP.SMCMD_JOIN_ACK);
-			} else {
-				// We have a session, but joined editor is on the other sm.
-				// SELECT_ACK is sent to the session ring to
-				// find out the joined editor.
-				sendCommand.setCMD(REP.SMCMD_SELECT_ACK);
-			}
-			sendCommand.setSID(sid);
-			sendCommand.string = session.getName();
-			sendCommand.setEID(eid);
-			editor.send(sendCommand);
-		}else {
-			forwardSelect(sid, session, eid, editor);
-		}
-	}
-
-	private void forwardSelect(int sid, Session session, int eid,
+	public void forwardSelect(int sid, Session session, int eid,
 			REPNode editor) {
 		REPNode next;
 		// session searching continue...
@@ -241,11 +219,16 @@
 	/*
 	 * Create and send UPDATE command.
 	 */
-	private void sendUpdate(int sid) {
+	public void sendUpdate(int sid) {
 		REPCommand command = makeREPCommandWithSessionList(REP.SMCMD_UPDATE);
 		command.setSID(sid);
 		command.setEID(REP.SM_EID.id);
-		smList.sendToMaster(command);
+		if (isMaster()) {
+			command.setCMD(REP.SMCMD_UPDATE_ACK);
+			smList.sendToSlaves(command);
+		} else {
+			smList.sendToMaster(command);
+		}
 	}
 
 	/*
@@ -403,7 +386,7 @@
 			// shared among sessions.
 			REPNode f = createSessionForwarder(command.sid, forwarder);
 			session.addForwarder(f); // f.next is set up here.
-			selectSession(command.sid, session, command.eid, forwarder);
+			forwarder.selectSession(command,session);
 		}
 			break;
 		case SMCMD_SELECT_ACK:
@@ -435,20 +418,17 @@
 			}
 		}
 		break;
-	
+
+		case SMCMD_SYNC_ACK:
+			break;
+			
 		case SMCMD_SM_JOIN_ACK:				
 			send_sm_join_ack(command.eid, command.sid, command);
 			break;
 	
 		case SMCMD_UPDATE:
-			if (!isMaster()) {
-				command.setString(mergeUpdate(command));
-				// 上に知らせる
-				smList.sendToMaster(command);
-				break;
-			}
-			// fall thru
-			command.setCMD(REP.SMCMD_UPDATE_ACK);
+			sendUpdate(command.sid);
+			break;
 		case SMCMD_UPDATE_ACK:
 			command.setString(mergeUpdate(command));
 			// 下に知らせる
@@ -506,6 +486,12 @@
 				// select したeditor を見つけた
 				command.cmd=REP.SMCMD_JOIN_ACK;
 				editor.send(command);
+				sendUpdate(command.sid);
+				if (sync) {
+					REPCommand sync = new REPCommand(command);
+					sync.setCMD(REP.SMCMD_SYNC);
+					editor.sendSync(sync);
+				}
 				return;
 			}
 		}
--- a/rep/handler/Dispatcher.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/handler/Dispatcher.java	Mon Nov 10 22:19:34 2008 +0900
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 
-import rep.PacketSet;
 import rep.REPCommand;
 import rep.ServerMainLoop;
 import rep.Session;
@@ -77,11 +76,5 @@
 		return false;
 	}
 
-	@Override
-	public void send(REPCommand command) {
-		assert(command!=null);
-		assert(channel!=null);
-		REPCommand c = new REPCommand(command);
-		manager.addWriteQueue(new PacketSet(channel,null,  c));
-	}
+
 }
--- a/rep/handler/Editor.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/handler/Editor.java	Mon Nov 10 22:19:34 2008 +0900
@@ -171,6 +171,13 @@
 			}
 			break;
 		}
+		
+		case SMCMD_SYNC:
+			if (isMaster()) 
+				send(receivedCommand);
+			else
+				next.send(receivedCommand);
+			
 		case SMCMD_QUIT:
 		{
 			next.send(receivedCommand);
@@ -222,6 +229,7 @@
 	public boolean isMaster() {
 		return mode==REP.SMCMD_PUT;
 	}
+
 	
 	/* Handle special case first, usually these cases
 	 * are handled in the next Editor in a session manager, but 
@@ -247,11 +255,4 @@
 		send(command);
 	}
 
-	@Override
-	public void send(REPCommand command) {
-		assert(command!=null);
-		assert(channel!=null);
-		REPCommand c = new REPCommand(command);
-		manager.addWriteQueue(new PacketSet(channel,null,  c));
-	}
 }
--- a/rep/handler/Forwarder.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/handler/Forwarder.java	Mon Nov 10 22:19:34 2008 +0900
@@ -5,6 +5,7 @@
 import rep.PacketSet;
 import rep.REP;
 import rep.REPCommand;
+import rep.Session;
 import rep.SessionManager;
 import rep.channel.REPLogger;
 import rep.channel.REPSelectionKey;
@@ -93,5 +94,35 @@
 		return false;
 	}
 
+	public void selectSession(REPCommand sendCommand,Session session) {
+		if(session.hasOwner()){
+			// we have a selected session.
+			if (isDirect()&&getEID()==sendCommand.eid) {
+				// Found directly connected joined editor. Send join_ack().
+				// we have one more point to send JOIN_ACK to the editor.
+				session.addForwarder(this);
+				manager.sendUpdate(session.getSID());
+				sendCommand.setCMD(REP.SMCMD_JOIN_ACK);
+				if (manager.sync) {
+					REPCommand sync = new REPCommand(sendCommand);
+					sync.setCMD(REP.SMCMD_SYNC);
+					sendSync(sync);
+				}
+			} else {
+				// We have a session, but joined editor is on the other sm.
+				// SELECT_ACK is sent to the session ring to
+				// find out the joined editor.
+				sendCommand.setCMD(REP.SMCMD_SELECT_ACK);
+			}
+			sendCommand.string = session.getName();
+			send(sendCommand);
+		}else {
+			manager.forwardSelect(sid, session, eid, this);
+		}
+	}
 
+	
+	
+	
+	
 }
\ No newline at end of file
--- a/rep/handler/REPNode.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/handler/REPNode.java	Mon Nov 10 22:19:34 2008 +0900
@@ -4,6 +4,7 @@
 
 import rep.REP;
 import rep.REPCommand;
+import rep.Session;
 import rep.channel.REPSelectionKey;
 import rep.channel.REPSocketChannel;
 
@@ -103,6 +104,7 @@
 
 	public abstract void send(REPCommand command) ;
 
+	public abstract void sendWithSeq(REPCommand command) ;
 
 	public abstract void setQuit2(REPCommand receivedCommand) ;
 
@@ -114,6 +116,8 @@
 	public abstract boolean manage(REPCommand command) ;
 
 
+	public abstract void selectSession(REPCommand sendCommand,Session session) ;
+
 	public void setMode(REP cmd) {
 		mode = cmd;
 	}
@@ -136,6 +140,10 @@
 	public void setNext(REPNode f) {
 		next = f;
 	}
-	
+
 
+	public void sendSync(REPCommand sync) {
+		next.sendWithSeq(sync);
+	}
+	
 }
--- a/rep/xml/SessionXMLDecoder.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/rep/xml/SessionXMLDecoder.java	Mon Nov 10 22:19:34 2008 +0900
@@ -9,6 +9,8 @@
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -22,15 +24,13 @@
 	DocumentBuilderFactory factory;
 	DocumentBuilder builder;
 
-	public SessionXMLDecoder(String string) throws SAXException, IOException {
-		decode(string);
-	}
 
 	public SessionXMLDecoder() {
 		factory = DocumentBuilderFactory.newInstance();
 		try {
-			factory.newDocumentBuilder();
+			builder = factory.newDocumentBuilder();
 		} catch (ParserConfigurationException e) {
+			assert false;
 		}
 	}
 
@@ -65,9 +65,9 @@
 		SessionList sessionlist = new SessionList();
 		NodeList nodelistSession = element.getElementsByTagName("Session");
 		for(int i = 0; i < nodelistSession.getLength(); i++){
-			Element elementSession = (Element) nodelistSession.item(i);
-			int sid = Integer.parseInt(elementSession.getAttribute("sid"));
-			NodeList nodelistEditor = elementSession.getElementsByTagName("Editor");
+			Node elementSession = nodelistSession.item(i);
+			int sid = getIntValue(elementSession,"sid");
+			NodeList nodelistEditor = ((Element)elementSession).getElementsByTagName("Editor");
 			
 			Session session = null;
 			for(int j = 0; j < nodelistEditor.getLength(); j++){
@@ -76,7 +76,8 @@
 				Element elementEditor = (Element) nodelistEditor.item(j);
 				NodeList nodelistEditorHost = elementEditor.getElementsByTagName("host");
 				Element elementHost = (Element) nodelistEditorHost.item(0); 
-				String host = elementHost.getFirstChild().getNodeValue();
+				Node hostValue = elementHost.getFirstChild();
+				String host = hostValue==null?"":hostValue.getNodeValue();
 				
 				if(elementEditor.getChildNodes().getLength() > 2){
 					NodeList nodelistEditorFile = elementEditor.getElementsByTagName("file");
@@ -100,5 +101,18 @@
 		}
 		return sessionlist;
 	}
+
+	private int getIntValue(Node elementSession, String attrName) {
+		NamedNodeMap attr = elementSession.getAttributes();
+		Node sidNode = attr.getNamedItem(attrName);
+		int sid = Integer.parseInt(sidNode.getNodeValue());
+		return sid;
+	}
+//	
+//	private String getString(Node elementSession, String attrName) {
+//		NamedNodeMap attr = elementSession.getAttributes();
+//		Node sidNode = attr.getNamedItem(attrName);
+//		return sidNode.getNodeValue();
+//	}
 	
 }
--- a/test/Text.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/test/Text.java	Mon Nov 10 22:19:34 2008 +0900
@@ -28,13 +28,13 @@
 		return strList.remove(i);
 	}
 	public String replace(int i, String str){
-		assert 0<i && i<strList.size();
+		assert 0<=i && i<strList.size();
 		String replaced = strList.get(i);
 		strList.set(i, str);
 		return replaced;
 	}
 	public String get(int i){
-		assert 0<i && i<strList.size();
+		assert 0<=i && i<strList.size();
 		return strList.get(i);
 	}
 	public String edit(REPCommand cmd){
--- a/test/XMLTest.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/test/XMLTest.java	Mon Nov 10 22:19:34 2008 +0900
@@ -1,5 +1,9 @@
 package test;
 
+import java.io.IOException;
+
+import org.xml.sax.SAXException;
+
 import rep.Session;
 import rep.SessionList;
 import rep.handler.Editor;
@@ -41,9 +45,12 @@
 		SessionXMLDecoder decoder = new SessionXMLDecoder();
 		try {
 			sessionlist2 = decoder.decode(t1);
-		} catch (Exception e) {
+		} catch (SAXException e) {
+			return;
+		} catch (IOException e) {
 			return;
 		}
+
 		
 		/*** SessionList から XML へ ***/
 		//SessionXMLEncoder encoder2 = new SessionXMLEncoder(sessionlist2.getList());
--- a/test/sematest/TestEditor.java	Mon Nov 10 22:18:14 2008 +0900
+++ b/test/sematest/TestEditor.java	Mon Nov 10 22:19:34 2008 +0900
@@ -49,7 +49,7 @@
 		super(name);
 		LinkedList<REPCommand>cmdList = new LinkedList<REPCommand>();
 		String[] txts = {
-			"aaa", "bbb", "ccc", "ddd", "eee",
+			"aaa", "bbb", // "ccc", "ddd", "eee",
 		};	
 		port = _port;
 		semaIP = new InetSocketAddress(_host, _port);
@@ -82,6 +82,8 @@
 		if (master) {
 			this.master=true;
 			text = new Text(txts);
+		} else {
+			text = new Text(new String[0]);
 		}
 	}
 
@@ -195,8 +197,9 @@
 				assert(false);
 			}
 		} else {
-			// no more command to send
-			timeout = 0;
+			if(syncCounter==0)
+			// no more command to send, and we don't have syncCounter
+				timeout = 0;
 		}
 	}
 
@@ -300,8 +303,11 @@
 			 // start contents sync with newly joined editor
 			 cmd.cmd = REP.SMCMD_SYNC_ACK;
 			 forwardCommand(cmd);
-			 if (cmd.eid==eid) 
+			 //if (cmd.eid==eid) {
+			 if (master) {
 				 syncCounter = 1;
+				 timeout = 1;
+			 }
 			 break;
 		 default:
 			 assert(false);