static mmc_t *mmc_consistent_find(mmc_consistent_state_t *state, unsigned int point) /* {{{ */ { int lo = 0, hi = state->num_points - 1, mid; while (1) { /* point is outside interval or lo >= hi, wrap-around */ if (point <= state->points[lo].point || point > state->points[hi].point) { return state->points[lo].server; } /* test middle point */ mid = lo + (hi - lo) / 2; MMC_DEBUG(("mmc_consistent_find: lo %d, hi %d, mid %d, point %u, midpoint %u", lo, hi, mid, point, state->points[mid].point)); /* perfect match */ if (point <= state->points[mid].point && point > (mid ? state->points[mid-1].point : 0)) { return state->points[mid].server; } /* too low, go up */ if (state->points[mid].point < point) { lo = mid + 1; } else { hi = mid - 1; } } }
mmc_t *mmc_consistent_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */ { mmc_consistent_state_t *state = s; mmc_t *mmc; if (state->num_servers > 1) { unsigned int i, hash = state->hash(key, key_len); if (!state->buckets_populated) { mmc_consistent_populate_buckets(state); } mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS]; /* perform failover if needed */ for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) { char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1); int next_len = sprintf(next_key, "%s-%d", key, i); MMC_DEBUG(("mmc_consistent_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status)); hash = state->hash(next_key, next_len); mmc = state->buckets[hash % MMC_CONSISTENT_BUCKETS]; efree(next_key); } } else { mmc = state->points[0].server; mmc_open(mmc, 0, NULL, NULL TSRMLS_CC); } return mmc->status != MMC_STATUS_FAILED ? mmc : NULL; }
mmc_t *mmc_standard_find_server(void *s, const char *key, int key_len TSRMLS_DC) /* {{{ */ { mmc_standard_state_t *state = s; mmc_t *mmc; if (state->num_servers > 1) { unsigned int hash = mmc_hash(state, key, key_len), i; mmc = state->buckets[hash % state->num_buckets]; /* perform failover if needed */ for (i=0; !mmc_open(mmc, 0, NULL, NULL TSRMLS_CC) && MEMCACHE_G(allow_failover) && i<MEMCACHE_G(max_failover_attempts); i++) { char *next_key = emalloc(key_len + MAX_LENGTH_OF_LONG + 1); int next_len = sprintf(next_key, "%d%s", i+1, key); MMC_DEBUG(("mmc_standard_find_server: failed to connect to server '%s:%d' status %d, trying next", mmc->host, mmc->port, mmc->status)); hash += mmc_hash(state, next_key, next_len); mmc = state->buckets[hash % state->num_buckets]; efree(next_key); } } else { mmc = state->buckets[0]; mmc_open(mmc, 0, NULL, NULL TSRMLS_CC); } return mmc->status != MMC_STATUS_FAILED ? mmc : NULL; }
void mmc_consistent_add_server(void *s, mmc_t *mmc, unsigned int weight) /* {{{ */ { mmc_consistent_state_t *state = s; int i, key_len, points = weight * MMC_CONSISTENT_POINTS; /* buffer for "host:port-i\0" */ char *key = emalloc(strlen(mmc->host) + MAX_LENGTH_OF_LONG * 2 + 3); /* add weight * MMC_CONSISTENT_POINTS number of points for this server */ state->points = erealloc(state->points, sizeof(mmc_consistent_point_t) * (state->num_points + points)); for (i=0; i<points; i++) { key_len = sprintf(key, "%s:%d-%d", mmc->host, mmc->port, i); state->points[state->num_points + i].server = mmc; state->points[state->num_points + i].point = state->hash(key, key_len); MMC_DEBUG(("mmc_consistent_add_server: key %s, point %lu", key, state->points[state->num_points + i].point)); } state->num_points += points; state->num_servers++; state->buckets_populated = 0; efree(key); }