Mercurial > hg > RemoteEditor > REPSessionManager
view test/editortest/REPEditor.java @ 419:7ff127c8ad64
(no commit message)
author | one |
---|---|
date | Tue, 20 Jan 2009 18:39:02 +0900 |
parents | 267f9748e826 |
children | 5c95a9020e31 |
line wrap: on
line source
package test.editortest; 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 = false; private boolean master; private boolean syncEnable = true; private LogTarget logTarget; 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())); } public 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(logTarget, command); // if(inputLock) Logger.print(logTarget, 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() { 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++; } } public void setLogTarget(LogTarget target){ logTarget = target; } public REPText getREPText() { return repText; } }