Mercurial > hg > RemoteEditor > Eclipse
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 } |