Dictionary and hash table to implement Redis source code

Through the study of "Redis design and implementation", I intend to implement a "Redis source code" as my own learning record. Stu...
Implementation of dictionary dict

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 dictionary

dict dictCreate(dictType type,int hashSize);

(2) find the corresponding node in the hashTable according to the key

dictEntry 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);

(4) return the value of the given key

void dictFetchValue(dict d, void *key);

(5) delete the key value pair corresponding to the given key from the dictionary

void dictDelete(dict d, void key);

(6) release the given dictionary and all key value pairs contained in the dictionary

void 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; }*/



3 December 2019, 10:09 | Views: 3124

Add new comment

For adding a comment, please log in
or create account

0 comments