(sentinels []string, timeout time.Duration)
| 342 | } |
| 343 | |
| 344 | func (s *Sentinel) Masters(sentinels []string, timeout time.Duration) (map[int]string, error) { |
| 345 | cntx, cancel := context.WithTimeout(s.Context, timeout) |
| 346 | defer cancel() |
| 347 | |
| 348 | timeout += time.Second * 5 |
| 349 | results := make(chan map[int]*SentinelMaster, len(sentinels)) |
| 350 | |
| 351 | var majority = 1 + len(sentinels)/2 |
| 352 | |
| 353 | for i := range sentinels { |
| 354 | go func(sentinel string) { |
| 355 | masters, err := s.mastersDispatch(cntx, sentinel, timeout) |
| 356 | if err != nil { |
| 357 | s.errorf(err, "sentinel-[%s] masters failed", sentinel) |
| 358 | } |
| 359 | results <- masters |
| 360 | }(sentinels[i]) |
| 361 | } |
| 362 | |
| 363 | masters := make(map[int]string) |
| 364 | current := make(map[int]*SentinelMaster) |
| 365 | |
| 366 | var voted int |
| 367 | for alive := len(sentinels); ; alive-- { |
| 368 | if alive == 0 { |
| 369 | switch { |
| 370 | case cntx.Err() != context.DeadlineExceeded && cntx.Err() != nil: |
| 371 | s.printf("sentinel masters canceled (%v)", cntx.Err()) |
| 372 | return nil, errors.Trace(cntx.Err()) |
| 373 | case voted != len(sentinels): |
| 374 | s.printf("sentinel masters voted = (%d/%d) masters = %d (%v)", voted, len(sentinels), len(masters), cntx.Err()) |
| 375 | } |
| 376 | if voted < majority { |
| 377 | return nil, errors.Errorf("lost majority (%d/%d)", voted, len(sentinels)) |
| 378 | } |
| 379 | return masters, nil |
| 380 | } |
| 381 | select { |
| 382 | case <-cntx.Done(): |
| 383 | switch { |
| 384 | case cntx.Err() != context.DeadlineExceeded: |
| 385 | s.printf("sentinel masters canceled (%v)", cntx.Err()) |
| 386 | return nil, errors.Trace(cntx.Err()) |
| 387 | default: |
| 388 | s.printf("sentinel masters voted = (%d/%d) masters = %d (%v)", voted, len(sentinels), len(masters), cntx.Err()) |
| 389 | } |
| 390 | if voted < majority { |
| 391 | return nil, errors.Errorf("lost majority (%d/%d)", voted, len(sentinels)) |
| 392 | } |
| 393 | return masters, nil |
| 394 | case m := <-results: |
| 395 | if m == nil { |
| 396 | continue |
| 397 | } |
| 398 | for gid, master := range m { |
| 399 | if current[gid] == nil || current[gid].Epoch < master.Epoch { |
| 400 | current[gid] = master |
| 401 | masters[gid] = master.Addr |
no test coverage detected