Mercurial > hg > RemoteEditor > REPSessionManager
comparison rep/handler/Editor.java @ 483:c792a1ebc0ff
new merge (again...)
author | one |
---|---|
date | Sat, 16 Oct 2010 20:48:38 +0900 |
parents | 200166a494e9 |
children | 7420dea70dd7 |
comparison
equal
deleted
inserted
replaced
482:200166a494e9 | 483:c792a1ebc0ff |
---|---|
150 case REPCMD_MERGE_MARK: | 150 case REPCMD_MERGE_MARK: |
151 if (command.eid == REP.MERGE_EID.id){ | 151 if (command.eid == REP.MERGE_EID.id){ |
152 //マージコマンドが返ってきた | 152 //マージコマンドが返ってきた |
153 if(checkMergeConflict(command)){ | 153 if(checkMergeConflict(command)){ |
154 //マージ中にエディタからの割り込みがあった場合 | 154 //マージ中にエディタからの割り込みがあった場合 |
155 getMergeAgain(this); | 155 getMergeAgain(); |
156 } | 156 } |
157 checkEndMerge(); | 157 checkEndMerge(); |
158 return; | 158 return; |
159 } | 159 } |
160 if (command.eid == eid){ | 160 if (command.eid == eid){ |
168 return; | 168 return; |
169 } | 169 } |
170 | 170 |
171 //他のエディタからの編集コマンド | 171 //他のエディタからの編集コマンド |
172 transReceiveCmd(next,command); | 172 transReceiveCmd(next,command); |
173 | 173 if (mergeMode==MergeMode.Direct) |
174 sendEditorCommand(command); | 174 startMerge(command); |
175 else | |
176 sendEditorCommand(command); | |
175 return; | 177 return; |
176 default: | 178 default: |
177 assert(false); | 179 assert(false); |
178 } | 180 } |
179 } | 181 } |
180 | 182 |
181 private void userEditorCommand(REPCommand command) { | 183 private void userEditorCommand(REPCommand command) { |
182 //エディタからの新たな編集コマンド | 184 //エディタからの新たな編集コマンド |
185 if (mergeMode==MergeMode.Direct) | |
186 truncateSentList(command); | |
183 if (next==this) return; // singleton case | 187 if (next==this) return; // singleton case |
184 transSendCmd(command); | 188 transSendCmd(command); |
185 sendEditorCommand(command); | 189 sendEditorCommand(command); |
186 return; | 190 return; |
187 } | 191 } |
207 // } | 211 // } |
208 // assert(count==0); | 212 // assert(count==0); |
209 // } | 213 // } |
210 | 214 |
211 /** | 215 /** |
216 * truncate sentList and unMergedCmds | |
217 */ | |
218 private void truncateSentList(REPCommand command) { | |
219 | |
220 } | |
221 | |
222 /** | |
212 * Sending to Editor and waiting Queue | 223 * Sending to Editor and waiting Queue |
213 * +--------+ | 224 * +--------+ |
214 * send() --> write() -> | Editor | -> handle() -> manager() | 225 * send() --> write() -> | Editor | -> handle() -> manager() |
215 * +--------+ | 226 * +--------+ |
216 * waitingQueue | 227 * waitingQueue |
275 command.string=null; | 286 command.string=null; |
276 } | 287 } |
277 next.send(command); | 288 next.send(command); |
278 } | 289 } |
279 | 290 |
280 public List<REPCommand> getSentList() { | |
281 return sentList; | |
282 } | |
283 | |
284 public void setSentList(LinkedList<REPCommand> list) { | |
285 sentList = list; | |
286 } | |
287 | |
288 /** | 291 /** |
289 * 一周して来たcommandの処理。 | 292 * 一周して来たcommandの処理。 |
290 * | 293 * |
291 * INSERT/DELETEを受け取った時に、sentListに登録 | 294 * INSERT/DELETEを受け取った時に、sentListに登録 |
292 * INSERT_ACK/DELETE_ACKが来たら一周。そこで、Mergeする。 | 295 * INSERT_ACK/DELETE_ACKが来たら一周。そこで、Mergeする。 |
296 * 途中から参加した場合、自分が受けとってないcommandのACKが先に来ることが | 299 * 途中から参加した場合、自分が受けとってないcommandのACKが先に来ることが |
297 * ある。それは、無視して良い。 | 300 * ある。それは、無視して良い。 |
298 * @param command | 301 * @param command |
299 */ | 302 */ |
300 void checkReturnedCommand(REPCommand command) { | 303 void checkReturnedCommand(REPCommand command) { |
304 if (mergeMode!=MergeMode.Direct) | |
305 startMerge(command); | |
306 } | |
307 | |
308 void startMerge(REPCommand command) { | |
301 ServerMainLoop.logger.writeLog("Editor"+eid+": startMerge "+command); | 309 ServerMainLoop.logger.writeLog("Editor"+eid+": startMerge "+command); |
302 preMergeCommand = new REPCommand(command); | 310 preMergeCommand = new REPCommand(command); |
303 // merge は必須だが、EditorのCommand実装をテストするには邪魔なので、off に出来るようにする。 | 311 // merge は必須だが、EditorのCommand実装をテストするには邪魔なので、off に出来るようにする。 |
304 if (mergeMode==MergeMode.NoMerge) { | 312 if (mergeMode==MergeMode.NoMerge) { |
305 checkQuit(); | 313 checkQuit(); |
313 merging = true; | 321 merging = true; |
314 // Session Manager 側で、このeditorへの他のeditorからの | 322 // Session Manager 側で、このeditorへの他のeditorからの |
315 // 入力を止めて、merge にそなえる。merge は、eidtor 側から | 323 // 入力を止めて、merge にそなえる。merge は、eidtor 側から |
316 // ACKが来てから始まる。 | 324 // ACKが来てから始まる。 |
317 } | 325 } |
318 | 326 |
319 /** | 327 /** |
320 * sentList と ack を見比べて、正しい順序で来たかどうかを調べる。途中参加したEditorの場合は、Ackは | 328 * sentList と ack を見比べて、正しい順序で来たかどうかを調べる。途中参加したEditorの場合は、Ackは |
321 * 無視して良い。 | 329 * 無視して良い。 |
322 * @param command | 330 * @param command |
323 * @return | 331 * @return |
366 if (quit_2!=null) checkQuit(); | 374 if (quit_2!=null) checkQuit(); |
367 } | 375 } |
368 | 376 |
369 | 377 |
370 private void endMerge() { | 378 private void endMerge() { |
371 sortedEditCmds = null; | |
372 LinkedList<REPCommand>u = new LinkedList<REPCommand>(); | |
373 boolean flag=true; | |
374 for(REPCommand command:unMergedCmds) { | |
375 if (command.cmd==REP.REPCMD_MERGE_MARK) { | |
376 flag = false; | |
377 } | |
378 if (flag) u.addLast(command); | |
379 } | |
380 unMergedCmds = u; | |
381 | |
382 REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,sid,eid,seq(),0,""); | 379 REPCommand mergeEnd = new REPCommand(REP.SMCMD_END_MERGE,sid,eid,seq(),0,""); |
383 sendToEditor(mergeEnd); | 380 sendToEditor(mergeEnd); |
381 if (mergeMode==MergeMode.Direct) { | |
382 sendEditorCommand(preMergeCommand); | |
383 preMergeCommand = null; | |
384 return ; | |
385 } | |
386 sortedEditCmds = null; | |
387 truncateUnMergedCmds(); | |
384 checkAck(preMergeCommand); | 388 checkAck(preMergeCommand); |
385 if (preMergeCommand.eid==eid) { | 389 if (preMergeCommand.eid==eid) { |
386 if (mergeMode==MergeMode.Early) { | 390 if (mergeMode==MergeMode.Early) { |
387 sendAck(preMergeCommand); | 391 sendAck(preMergeCommand); |
388 } | 392 } |
390 ServerMainLoop.logger.writeLog("Editor"+eid+": send preMergeCommand "+preMergeCommand); | 394 ServerMainLoop.logger.writeLog("Editor"+eid+": send preMergeCommand "+preMergeCommand); |
391 next.send(preMergeCommand); | 395 next.send(preMergeCommand); |
392 } | 396 } |
393 // sentList.clear(); | 397 // sentList.clear(); |
394 preMergeCommand = null; | 398 preMergeCommand = null; |
399 } | |
400 | |
401 public void truncateUnMergedCmds() { | |
402 LinkedList<REPCommand>u = new LinkedList<REPCommand>(); | |
403 boolean flag=true; | |
404 for(REPCommand command:unMergedCmds) { | |
405 if (command.cmd==REP.REPCMD_MERGE_MARK) { | |
406 flag = false; | |
407 } | |
408 if (flag) u.addLast(command); | |
409 } | |
410 unMergedCmds = u; | |
395 } | 411 } |
396 | 412 |
397 private void sendAck(REPCommand command) { | 413 private void sendAck(REPCommand command) { |
398 REPCommand keep = new REPCommand(command); | 414 REPCommand keep = new REPCommand(command); |
399 // First Phase End, send ACK | 415 // First Phase End, send ACK |
439 | 455 |
440 case SMCMD_START_MERGE_ACK: | 456 case SMCMD_START_MERGE_ACK: |
441 { | 457 { |
442 // マージの処理と次のエディタへコマンドを送信する処理 | 458 // マージの処理と次のエディタへコマンドを送信する処理 |
443 mergeAck(); | 459 mergeAck(); |
444 if (!merge(this, preMergeCommand)) { | 460 if (!merge(preMergeCommand)) { |
445 // nothing to do, send END_MERGE | 461 // nothing to do, send END_MERGE |
446 checkEndMerge(); | 462 checkEndMerge(); |
447 } | 463 } |
448 break; | 464 break; |
449 } | 465 } |
568 * is returned. At this | 584 * is returned. At this |
569 * stage my writeQueue is empty, our editor is waiting for me. | 585 * stage my writeQueue is empty, our editor is waiting for me. |
570 * Start merge process. | 586 * Start merge process. |
571 * @param cmd | 587 * @param cmd |
572 */ | 588 */ |
573 public boolean merge(Editor editor, REPCommand prev){ | 589 public boolean merge(REPCommand prev){ |
574 logger.writeLog("beforeMerge"+eid+":"+unMergedCmds); | 590 logger.writeLog("beforeMerge"+eid+":"+unMergedCmds); |
575 LinkedList<REPCommand> output = new LinkedList<REPCommand>(); | 591 LinkedList<REPCommand> output = new LinkedList<REPCommand>(); |
576 LinkedList<REPCommand> newSentList = new LinkedList<REPCommand>(); | 592 LinkedList<REPCommand> newSentList = new LinkedList<REPCommand>(); |
577 // merge queue上にあるコマンドを全部undoコマンドするのと同時に | 593 // merge queue上にあるコマンドを全部undoコマンドするのと同時に |
578 // sort したコマンド列を生成する | 594 // sort したコマンド列を生成する |
579 for( REPCommand cmd0 : unMergedCmds) { | 595 for( REPCommand cmd0 : unMergedCmds) { |
580 output.addLast( createUndo(cmd0) ); | 596 output.addLast( createUndo(cmd0) ); |
581 } | 597 } |
582 | 598 |
583 sortedEditCmds = new TreeSet<REPCommand>(new REPCommandComparator(1)); | 599 sortedEditCmds = new TreeSet<REPCommand>(new REPCommandComparator(1)); |
584 logger.writeLog("sentList"+eid+":"+editor.getSentList()); | 600 logger.writeLog("sentList"+eid+":"+sentList); |
585 for( REPCommand cmd0 : editor.getSentList()) { | 601 for( REPCommand cmd0 : sentList ) { |
586 if (cmd0.cmd==REP.REPCMD_INSERT || cmd0.cmd==REP.REPCMD_DELETE) { | 602 if (cmd0.cmd==REP.REPCMD_INSERT || cmd0.cmd==REP.REPCMD_DELETE) { |
587 sortedEditCmds.add(cmd0); | 603 sortedEditCmds.add(cmd0); |
588 } | 604 } |
589 } | 605 } |
590 output.addAll(sortedEditCmds); | 606 output.addAll(sortedEditCmds); |
591 output.addLast(new REPCommand(REP.REPCMD_MERGE_MARK,0, editor.getSID(), REP.MERGE_EID.id, editor.seq(), "")); | 607 output.addLast(new REPCommand(REP.REPCMD_MERGE_MARK,0,sid, REP.MERGE_EID.id, seq(), "")); |
592 logger.writeLog("sortedMerge"+eid+":"+sortedEditCmds); | 608 logger.writeLog("sortedMerge"+eid+":"+sortedEditCmds); |
593 // unMerged command のdeleteのundo string は、この時点で使えない。 | 609 // unMerged command のdeleteのundo string は、この時点で使えない。 |
594 // Editor 側から送り返して来たものを使う必要がある。 | 610 // Editor 側から送り返して来たものを使う必要がある。 |
595 unMergedCmds.clear(); | 611 unMergedCmds.clear(); |
612 sentList = newSentList; | |
596 logger.writeLog("outputMerge"+eid+":"+output); | 613 logger.writeLog("outputMerge"+eid+":"+output); |
597 editor.setSentList(newSentList); | 614 return optimizedSend(this,output); |
598 return optimizedSend(editor,output); | |
599 } | 615 } |
600 | 616 |
601 /** | 617 /** |
602 * Sent optimized merged command list | 618 * Sent optimized merged command list |
603 * @param editor | 619 * @param editor |
681 merge_mode=false; | 697 merge_mode=false; |
682 } | 698 } |
683 return mergeAgain; | 699 return mergeAgain; |
684 } | 700 } |
685 | 701 |
686 public void getMergeAgain(Editor editor) { | 702 public void getMergeAgain() { |
687 if (sentMergedList.size()>0) return; // wait for previous merge completion | 703 if (sentMergedList.size()>0) return; // wait for previous merge completion |
688 | 704 |
689 LinkedList<REPCommand> returnCommand = new LinkedList<REPCommand>(); | 705 LinkedList<REPCommand> returnCommand = new LinkedList<REPCommand>(); |
690 for(REPCommand command : unMergedCmds) { | 706 for(REPCommand command : unMergedCmds) { |
691 if (command.cmd==REP.REPCMD_INSERT||command.cmd==REP.REPCMD_DELETE) | 707 if (command.cmd==REP.REPCMD_INSERT||command.cmd==REP.REPCMD_DELETE) |
692 returnCommand.add(createUndo(command)); | 708 returnCommand.add(createUndo(command)); |
693 } | 709 } |
694 returnCommand.addAll(sortedEditCmds); | 710 returnCommand.addAll(sortedEditCmds); |
695 returnCommand.addLast(new REPCommand(REP.REPCMD_MERGE_MARK,0, editor.getSID(), REP.MERGE_EID.id, editor.seq(), "")); | 711 returnCommand.addLast(new REPCommand(REP.REPCMD_MERGE_MARK,0, sid, REP.MERGE_EID.id, seq(), "")); |
696 returnCommand.addAll(editor.getSentList()); | 712 returnCommand.addAll(sentList); |
697 unMergedCmds.clear(); | 713 unMergedCmds.clear(); |
698 logger.writeLog("MergeAgain "+eid+" ret="+returnCommand.size()); | 714 logger.writeLog("MergeAgain "+eid+" ret="+returnCommand.size()); |
699 mergeAgain = false; | 715 mergeAgain = false; |
700 optimizedSend(editor, returnCommand); | 716 optimizedSend(this, returnCommand); |
701 } | 717 } |
702 // | 718 // |
703 // public boolean isFinished() { | 719 // public boolean isFinished() { |
704 // if(unMergedCmds.size() > 0) return false; | 720 // if(unMergedCmds.size() > 0) return false; |
705 // if(sentMergedList.size() > 0) return false; | 721 // if(sentMergedList.size() > 0) return false; |