]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/htable.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / lib / htable.c
index 66f5040cb7a5041c03bd79c3c325aac1ccf428db..9fe280f2b8f95e1120de72ae729ac8c73bd4d99d 100644 (file)
@@ -1,29 +1,20 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2003-2011 Free Software Foundation Europe e.V.
-
-   The main author of Bacula is Kern Sibbald, with contributions from
-   many others, a complete list can be found in the file AUTHORS.
-   This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version three of the GNU Affero General Public
-   License as published by the Free Software Foundation and included
-   in the file LICENSE.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU Affero General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Bacula® is a registered trademark of Kern Sibbald.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2018 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *  Bacula hash table routines
  */
 
 #include "bacula.h"
+#include "htable.h"
 
-#define PAGE_SIZE 4096
-#define MIN_PAGES 32
-#define MAX_PAGES 2400
-#define MIN_BUF_SIZE (MIN_PAGES * PAGE_SIZE) /* 128 Kb */
-#define MAX_BUF_SIZE (MAX_PAGES * PAGE_SIZE) /* approx 10MB */
-
+#define lli long long int
 static const int dbglvl = 500;
 
 /* ===================================================================
  *    htable
  */
 
+#ifdef BIG_MALLOC
 /*
  * This subroutine gets a big buffer.
  */
@@ -92,31 +80,41 @@ void htable::hash_big_free()
    }
 }
 
+#endif
+
 /*
  * Normal hash malloc routine that gets a 
  *  "small" buffer from the big buffer
  */
 char *htable::hash_malloc(int size)
 {
-   int mb_size;
+#ifdef BIG_MALLOC
    char *buf;
    int asize = BALIGN(size);
 
    if (mem_block->rem < asize) {
-      if (total_size >= (extend_length / 2)) {
-         mb_size = extend_length;
+      uint32_t mb_size;
+      if (total_size >= 1000000) {
+         mb_size = 1000000;
       } else {
-         mb_size = extend_length / 2;
+         mb_size = 100000;
       }
       malloc_big_buf(mb_size);
-      Dmsg1(100, "Created new big buffer of %ld bytes\n", mb_size);
    }
    mem_block->rem -= asize;
    buf = mem_block->mem;
    mem_block->mem += asize;
    return buf;
+#else 
+   total_size += size;
+   blocks++;
+   return (char *)malloc(size);
+#endif
 }
 
+
+
 /*
  * Create hash of key, stored in hash then
  *  create and return the pseudo random bucket index
@@ -128,41 +126,31 @@ void htable::hash_index(char *key)
       hash +=  ((hash << 5) | (hash >> (sizeof(hash)*8-5))) + (uint32_t)*p;
    }
    /* Multiply by large prime number, take top bits, mask for remainder */
-   index = ((hash * 1103515249) >> rshift) & mask;
-   Dmsg2(dbglvl, "Leave hash_index hash=0x%llx index=%d\n", hash, index);
-}
-
-void htable::hash_index(uint32_t key)
-{
-   hash = key;
-   /* Multiply by large prime number, take top bits, mask for remainder */
-   index = ((hash * 1103515249) >> rshift) & mask;
-   Dmsg2(dbglvl, "Leave hash_index hash=0x%llx index=%d\n", hash, index);
-}
-
-void htable::hash_index(uint64_t key)
-{
-   hash = key;
-   /* Multiply by large prime number, take top bits, mask for remainder */
-   index = ((hash * 1103515249) >> rshift) & mask;
-   Dmsg2(dbglvl, "Leave hash_index hash=0x%llx index=%d\n", hash, index);
-}
-
+   index = ((hash * 1103515249LL) >> rshift) & mask;
+   Dmsg2(dbglvl, "Leave hash_index hash=0x%x index=%d\n", hash, index);
+} 
+void htable::hash_index(uint64_t ikey)
+{ 
+   hash = ikey;           /* already have starting binary hash */
+   /* Same algorithm as for char * */
+   index = ((hash * 1103515249LL) >> rshift) & mask;
+   Dmsg2(dbglvl, "Leave hash_index hash=0x%x index=%d\n", hash, index);
+} 
 /*
  * tsize is the estimated number of entries in the hash table
  */
