X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/ed9b544e10b84cd43348ddfab7068b610a5df1f7..8bca8773b4e2542f9537b8403764867aa76273a5:/dict.c?ds=inline diff --git a/dict.c b/dict.c index 2d186c1d..23f7933b 100644 --- a/dict.c +++ b/dict.c @@ -5,7 +5,7 @@ * tables of power of two in size are used, collisions are handled by * chaining. See the source code for more information... :) * - * Copyright (c) 2006-2009, Salvatore Sanfilippo + * Copyright (c) 2006-2010, Salvatore Sanfilippo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,11 +33,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "fmacros.h" + #include #include #include #include #include +#include #include "dict.h" #include "zmalloc.h" @@ -57,7 +60,7 @@ static void _dictPanic(const char *fmt, ...) /* ------------------------- Heap Management Wrappers------------------------ */ -static void *_dictAlloc(int size) +static void *_dictAlloc(size_t size) { void *p = zmalloc(size); if (p == NULL) @@ -72,7 +75,7 @@ static void _dictFree(void *ptr) { /* -------------------------- private prototypes ---------------------------- */ static int _dictExpandIfNeeded(dict *ht); -static unsigned int _dictNextPower(unsigned int size); +static unsigned long _dictNextPower(unsigned long size); static int _dictKeyIndex(dict *ht, const void *key); static int _dictInit(dict *ht, dictType *type, void *privDataPtr); @@ -150,10 +153,10 @@ int dictResize(dict *ht) } /* Expand or create the hashtable */ -int dictExpand(dict *ht, unsigned int size) +int dictExpand(dict *ht, unsigned long size) { dict n; /* the new hashtable */ - unsigned int realsize = _dictNextPower(size), i; + unsigned long realsize = _dictNextPower(size), i; /* the size is invalid if it is smaller than the number of * elements already inside the hashtable */ @@ -223,21 +226,30 @@ int dictAdd(dict *ht, void *key, void *val) return DICT_OK; } -/* Add an element, discarding the old if the key already exists */ +/* Add an element, discarding the old if the key already exists. + * Return 1 if the key was added from scratch, 0 if there was already an + * element with such key and dictReplace() just performed a value update + * operation. */ int dictReplace(dict *ht, void *key, void *val) { - dictEntry *entry; + dictEntry *entry, auxentry; /* Try to add the element. If the key * does not exists dictAdd will suceed. */ if (dictAdd(ht, key, val) == DICT_OK) - return DICT_OK; + return 1; /* It already exists, get the entry */ entry = dictFind(ht, key); /* Free the old value and set the new one */ - dictFreeEntryVal(ht, entry); + /* Set the new value and free the old one. Note that it is important + * to do that in this order, as the value may just be exactly the same + * as the previous one. In this context, think to reference counting, + * you want to increment (set), and then decrement (free), and not the + * reverse. */ + auxentry = *entry; dictSetHashVal(ht, entry, val); - return DICT_OK; + dictFreeEntryVal(ht, &auxentry); + return 0; } /* Search and remove an element */ @@ -284,7 +296,7 @@ int dictDeleteNoFree(dict *ht, const void *key) { /* Destroy an entire hash table */ int _dictClear(dict *ht) { - unsigned int i; + unsigned long i; /* Free all the elements */ for (i = 0; i < ht->size && ht->used > 0; i++) { @@ -375,7 +387,7 @@ dictEntry *dictGetRandomKey(dict *ht) unsigned int h; int listlen, listele; - if (ht->size == 0) return NULL; + if (ht->used == 0) return NULL; do { h = random() & ht->sizemask; he = ht->table[h]; @@ -411,12 +423,11 @@ static int _dictExpandIfNeeded(dict *ht) } /* Our hash table capability is a power of two */ -static unsigned int _dictNextPower(unsigned int size) +static unsigned long _dictNextPower(unsigned long size) { - unsigned int i = DICT_HT_INITIAL_SIZE; + unsigned long i = DICT_HT_INITIAL_SIZE; - if (size >= 2147483648U) - return 2147483648U; + if (size >= LONG_MAX) return LONG_MAX; while(1) { if (i >= size) return i; @@ -453,9 +464,9 @@ void dictEmpty(dict *ht) { #define DICT_STATS_VECTLEN 50 void dictPrintStats(dict *ht) { - unsigned int i, slots = 0, chainlen, maxchainlen = 0; - unsigned int totchainlen = 0; - unsigned int clvector[DICT_STATS_VECTLEN]; + unsigned long i, slots = 0, chainlen, maxchainlen = 0; + unsigned long totchainlen = 0; + unsigned long clvector[DICT_STATS_VECTLEN]; if (ht->used == 0) { printf("No stats available for empty dictionaries\n"); @@ -483,16 +494,16 @@ void dictPrintStats(dict *ht) { totchainlen += chainlen; } printf("Hash table stats:\n"); - printf(" table size: %d\n", ht->size); - printf(" number of elements: %d\n", ht->used); - printf(" different slots: %d\n", slots); - printf(" max chain length: %d\n", maxchainlen); + printf(" table size: %ld\n", ht->size); + printf(" number of elements: %ld\n", ht->used); + printf(" different slots: %ld\n", slots); + printf(" max chain length: %ld\n", maxchainlen); printf(" avg chain length (counted): %.02f\n", (float)totchainlen/slots); printf(" avg chain length (computed): %.02f\n", (float)ht->used/slots); printf(" Chain length distribution:\n"); for (i = 0; i < DICT_STATS_VECTLEN-1; i++) { if (clvector[i] == 0) continue; - printf(" %s%d: %d (%.02f%%)\n",(i == DICT_STATS_VECTLEN-1)?">= ":"", i, clvector[i], ((float)clvector[i]/ht->size)*100); + printf(" %s%ld: %ld (%.02f%%)\n",(i == DICT_STATS_VECTLEN-1)?">= ":"", i, clvector[i], ((float)clvector[i]/ht->size)*100); } }