15 #include "default_engine.h" 
   17 #define hashsize(n) ((uint32_t)1<<(n)) 
   18 #define hashmask(n) (hashsize(n)-1) 
   21     engine->assoc.primary_hashtable = calloc(hashsize(engine->assoc.hashpower), 
sizeof(
void *));
 
   22     return (engine->assoc.primary_hashtable != NULL) ? ENGINE_SUCCESS : ENGINE_ENOMEM;
 
   27     unsigned int oldbucket;
 
   29     if (engine->assoc.expanding &&
 
   30         (oldbucket = (hash & hashmask(engine->assoc.hashpower - 1))) >= engine->assoc.expand_bucket)
 
   32         it = engine->assoc.old_hashtable[oldbucket];
 
   34         it = engine->assoc.primary_hashtable[hash & hashmask(engine->assoc.hashpower)];
 
   40         if ((nkey == it->
nkey) && (memcmp(key, item_get_key(it), nkey) == 0)) {
 
   47     MEMCACHED_ASSOC_FIND(key, nkey, depth);
 
   59     unsigned int oldbucket;
 
   61     if (engine->assoc.expanding &&
 
   62         (oldbucket = (hash & hashmask(engine->assoc.hashpower - 1))) >= engine->assoc.expand_bucket)
 
   64         pos = &engine->assoc.old_hashtable[oldbucket];
 
   66         pos = &engine->assoc.primary_hashtable[hash & hashmask(engine->assoc.hashpower)];
 
   69     while (*pos && ((nkey != (*pos)->nkey) || memcmp(key, item_get_key(*pos), nkey))) {
 
   70         pos = &(*pos)->h_next;
 
   75 static void *assoc_maintenance_thread(
void *arg);
 
   79     engine->assoc.old_hashtable = engine->assoc.primary_hashtable;
 
   81     engine->assoc.primary_hashtable = calloc(hashsize(engine->assoc.hashpower + 1), 
sizeof(
void *));
 
   82     if (engine->assoc.primary_hashtable) {
 
   83         engine->assoc.hashpower++;
 
   84         engine->assoc.expanding = 
true;
 
   85         engine->assoc.expand_bucket = 0;
 
   92         if (pthread_attr_init(&attr) != 0 ||
 
   93             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0 ||
 
   94             (ret = pthread_create(&tid, &attr,
 
   95                                   assoc_maintenance_thread, engine)) != 0)
 
   99             logger->
log(EXTENSION_LOG_WARNING, NULL,
 
  100                         "Can't create thread: %s\n", strerror(ret));
 
  101             engine->assoc.hashpower--;
 
  102             engine->assoc.expanding = 
false;
 
  103             free(engine->assoc.primary_hashtable);
 
  104             engine->assoc.primary_hashtable =engine->assoc.old_hashtable;
 
  107         engine->assoc.primary_hashtable = engine->assoc.old_hashtable;
 
  114     unsigned int oldbucket;
 
  116     assert(assoc_find(engine, hash, item_get_key(it), it->
nkey) == 0);  
 
  118     if (engine->assoc.expanding &&
 
  119         (oldbucket = (hash & hashmask(engine->assoc.hashpower - 1))) >= engine->assoc.expand_bucket)
 
  121         it->h_next = engine->assoc.old_hashtable[oldbucket];
 
  122         engine->assoc.old_hashtable[oldbucket] = it;
 
  124         it->h_next = engine->assoc.primary_hashtable[hash & hashmask(engine->assoc.hashpower)];
 
  125         engine->assoc.primary_hashtable[hash & hashmask(engine->assoc.hashpower)] = it;
 
  128     engine->assoc.hash_items++;
 
  129     if (! engine->assoc.expanding && engine->assoc.hash_items > (hashsize(engine->assoc.hashpower) * 3) / 2) {
 
  130         assoc_expand(engine);
 
  133     MEMCACHED_ASSOC_INSERT(item_get_key(it), it->
nkey, engine->assoc.hash_items);
 
  137 void assoc_delete(
struct default_engine *engine, uint32_t hash, 
const char *key, 
const size_t nkey) {
 
  138     hash_item **before = _hashitem_before(engine, hash, key, nkey);
 
  142         engine->assoc.hash_items--;
 
  146         MEMCACHED_ASSOC_DELETE(key, nkey, engine->assoc.hash_items);
 
  147         nxt = (*before)->h_next;
 
  148         (*before)->h_next = 0;   
 
  154     assert(*before != 0);
 
  159 #define DEFAULT_HASH_BULK_MOVE 1 
  160 int hash_bulk_move = DEFAULT_HASH_BULK_MOVE;
 
  162 static void *assoc_maintenance_thread(
void *arg) {
 
  169         for (ii = 0; ii < hash_bulk_move && engine->assoc.expanding; ++ii) {
 
  173             for (it = engine->assoc.old_hashtable[engine->assoc.expand_bucket];
 
  174                  NULL != it; it = next) {
 
  177                 bucket = engine->server.core->
hash(item_get_key(it), it->
nkey, 0)
 
  178                     & hashmask(engine->assoc.hashpower);
 
  179                 it->h_next = engine->assoc.primary_hashtable[bucket];
 
  180                 engine->assoc.primary_hashtable[bucket] = it;
 
  183             engine->assoc.old_hashtable[engine->assoc.expand_bucket] = NULL;
 
  184             engine->assoc.expand_bucket++;
 
  185             if (engine->assoc.expand_bucket == hashsize(engine->assoc.hashpower - 1)) {
 
  186                 engine->assoc.expanding = 
false;
 
  187                 free(engine->assoc.old_hashtable);
 
  188                 if (engine->config.verbose > 1) {
 
  191                     logger->
log(EXTENSION_LOG_INFO, NULL,
 
  192                                 "Hash table expansion done\n");
 
  196         if (!engine->assoc.expanding) {