uint32_t server_pool_idx(struct server_pool *pool, uint8_t *key, uint32_t keylen) { uint32_t hash, idx; ASSERT(array_n(&pool->server) != 0); ASSERT(key != NULL); /* * If hash_tag: is configured for this server pool, we use the part of * the key within the hash tag as an input to the distributor. Otherwise * we use the full key */ if (!string_empty(&pool->hash_tag)) { struct string *tag = &pool->hash_tag; uint8_t *tag_start, *tag_end; tag_start = nc_strchr(key, key + keylen, tag->data[0]); if (tag_start != NULL) { tag_end = nc_strchr(tag_start + 1, key + keylen, tag->data[1]); if ((tag_end != NULL) && (tag_end - tag_start > 1)) { key = tag_start + 1; keylen = (uint32_t)(tag_end - key); } } } switch (pool->dist_type) { case DIST_KETAMA: hash = server_pool_hash(pool, key, keylen); idx = ketama_dispatch(pool->continuum, pool->ncontinuum, hash); break; case DIST_MODULA: hash = server_pool_hash(pool, key, keylen); idx = modula_dispatch(pool->continuum, pool->ncontinuum, hash); break; case DIST_RANDOM: idx = random_dispatch(pool->continuum, pool->ncontinuum, 0); break; default: NOT_REACHED(); return 0; } ASSERT(idx < array_n(&pool->server)); return idx; }
static struct server * server_pool_server(struct server_pool *pool, uint8_t *key, uint32_t keylen) { struct server *server; uint32_t hash, idx; ASSERT(array_n(&pool->server) != 0); ASSERT(key != NULL && keylen != 0); switch (pool->dist_type) { case DIST_KETAMA: hash = server_pool_hash(pool, key, keylen); idx = ketama_dispatch(pool->continuum, pool->ncontinuum, hash); break; case DIST_MODULA: hash = server_pool_hash(pool, key, keylen); idx = modula_dispatch(pool->continuum, pool->ncontinuum, hash); break; case DIST_RANDOM: idx = random_dispatch(pool->continuum, pool->ncontinuum, 0); break; default: NOT_REACHED(); return NULL; } ASSERT(idx < array_n(&pool->server)); server = array_get(&pool->server, idx); log_debug(LOG_VERB, "key '%.*s' on dist %d maps to server '%.*s'", keylen, key, pool->dist_type, server->pname.len, server->pname.data); return server; }
static struct server * dnode_peer_pool_server(struct server_pool *pool, struct rack *rack, uint8_t *key, uint32_t keylen) { struct server *server; uint32_t hash, idx; struct dyn_token *token = NULL; ASSERT(array_n(&pool->peers) != 0); //ASSERT(rack != NULL); switch (pool->dist_type) { case DIST_KETAMA: token = dnode_peer_pool_hash(pool, key, keylen); hash = token->mag[0]; idx = ketama_dispatch(rack->continuum, rack->ncontinuum, hash); break; case DIST_VNODE: if (keylen == 0) { idx = 0; //for no argument command break; } token = dnode_peer_pool_hash(pool, key, keylen); //print_dyn_token(token, 1); idx = vnode_dispatch(rack->continuum, rack->ncontinuum, token); //loga("found idx %d for rack '%.*s' ", idx, rack->name->len, rack->name->data); break; case DIST_MODULA: token = dnode_peer_pool_hash(pool, key, keylen); hash = token->mag[0]; idx = modula_dispatch(rack->continuum, rack->ncontinuum, hash); break; case DIST_RANDOM: idx = random_dispatch(rack->continuum, rack->ncontinuum, 0); break; case DIST_SINGLE: idx = 0; break; default: NOT_REACHED(); return NULL; } //TODOs: should reuse the token if (token != NULL) { deinit_dyn_token(token); dn_free(token); } ASSERT(idx < array_n(&pool->peers)); server = array_get(&pool->peers, idx); log_debug(LOG_VERB, "dyn: key '%.*s' on dist %d maps to server '%.*s'", keylen, key, pool->dist_type, server->pname.len, server->pname.data); return server; }