# HG changeset patch
# User one
# Date 1262370023 -32400
# Node ID 622a8e15ff40dad2b63054b28037c9d0a82c8ed9
# Parent 1acc3dfde5d38899d4f092462b1b2af52a3fc978
Merge Worked ?
diff -r 1acc3dfde5d3 -r 622a8e15ff40 Test.mf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Test.mf Sat Jan 02 03:20:23 2010 +0900
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Created-By: 0.1.0 (Shinji KONO @ University of the Ryukyus)
+Main-Class: test.sematest.TestSessionManager
+
diff -r 1acc3dfde5d3 -r 622a8e15ff40 Todo
--- a/Todo Fri Jan 01 00:06:23 2010 +0900
+++ b/Todo Sat Jan 02 03:20:23 2010 +0900
@@ -1,3 +1,62 @@
+Sat Jan 2 00:02:41 JST 2010
+
+Todo:
+ writeLog に level/flag を付けるか?
+
+Selector.select() のフラグは意味がない。その後、必ず、
+selectedKeys() を調べる必要がある。これは、Simulator
+と実ソケットの動作が異なる部分。Warning とか出せないものか?
+
+確かに、Merge 変かも。unMerged を undo するのは良いが、
+sort するのは、unMerged であって、undo を付加したものではないはず。
+
+いや、それは正しく出来ている。output に先にundoを入れて、
+cmd には、そのまま残している。(順序は sort されるので関係ない)
+
+でも、sortedCmds1 に add する時に、Comparator で順序付けされて
+しまう。getPrecedence() は必要な列の切出しに使う。
+
+Self Merge case
+ E_{00} E_{12} E_{01} E_{23} E_{02} (E_{00})
+Other Merge case
+ E_{10} E_{11} E_{23} E_{01} E_{02} (Eack_{10})
+
+ack が間に入ることはない(merge で消されるから)
+original command の存在しない ack もない。
+ (あったら、エラー。無視して良い)
+ack の来ない original command は sequence エラーとなるなず。
+ (あるいは time out)
+
+ということは、getPrecedence せずに、うむを言わせず
+全部 sort すれば良いってこと? ってことは実は、E_{12}
+が来た段階で追い越せるかどうかはわかる?
+
+Ack を受け取ったら、それは、必ず先頭にあるはず。
+
+ E_{00} E_{10} E_{11} E_{23} E_{01} E_{02} (Eack_{10})
+
+とかはない。ack は追い越せないから。この間の入力は確定で、
+優先順位にしたがって順序付しsortする。次は、
+
+ E_{10} E_{11} E_{23} E_{01} E_{02} (Eack_{10})
+ E_{11} E_{23} E_{01} E_{02} E_{12} (Eack_{11})
+
+で、これは、E_{12} までをsort すれば良い。ということは、
+取れるのは最初の一個だけってこと。
+
+nop の場合は、command が着いた直後に出力されるけど、
+ack の場合は、それは出力されないで、もう一周する
+ack が流される。ack は、一つ前のエディタが出力した
+nop に相当する。
+
+この方法だと、編集コマンドの干渉を気にする必要はない。それは、
+最適化フェーズで自動的に排除される。(はず) ということは、
+getPrecedece の方で sort してやって、今の lineno の比較は
+無意味なので排除ということですね。
+
+2方向をスター型/木型に順々に処理する方法でも良いのか。
+
+
Wed Nov 26 15:15:16 JST 2008
Ring 構造なので、一部のeidtorで止まると全体が止まってしまう。
diff -r 1acc3dfde5d3 -r 622a8e15ff40 build.xml
--- a/build.xml Fri Jan 01 00:06:23 2010 +0900
+++ b/build.xml Sat Jan 02 03:20:23 2010 +0900
@@ -34,6 +34,11 @@
+
+
+
+
+
@@ -58,4 +63,4 @@
-
\ No newline at end of file
+
diff -r 1acc3dfde5d3 -r 622a8e15ff40 rep/handler/Editor.java
--- a/rep/handler/Editor.java Fri Jan 01 00:06:23 2010 +0900
+++ b/rep/handler/Editor.java Sat Jan 02 03:20:23 2010 +0900
@@ -39,6 +39,44 @@
translator = new Translator(eid,optimizer);
}
+ /*
+ * Merge Protocol
+ (1) Editor CommandをSession Ring 上に流し、それが戻って来るまでに、他のEditorから
+ 受け取った Editor Command をキューに入れておく。
+ (2) 戻って来たタイミングで、キュー上のEditor Commandを、eid とCommandの
+ 順序を基にソートする。(self merge)
+ (3) 他のEditorにソートのタイミングを与えるために、Editor Command の
+ ack を、もう一周させる。
+ (4) 他のEditorのCommandを受け取ってから、ack が来るまでのCommandをキューに
+ 入れておき、ack が来たら、eid とCommandの順序を基にソートする。(other merge)
+
+ Editor には、ソートした編集結果になるように、それまで行なった編集をUndo
+ して、ソートした編集結果を適用する。Undo が無駄な動作をしないように最適化する。
+
+ handle()
+ セッションの処理
+ manage()
+ 編集コマンドは translate() へ
+ 一周して来た編集コマンドのACKは廃棄 (merge queue から削除)
+ 一周して来た自分のコマンドならself merge
+ 他のエディタの編集コマンドのACK->other merge
+ それ以外は、そのまま実行、merge queue へ格納
+ merge は checkReturnedCommand() から
+ startMerge() へ
+ まず、接続されている Editor に START_MERGE を送る
+ 邪魔されないように、他のcommand は block する
+ manager()
+ START_MERGE_ACK が来たら、translator.mergeAck() で教えて、
+ merge()->
+ translator.checkOwnCommand() へ
+ ここで、sort されて、Merge Command をEditorへ送信
+ checkEndMerge()から
+ endMerge() が呼ばれる。
+ 自分のエディタにEND_MERGE で Merge終了を通知
+ 自分のコマンドは、ACKに変えて送信 (3)
+ それ以外は、そのまま送信 (一周させる)
+
+ */
public void translate(REPCommand command){
switch(command.cmd) {
@@ -217,7 +255,7 @@
// Session Manager 側で、このeditorへの他のeditorからの
// 入力を止めて、merge にそなえる。merge は、eidtor 側から
// ACKが来てから始まる。
- translator.startMerge(cmd);
+ translator.startMerge(command);
}
@Override
@@ -360,6 +398,7 @@
+" from "+manager.editorList.editorByChannel(channel));
if (command.cmd==REP.SMCMD_JOIN||command.cmd==REP.SMCMD_PUT) {
// assert false;
+ // 一つのエディタ上に複数のセッションが作られた場合。
// 若干問題があるらしい
next = new Forwarder(manager,next.channel);
REPNode first = new FirstConnector(manager,channel);
diff -r 1acc3dfde5d3 -r 622a8e15ff40 rep/handler/Translator.java
--- a/rep/handler/Translator.java Fri Jan 01 00:06:23 2010 +0900
+++ b/rep/handler/Translator.java Sat Jan 02 03:20:23 2010 +0900
@@ -1,6 +1,5 @@
package rep.handler;
-import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
@@ -55,22 +54,18 @@
* @param cmd
*/
public boolean catchOwnCommand(REPNode editor){
- logger.writeLog("beforeMarge:"+unMergedCmds);
+ logger.writeLog("beforeMerge:"+unMergedCmds);
LinkedList output = new LinkedList();
- LinkedList cmds = new LinkedList();
- //スタック上にあるコマンドを全部undoコマンドにする
- while ( !unMergedCmds.isEmpty() ){
- REPCommand cmd0 = unMergedCmds.removeLast();
+ TreeSet cmds = new TreeSet(new REPCommandComparator());
+ // merge queue上にあるコマンドを全部undoコマンドするのと同時に
+ // sort したコマンド列を生成する
+ for( REPCommand cmd0 : unMergedCmds) {
output.add( createUndo(cmd0) );
cmds.add(cmd0);
}
-
- /* 必要な分だけソートして返却用のリストに追加 */
- output.addAll( sortCmds(cmds) );
-
- /* 残ったコマンドも再び実行させるが、まだマージされてないのでunMergedにも入れる */
output.addAll(cmds);
- unMergedCmds.addAll(cmds);
+ // ACKが来たものは必ず先頭
+ unMergedCmds.removeFirst();
logger.writeLog("outputMerge:"+output);
logger.writeLog("afterMerge:"+unMergedCmds);
return optimizedSend(editor,output);
@@ -109,52 +104,15 @@
class REPCommandComparator implements Comparator{
public int compare(REPCommand o1, REPCommand o2) {
-
- if ( o2.lineno > o1.lineno ) return 1;
- else if ( o2.lineno < o1.lineno
- || o2.eid > o1.eid )
- return -1;
-
- return 1;
+ if ( o1.eido2.eid ) return 1;
+ if ( o1.seqo2.seq ) return 1;
+ assert(false);
+ return 0;
}
-
}
- private Collection sortCmds(LinkedList cmds) {
- TreeSet sortedCmds1 = new TreeSet(new REPCommandComparator());
- int top;
- int prevEid=-1;
- while ( -1 != (top=getPrecedence(cmds, prevEid+1)) ){
- REPCommand tmp = cmds.remove(top);
- sortedCmds1.add(tmp);
- prevEid = tmp.eid;
- }
-
- return sortedCmds1;
- }
-
- /* search cmd. ordering by min EID that is lower lowEid and min SEQ. */
- private int getPrecedence(LinkedList cmds, int lowEid) {
- int cEid, cSeq;
- cEid=cSeq=Integer.MAX_VALUE;
- int ret=-1;
- for (int i=0; icEid ) continue;
- else if ( c.eid==cEid ) {
- if ( c.seq>cSeq ) continue;
- cSeq=c.seq;
- ret = i;
- } else { /* tmp.eid