do a complete agreement. it might choose the wrong leader initially, and have to re-submit after giving up. entirely gives up after about 10 seconds. indirectly checks that the servers agree on the same value, since nCommitted() checks this, as do the threads that read from applyCh. returns index. i
(cmd interface{}, expectedServers int, retry bool)
| 498 | // if retry==false, calls Start() only once, in order |
| 499 | // to simplify the early Lab 2B tests. |
| 500 | func (cfg *config) one(cmd interface{}, expectedServers int, retry bool) int { |
| 501 | t0 := time.Now() |
| 502 | starts := 0 |
| 503 | for time.Since(t0).Seconds() < 10 { |
| 504 | // try all the servers, maybe one is the leader. |
| 505 | index := -1 |
| 506 | for si := 0; si < cfg.n; si++ { |
| 507 | starts = (starts + 1) % cfg.n |
| 508 | var rf *Raft |
| 509 | cfg.mu.Lock() |
| 510 | if cfg.connected[starts] { |
| 511 | rf = cfg.rafts[starts] |
| 512 | } |
| 513 | cfg.mu.Unlock() |
| 514 | if rf != nil { |
| 515 | index1, _, ok := rf.Start(cmd) |
| 516 | if ok { |
| 517 | index = index1 |
| 518 | break |
| 519 | } |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | if index != -1 { |
| 524 | // somebody claimed to be the leader and to have |
| 525 | // submitted our command; wait a while for agreement. |
| 526 | t1 := time.Now() |
| 527 | for time.Since(t1).Seconds() < 2 { |
| 528 | nd, cmd1 := cfg.nCommitted(index) |
| 529 | if nd > 0 && nd >= expectedServers { |
| 530 | // committed |
| 531 | if cmd1 == cmd { |
| 532 | // and it was the command we submitted. |
| 533 | return index |
| 534 | } |
| 535 | } |
| 536 | time.Sleep(20 * time.Millisecond) |
| 537 | } |
| 538 | if retry == false { |
| 539 | cfg.t.Fatalf("one(%v) failed to reach agreement", cmd) |
| 540 | } |
| 541 | } else { |
| 542 | time.Sleep(50 * time.Millisecond) |
| 543 | } |
| 544 | } |
| 545 | cfg.t.Fatalf("one(%v) failed to reach agreement", cmd) |
| 546 | return -1 |
| 547 | } |
| 548 | |
| 549 | // start a Test. |
| 550 | // print the Test message. |