//item的具体结构 typedefstruct_stritem { //记录下一个item的地址,主要用于LRU链和freelist链 struct_stritem *next; //记录上一个item的地址,主要用于LRU链和freelist链 struct_stritem *prev; //记录HashTable的下一个Item的地址 struct_stritem *h_next; //最近访问的时间,只有set/add/replace等操作才会更新这个字段 //当执行flush命令的时候,需要用这个时间和执行flush命令的时间相比较,来判断是否失效 rel_time_t time; /* least recent access */ //缓存的过期时间。设置为0的时候,则永久有效。 //如果Memcached不能分配新的item的时候,设置为0的item也有可能被LRU淘汰 rel_time_t exptime; /* expire time */ //value数据大小 int nbytes; /* size of data */ //引用的次数。通过这个引用的次数,可以判断item是否被其它的线程在操作中。 //也可以通过refcount来判断当前的item是否可以被删除,只有refcount -1 = 0的时候才能被删除 unsignedshort refcount; uint8_t nsuffix; /* length of flags-and-length string */ uint8_t it_flags; /* ITEM_* above */ //slabs_class的ID。 uint8_t slabs_clsid;/* which slab class we're in */ uint8_t nkey; /* key length, w/terminating null and padding */ /* this odd type prevents type-punning issues when we do * the little shuffle to save space when not using CAS. */ //数据存储结构 union { uint64_t cas; char end; } data[]; /* if it_flags & ITEM_CAS we have 8 bytes CAS */ /* then null-terminated key */ /* then " flags length\r\n" (no terminating null) */ /* then data with terminating \r\n (no terminating null; it's binary!) */ } item;
//如果Item存在,则当前的Item值指向下一个Item的指针地址 if (*before) { item *nxt; hash_items--; //item个数减去1 /* The DTrace probe cannot be triggered as the last instruction * due to possible tail-optimization by the compiler */ MEMCACHED_ASSOC_DELETE(key, nkey, hash_items); nxt = (*before)->h_next; (*before)->h_next = 0; /* probably pointless, but whatever. */ *before = nxt; return; } /* Note: we never actually get here. the callers don't delete things they can't find. */ assert(*before != 0); }
staticvoidassoc_start_expand(void){ if (started_expanding) return; started_expanding = true; //唤醒线程 pthread_cond_signal(&maintenance_cond); } /* grows the hashtable to the next power of 2. */ //扩容方法 staticvoidassoc_expand(void){ old_hashtable = primary_hashtable;