rpmhash: Grow when hash table gets too full
authorFlorian Festi <ffesti@redhat.com>
Thu, 25 Mar 2010 11:06:22 +0000 (12:06 +0100)
committerFlorian Festi <ffesti@redhat.com>
Thu, 6 May 2010 14:07:56 +0000 (16:07 +0200)
Add some statistics to be able to find out how full the hash is

lib/rpmhash.C

index 79a82b0..d8cfdd7 100644 (file)
@@ -30,7 +30,10 @@ struct HASHSTRUCT {
     hashFunctionType fn;               /*!< generate hash value for key */
     hashEqualityType eq;               /*!< compare hash keys for equality */
     hashFreeKey freeKey;
+    int bucketCount;                   /*!< number of used buckets */
+    int keyCount;                      /*!< number of keys */
 #ifdef HTDATATYPE
+    int dataCount;                     /*!< number of data entries */
     hashFreeData freeData;
 #endif
 };
@@ -72,12 +75,33 @@ HASHTYPE HASHPREFIX(Create)(int numBuckets,
     ht->freeKey = freeKey;
 #ifdef HTDATATYPE
     ht->freeData = freeData;
+    ht->dataCount = 0;
 #endif
     ht->fn = fn;
     ht->eq = eq;
+    ht->bucketCount = ht->keyCount = 0;
     return ht;
 }
 
+static HASHPREFIX(Resize)(HASHTYPE ht, int numBuckets) {
+    Bucket * buckets = xcalloc(numBuckets, sizeof(*ht->buckets));
+
+    for (int i=0; i<ht->numBuckets; i++) {
+       Bucket b = ht->buckets[i];
+       Bucket nextB;
+       while (b != NULL) {
+           unsigned int hash = ht->fn(b->key) % numBuckets;
+           nextB = b->next;
+           b->next = buckets[hash];
+           buckets[hash] = b;
+           b = nextB;
+       }
+    }
+    free(ht->buckets);
+    ht->buckets = buckets;
+    ht->numBuckets = numBuckets;
+}
+
 void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key
 #ifdef HTDATATYPE
 , HTDATATYPE data
@@ -92,12 +116,17 @@ void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key
     b = ht->buckets[hash];
     b_addr = ht->buckets + hash;
 
+    if (b == NULL) {
+       ht->bucketCount += 1;
+    }
+
     while (b && ht->eq(b->key, key)) {
        b_addr = &(b->next);
        b = b->next;
     }
 
     if (b == NULL) {
+       ht->keyCount += 1;
        b = xmalloc(sizeof(*b));
        b->key = key;
 #ifdef HTDATATYPE
@@ -116,7 +145,11 @@ void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key
        // though increasing dataCount after the resize
        b->data[b->dataCount++] = data;
     }
+    ht->dataCount += 1;
 #endif
+    if (ht->keyCount > ht->numBuckets) {
+       HASHPREFIX(Resize)(ht, ht->numBuckets * 2);
+    }
 }
 
 HASHTYPE HASHPREFIX(Free)(HASHTYPE ht)