Mercurial > hg > RemoteEditor > Eclipse
diff src/remoteeditor/editors/REPEditor.java @ 193:3133040ee4f4
(no commit message)
author | one |
---|---|
date | Wed, 31 Dec 2008 15:06:22 +0900 |
parents | |
children | ca9f72b8b4ab |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/remoteeditor/editors/REPEditor.java Wed Dec 31 15:06:22 2008 +0900 @@ -0,0 +1,243 @@ +package remoteeditor.editors; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; +import java.util.LinkedList; +import rep.REP; +import rep.REPCommand; +import rep.REPCommandPacker; +import rep.channel.REPSelectionKey; +import rep.channel.REPSelector; +import rep.channel.REPSocketChannel; + + +public class REPEditor extends Thread implements REPTextListener{ + + private REPSocketChannel<REPCommand> channel; + REPSelector<REPCommand> selector; + private boolean running = true; + private boolean inputLock = false; + private long timeout = 1; + private int syncCounter = 0; + private LinkedList<REPCommand> userCommand = new LinkedList<REPCommand>(); + private LinkedList<Runnable> runners = new LinkedList<Runnable>(); + private String name = "test"; + private int seq; + private int eid; + private int sid; + private REPText repText; + private boolean hasInputLock; + private boolean master; + private boolean syncEnable = true; + + public REPEditor(REPText repText, boolean master){ + this.repText = repText; + this.master = master; + repText.addTextListener(this); + if(master){ + userCommand.add(new REPCommand(REP.SMCMD_PUT,0,0,0,0,name +"-file")); + }else{ + userCommand.add(new REPCommand(REP.SMCMD_JOIN, 0, 0, 0, 0, name)); + } + } + + public void textDeleted(REPTextEvent event) { + Logger.print(event.getText()); + addUserInput(new REPCommand(REP.REPCMD_DELETE_USER, 0, 0, 0, event.getLineno(), event.getText())); + } + + public void textInserted(REPTextEvent event) { + Logger.print(event.getText()); + addUserInput(new REPCommand(REP.REPCMD_INSERT_USER, 0, 0, 0, event.getLineno(), event.getText())); + } + + private void addUserInput(final REPCommand command) { + Runnable runner = new Runnable(){ + public void run(){ + userCommand.add(command); + timeout = 1; + } + }; + synchronized(runners){ + runners.add(runner); + } + if(selector != null){ + selector.wakeup(); + } + } + + public void run(){ + /* + * Create Socket and connect to the session manager + */ + try { + channel = REPSocketChannel.<REPCommand>create(new REPCommandPacker()); + } catch (IOException e) { + e.printStackTrace(); + return; + } + try { + InetSocketAddress semaIP = new InetSocketAddress("localhost", 8766); + while (!channel.connect(semaIP)){ + Logger.print("SeMa not listen to socket yet, wait"); + } + } catch (IOException e) { + e.printStackTrace(); + return; + } + /* + * Start editor main loop + * public REPCommand(REP cmd,int sid,int eid, int seq, int lineno, String string) + */ + try { + mainloop(); + } catch (IOException e) { + } + } + + /* + * Editor main loop with input lock + */ + private void mainloop() throws IOException { + + channel.configureBlocking(false); + selector = REPSelector.create(); + channel.register(selector, SelectionKey.OP_READ); + while(running) { + + synchronized(runners){ + for(Runnable runner : runners){ + runner.run(); + } + runners.clear(); + } + + if (inputLock) { + // No user input during merge mode (optional) + if (selector.select(0)>0) { + handle(channel.read()); + } + continue; + } else if (selector.select(timeout)<=0) { + if (syncCounter>0) { + syncText(); // send the master editor buffer to clients. + } + userInput(); + } + // selector(timeout) returns 0, but it may contain readable channel.. + for(REPSelectionKey<REPCommand> key : selector.selectedKeys1()) { + REPSocketChannel<REPCommand> ch = key.channel1(); + handle(ch.read()); + } + } + } + + private void handle(REPCommand command) { + Logger.print(command); + if(command == null) return; + switch(command.cmd){ + case REPCMD_DELETE: + if(command.eid != eid){ + String del = repText.delete(command.lineno); + command.setString(del); + } + forward(command); + break; + case REPCMD_INSERT: + if(command.eid != eid){ + repText.insert(command.lineno, command.string); + } + forward(command); + break; + case REPCMD_NOP: + case REPCMD_INSERT_ACK: + case REPCMD_DELETE_ACK: + forward(command); + break; + case SMCMD_PUT_ACK: + sid = command.sid; + eid = command.eid; + name += "(eid="+eid+",sid="+sid+")"; + inputLock = false; + break; + case SMCMD_JOIN_ACK : + sid = command.sid; + eid = command.eid; + name += "(eid="+eid+",sid="+sid+")"; + inputLock = false; + break; + case SMCMD_START_MERGE : + // lock user input during merge (optional) + inputLock = hasInputLock; + command.cmd = REP.SMCMD_START_MERGE_ACK; + send(command); + break; + case SMCMD_END_MERGE : + inputLock = false; + break; + case SMCMD_SYNC: + // start contents sync with newly joined editor + command.cmd = REP.SMCMD_SYNC_ACK; + forward(command); + //if (cmd.eid==eid) { + if (master && syncEnable ) { + syncCounter = 1; + timeout = 1; + } + break; + } + } + + private void userInput() { + Logger.print(); + REPCommand command = userCommand.poll(); + if(command != null){ + switch(command.cmd){ + case REPCMD_DELETE_USER: + send(command); + break; + case REPCMD_INSERT_USER: + send(command); + break; + case SMCMD_PUT: + case SMCMD_JOIN: + send(command); + break; + } + }else{ + if(syncCounter == 0){ + timeout = 0; + } + } + } + + private void forward(REPCommand command) { + REPCommand cmd = new REPCommand(command); + channel.write(cmd); + } + + private void send(REPCommand command) { + REPCommand cmd = new REPCommand(command); + cmd.setSEQID(seq++); + cmd.setEID(eid); + cmd.setSID(sid); + channel.write(cmd); + } + + private void syncText() { + Logger.print(); + if(syncCounter>repText.size()){ + syncCounter = 0; + }else { + if(inputLock) return; + int i = syncCounter - 1; + REPCommand del = new REPCommand(REP.REPCMD_DELETE_USER, sid, eid, 0, i, repText.get(i)); + REPCommand ins = new REPCommand(REP.REPCMD_INSERT_USER, sid, eid, 0, i, repText.get(i)); + send(del); + send(ins); + syncCounter++; + } + } + +}