Through the study of "Redis design and implementation", I intend to implement a "Redis source code" as my own learning record.
Students interested in Redis can view another article of mine Make a wheel write a Redis by yourself.
This chapter introduces the dictionary in Redis source code and the implementation of its internal hash table.
Implementation of dictionary dict
API of dict
(1) create a new dictionarydict dictCreate(dictType type,int hashSize);
(2) find the corresponding node in the hashTable according to the keydictEntry lookup(dict d,void *key);
(3) add the given key value pair to the dictionary(if the key already exists in the dictionary, replace the old value with the new value)
bool dictInsert(dict d, void key, void *val);
void dictFetchValue(dict d, void *key);
(5) delete the key value pair corresponding to the given key from the dictionaryvoid dictDelete(dict d, void key);
(6) release the given dictionary and all key value pairs contained in the dictionaryvoid dictRelease(dict *d);
Header file
#ifndef __DICT_H #define __DICT_H //The nodes of hash table are represented by dictEntry structure //Each dictEntry structure holds a key value typedef struct dictEntry{ //key void *key; //value void *value; //Point to the next hash table node to form a linked list -- avoid key conflicts struct dictEntry *next; }dictEntry; //Save a set of functions for manipulating a specific type of key value pair typedef struct dictType { //Function to calculate hash value unsigned int (*hashFunction)(void *key,int size); //Copy function of key void *(*keyDup)(void *key); //Function to copy values void *(*valDup)(void *obj); //Functions of comparison keys int (*keyCompare)(void *key1, void *key2); //Function to destroy key void (*keyDestructor)(void *key); //Function to destroy value void (*valDestructor)(void *obj); } dictType; //Hashtable typedef struct dictht { //Hash table array dictEntry **table; //Hash table size int size; //Number of existing nodes in the hash table int used; } dictht; //Dictionaries //In fact, a dictionary is another layer of encapsulation for a common hash table //Added some attributes typedef struct dict { //Type specific function dictType *type; //Hashtable dictht *ht; } dict; //Create a new dictionary //The size of the incoming hash table is required dict *dictCreate(dictType *type,int hashSize); //Find the corresponding node in hashTable according to key dictEntry* lookup(dict *d,void *key); //Add the given key value pair to the dictionary //Add the given key value pair to the dictionary. If the key already exists in the dictionary, //Then replace the original value with the new value bool dictInsert(dict *d, void *key, void *val); //Returns the value of the given key void *dictFetchValue(dict *d, void *key); //Delete the key value pair corresponding to the given key from the dictionary void dictDelete(dict *d, void *key); //Release the given dictionary and all key value pairs contained in the dictionary void dictRelease(dict *d); #endif
Implementation of dict API
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "dict.h" //Size of hash table #define HASHSIZE 10 //Define the set of functions that operate on the hash table //Function to calculate hash value unsigned int myHashFunction(void *key,int size){ char* charkey=(char*)key; unsigned int hash=0; for(;*charkey;++charkey){ hash=hash*33+*charkey; } return hash%size; } //Copy function of key void *myKeyDup(void *key){ return key; } //Function to copy values void *myValDup(void *obj){ return obj; } //Functions of comparison keys int myKeyCompare(void *key1, void *key2){ char*charkey1=(char*)key1; char*charkey2=(char*)key2; return strcmp(charkey1,charkey2); } //Function to destroy key void myKeyDestructor(void *key){ //free(key); } //Function to destroy value void myValDestructor(void *obj){ //free(obj); } //Create a new dictionary dict *dictCreate(dictType *type,int hashSize){ dict* d=(dict*)malloc(sizeof(dict)); //A specific set of functions related to hashTable operations if(type==NULL){ printf("PIG Redis WARNING : Type is NULL.\n"); } d->type=type; //Hash table initialization d->ht=(dictht*)malloc(sizeof(dictht)); d->ht->size=hashSize; d->ht->used=0; d->ht->table=(dictEntry**)malloc(sizeof(dictEntry*)*hashSize); //All nodes are set to NULL for(int i=0;i<hashSize;i++){ d->ht->table[i]=NULL; } return d; } //Find the corresponding node in hashTable according to key dictEntry* lookup(dict *d,void *key){ dictEntry* node; //The subscript corresponding to the key in the hashTable unsigned int index; index=d->type->hashFunction(key,d->ht->size); for(node=d->ht->table[index];node;node=node->next){ if(!(d->type->keyCompare(key,node->key))){ return node; } } return NULL; } //Add the given key value pair to the dictionary bool dictInsert(dict *d, void *key, void *val){ unsigned int index; dictEntry* node; if(!(node=lookup(d,key))){ index=d->type->hashFunction(key,d->ht->size); node=(dictEntry*)malloc(sizeof(dictEntry)); if(!node)return false; node->key=d->type->keyDup(key); node->next=d->ht->table[index]; d->ht->table[index]=node; } //If it exists, modify its corresponding value value directly node->value=d->type->valDup(val); return true; } //Returns the value of the given key void *dictFetchValue(dict *d, void *key){ unsigned int index; dictEntry* node; //This node cannot be found if(!(node=lookup(d,key))){ return NULL; } return node->value; } //Delete the key value pair corresponding to the given key from the dictionary void dictDelete(dict *d, void *key){ dictEntry* node; dictEntry* temp; //The subscript corresponding to the key in the hashTable unsigned int index; index=d->type->hashFunction(key,d->ht->size); node=d->ht->table[index]; //key is the same. if(!(d->type->keyCompare(key,node->key))){ d->ht->table[index]=node->next; d->type->keyDestructor(node->key); d->type->valDestructor(node->value); free(node); return; } temp=node; node=node->next; while(node){ if(!(d->type->keyCompare(key,node->key))){ temp->next=node->next; d->type->keyDestructor(node->key); d->type->valDestructor(node->value); free(node); return; } temp=node; node=node->next; } return; } //Release the given dictionary and all key value pairs contained in the dictionary void dictRelease(dict *d){ dictEntry* node; dictEntry* temp; for(int i=0;i<d->ht->size;i++){ node=d->ht->table[i]; //printf("%d\n",i); while(node){ char* t=(char*)node->value; //printf("%s\n",t); temp=node; node=node->next; d->type->keyDestructor(temp->key); d->type->valDestructor(temp->value); free(temp); } } free(d->ht); free(d->type); free(d); } /*int main(){ dictType*type=(dictType*)malloc(sizeof(dictType)); type->hashFunction=myHashFunction; type->keyDup=myKeyDup; type->valDup=myValDup; type->keyCompare=myKeyCompare; type->keyDestructor=myKeyDestructor; type->valDestructor=myValDestructor; dict* d=dictCreate(type,HASHSIZE); char*key1="sss"; char*value1="111"; bool result=dictInsert(d,key1,value1); if(result){ printf("insert1 success\n"); }else{ printf("insert1 fail\n"); } char*key2="3sd"; char*value2="ddd"; result=dictInsert(d,key2,value2); if(result){ printf("insert2 success\n"); }else{ printf("insert2 fail\n"); } char*key3="ddds"; char*value3="1ss"; result=dictInsert(d,key3,value3); if(result){ printf("insert3 success\n"); }else{ printf("insert3 fail\n"); } char *value4=(char*)dictFetchValue(d,key3); printf("---%s\n",value4); dictDelete(d,key3); value4=(char*)dictFetchValue(d,key3); printf("---%s\n",value4); dictRelease(d); system("pause"); return 0; }*/