| 4702 | } |
| 4703 | |
| 4704 | sentinelRedisInstance *sentinelSelectSlave(sentinelRedisInstance *master) { |
| 4705 | sentinelRedisInstance **instance = (sentinelRedisInstance**) |
| 4706 | zmalloc(sizeof(instance[0])*dictSize(master->slaves), MALLOC_LOCAL); |
| 4707 | sentinelRedisInstance *selected = NULL; |
| 4708 | int instances = 0; |
| 4709 | dictIterator *di; |
| 4710 | dictEntry *de; |
| 4711 | mstime_t max_master_down_time = 0; |
| 4712 | |
| 4713 | if (master->flags & SRI_S_DOWN) |
| 4714 | max_master_down_time += mstime() - master->s_down_since_time; |
| 4715 | max_master_down_time += master->down_after_period * 10; |
| 4716 | |
| 4717 | di = dictGetIterator(master->slaves); |
| 4718 | while((de = dictNext(di)) != NULL) { |
| 4719 | sentinelRedisInstance *slave = (sentinelRedisInstance*)dictGetVal(de); |
| 4720 | mstime_t info_validity_time; |
| 4721 | |
| 4722 | if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue; |
| 4723 | if (slave->link->disconnected) continue; |
| 4724 | if (mstime() - slave->link->last_avail_time > SENTINEL_PING_PERIOD*5) continue; |
| 4725 | if (slave->slave_priority == 0) continue; |
| 4726 | |
| 4727 | /* If the master is in SDOWN state we get INFO for slaves every second. |
| 4728 | * Otherwise we get it with the usual period so we need to account for |
| 4729 | * a larger delay. */ |
| 4730 | if (master->flags & SRI_S_DOWN) |
| 4731 | info_validity_time = SENTINEL_PING_PERIOD*5; |
| 4732 | else |
| 4733 | info_validity_time = SENTINEL_INFO_PERIOD*3; |
| 4734 | if (mstime() - slave->info_refresh > info_validity_time) continue; |
| 4735 | if (slave->master_link_down_time > max_master_down_time) continue; |
| 4736 | instance[instances++] = slave; |
| 4737 | } |
| 4738 | dictReleaseIterator(di); |
| 4739 | if (instances) { |
| 4740 | qsort(instance,instances,sizeof(sentinelRedisInstance*), |
| 4741 | compareSlavesForPromotion); |
| 4742 | selected = instance[0]; |
| 4743 | } |
| 4744 | zfree(instance); |
| 4745 | return selected; |
| 4746 | } |
| 4747 | |
| 4748 | /* ---------------- Failover state machine implementation ------------------- */ |
| 4749 | void sentinelFailoverWaitStart(sentinelRedisInstance *ri) { |
no test coverage detected