AFFEND static void hashtable_expand(arc *c, value hash) { unsigned int hv, index, i, j, nhashbits; value oldtbl, newtbl, e; nhashbits = HASH_BITS(hash) + 1; newtbl = arc_mkvector(c, HASHSIZE(nhashbits)); ((struct cell *)newtbl)->_type = T_TABLEVEC; for (i=0; i<HASHSIZE(nhashbits); i++) XVINDEX(newtbl, i) = CUNBOUND; oldtbl = HASH_TABLE(hash); /* Search for active keys and move them into the new table */ for (i=0; i<VECLEN(oldtbl); i++) { e = VINDEX(oldtbl, i); if (EMPTYP(e)) continue; /* remove the old link now that we have a copy */ SVINDEX(oldtbl, i, CUNBOUND); /* insert the old key into the new table */ hv = (unsigned int)FIX2INT(BHASHVAL(e)); index = hv & HASHMASK(nhashbits); for (j=0; !EMPTYP(VINDEX(newtbl, index)); j++) index = (index + PROBE(j)) & HASHMASK(nhashbits); BTABLE(e) = newtbl; XVINDEX(newtbl, index) = e; SBINDEX(e, index); /* change index */ SVINDEX(oldtbl, i, CUNBOUND); } SET_HASHBITS(hash, nhashbits); SET_LLIMIT(hash, (HASHSIZE(nhashbits)*MAX_LOAD_FACTOR) / 100); HASH_TABLE(hash) = newtbl; }
struct hash_table * hashtable_create(uint32_t hash_power) { struct hash_table *ht; uint64_t size; ASSERT(hash_power > 0); /* alloc struct */ ht = cc_alloc(sizeof(struct hash_table)); if (ht == NULL) { return NULL; } /* init members */ ht->table = NULL; ht->hash_power = hash_power; ht->nhash_item = 0; size = HASHSIZE(ht->hash_power); /* alloc table */ ht->table = _hashtable_alloc(size); if (ht->table == NULL) { cc_free(ht); return NULL; } return ht; }
value arc_mkhash(arc *c, int hashbits) { value hash, hv; int i; hash = arc_mkobject(c, sizeof(value)*HASH_SIZE, T_TABLE); SET_HASHBITS(hash, hashbits); SET_NENTRIES(hash, 0); SET_LLIMIT(hash, (HASHSIZE(hashbits)*MAX_LOAD_FACTOR) / 100); hv = arc_mkvector(c, HASHSIZE(hashbits)); ((struct cell *)hv)->_type = T_TABLEVEC; HASH_TABLE(hash) = hv; for (i=0; i<HASHSIZE(hashbits); i++) XVINDEX(HASH_TABLE(hash), i) = CUNBOUND; return(hash); }
static void * assoc_maintenance_thread(void *arg) { uint32_t i, hv; struct item_slh *old_bucket, *new_bucket; struct item *it, *next; while (run_maintenance_thread) { /* * Lock the cache, and bulk move multiple buckets to the new * hash table */ pthread_mutex_lock(&cache_lock); for (i = 0; i < nhash_move_size && expanding == 1; i++) { old_bucket = &old_hashtable[expand_bucket]; SLIST_FOREACH_SAFE(it, old_bucket, h_sle, next) { hv = hash(item_key(it), it->nkey, 0); new_bucket = &primary_hashtable[hv & HASHMASK(hash_power)]; SLIST_REMOVE(old_bucket, it, item, h_sle); SLIST_INSERT_HEAD(new_bucket, it, h_sle); } expand_bucket++; if (expand_bucket == HASHSIZE(hash_power - 1)) { expanding = 0; mc_free(old_hashtable); nbyte_old = 0; } } if (expanding == 0) { /* we are done expanding, just wait for the next invocation */ pthread_cond_wait(&maintenance_cond, &cache_lock); } pthread_mutex_unlock(&cache_lock); }