Mercurial > hg > RemoteEditor > REPSessionManager
view rep/Editor.java @ 319:dfed28488274
*** empty log message ***
author | kono |
---|---|
date | Thu, 09 Oct 2008 17:26:55 +0900 |
parents | dc57e24ea3df |
children | 1e605880d49e |
line wrap: on
line source
package rep; 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 TranslaterImp1 translater; private List<REPCommand> sentList = new LinkedList<REPCommand>(); // REPCommands we are going to send to the next editor private REPCommandOptimizer optimizer; //private REPCommand quit2 = null; private SessionManager manager; private REPCommand quit2=null; public Editor(SessionManager manager,boolean doOptimize,int editorNo){ super(manager); this.manager = manager; eid = editorNo; translater = new TranslaterImp1(eid); if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ else optimizer = new NullOptimizer(); //なにもしないけどOptimizer. } public Editor(SessionManager manager,int editorNo, REPSocketChannel<REPCommand> channel){ this(manager,false,editorNo); this.channel = channel; setHostAndPort(channel); } public void translate(Forwarder nextEditor, REPCommand command){ if(command.eid == nextEditor.getEID()){ if(checkReturnedCommand(command)){ // エディタからのコマンドが元のエディタに戻ってきた // START_MERGE を送る REPCommand cmd = new REPCommand(REP.SMCMD_START_MERGE,command.sid,REP.SM_EID.id,seq(),0,""); nextEditor.send(cmd); // Session Manager 側で、このeditorへの他のeditorからの // 入力を止めて、merge にそなえる。merge は、eidtor 側から // ACKが来てから始まる。 return; } else assert(false); } else if(command.eid == eid){ //エディタからの新たな編集コマンド sentList.add(command); assert(sentList.size()<limit); translater.transSendCmd(command); nextEditor.send(command); return; }else if(command.eid == REP.MERGE_EID.id){ //マージコマンドが返ってきた if(translater.checkMergeConflict(command)){ //マージ中にエディタからの割り込みがあった場合 if (optimizedSend(translater.getMergeAgain())) { return; } } if(!isMerging()) { endMerge(); } }else{ //他のエディタからの編集コマンド if(!isMerging()) { translater.transReceiveCmd(nextEditor,command); return; } manager.addWaitingCommand(new PacketSet(getChannel(), this, command)); } return; } boolean merge(Editor editor,REPCommand command) { REPCommand prev = translater.prev(); if(prev==null) return false; assert(prev.eid==command.eid); //マージして送信 return translater.catchOwnCommand(editor); } boolean checkReturnedCommand(REPCommand command) { if(sentList.size() > 0){ if(sentList.get(0).seq == command.seq){ sentList.remove(0); if (quit2!=null&&sentList.size()==0) { send(quit2); manager.remove(this); } return true; }else{ System.err.println("Editor.checkReturnedCommand() : command = " + command); assert(false); } } return false; } @Override public void setQuit2(REPCommand cmd) { if (sentList.size()==0) { send(cmd); manager.remove(this); } // do not send quit2 until we received all pending // command quit2 = cmd; } private void setHostAndPort(REPSocketChannel<REPCommand> myChannel2) { //host = myChannel2.socket().getRemoteSocketAddress().toString(); } @Override public void setEID(int eid) { this.eid = eid; translater.setEid(eid); } public String toString(){ return ("Editor eid="+eid+" sid="+sid+" " + host + ":" + file); } public boolean isMerging() { return translater.isMerging(); } public boolean hasSession() { return sid != -1; } public void setSID(int sessionID) { sid = sessionID; } /** * Sent optimized merged command list * @param output * @return if any sent commands output */ public boolean optimizedSend(LinkedList<REPCommand> output) { List<REPCommand> output1 = optimizer.optimize(output); if (output1.size()==0) return false; for(REPCommand c:output1) { REPCommand m = new REPCommand(c); m.setEID(REP.MERGE_EID.id); m.setSEQID(seq()); send(m); } return true; } void endMerge() { REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,eid,sid,seq(),0,""); 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; } }