comparison test/editortest/REPEditor.java @ 417:267f9748e826

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