Mercurial > hg > RemoteEditor > REPSessionManager
view rep/handler/Translator.java @ 427:622a8e15ff40
Merge Worked ?
author | one |
---|---|
date | Sat, 02 Jan 2010 03:20:23 +0900 |
parents | 1acc3dfde5d3 |
children | 1bb59652d89c |
line wrap: on
line source
package rep.handler; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.TreeSet; import rep.REP; import rep.REPCommand; import rep.SessionManager; import rep.channel.REPLogger; import rep.optimizers.REPCommandOptimizer; public class Translator { public int eid; public REPCommandOptimizer optimizer; private LinkedList<REPCommand> unMergedCmds; public LinkedList<REPCommand> sentMergedList; private LinkedList<REPCommand> mergeAgainList; public REPLogger logger = SessionManager.logger; boolean merge_mode = false; public Translator(int _eid,REPCommandOptimizer opt){ eid = _eid; optimizer = opt; unMergedCmds = new LinkedList<REPCommand>(); mergeAgainList = new LinkedList<REPCommand>(); sentMergedList = new LinkedList<REPCommand>(); } /** * New command from an editor * The command is sent to the next editor * @param cmd * @return translated command. */ public REPCommand transSendCmd(REPCommand cmd){ assert(cmd.eid==eid); unMergedCmds.add(cmd); //マージ中にユーザから割り込みがあった場合 if(isMerging()){ mergeAgainList.add(cmd); } return cmd; } /** * My command is returned from the session ring, and START_MERGE_ACK * is returned. At this * stage my writeQueue is empty, our editor is waiting for me. * Start merge process. * @param cmd */ public boolean catchOwnCommand(REPNode editor){ logger.writeLog("beforeMerge:"+unMergedCmds); LinkedList<REPCommand> output = new LinkedList<REPCommand>(); TreeSet<REPCommand> cmds = new TreeSet<REPCommand>(new REPCommandComparator()); // merge queue上にあるコマンドを全部undoコマンドするのと同時に // sort したコマンド列を生成する for( REPCommand cmd0 : unMergedCmds) { output.add( createUndo(cmd0) ); cmds.add(cmd0); } output.addAll(cmds); // ACKが来たものは必ず先頭 unMergedCmds.removeFirst(); logger.writeLog("outputMerge:"+output); logger.writeLog("afterMerge:"+unMergedCmds); return optimizedSend(editor,output); } /** * Sent optimized merged command list * @param editor * @param output * @return if any sent commands output */ public boolean optimizedSend(REPNode editor, LinkedList<REPCommand> output) { List<REPCommand> output1 = optimizer.optimize(output); if (output1.size()==0) { merge_mode = false; return false; } for(REPCommand c:output1) { REPCommand m = new REPCommand(c); m.setEID(REP.MERGE_EID.id); m.setSEQID(editor.seq()); sentMergedList.add(m); editor.send(m); } merge_mode = true; return true; } private REPCommand createUndo(REPCommand cmd){ REPCommand retCmd = new REPCommand(cmd); if (cmd.cmd==REP.REPCMD_INSERT) retCmd.cmd=REP.REPCMD_DELETE; else if (cmd.cmd==REP.REPCMD_DELETE) retCmd.cmd=REP.REPCMD_INSERT; return retCmd; } class REPCommandComparator implements Comparator<REPCommand>{ public int compare(REPCommand o1, REPCommand o2) { if ( o1.eid<o2.eid ) return -1; if ( o1.eid>o2.eid ) return 1; if ( o1.seq<o2.seq ) return -1; if ( o1.seq>o2.seq ) return 1; assert(false); return 0; } } /** * Translate Command cmd that was received from SeMa. * @param cmd the command to be translated. * @return translated commannd. */ public void transReceiveCmd(REPNode nextEditor,REPCommand cmd){ assert (cmd.eid != eid); unMergedCmds.add(cmd); } public void setEid(int _eid){ eid = _eid; } public boolean checkMergeConflict(REPCommand command) { REPCommand prev = sentMergedList.remove(); assert (prev.seq==command.seq); if(mergeAgainList.size() > 0){ mergeAgainList.add(command); return true; } if(sentMergedList.size()==0) { merge_mode=false; } return false; } public void getMergeAgain(REPNode editor) { LinkedList<REPCommand> returnCommand = new LinkedList<REPCommand>(); for(int i = 0; i < mergeAgainList.size(); i++){ //eid = REP.MEGE_EID returnCommand.add(createUndo(mergeAgainList.get(mergeAgainList.size() - i -1))); } for(REPCommand command : mergeAgainList){ if(command.eid == REP.MERGE_EID.id){ returnCommand.add(command); } } for(REPCommand command : mergeAgainList){ if(command.eid == eid){ command.eid = REP.MERGE_EID.id; returnCommand.add(command); } } // int count = 0; // for(REPCommand command: returnCommand) { // switch(command.cmd) { // case REPCMD_INSERT: count++; break; // case REPCMD_DELETE: count--; break; // default: assert false; // } // } logger.writeLog("MergeAgain ret="+returnCommand.size()); // +" increment="+count); mergeAgainList.clear(); optimizedSend(editor, returnCommand); } public boolean isFinished() { if(unMergedCmds.size() > 0) return false; if(sentMergedList.size() > 0) return false; return true; } public boolean isMerging() { return merge_mode; } public void startMerge(REPCommand cmd) { logger.writeLog("START MERGE command ="+cmd+" and top of unMergedCmds = "+ unMergedCmds.getFirst()); merge_mode = true; } public void mergeAck() { } }