1
|
1 package rep;
|
|
2
|
213
|
3 import java.util.ArrayList;
|
122
|
4 import java.util.LinkedList;
|
142
|
5 import java.util.List;
|
1
|
6
|
304
|
7 import rep.channel.REPLogger;
|
131
|
8 import rep.channel.REPSocketChannel;
|
224
|
9 import rep.optimizers.*;
|
142
|
10 import rep.translater.TranslaterImp1;
|
131
|
11
|
1
|
12 public class Editor {
|
281
|
13 private int eid; // unique id in a session
|
|
14 private int sid = -1 ; // globally unique session id
|
132
|
15 private REPSocketChannel<REPCommand> myChannel;
|
21
|
16 private String host;
|
39
|
17 private String file;
|
142
|
18 private TranslaterImp1 translater;
|
|
19 private List<REPCommand> sentList;
|
213
|
20 private List<REPCommand> sentMergedList;
|
224
|
21 private REPCommandOptimizer optimizer;
|
300
|
22 private List<REPCommand> writeQueue;
|
|
23 private REPCommand quit2 = null;
|
304
|
24 private REPLogger ns = REPLogger.singleton();
|
308
|
25 private final int limit=100;
|
155
|
26
|
|
27 public Editor(){
|
224
|
28 this(true);
|
|
29 }
|
|
30 public Editor(boolean doOptimize){
|
155
|
31 setHostAndPort(myChannel);
|
|
32 translater = new TranslaterImp1(eid);
|
|
33 sentList = new LinkedList<REPCommand>();
|
265
|
34 sentMergedList = new LinkedList<REPCommand>();
|
300
|
35 writeQueue = new LinkedList<REPCommand>();
|
224
|
36
|
|
37 if (doOptimize) optimizer = new DeleteInsertOptimizer(); //タカノがつくったおぷてぃまいざ
|
|
38 else optimizer = new NullOptimizer(); //なにもしないけどOptimizer.
|
|
39
|
155
|
40 }
|
1
|
41
|
132
|
42 public Editor(int editorNo, REPSocketChannel<REPCommand> channel){
|
23
|
43 this.eid = editorNo;
|
56
|
44 this.myChannel = channel;
|
142
|
45 translater = new TranslaterImp1(eid);
|
|
46 sentList = new LinkedList<REPCommand>();
|
265
|
47 sentMergedList = new LinkedList<REPCommand>();
|
300
|
48 writeQueue = new LinkedList<REPCommand>();
|
152
|
49 setHostAndPort(myChannel);
|
56
|
50 }
|
142
|
51
|
132
|
52 public Editor(REPSocketChannel<REPCommand> channel) {
|
56
|
53 this.myChannel = channel;
|
|
54 setHostAndPort(myChannel);
|
152
|
55 translater = new TranslaterImp1(eid);
|
|
56 sentList = new LinkedList<REPCommand>();
|
300
|
57 writeQueue = new LinkedList<REPCommand>();
|
56
|
58 }
|
142
|
59
|
224
|
60 public List<REPCommand> translate(REPCommand command){
|
|
61 List<REPCommand> list = new LinkedList<REPCommand>();
|
142
|
62 if(command.eid == eid){
|
|
63 if(checkReturnedCommand(command)){
|
152
|
64 //エディタからのコマンドが元のエディタに戻ってきた
|
164
|
65 //マージして送信
|
213
|
66 ArrayList<REPCommand> cmds = translater.catchOwnCommand(command);
|
|
67 //optimizer
|
|
68 //マージ中のエディタからの割り込み検知に使う
|
|
69 sentMergedList.addAll(cmds);
|
142
|
70 sendMergedCommand(cmds);
|
265
|
71 return list;
|
142
|
72 }else{
|
152
|
73 //エディタからの新たな編集コマンド
|
142
|
74 sentList.add(command);
|
308
|
75 assert(sentList.size()<limit);
|
142
|
76 translater.transSendCmd(command);
|
|
77 list.add(command);
|
|
78 }
|
271
|
79 }else if(eid == REP.MERGE_EID.id){
|
179
|
80 //マージコマンドが返ってきた
|
|
81 if(translater.checkMergeConflict(command)){
|
|
82 //マージ中にエディタからの割り込みがあった場合
|
224
|
83 List<REPCommand> mergeAgainList = translater.getMergeAgain();
|
|
84
|
|
85 mergeAgainList = optimizer.optimize(mergeAgainList);
|
300
|
86 writeQueue.addAll(mergeAgainList);
|
308
|
87 assert(writeQueue.size()<limit);
|
179
|
88 }
|
142
|
89 }else{
|
152
|
90 //他のエディタからの編集コマンド
|
142
|
91 REPCommand[] cmds = translater.transReceiveCmd(command);
|
|
92 for(REPCommand cmd : cmds){
|
|
93 list.add(cmd);
|
|
94 }
|
|
95 }
|
|
96 return list;
|
|
97 }
|
|
98
|
213
|
99 private void sendMergedCommand(ArrayList<REPCommand> cmds) {
|
|
100 for(REPCommand mergeCommand : cmds){
|
271
|
101 mergeCommand.setEID(REP.MERGE_EID.id);
|
300
|
102 writeQueue.add(mergeCommand);
|
308
|
103 assert(writeQueue.size()<limit);
|
142
|
104 }
|
|
105 }
|
56
|
106
|
142
|
107 private boolean checkReturnedCommand(REPCommand command) {
|
|
108 if(sentList.size() > 0){
|
|
109 if(sentList.get(0).seq == command.seq){
|
|
110 sentList.remove(0);
|
|
111 return true;
|
|
112 }else{
|
296
|
113 System.err.println("Editor.checkReturnedCommand() : command = " + command);
|
302
|
114 //assert(false);
|
142
|
115 }
|
|
116 }
|
|
117 return false;
|
74
|
118 }
|
|
119
|
300
|
120
|
|
121 public boolean doWaitingWrite() {
|
|
122 // 一気に送ると、向こう側(Editor)で、dead lock する可能性がある。
|
|
123 // select loop の中で一つ一つ送るしかない。Editor側から割り込まれる可能性も
|
|
124 // ある。その時に複数のコマンドを送っていると、どこに割り込まれたかを判断する
|
|
125 // ことが出来ない。そこで、一つ一つReturnを確認する必要がある。つまり、
|
|
126 // select loop で送るしかない。
|
|
127 REPCommand cmd;
|
|
128 if (writeQueue.size()>0) {
|
|
129 cmd = writeQueue.remove(0);
|
304
|
130 ns.writeLog("SessionManager write to "+myChannel+" cmd="+cmd);
|
300
|
131 myChannel.write(cmd);
|
|
132 return true;
|
|
133 } else if (quit2!=null && sentList.size()==0) {
|
304
|
134 //myChannel.write(quit2);
|
302
|
135 quit2 = null;
|
300
|
136 return true;
|
|
137 }
|
|
138 return false;
|
|
139 }
|
|
140
|
|
141 public void setQuit2(REPCommand cmd) {
|
|
142 quit2 = cmd;
|
|
143 }
|
|
144
|
132
|
145 private void setHostAndPort(REPSocketChannel<REPCommand> myChannel2) {
|
195
|
146 //host = myChannel2.socket().getRemoteSocketAddress().toString();
|
178
|
147
|
1
|
148 }
|
|
149
|
132
|
150 public REPSocketChannel<REPCommand> getChannel() {
|
56
|
151 return myChannel;
|
1
|
152 }
|
21
|
153
|
|
154 public void setHost(String host){
|
|
155 this.host = host;
|
|
156 }
|
178
|
157
|
21
|
158
|
|
159 public String getHost(){
|
|
160 return host;
|
|
161 }
|
178
|
162
|
21
|
163
|
23
|
164 public int getEID() {
|
|
165 return eid;
|
|
166 }
|
|
167
|
|
168 public void setEID(int eid) {
|
|
169 this.eid = eid;
|
300
|
170 translater.setEid(eid);
|
23
|
171 }
|
24
|
172 public String toString(){
|
304
|
173 return ("Editor eid="+eid+" sid="+sid+" " + host + ":" + file);
|
24
|
174 }
|
23
|
175
|
38
|
176 public String getName() {
|
39
|
177 return file;
|
|
178 }
|
|
179
|
|
180 public void setName(String string) {
|
|
181 file = string;
|
38
|
182 }
|
|
183
|
179
|
184 public void send(REPCommand command) {
|
304
|
185 writeQueue.add(command);
|
308
|
186 assert(writeQueue.size()<limit);
|
56
|
187 }
|
|
188
|
178
|
189 public void setChannel(REPSocketChannel<REPCommand> channel) {
|
83
|
190 myChannel = channel;
|
|
191 }
|
|
192
|
164
|
193 public boolean isMerging() {
|
|
194 return translater.isMerging();
|
|
195 }
|
281
|
196 public boolean hasSession() {
|
|
197 return sid != -1;
|
|
198 }
|
|
199 public void setSID(int sessionID) {
|
|
200 sid = sessionID;
|
|
201 }
|
164
|
202
|
1
|
203 }
|