-htable::htable(void *item, void *link, int tsize, int nr_pages)
+htable::htable(void *item, void *link, int tsize)
 {
-   init(item, link, tsize, nr_pages);
+   init(item, link, tsize);
 }
 
-void htable::init(void *item, void *link, int tsize, int nr_pages)
+void htable::init(void *item, void *link, int tsize)
 {
    int pwr;
-   int pagesize;
-   int buffer_size;
 
-   memset(this, 0, sizeof(htable));
+   bmemzero(this, sizeof(htable));
    if (tsize < 31) {
       tsize = 31;
    }
@@ -171,31 +159,15 @@ void htable::init(void *item, void *link, int tsize, int nr_pages)
       tsize >>= 1;
    }
    loffset = (char *)link - (char *)item;
-   mask = ~((~0) << pwr);             /* 3 bits => table size = 8 */
+   mask = ~((~0)<<pwr);               /* 3 bits => table size = 8 */
    rshift = 30 - pwr;                 /* start using bits 28, 29, 30 */
-   buckets = 1 << pwr;                /* hash table size -- power of two */
+   buckets = 1<<pwr;                  /* hash table size -- power of two */
    max_items = buckets * 4;           /* allow average 4 entries per chain */
    table = (hlink **)malloc(buckets * sizeof(hlink *));
-   memset(table, 0, buckets * sizeof(hlink *));
-
-#ifdef HAVE_GETPAGESIZE
-   pagesize = getpagesize();
-#else
-   pagesize = PAGE_SIZE;
-#endif
-   if (nr_pages == 0) {
-      buffer_size = MAX_BUF_SIZE;
-   } else {
-      buffer_size = pagesize * nr_pages;
-      if (buffer_size > MAX_BUF_SIZE) {
-         buffer_size = MAX_BUF_SIZE;
-      } else if (buffer_size < MIN_BUF_SIZE) {
-         buffer_size = MIN_BUF_SIZE;
-      }
-   }
-   malloc_big_buf(buffer_size);
-   extend_length = buffer_size;
-   Dmsg1(100, "Allocated big buffer of %ld bytes\n", buffer_size);
+   bmemzero(table, buckets * sizeof(hlink *));
+#ifdef BIG_MALLOC
+   malloc_big_buf(1000000);   /* ***FIXME*** need variable or some estimate */
+#endif /* BIG_MALLOC */
 }
 
 uint32_t htable::size()
@@ -242,19 +214,19 @@ void htable::stats()
    }
    printf("buckets=%d num_items=%d max_items=%d\n", buckets, num_items, max_items);
    printf("max hits in a bucket = %d\n", max);
-   printf("total bytes malloced = %lld\n", (long long int)total_size);
+#ifdef BIG_MALLOC
+   char ed1[100];
+   edit_uint64(total_size, ed1);
+   printf("total bytes malloced = %s\n", ed1);
    printf("total blocks malloced = %d\n", blocks);
