comparison src/remoteeditor/editors/REPEditor.java @ 193:3133040ee4f4

(no commit message)
author one
date Wed, 31 Dec 2008 15:06:22 +0900
parents
children ca9f72b8b4ab
comparison
equal deleted inserted replaced
192:c921022bf494 193:3133040ee4f4
1 package remoteeditor.editors;
2
3 import java.io.IOException;
4 import java.net.InetSocketAddress;
5 import java.nio.channels.SelectionKey;
6 import java.util.LinkedList;
7 import rep.REP;
8 import rep.REPCommand;
9 import rep.REPCommandPacker;
10 import rep.channel.REPSelectionKey;
11 import rep.channel.REPSelector;
12 import rep.channel.REPSocketChannel;
13
14
15 public class REPEditor extends Thread implements REPTextListener{
16
17 private REPSocketChannel<REPCommand> channel;
18 REPSelector<REPCommand> selector;
19 private boolean running = true;
20 private boolean inputLock = false;
21 private long timeout = 1;
22 private int syncCounter = 0;
23 private LinkedList<REPCommand> userCommand = new LinkedList<REPCommand>();
24 private LinkedList<Runnable> runners = new LinkedList<Runnable>();
25 private String name = "test";
26 private int seq;
27 private int eid;
28 private int sid;
29 private REPText repText;
30 private boolean hasInputLock;
31 private boolean master;
32 private boolean syncEnable = true;
33
34 public REPEditor(REPText repText, boolean master){
35 this.repText = repText;
36 this.master = master;
37 repText.addTextListener(this);
38 if(master){
39 userCommand.add(new REPCommand(REP.SMCMD_PUT,0,0,0,0,name +"-file"));
40 }else{
41 userCommand.add(new REPCommand(REP.SMCMD_JOIN, 0, 0, 0, 0, name));
42 }
43 }
44
45 public void textDeleted(REPTextEvent event) {
46 Logger.print(event.getText());
47 addUserInput(new REPCommand(REP.REPCMD_DELETE_USER, 0, 0, 0, event.getLineno(), event.getText()));
48 }
49
50 public void textInserted(REPTextEvent event) {
51 Logger.print(event.getText());
52 addUserInput(new REPCommand(REP.REPCMD_INSERT_USER, 0, 0, 0, event.getLineno(), event.getText()));
53 }
54
55 private void addUserInput(final REPCommand command) {
56 Runnable runner = new Runnable(){
57 public void run(){
58 userCommand.add(command);
59 timeout = 1;
60 }
61 };
62 synchronized(runners){
63 runners.add(runner);
64 }
65 if(selector != null){
66 selector.wakeup();
67 }
68 }
69
70 public void run(){
71 /*
72 * Create Socket and connect to the session manager
73 */
74 try {
75 channel = REPSocketChannel.<REPCommand>create(new REPCommandPacker());
76 } catch (IOException e) {
77 e.printStackTrace();
78 return;
79 }
80 try {
81 InetSocketAddress semaIP = new InetSocketAddress("localhost", 8766);
82 while (!channel.connect(semaIP)){
83 Logger.print("SeMa not listen to socket yet, wait");
84 }
85 } catch (IOException e) {
86 e.printStackTrace();
87 return;
88 }
89 /*
90 * Start editor main loop
91 * public REPCommand(REP cmd,int sid,int eid, int seq, int lineno, String string)
92 */
93 try {
94 mainloop();
95 } catch (IOException e) {
96 }
97 }
98
99 /*
100 * Editor main loop with input lock
101 */
102 private void mainloop() throws IOException {
103
104 channel.configureBlocking(false);
105 selector = REPSelector.create();
106 channel.register(selector, SelectionKey.OP_READ);
107 while(running) {
108
109 synchronized(runners){
110 for(Runnable runner : runners){
111 runner.run();
112 }
113 runners.clear();
114 }
115
116 if (inputLock) {
117 // No user input during merge mode (optional)
118 if (selector.select(0)>0) {
119 handle(channel.read());
120 }
121 continue;
122 } else if (selector.select(timeout)<=0) {
123 if (syncCounter>0) {
124 syncText(); // send the master editor buffer to clients.
125 }
126 userInput();
127 }
128 // selector(timeout) returns 0, but it may contain readable channel..
129 for(REPSelectionKey<REPCommand> key : selector.selectedKeys1()) {
130 REPSocketChannel<REPCommand> ch = key.channel1();
131 handle(ch.read());
132 }
133 }
134 }
135
136 private void handle(REPCommand command) {
137 Logger.print(command);
138 if(command == null) return;
139 switch(command.cmd){
140 case REPCMD_DELETE:
141 if(command.eid != eid){
142 String del = repText.delete(command.lineno);
143 command.setString(del);
144 }
145 forward(command);
146 break;
147 case REPCMD_INSERT:
148 if(command.eid != eid){
149 repText.insert(command.lineno, command.string);
150 }
151 forward(command);
152 break;
153 case REPCMD_NOP:
154 case REPCMD_INSERT_ACK:
155 case REPCMD_DELETE_ACK:
156 forward(command);
157 break;
158 case SMCMD_PUT_ACK:
159 sid = command.sid;
160 eid = command.eid;
161 name += "(eid="+eid+",sid="+sid+")";
162 inputLock = false;
163 break;
164 case SMCMD_JOIN_ACK :
165 sid = command.sid;
166 eid = command.eid;
167 name += "(eid="+eid+",sid="+sid+")";
168 inputLock = false;
169 break;
170 case SMCMD_START_MERGE :
171 // lock user input during merge (optional)
172 inputLock = hasInputLock;
173 command.cmd = REP.SMCMD_START_MERGE_ACK;
174 send(command);
175 break;
176 case SMCMD_END_MERGE :
177 inputLock = false;
178 break;
179 case SMCMD_SYNC:
180 // start contents sync with newly joined editor
181 command.cmd = REP.SMCMD_SYNC_ACK;
182 forward(command);
183 //if (cmd.eid==eid) {
184 if (master && syncEnable ) {
185 syncCounter = 1;
186 timeout = 1;
187 }
188 break;
189 }
190 }
191
192 private void userInput() {
193 Logger.print();
194 REPCommand command = userCommand.poll();
195 if(command != null){
196 switch(command.cmd){
197 case REPCMD_DELETE_USER:
198 send(command);
199 break;
200 case REPCMD_INSERT_USER:
201 send(command);
202 break;
203 case SMCMD_PUT:
204 case SMCMD_JOIN:
205 send(command);
206 break;
207 }
208 }else{
209 if(syncCounter == 0){
210 timeout = 0;
211 }
212 }
213 }
214
215 private void forward(REPCommand command) {
216 REPCommand cmd = new REPCommand(command);
217 channel.write(cmd);
218 }
219
220 private void send(REPCommand command) {
221 REPCommand cmd = new REPCommand(command);
222 cmd.setSEQID(seq++);
223 cmd.setEID(eid);
224 cmd.setSID(sid);
225 channel.write(cmd);
226 }
227
228 private void syncText() {
229 Logger.print();
230 if(syncCounter>repText.size()){
231 syncCounter = 0;
232 }else {
233 if(inputLock) return;
234 int i = syncCounter - 1;
235 REPCommand del = new REPCommand(REP.REPCMD_DELETE_USER, sid, eid, 0, i, repText.get(i));
236 REPCommand ins = new REPCommand(REP.REPCMD_INSERT_USER, sid, eid, 0, i, repText.get(i));
237 send(del);
238 send(ins);
239 syncCounter++;
240 }
241 }
242
243 }