long rehashidx; /* rehashing not in progress if rehashidx == -1 */
/* Keep small vars at end for optimal (minimal) struct padding */ int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */ signedchar ht_size_exp[2]; /* exponent of size. (size = 1<<exp) */
void *metadata[]; /* An arbitrary number of bytes (starting at a * pointer-aligned address) of size as defined * by dictType's dictEntryBytes. */ };
structdictEntry { void *key; union { void *val; uint64_t u64; int64_t s64; double d; } v; structdictEntry *next;/* Next entry in the same hash bucket. */ void *metadata[]; /* An arbitrary number of bytes (starting at a * pointer-aligned address) of size as returned * by dictType's dictEntryMetadataBytes(). */ };
/* rehash操作 */ if (dictIsRehashing(d)) _dictRehashStep(d); /* 移动元素的操作 */ d->ht_table[1][h] = de; d->ht_used[0]--; d->ht_used[1]++; de = nextde; } d->ht_table[0][d->rehashidx] = NULL; d->rehashidx++; /* 移动结束,切换指针 */ /* Check if we already rehashed the whole table... */ if (d->ht_used[0] == 0) { zfree(d->ht_table[0]); /* Copy the new ht onto the old one */ d->ht_table[0] = d->ht_table[1]; d->ht_used[0] = d->ht_used[1]; d->ht_size_exp[0] = d->ht_size_exp[1]; _dictReset(d, 1); d->rehashidx = -1; return0; }
判断key是否存在
什么时候会返回当前key?什么时候把key插入到当前entry的链表中?
1 2 3 4 5 6 7 8 9 10
/* Search if this slot does not already contain the given key */ void *he_key = dictGetKey(he); /* 如果key == he_key,则判断existing是否为空,如果不为空,赋值*existing,调用方可以通过*existing获取当前节点*/ /* 如果key != he_key, 则通过next指针进行往下找*/ if (key == he_key || dictCompareKeys(d, key, he_key)) { if (existing) *existing = he; returnNULL; } he = dictGetNext(he);
structredisObject { unsigned type:4; unsigned encoding:4; unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or * LFU data (least significant 8 bits frequency * and most significant 16 bits access time). */ int refcount; void *ptr; };
Type
代表各种数据类型。包含5种,分别如下:
1 2 3 4 5 6
/* The actual Redis Object */ #define OBJ_STRING 0 /* String object. */ #define OBJ_LIST 1 /* List object. */ #define OBJ_SET 2 /* Set object. */ #define OBJ_ZSET 3 /* Sorted set object. */ #define OBJ_HASH 4 /* Hash object. */
/* Objects encoding. Some kind of objects like Strings and Hashes can be * internally represented in multiple ways. The 'encoding' field of the object * is set to one of this fields for this object. */ #define OBJ_ENCODING_RAW 0 /* Raw representation */ #define OBJ_ENCODING_INT 1 /* Encoded as integer */ #define OBJ_ENCODING_HT 2 /* Encoded as hash table */ #define OBJ_ENCODING_ZIPMAP 3 /* No longer used: old hash encoding. */ #define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */ #define OBJ_ENCODING_ZIPLIST 5 /* No longer used: old list/hash/zset encoding. */ #define OBJ_ENCODING_INTSET 6 /* Encoded as intset */ #define OBJ_ENCODING_SKIPLIST 7 /* Encoded as skiplist */ #define OBJ_ENCODING_EMBSTR 8 /* Embedded sds string encoding */ #define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of listpacks */ #define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */ #define OBJ_ENCODING_LISTPACK 11 /* Encoded as a listpack */
/* quicklist is a 40 byte struct (on 64-bit systems) describing a quicklist */ typedefstructquicklist { quicklistNode *head; quicklistNode *tail; unsignedlong count; /* total count of all entries in all listpacks */ unsignedlong len; /* number of quicklistNodes */ signedint fill : QL_FILL_BITS; /* fill factor for individual nodes */ unsignedint compress : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */ unsignedint bookmark_count: QL_BM_BITS; quicklistBookmark bookmarks[]; } quicklist;
/* quicklistNode is a 32 byte struct describing a listpack for a quicklist */ typedefstructquicklistNode { structquicklistNode *prev; structquicklistNode *next; unsignedchar *entry; size_t sz; /* entry size in bytes */ unsignedint count : 16; /* count of items in listpack */ unsignedint encoding : 2; /* RAW==1 or LZF==2 */ unsignedint container : 2; /* PLAIN==1 or PACKED==2 */ unsignedint recompress : 1; /* was this node previous compressed? */ unsignedint attempted_compress : 1; /* node can't compress; too small */ unsignedint dont_compress : 1; /* prevent compression of entry that will be used later */ unsignedint extra : 9; /* more bits to steal for future usage */ } quicklistNode;
/* Wrapper to allow argument-based switching between HEAD/TAIL pop */ voidquicklistPush(quicklist *quicklist, void *value, constsize_t sz, int where) { /* The head and tail should never be compressed (we don't attempt to decompress them) */ if (quicklist->head) assert(quicklist->head->encoding != QUICKLIST_NODE_ENCODING_LZF); if (quicklist->tail) assert(quicklist->tail->encoding != QUICKLIST_NODE_ENCODING_LZF);
/* Add new entry to head node of quicklist. * * Returns 0 if used existing head. * Returns 1 if new head created. */ intquicklistPushHead(quicklist *quicklist, void *value, size_t sz) { quicklistNode *orig_head = quicklist->head;
if (unlikely(isLargeElement(sz))) { __quicklistInsertPlainNode(quicklist, quicklist->head, value, sz, 0); return1; }