+#endif
 }
 
 void htable::grow_table()
 {
-   htable *big;
-   hlink *cur;
-   void *ni;
-
    Dmsg1(100, "Grow called old size = %d\n", buckets);
    /* Setup a bigger table */
-   big = (htable *)malloc(sizeof(htable));
+   htable *big = (htable *)malloc(sizeof(htable));
    memcpy(big, this, sizeof(htable));  /* start with original class data */
    big->loffset = loffset;
    big->mask = mask<<1 | 1;
@@ -264,7 +236,7 @@ void htable::grow_table()
    big->max_items = big->buckets * 4;
    /* Create a bigger hash table */
    big->table = (hlink **)malloc(big->buckets * sizeof(hlink *));
-   memset(big->table, 0, big->buckets * sizeof(hlink *));
+   bmemzero(big->table, big->buckets * sizeof(hlink *));
    big->walkptr = NULL;
    big->walk_index = 0;
    /* Insert all the items in the new hash table */
@@ -277,22 +249,15 @@ void htable::grow_table()
     * to the next bucket.
     */
    for (void *item=first(); item; ) {
-      cur = (hlink *)((char *)item+loffset);
-      ni = cur->next; /* save link overwritten by insert */
-      switch (cur->key_type) {
-      case KEY_TYPE_CHAR:
-         Dmsg1(100, "Grow insert: %s\n", cur->key.char_key);
-         big->insert(cur->key.char_key, item);
-         break;
-      case KEY_TYPE_UINT32:
-         Dmsg1(100, "Grow insert: %ld\n", cur->key.uint32_key);
-         big->insert(cur->key.uint32_key, item);
-         break;
-      case KEY_TYPE_UINT64:
-         Dmsg1(100, "Grow insert: %ld\n", cur->key.uint64_key);
-         big->insert(cur->key.uint64_key, item);
-         break;
-      }
+      void *ni = ((hlink *)((char *)item+loffset))->next;  /* save link overwritten by insert */
+      hlink *hp = (hlink *)((char *)item+loffset);
+      if (hp->is_ikey) {
+         Dmsg1(100, "Grow insert: %lld\n", hp->key.ikey);
+         big->insert(hp->key.ikey, item);
+      } else {
+         Dmsg1(100, "Grow insert: %s\n", hp->key.key);
+         big->insert(hp->key.key, item);
+      }  
       if (ni) {
          item = (void *)((char *)ni-loffset);
       } else {
@@ -313,7 +278,6 @@ void htable::grow_table()
 bool htable::insert(char *key, void *item)
 {
    hlink *hp;
-
    if (lookup(key)) {
       return false;                   /* already exists */
    }
@@ -324,11 +288,11 @@ bool htable::insert(char *key, void *item)
       index, item, loffset);
    hp->next = table[index];
    hp->hash = hash;
-   hp->key_type = KEY_TYPE_CHAR;
-   hp->key.char_key = key;
+   hp->key.key = key;
+   hp->is_ikey = false;
    table[index] = hp;
-   Dmsg3(dbglvl, "Insert hp->next=%p hp->hash=0x%llx hp->key=%s\n",
-      hp->next, hp->hash, hp->key.char_key);
+   Dmsg3(dbglvl, "Insert hp->next=%p hp->hash=0x%x hp->key=%s\n",
+      hp->next, hp->hash, hp->key.key);
 
    if (++num_items >= max_items) {
       Dmsg2(dbglvl, "num_items=%d max_items=%d\n", num_items, max_items);
@@ -338,102 +302,60 @@ bool htable::insert(char *key, void *item)
    return true;
 }
 
-bool htable::insert(uint32_t key, void *item)
-{
-   hlink *hp;
-
-   if (lookup(key)) {
-      return false;                   /* already exists */
-   }
-   ASSERT(index < buckets);
-   Dmsg2(dbglvl, "Insert: hash=%p index=%d\n", hash, index);
-   hp = (hlink *)(((char *)item)+loffset);
-   Dmsg4(dbglvl, "Insert hp=%p index=%d item=%p offset=%u\n", hp,
-      index, item, loffset);
-   hp->next = table[index];
-   hp->hash = hash;
-   hp->key_type = KEY_TYPE_UINT32;
-   hp->key.uint32_key = key;
-   table[index] = hp;
-   Dmsg3(dbglvl, "Insert hp->next=%p hp->hash=0x%llx hp->key=%d\n",
-      hp->next, hp->hash, hp->key.uint32_key);
-
-   if (++num_items >= max_items) {
-      Dmsg2(dbglvl, "num_items=%d max_items=%d\n", num_items, max_items);
-      grow_table();
-   }
-   Dmsg3(dbglvl, "Leave insert index=%d num_items=%d key=%d\n", index, num_items, key);
-   return true;
-}
-
-bool htable::insert(uint64_t key, void *item)
-{
-   hlink *hp;
-
-   if (lookup(key)) {
-      return false;                   /* already exists */
-   }
-   ASSERT(index < buckets);
-   Dmsg2(dbglvl, "Insert: hash=%p index=%d\n", hash, index);
-   hp = (hlink *)(((char *)item)+loffset);
-   Dmsg4(dbglvl, "Insert hp=%p index=%d item=%p offset=%u\n", hp,
-      index, item, loffset);
-   hp->next = table[index];
-   hp->hash = hash;
-   hp->key_type = KEY_TYPE_UINT64;
-   hp->key.uint64_key = key;
-   table[index] = hp;
-   Dmsg3(dbglvl, "Insert hp->next=%p hp->hash=0x%llx hp->key=%ld\n",
-      hp->next, hp->hash, hp->key.uint64_key);
-
-   if (++num_items >= max_items) {
-      Dmsg2(dbglvl, "num_items=%d max_items=%d\n", num_items, max_items);
-      grow_table();
-   }
-   Dmsg3(dbglvl, "Leave insert index=%d num_items=%d key=%lld\n", index, num_items, key);
-   return true;
-}
-
 void *htable::lookup(char *key)
-{
-   hash_index(key);
-   for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) {
-      ASSERT(hp->key_type == KEY_TYPE_CHAR);
-//    Dmsg2(100, "hp=%p key=%s\n", hp, hp->key.char_key);
-      if (hash == hp->hash && strcmp(key, hp->key.char_key) == 0) {
-         Dmsg1(dbglvl, "lookup return %p\n", ((char *)hp)-loffset);
-         return ((char *)hp)-loffset;
-      }
-   }
-   return NULL;
-}
-
-void *htable::lookup(uint32_t key)
-{
-   hash_index(key);
-   for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) {
-      ASSERT(hp->key_type == KEY_TYPE_UINT32);
-      if (hash == hp->hash && key == hp->key.uint32_key) {
-         Dmsg1(dbglvl, "lookup return %p\n", ((char *)hp)-loffset);
-         return ((char *)hp)-loffset;
-      }
-   }
-   return NULL;
-}
-
-void *htable::lookup(uint64_t key)
-{
-   hash_index(key);
-   for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) {
-      ASSERT(hp->key_type == KEY_TYPE_UINT64);
-      if (hash == hp->hash && key == hp->key.uint64_key) {
-         Dmsg1(dbglvl, "lookup return %p\n", ((char *)hp)-loffset);
-         return ((char *)hp)-loffset;
-      }
-   }
-   return NULL;
-}
-
+{ 
+   hash_index(key); 
+   for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) { 
+//    Dmsg2(100, "hp=%p key=%s\n", hp, hp->key.key);
+      if (hash == hp->hash && strcmp(key, hp->key.key) == 0) {
+         Dmsg1(dbglvl, "lookup return %p\n", ((char *)hp)-loffset); 
+         return ((char *)hp)-loffset; 
+      } 
+   } 
+   return NULL; 
+} 
+bool htable::insert(uint64_t ikey, void *item)
+{ 
+   hlink *hp; 
+   if (lookup(ikey)) {
+      return false;                  /* already exists */
+   } 
+   ASSERT(index < buckets); 
+   Dmsg2(dbglvl, "Insert: hash=%p index=%d\n", hash, index); 
+   hp = (hlink *)(((char *)item)+loffset); 
+   Dmsg4(dbglvl, "Insert hp=%p index=%d item=%p offset=%u\n", hp, index, 
+     item, loffset);
+   hp->next = table[index]; 
+   hp->hash = hash; 
+   hp->key.ikey = ikey;
+   hp->is_ikey = true;
+   table[index] = hp; 
+   Dmsg3(dbglvl, "Insert hp->next=%p hp->hash=0x%x hp->ikey=%lld\n", hp->next, 
+      hp->hash, hp->key.ikey);
+   if (++num_items >= max_items) { 
+      Dmsg2(dbglvl, "num_items=%d max_items=%d\n", num_items, max_items); 
+      grow_table(); 
+   } 
+   Dmsg3(dbglvl, "Leave insert index=%d num_items=%d key=%lld\n",
+      index, num_items, ikey);
+   return true;  
+} 
+void *htable::lookup(uint64_t ikey)
+{ 
+   hash_index(ikey);
+   for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) { 
+//    Dmsg2(100, "hp=%p key=%lld\n", hp, hp->key.ikey);
+      if (hash == hp->hash && ikey == hp->key.ikey) {
+         Dmsg1(dbglvl, "lookup return %p\n", ((char *)hp)-loffset); 
+         return ((char *)hp)-loffset; 
+      } 
+   } 
+   return NULL; 
+} 
 void *htable::next()
 {
    Dmsg1(dbglvl, "Enter next: walkptr=%p\n", walkptr);
@@ -479,11 +401,21 @@ void *htable::first()
 /* Destroy the table and its contents */
 void htable::destroy()
 {
+#ifdef BIG_MALLOC
    hash_big_free();
+#else
+   void *ni;
+   void *li = first();
+
+   while (li) {
+      ni = next();
+      free(li);
+      li=ni;
+   }
+#endif
 
    free(table);
    table = NULL;
-   garbage_collect_memory();
    Dmsg0(100, "Done destroy.\n");
 }
 
@@ -492,19 +424,11 @@ void htable::destroy()
 #ifdef TEST_PROGRAM
 
 struct MYJCR {
-#ifndef TEST_NON_CHAR
    char *key;
-#else
-   uint32_t key;
-#endif
    hlink link;
 };
 
-#ifndef TEST_SMALL_HTABLE
 #define NITEMS 5000000
-#else
-#define NITEMS 5000
-#endif
 
 int main()
 {
@@ -515,25 +439,16 @@ int main()
    int count = 0;
 
    jcrtbl = (htable *)malloc(sizeof(htable));
+   jcrtbl->init(jcr, &jcr->link, NITEMS); 
 
-#ifndef TEST_SMALL_HTABLE
-   jcrtbl->init(jcr, &jcr->link, NITEMS);
-#else
-   jcrtbl->init(jcr, &jcr->link, NITEMS, 128);
-#endif
    Dmsg1(000, "Inserting %d items\n", NITEMS);
    for (int i=0; i<NITEMS; i++) {
-#ifndef TEST_NON_CHAR
       int len;
       len = sprintf(mkey, "This is htable item %d", i) + 1;
 
       jcr = (MYJCR *)jcrtbl->hash_malloc(sizeof(MYJCR));
       jcr->key = (char *)jcrtbl->hash_malloc(len);
       memcpy(jcr->key, mkey, len);
-#else
-      jcr = (MYJCR *)jcrtbl->hash_malloc(sizeof(MYJCR));
-      jcr->key = i;
-#endif
       Dmsg2(100, "link=%p jcr=%p\n", jcr->link, jcr);
 
       jcrtbl->insert(jcr->key, jcr);
@@ -544,21 +459,15 @@ int main()
    if (!(item = (MYJCR *)jcrtbl->lookup(save_jcr->key))) {
       printf("Bad news: %s not found.\n", save_jcr->key);
    } else {
-#ifndef TEST_NON_CHAR
       printf("Item 10's key is: %s\n", item->key);
-#else
-      printf("Item 10's key is: %ld\n", item->key);
-#endif
    }
 
    jcrtbl->stats();
    printf("Walk the hash table:\n");
    foreach_htable (jcr, jcrtbl) {
-#ifndef TEST_NON_CHAR
 //    printf("htable item = %s\n", jcr->key);
 #ifndef BIG_MALLOC
       free(jcr->key);
-#endif
 #endif
       count++;
    }