... if (hash_init(hash_type) != 0) { fprintf(stderr, "Failed to initialize hash_algorithm!\n"); exit(EX_USAGE); } ...
main@memcached.c:5849
其中参数 hash_type 被设置为 MURMUR3_HASH。这个是由命令行参数 modern 决定的。
... case MODERN: /* Modernized defaults. Need to add equivalent no_* flags * before making truly default. */ ... hash_type = MURMUR3_HASH; ... break; ...
main@memcached.c:5849
第二个方法
assoc_init
为上述固定大小数组分配内存。
voidassoc_init(constint hashtable_init){ if (hashtable_init) { hashpower = hashtable_init; } primary_hashtable = calloc(hashsize(hashpower), sizeof(void *)); if (! primary_hashtable) { fprintf(stderr, "Failed to init hashtable.\n"); exit(EXIT_FAILURE); } ...// scr: stat }
... case HASHPOWER_INIT: if (subopts_value == NULL) { fprintf(stderr, "Missing numeric argument for hashpower\n"); return1; } settings.hashpower_init = atoi(subopts_value); if (settings.hashpower_init < 12) { fprintf(stderr, "Initial hashtable multiplier of %d is too low\n", settings.hashpower_init); return1; } elseif (settings.hashpower_init > 64) { fprintf(stderr, "Initial hashtable multiplier of %d is too high\n" "Choose a value based on \"STAT hash_power_level\" from a running instance\n", settings.hashpower_init); return1; } break; ...
mutex_lock(&maintenance_lock); while (do_run_maintenance_thread/* scr: the flag*/) { int ii = 0;
/* There is only one expansion thread, so no need to global lock. */ for (ii = 0; ii < hash_bulk_move && expanding; ++ii) { // scr: ----> 2) item *it, *next; int bucket; void *item_lock = NULL;
/* bucket = hv & hashmask(hashpower) =>the bucket of hash table * is the lowest N bits of the hv, and the bucket of item_locks is * also the lowest M bits of hv, and N is greater than M. * So we can process expanding with only one item_lock. cool! */ if ((item_lock = item_trylock(expand_bucket))) { // scr: --------> 3) for (it = old_hashtable[expand_bucket]; NULL != it; it = next) { next = it->h_next; // scr: ----------------------------------> 4) bucket = hash(ITEM_key(it), it->nkey) & hashmask(hashpower); it->h_next = primary_hashtable[bucket]; primary_hashtable[bucket] = it; }
if (!expanding) { /* We are done expanding.. just wait for next invocation */ started_expanding = false; pthread_cond_wait(&maintenance_cond, &maintenance_lock); // scr: > 0) /* assoc_expand() swaps out the hash table entirely, so we need * all threads to not hold any references related to the hash * table while this happens. * This is instead of a more complex, possibly slower algorithm to * allow dynamic hash table expansion without causing significant * wait times. */ pause_threads(PAUSE_ALL_THREADS); assoc_expand(); // scr: -----------------------------------------> 1) pause_threads(RESUME_ALL_THREADS); } } returnNULL; }