CUBRID Engine  latest
memory_hash.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * memory_hash.c - memory hash table
21  */
22 
23 #ident "$Id$"
24 
25 /*
26  * The structure of the hash table is approximately as follows;
27  *
28  * Hash Table header
29  * -----------------
30  * |hash_fun |
31  * |cmp_fun |
32  * |table_name |
33  * |Ptr to entries-----> The entries
34  * |size | -------------------
35  * |rehash_at | | key, data, next |--> ... -> key, data, next
36  * |num_entries | | . |
37  * |num_collisions | | . |
38  * ----------------- | . |
39  * -------------------
40  */
41 
42 #include "config.h"
43 
44 #include <stdio.h>
45 #include <assert.h>
46 
47 #include "memory_hash.h"
48 #include "chartype.h"
49 #include "misc_string.h"
50 #include "error_manager.h"
51 #include "memory_alloc.h"
52 #include "message_catalog.h"
53 #include "environment_variable.h"
54 #include "set_object.h"
55 #include "language_support.h"
56 #include "intl_support.h"
57 #include "object_primitive.h"
58 #include "dbtype.h"
59 
60 #if __WORDSIZE == 32
61 #define GET_PTR_FOR_HASH(key) ((unsigned int)(key))
62 #else
63 #define GET_PTR_FOR_HASH(key) (((UINT64)(key)) & 0xFFFFFFFFUL)
64 #endif
65 
66 /* constants for rehash */
67 static const float MHT_REHASH_TRESHOLD = 0.7f;
68 static const float MHT_REHASH_FACTOR = 1.3f;
69 
70 /* options for mht_put() */
72 {
77 };
78 typedef enum mht_put_opt MHT_PUT_OPT;
79 
80 /*
81  * A table of prime numbers.
82  *
83  * Some prime numbers which were picked randomly.
84  * This table contains more smaller prime numbers.
85  * Some of the prime numbers included are:
86  * between 1000 and 2000, prime numbers that are farther than 50 units.
87  * between 2000 and 7000, prime numbers that are farther than 100 units.
88  * between 7000 and 12000, prime numbers that are farther than 200 units.
89  * between 12000 and 17000, prime numbers that are farther than 400 units.
90  * between 17000 and 22000, prime numbers that are farther than 800 units.
91  * above 22000, prime numbers that are farther than 1000 units.
92  *
93  * Note: if x is a prime number, the n is prime if X**(n-1) mod n == 1
94  */
95 
96 static unsigned int mht_1str_pseudo_key (const void *key, int key_size);
97 static unsigned int mht_3str_pseudo_key (const void *key, int key_size, const unsigned int max_value);
98 static unsigned int mht_4str_pseudo_key (const void *key, int key_size);
99 static unsigned int mht_5str_pseudo_key (const void *key, int key_size);
100 
101 static unsigned int mht_calculate_htsize (unsigned int ht_size);
102 static int mht_rehash (MHT_TABLE * ht);
103 
104 static const void *mht_put_internal (MHT_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt);
105 static const void *mht_put2_internal (MHT_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt);
106 static const void *mht_put_hls_internal (MHT_HLS_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt);
107 
108 static unsigned int mht_get_shiftmult32 (unsigned int key, const unsigned int ht_size);
109 #if defined (ENABLE_UNUSED_FUNCTION)
110 static unsigned int mht_get32_next_power_of_2 (unsigned int const ht_size);
111 static unsigned int mht_get_linear_hash32 (const unsigned int key, const unsigned int ht_size);
112 #endif /* ENABLE_UNUSED_FUNCTION */
113 
114 /*
115  * Several hasing functions for different data types
116  */
117 
118 /*
119  * mht_1str_pseudo_key() - hash string key into pseudo integer key
120  * return: pseudo integer key
121  * key(in): string key to hash
122  * key_size(in): size of key or -1 when unknown
123  *
124  * Note: It generates a pseudo integer key based on Gosling's emacs hash
125  * function.
126  */
127 static unsigned int
128 mht_1str_pseudo_key (const void *key, int key_size)
129 {
130  unsigned const char *byte_p = (unsigned char *) key;
131  unsigned int pseudo_key;
132 
133  assert (key != NULL);
134 
135  for (pseudo_key = 0;; byte_p++)
136  {
137  if (key_size == -1)
138  {
139  if (!(*byte_p))
140  {
141  break;
142  }
143  }
144  else
145  {
146  if (key_size <= 0)
147  {
148  break;
149  }
150  }
151 
152  pseudo_key = (pseudo_key << 5) - pseudo_key + *byte_p;
153 
154  if (key_size > 0)
155  {
156  key_size--;
157  }
158  }
159 
160  return pseudo_key;
161 }
162 
163 /*
164  * mht_2str_pseudo_key() - hash string key into pseudo integer key
165  * return: pseudo integer key
166  * key(in): string key to hash
167  * key_size(in): size of key or -1 when unknown
168  *
169  * Note: It generates a pseudo integer key based on hash function from
170  * Aho, Sethi, and Ullman's dragon book; pp. 436.
171  * This function can handles strings when they are binary different.
172  * For collation dependent function use 'mht2str'.
173  */
174 unsigned int
175 mht_2str_pseudo_key (const void *key, int key_size)
176 {
177  unsigned const char *byte_p = (unsigned char *) key;
178  unsigned int pseudo_key;
179  unsigned int i;
180 
181  assert (key != NULL);
182 
183  for (pseudo_key = 0;; byte_p++)
184  {
185  if (key_size == -1)
186  {
187  if (!(*byte_p))
188  {
189  break;
190  }
191  }
192  else
193  {
194  if (key_size <= 0)
195  {
196  break;
197  }
198  }
199 
200  pseudo_key = (pseudo_key << 4) + *byte_p;
201  i = pseudo_key & 0xf0000000;
202  if (i != 0)
203  {
204  pseudo_key ^= i >> 24;
205  pseudo_key ^= i;
206  }
207 
208  if (key_size > 0)
209  {
210  key_size--;
211  }
212  }
213 
214  return pseudo_key;
215 }
216 
217 /*
218  * mht_3str_pseudo_key() - hash string key into pseudo integer key
219  * return: pseudo integer key
220  * key(in): string key to hash
221  * key_size(in): size of key or -1 when unknown
222  * max_value(in) : generally a prime number which represents the size of hash
223  * table
224  *
225  * Note: It generates a pseudo integer key based on hash function from
226  * Sedgewick's Algorithm book. The function needs a prime number for
227  * the range. This prime number is usually the hash table size.
228  */
229 static unsigned int
230 mht_3str_pseudo_key (const void *key, int key_size, const unsigned int max_value)
231 {
232  unsigned const char *byte_p = (unsigned char *) key;
233  unsigned int pseudo_key = 0;
234 
235  assert (key != NULL);
236 
237  for (pseudo_key = 0;; byte_p++)
238  {
239  if (key_size == -1)
240  {
241  if (!(*byte_p))
242  {
243  break;
244  }
245  }
246  else
247  {
248  if (key_size <= 0)
249  {
250  break;
251  }
252  }
253 
254  pseudo_key = (pseudo_key * 32 + *byte_p++) % max_value;
255 
256  if (key_size > 0)
257  {
258  key_size--;
259  }
260  }
261 
262  return pseudo_key;
263 }
264 
265 /*
266  * mht_4str_pseudo_key() - hash string key into pseudo integer key
267  * return: pseudo integer key
268  * key(in): string key to hash
269  * key_size(in): size of key or -1 when unknown
270  *
271  * Note: It generates four values between 0 and 255, concatenate them,
272  * and returns the result.
273  * Based on Fast Hashing of Variable-Length Text Strings
274  * by Peter K. Pearson Communications of the ACM, June 1990.
275  */
276 static unsigned int
277 mht_4str_pseudo_key (const void *key, int key_size)
278 {
279  /* a permutation of values 0 to 255 */
280  unsigned char tbl[] = {
281  166, 231, 148, 061, 050, 131, 000, 057, 126, 223,
282  044, 245, 138, 251, 24, 113, 86, 215, 196, 173,
283  226, 115, 48, 169, 46, 207, 92, 101, 58, 235,
284  72, 225, 6, 199, 244, 29, 146, 99, 96, 25,
285  222, 191, 140, 213, 234, 219, 120, 81, 182, 183,
286  36, 141, 66, 83, 144, 137, 142, 175, 188, 69,
287  154, 203, 168, 193, 102, 167, 84, 253, 242, 67,
288  192, 249, 62, 159, 236, 181, 74, 187, 216, 49,
289  22, 151, 132, 109, 162, 51, 240, 105, 238, 143,
290  28, 37, 250, 171, 8, 161, 198, 135, 180, 221,
291  82, 35, 32, 217, 158, 127, 76, 149, 170, 155,
292  56, 17, 118, 119, 228, 77, 2, 19, 80, 73, 78,
293  111, 124, 5, 90, 139, 104, 129, 38, 103, 20,
294  189, 178, 3, 128, 185, 254, 95, 172, 117, 10,
295  123, 152, 241, 214, 87, 68, 45, 98, 243, 176,
296  41, 174, 79, 220, 229, 186, 107, 200, 97, 134,
297  71, 116, 157, 18, 227, 224, 153, 94, 63, 12,
298  85, 106, 91, 248, 209, 54, 55, 164, 13, 194,
299  211, 16, 9, 14, 47, 60, 197, 26, 75, 40,
300  65, 230, 39, 212, 125, 114, 195, 64, 121, 190,
301  31, 108, 53, 202, 59, 88, 177, 150, 23, 4,
302  237, 34, 179, 112, 233, 110, 15, 156, 165, 122,
303  43, 136, 33, 70, 7, 52, 93, 210, 163, 160,
304  89, 30, 255, 204, 21, 42, 27, 184, 145, 246,
305  247, 100, 205, 130, 147, 208, 201, 206, 239, 252,
306  133, 218, 11, 232, 1, 0
307  };
308  unsigned int byte1, byte2, byte3, byte4;
309  unsigned const char *byte_p = (unsigned char *) key;
310 
311  assert (key != NULL);
312 
313  byte1 = tbl[*byte_p];
314  byte2 = tbl[(unsigned int) (*byte_p + 1) % 256];
315  byte3 = tbl[(unsigned int) (*byte_p + 2) % 256];
316  byte4 = tbl[(unsigned int) (*byte_p + 3) % 256];
317 
318  if (key_size == -1)
319  {
320  if (*byte_p)
321  {
322  byte_p++;
323  }
324  }
325  else if (key_size > 0)
326  {
327  byte_p++;
328  key_size--;
329  }
330 
331  for (;; byte_p++)
332  {
333  if (key_size == -1)
334  {
335  if (!(*byte_p))
336  {
337  break;
338  }
339  }
340  else
341  {
342  if (key_size <= 0)
343  {
344  break;
345  }
346  }
347 
348  /*
349  * Each of the following hash values,
350  * generates a value between 0 and 255
351  */
352  byte1 = tbl[byte1 ^ *byte_p];
353  byte2 = tbl[byte2 ^ *byte_p];
354  byte3 = tbl[byte3 ^ *byte_p];
355  byte4 = tbl[byte4 ^ *byte_p];
356 
357  if (key_size > 0)
358  {
359  key_size--;
360  }
361  }
362 
363  /* Concatenate all the values */
364  return (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24));
365 }
366 
367 /*
368  * mht_5str_pseudo_key() - hash string key into pseudo integer key
369  * return: pseudo integer key
370  * key(in): string key to hash
371  * key_size(in): size of key or -1 when unknown
372  *
373  * Note: Based on hash method reported by Diniel J. Bernstein.
374  */
375 static unsigned int
376 mht_5str_pseudo_key (const void *key, int key_size)
377 {
378  unsigned int hash = 5381;
379  int i = 0;
380  char *k;
381 
382  assert (key != NULL);
383  k = (char *) key;
384 
385  if (key_size == -1)
386  {
387  int c;
388  while ((c = *(k + i++)) != 0)
389  {
390  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
391  }
392  }
393  else
394  {
395  for (; i < key_size; i++)
396  {
397  hash = ((hash << 5) + hash) + *(k + i);
398  }
399  }
400 
401  hash += ~(hash << 9);
402  hash ^= ((hash >> 14) | (i << 18)); /* >>> */
403  hash += (hash << 4);
404  hash ^= ((hash >> 10) | (i << 22)); /* >>> */
405 
406  return hash;
407 }
408 
409 /*
410  * mht_1strlowerhash - hash a string key (in lowercase)
411  * return: hash value
412  * key(in): key to hash
413  * ht_size(in): size of hash table
414  *
415  * Note: Taken from Gosling's emacs
416  * This handles only ASCII characters; for charset-independent version
417  * use 'intl_identifier_mht_1strlowerhash'
418  */
419 unsigned int
420 mht_1strlowerhash (const void *key, const unsigned int ht_size)
421 {
422  unsigned int hash;
423  unsigned const char *byte_p = (unsigned char *) key;
424  unsigned int ch;
425 
426  assert (key != NULL);
427 
428  for (hash = 0; *byte_p; byte_p++)
429  {
430  /* TODO: Original comment originally this way but due to compiler problems on the PC, it doesn't always work
431  * consistently: hash = (hash << 5) - hash + tolower(*key++); */
432  ch = char_tolower (*byte_p);
433  hash = (hash << 5) - hash + ch;
434  }
435  return hash % ht_size;
436 }
437 
438 /*
439  * mht_1strhash - hash a string key
440  * return: hash value
441  * key(in): key to hash
442  * ht_size(in): size of hash table
443  *
444  * Note: Taken from Gosling's emacs
445  */
446 unsigned int
447 mht_1strhash (const void *key, const unsigned int ht_size)
448 {
449  assert (key != NULL);
450 
451  return mht_1str_pseudo_key (key, -1) % ht_size;
452 }
453 
454 /*
455  * mht_2strhash - hash a string key
456  * return: hash value
457  * key(in): key to hash
458  * ht_size(in): size of hash table
459  *
460  * Note: Form to hash strings.
461  * Taken from Aho, Sethi, and Ullman's dragon book; pp. 436.
462  * This function uses 'mht_2str_pseudo_key'.
463  * For collation dependent function use 'mht2str'.
464  */
465 unsigned int
466 mht_2strhash (const void *key, const unsigned int ht_size)
467 {
468  assert (key != NULL);
469 
470  return mht_2str_pseudo_key (key, -1) % ht_size;
471 }
472 
473 /*
474  * mht_3strhash - hash a string key
475  * return: hash value
476  * key(in): key to hash
477  * ht_size(in): size of hash table
478  *
479  * Note: Form to hash strings.
480  * Taken from Sedgewick's Algorithm book
481  */
482 unsigned int
483 mht_3strhash (const void *key, const unsigned int ht_size)
484 {
485  assert (key != NULL);
486 
487  return mht_3str_pseudo_key (key, -1, ht_size);
488 }
489 
490 /*
491  * mht_4strhash - hash a string key
492  * return: hash value
493  * key(in): key to hash
494  * ht_size(in): size of hash table
495  *
496  * Note: Form to hash strings.
497  * It generates four values between 0 and 255, concatenate them
498  * and applies the mod.
499  *
500  * Based on Fast Hashing of Variable-Length Text Strings
501  * by Peter K. Pearson
502  * Communications of the ACM, June 1990.
503  */
504 unsigned int
505 mht_4strhash (const void *key, const unsigned int ht_size)
506 {
507  assert (key != NULL);
508 
509  return mht_4str_pseudo_key (key, -1) % ht_size;
510 }
511 
512 /*
513  * mht_5strhash - hash a string key
514  * return: hash value
515  * key(in): key to hash
516  * ht_size(in): size of hash table
517  *
518  * Note: Based on hash method reported by Diniel J. Bernstein.
519  */
520 unsigned int
521 mht_5strhash (const void *key, const unsigned int ht_size)
522 {
523  return mht_5str_pseudo_key (key, -1) % ht_size;
524 }
525 
526 /*
527  * mht_numash - hash an integer key
528  * return: hash value
529  * key(in): void pointer to integer key to hash
530  * ht_size(in): size of hash table
531  */
532 unsigned int
533 mht_numhash (const void *key, const unsigned int ht_size)
534 {
535  assert (key != NULL);
536 
537  return (*(const unsigned int *) key) % ht_size;
538 }
539 
540 /*
541  * mht_ptrhash - hash a pointer key (hash memory pointers)
542  * return: hash value
543  * key(in): pointer value key to hash
544  * ht_size(in): size of hash table
545  */
546 unsigned int
547 mht_ptrhash (const void *key, const unsigned int ht_size)
548 {
549  assert (key != NULL);
550 
551  return GET_PTR_FOR_HASH (key) % ht_size;
552 }
553 
554 /*
555  * mht_valhash - hash a DB_VALUE key
556  * return: hash value
557  * key(in): pointer to DB_VALUE key to hash
558  * ht_size(in): size of hash table
559  */
560 unsigned int
561 mht_valhash (const void *key, const unsigned int ht_size)
562 {
563  unsigned int hash = 0;
564  const DB_VALUE *val = (const DB_VALUE *) key;
565  int t_n;
566  DB_VALUE t_val;
567 
568  if (key != NULL)
569  {
570  switch (db_value_type (val))
571  {
572  case DB_TYPE_NULL:
573  hash = 0;
574  break;
575  case DB_TYPE_INTEGER:
576  hash = (unsigned int) db_get_int (val);
577  break;
578  case DB_TYPE_SHORT:
579  hash = (unsigned int) db_get_short (val);
580  break;
581  case DB_TYPE_BIGINT:
582  {
583  DB_BIGINT bigint;
584  unsigned int x, y;
585 
586  bigint = db_get_bigint (val);
587  x = bigint >> 32;
588  y = (unsigned int) bigint;
589  hash = x ^ y;
590  break;
591  }
592  case DB_TYPE_FLOAT:
593  hash = (unsigned int) db_get_float (val);
594  break;
595  case DB_TYPE_DOUBLE:
596  hash = (unsigned int) db_get_double (val);
597  break;
598  case DB_TYPE_NUMERIC:
599  hash = mht_1str_pseudo_key (db_get_numeric (val), -1);
600  break;
601  case DB_TYPE_CHAR:
602  case DB_TYPE_NCHAR:
603  case DB_TYPE_VARCHAR:
604  case DB_TYPE_VARNCHAR:
606  break;
607  case DB_TYPE_BIT:
608  case DB_TYPE_VARBIT:
609  hash = mht_1str_pseudo_key (db_get_bit (val, &t_n), -1);
610  break;
611  case DB_TYPE_TIME:
612  {
613  unsigned int *time = db_get_time (val);
614  hash = (unsigned int) (*time);
615  break;
616  }
617  case DB_TYPE_TIMESTAMP:
619  {
620  DB_TIMESTAMP *time_st = db_get_timestamp (val);
621  hash = (unsigned int) (*time_st);
622  break;
623  }
624  case DB_TYPE_TIMESTAMPTZ:
625  {
626  DB_TIMESTAMPTZ *ts_tz = db_get_timestamptz (val);
627  hash = (unsigned int) (ts_tz->timestamp);
628  }
629  break;
630  case DB_TYPE_DATETIME:
631  case DB_TYPE_DATETIMELTZ:
632  {
633  DB_DATETIME *datetime;
634  datetime = db_get_datetime (val);
635  hash = (unsigned int) (datetime->date ^ datetime->time);
636  }
637  break;
638  case DB_TYPE_DATETIMETZ:
639  {
640  DB_DATETIMETZ *dt_tz;
641  dt_tz = db_get_datetimetz (val);
642  hash = (unsigned int) (dt_tz->datetime.date ^ dt_tz->datetime.time);
643  }
644  break;
645  case DB_TYPE_DATE:
646  {
647  DB_DATE *date = db_get_date (val);
648  hash = (unsigned int) (*date);
649  break;
650  }
651  case DB_TYPE_MONETARY:
652  {
653  DB_MONETARY *mon = db_get_monetary (val);
654  hash = (unsigned int) mon->amount;
655  break;
656  }
657  case DB_TYPE_SET:
658  case DB_TYPE_MULTISET:
659  case DB_TYPE_SEQUENCE:
660  db_make_null (&t_val);
661  {
662  DB_SET *set;
663  set = db_get_set (val);
664  if (set_get_element (set, 0, &t_val) == NO_ERROR)
665  {
666  hash = mht_valhash (&t_val, ht_size);
667  (void) pr_clear_value (&t_val);
668  t_n = set_size (set);
669  if ((t_n > 0) && set_get_element (set, t_n - 1, &t_val) == NO_ERROR)
670  {
671  hash += mht_valhash (&t_val, ht_size);
672  (void) pr_clear_value (&t_val);
673  }
674  }
675  }
676  break;
677  case DB_TYPE_OBJECT:
678  hash = GET_PTR_FOR_HASH (db_get_object (val));
679  break;
680  case DB_TYPE_OID:
681  hash = (unsigned int) OID_PSEUDO_KEY (db_get_oid (val));
682  break;
683  case DB_TYPE_MIDXKEY:
684  db_make_null (&t_val);
685  {
686  DB_MIDXKEY *midxkey;
687  midxkey = db_get_midxkey (val);
688  if (pr_midxkey_get_element_nocopy (midxkey, 0, &t_val, NULL, NULL) == NO_ERROR)
689  {
690  hash = mht_valhash (&t_val, ht_size);
691  t_n = midxkey->size;
692  if (t_n > 0 && pr_midxkey_get_element_nocopy (midxkey, t_n - 1, &t_val, NULL, NULL) == NO_ERROR)
693  {
694  hash += mht_valhash (&t_val, ht_size);
695  }
696  }
697  }
698  break;
699  case DB_TYPE_POINTER:
700  hash = GET_PTR_FOR_HASH (db_get_pointer (val));
701  break;
702  case DB_TYPE_BLOB:
703  case DB_TYPE_CLOB:
704  case DB_TYPE_SUB:
705  case DB_TYPE_ERROR:
706  case DB_TYPE_VOBJ:
707  case DB_TYPE_DB_VALUE:
708  case DB_TYPE_RESULTSET:
709  case DB_TYPE_TABLE:
710  default:
711  hash = GET_PTR_FOR_HASH (val);
712  break;
713  }
714  }
715 
716  return hash % ht_size;
717 }
718 
719 
720 /*
721  * Compare functions for datatypes
722  */
723 
724 /*
725  * mht_compare_ints_are_equal - compare two integer keys
726  * return: 0 or 1 (key1 == key2)
727  * key1(in): pointer to integer key1
728  * key2(in): pointer to integer key2
729  */
730 int
731 mht_compare_ints_are_equal (const void *key1, const void *key2)
732 {
733  return ((*(const int *) key1 == *(const int *) key2));
734 }
735 
736 /*
737  * mht_logpageid_compare_equal - compare two LOG_PAGEID keys
738  * return: 0 or 1 (key1 == key2)
739  * key1(in): pointer to LOG_PAGEID key1
740  * key2(in): pointer to LOG_PAGEID key2
741  */
742 int
743 mht_compare_logpageids_are_equal (const void *key1, const void *key2)
744 {
745  return ((*(const LOG_PAGEID *) key1 == *(const LOG_PAGEID *) key2));
746 }
747 
748 /*
749  * mht_compare_identifiers_equal - compare two identifiers keys (ignoring case)
750  * return: 0 or 1 (key1 == key2)
751  * key1(in): pointer to string key1
752  * key2(in): pointer to string key2
753  */
754 int
755 mht_compare_identifiers_equal (const void *key1, const void *key2)
756 {
757  return ((intl_identifier_casecmp ((const char *) key1, (const char *) key2)) == 0);
758 }
759 
760 /*
761  * mht_compare_strings_are_equal - compare two string keys (case sensitive)
762  * return: 0 or 1 (key1 == key2)
763  * key1(in): pointer to string key1
764  * key2(in): pointer to string key2
765  */
766 int
767 mht_compare_strings_are_equal (const void *key1, const void *key2)
768 {
769  return ((strcmp ((const char *) key1, (const char *) key2)) == 0);
770 }
771 
772 /*
773  * mht_compare_ptrs_are_equal - compare two pointer keys
774  * return: 0 or 1 (key1 == key2)
775  * key1(in): pointer key1
776  * key2(in): pointer key2
777  */
778 int
779 mht_compare_ptrs_are_equal (const void *key1, const void *key2)
780 {
781  return (key1 == key2);
782 }
783 
784 /*
785  * mht_compare_dbvalues_are_equal - compare two DB_VALUEs
786  * return: 0 or 1 (key1 == key2)
787  * key1(in): pointer to DB_VALUE key1
788  * key2(in): pointer to DB_VALUE key2
789  */
790 int
791 mht_compare_dbvalues_are_equal (const void *key1, const void *key2)
792 {
793  return ((key1 == key2) || (tp_value_compare ((DB_VALUE *) key1, (DB_VALUE *) key2, 0, 1) == DB_EQ));
794 }
795 
796 /*
797  * mht_calculate_htsize - find a good hash table size
798  * return: adjusted hash table size
799  * ht_size(in): given hash table size
800  *
801  * Note: Find a good size for a hash table. A prime number is the best
802  * size for a hash table, unfortunately prime numbers are
803  * difficult to found. If the given htsize, falls among the
804  * prime numbers known by this module, a close prime number to
805  * the given htsize value is returned, otherwise, a power of two
806  * is returned.
807  */
808 #define NPRIMES 170
809 static const unsigned int mht_Primes[NPRIMES] = {
810  11, 23, 37, 53, 67, 79, 97, 109, 127, 149,
811  167, 191, 211, 227, 251, 269, 293, 311, 331, 349,
812  367, 389, 409, 431, 449, 467, 487, 509, 541, 563,
813  587, 607, 631, 653, 673, 521, 541, 557, 569, 587,
814  599, 613, 641, 673, 701, 727, 751, 787, 821, 853,
815  881, 907, 941, 977, 1039, 1087, 1129, 1171, 1213, 1259,
816  1301, 1361, 1409, 1471, 1523, 1579, 1637, 1693, 1747, 1777,
817  1823, 1867, 1913, 1973, 2017, 2129, 2237, 2339, 2441, 2543,
818  2647, 2749, 2851, 2953, 3061, 3163, 3271, 3373, 3491, 3593,
819  3697, 3803, 3907, 4013, 4177, 4337, 4493, 4649, 4801, 4957,
820  5059, 5167, 5273, 5381, 5483, 5591, 5693, 5801, 5903, 6007,
821  6113, 6217, 6317, 6421, 6521, 6637, 6737, 6841, 6847, 7057,
822  7283, 7487, 7687, 7901, 8101, 8311, 8513, 8713, 8923, 9127,
823  9337, 9539, 9739, 9941, 10141, 10343, 10559, 10771, 10973, 11177,
824  11383, 11587, 11789, 12007, 12409, 12809, 13217, 13619, 14029, 14431,
825  14831, 15233, 15641, 16057, 16477, 16879, 17291, 18097, 18899, 19699,
826  20507, 21313, 22123, 23131, 24133, 25147, 26153, 27179, 28181, 29123
827 };
828 
829 static unsigned int
830 mht_calculate_htsize (unsigned int ht_size)
831 {
832  int left, right, middle; /* indices for binary search */
833 
834  if (ht_size > mht_Primes[NPRIMES - 1])
835  {
836  /* get a power of two */
837  if (!((ht_size & (ht_size - 1)) == 0))
838  {
839  /* Turn off some bits but the left most one */
840  while (!(ht_size & (ht_size - 1)))
841  {
842  ht_size &= (ht_size - 1);
843  }
844  ht_size <<= 1;
845  }
846  }
847  else
848  {
849  /* we can assign a primary number; binary search */
850  for (middle = 0, left = 0, right = NPRIMES - 1; left <= right;)
851  {
852  middle = CEIL_PTVDIV ((left + right), 2);
853  if (ht_size == mht_Primes[middle])
854  {
855  break;
856  }
857  else if (ht_size > mht_Primes[middle])
858  {
859  left = middle + 1;
860  }
861  else
862  {
863  right = middle - 1;
864  }
865  }
866  /* If we didn't find the size, get the larger size and not the small one */
867  if (ht_size > mht_Primes[middle] && middle < (NPRIMES - 1))
868  {
869  middle++;
870  }
871  ht_size = mht_Primes[middle];
872  }
873 
874  return ht_size;
875 }
876 
877 /*
878  * mht_create - create a hash table
879  * return: hash table
880  * name(in): name of hash table
881  * est_size(in): estimated number of entries
882  * hash_func(in): hash function
883  * cmp_func(in): key compare function
884  *
885  * Note: Create a new hash table. The estimated number of entries for
886  * the hash table may be adjusted (to a prime number) in order to
887  * obtain certain favorable circumstances when the table is
888  * created, when the table is almost full and there are at least
889  * 5% of collisions. 'hash_func' must return an integer between 0 and
890  * table_size - 1. 'cmp_func' must return TRUE if key1 = key2,
891  * otherwise, FALSE.
892  */
893 MHT_TABLE *
894 mht_create (const char *name, int est_size, unsigned int (*hash_func) (const void *key, unsigned int ht_size),
895  int (*cmp_func) (const void *key1, const void *key2))
896 {
897  MHT_TABLE *ht;
898  HENTRY_PTR *hvector; /* Entries of hash table */
899  unsigned int ht_estsize;
900  size_t size;
901 
902  assert (hash_func != NULL && cmp_func != NULL);
903 
904  /* Get a good number of entries for hash table */
905  if (est_size <= 0)
906  {
907  est_size = 2;
908  }
909 
910  ht_estsize = mht_calculate_htsize ((unsigned int) est_size);
911 
912  /* Allocate the header information for hash table */
913  ht = (MHT_TABLE *) malloc (DB_SIZEOF (MHT_TABLE));
914  if (ht == NULL)
915  {
917 
918  return NULL;
919  }
920 
921  /* Initialize the chunky memory manager */
922  ht->heap_id = db_create_fixed_heap (DB_SIZEOF (HENTRY), MAX (2, ht_estsize / 2 + 1));
923  if (ht->heap_id == 0)
924  {
926 
927  free_and_init (ht);
928  return NULL;
929  }
930 
931  /* Allocate the hash table entry pointers */
932  size = ht_estsize * DB_SIZEOF (*hvector);
933  hvector = (HENTRY_PTR *) malloc (size);
934  if (hvector == NULL)
935  {
937 
939  free_and_init (ht);
940  return NULL;
941  }
942 
943  ht->hash_func = hash_func;
944  ht->cmp_func = cmp_func;
945  ht->name = name;
946  ht->table = hvector;
947  ht->act_head = NULL;
948  ht->act_tail = NULL;
949  ht->lru_head = NULL;
950  ht->lru_tail = NULL;
951  ht->prealloc_entries = NULL;
952  ht->size = ht_estsize;
953  ht->rehash_at = (unsigned int) (ht_estsize * MHT_REHASH_TRESHOLD);
954  ht->nentries = 0;
955  ht->nprealloc_entries = 0;
956  ht->ncollisions = 0;
957  ht->build_lru_list = false;
958 
959  /* Initialize each of the hash entries */
960  for (; ht_estsize > 0; ht_estsize--)
961  {
962  *hvector++ = NULL;
963  }
964 
965  return ht;
966 }
967 
968 /*
969  * mht_create_hls - create a hash table
970  * return: hash table
971  * name(in): name of hash table
972  * est_size(in): estimated number of entries
973  * hash_func(in): hash function
974  * cmp_func(in): key compare function
975  *
976  * Note: Create a new hash table for HASH LIST SCAN.
977  * The estimated number of entries for the hash table is fixed in HASH LIST SCAN.
978  * rehashing hash table is not needed becaues of that.
979  * key comparison is performed in executor.
980  */
982 mht_create_hls (const char *name, int est_size, unsigned int (*hash_func) (const void *key, unsigned int ht_size),
983  int (*cmp_func) (const void *key1, const void *key2))
984 {
985  MHT_HLS_TABLE *ht;
986  HENTRY_HLS_PTR *hvector; /* Entries of hash table */
987  unsigned int ht_estsize;
988  size_t size;
989 
990  assert (hash_func != NULL && cmp_func != NULL);
991 
992  /* Get a good number of entries for hash table */
993  if (est_size <= 0)
994  {
995  est_size = 2;
996  }
997 
998  ht_estsize = mht_calculate_htsize ((unsigned int) est_size);
999 
1000  /* Allocate the header information for hash table */
1001  ht = (MHT_HLS_TABLE *) malloc (DB_SIZEOF (MHT_HLS_TABLE));
1002  if (ht == NULL)
1003  {
1005 
1006  return NULL;
1007  }
1008 
1009  /* Initialize the chunky memory manager */
1010  ht->heap_id = db_create_fixed_heap (DB_SIZEOF (HENTRY_HLS), MAX (2, ht_estsize / 2 + 1));
1011  if (ht->heap_id == 0)
1012  {
1014 
1015  free_and_init (ht);
1016  return NULL;
1017  }
1018 
1019  /* Allocate the hash table entry pointers */
1020  size = ht_estsize * DB_SIZEOF (*hvector);
1021  hvector = (HENTRY_HLS_PTR *) malloc (size);
1022  if (hvector == NULL)
1023  {
1025 
1027  free_and_init (ht);
1028  return NULL;
1029  }
1030 
1031  ht->hash_func = hash_func;
1032  ht->cmp_func = cmp_func;
1033  ht->name = name;
1034  ht->table = hvector;
1035  ht->prealloc_entries = NULL;
1036  ht->size = ht_estsize;
1037  ht->nentries = 0;
1038  ht->nprealloc_entries = 0;
1039  ht->ncollisions = 0;
1040  ht->build_lru_list = false;
1041 
1042  /* Initialize each of the hash entries */
1043  for (; ht_estsize > 0; ht_estsize--)
1044  {
1045  *hvector++ = NULL;
1046  }
1047 
1048  return ht;
1049 }
1050 
1051 /*
1052  * mht_rehash - rehash all entires of a hash table
1053  * return: error code
1054  * ht(in/out): hash table to rehash
1055  *
1056  * Note: Expand a hash table. All entries are rehashed onto a larger
1057  * hash table of entries.
1058  */
1059 static int
1061 {
1062  HENTRY_PTR *new_hvector; /* New entries of hash table */
1063  HENTRY_PTR *hvector; /* Entries of hash table */
1064  HENTRY_PTR hentry; /* A hash table entry. linked list */
1065  HENTRY_PTR next_hentry = NULL; /* Next element in linked list */
1066  float rehash_factor;
1067  unsigned int hash;
1068  unsigned int est_size;
1069  size_t size;
1070  unsigned int i;
1071 
1072  /* Find an estimated size for hash table entries */
1073 
1074  rehash_factor = (float) (1.0 + ((float) ht->ncollisions / (float) ht->nentries));
1075  if (MHT_REHASH_FACTOR > rehash_factor)
1076  {
1077  est_size = (unsigned int) (ht->size * MHT_REHASH_FACTOR);
1078  }
1079  else
1080  {
1081  est_size = (unsigned int) (ht->size * rehash_factor);
1082  }
1083 
1084  est_size = mht_calculate_htsize (est_size);
1085 
1086  /* Allocate a new vector to keep the estimated hash entries */
1087  size = est_size * DB_SIZEOF (*hvector);
1088  new_hvector = (HENTRY_PTR *) malloc (size);
1089  if (new_hvector == NULL)
1090  {
1092  return ER_OUT_OF_VIRTUAL_MEMORY;
1093  }
1094 
1095  /* Initialize all entries */
1096  memset (new_hvector, 0x00, size);
1097 
1098  /* Now rehash the current entries onto the vector of hash entries table */
1099  for (ht->ncollisions = 0, hvector = ht->table, i = 0; i < ht->size; hvector++, i++)
1100  {
1101  /* Go over each linked list */
1102  for (hentry = *hvector; hentry != NULL; hentry = next_hentry)
1103  {
1104  next_hentry = hentry->next;
1105 
1106  hash = (*ht->hash_func) (hentry->key, est_size);
1107  if (hash >= est_size)
1108  {
1109  hash %= est_size;
1110  }
1111 
1112  /* Link the new entry with any previous elements */
1113  hentry->next = new_hvector[hash];
1114  if (hentry->next != NULL)
1115  {
1116  ht->ncollisions++;
1117  }
1118  new_hvector[hash] = hentry;
1119  }
1120  }
1121 
1122  /* Now move to new vector of entries */
1123  free_and_init (ht->table);
1124 
1125  ht->table = new_hvector;
1126  ht->size = est_size;
1127  ht->rehash_at = (int) (est_size * MHT_REHASH_TRESHOLD);
1128 
1129  return NO_ERROR;
1130 }
1131 
1132 /*
1133  * mht_destroy - destroy a hash table
1134  * return: void
1135  * ht(in/out): hash table
1136  *
1137  * Note: ht is set as a side effect
1138  */
1139 void
1141 {
1142  assert (ht != NULL);
1143 
1144  free_and_init (ht->table);
1145 
1146  /* release hash table entry storage */
1148 
1149  free_and_init (ht);
1150 }
1151 
1152 /*
1153  * mht_destroy_hls - destroy a hash table
1154  * return: void
1155  * ht(in/out): hash table
1156  *
1157  * Note: ht is set as a side effect
1158  */
1159 void
1161 {
1162  assert (ht != NULL);
1163 
1164  free_and_init (ht->table);
1165 
1166  /* release hash table entry storage */
1168 
1169  free_and_init (ht);
1170 }
1171 
1172 /*
1173  * mht_clear - remove and free all entries of hash table
1174  * return: error code
1175  * ht(in/out): hash table
1176  * rem_func(in): removal function
1177  * func_args(in): removal function arguments
1178  */
1179 int
1180 mht_clear (MHT_TABLE * ht, int (*rem_func) (const void *key, void *data, void *args), void *func_args)
1181 {
1182  HENTRY_PTR *hvector; /* Entries of hash table */
1183  HENTRY_PTR hentry; /* A hash table entry. linked list */
1184  HENTRY_PTR next_hentry = NULL; /* Next element in linked list */
1185  unsigned int i, error_code;
1186 
1187  assert (ht != NULL);
1188 
1189  /*
1190  * Go over the hash table, removing all entries and setting the vector
1191  * entries to NULL.
1192  */
1193  for (hvector = ht->table, i = 0; i < ht->size; hvector++, i++)
1194  {
1195  /* Go over the linked list for this hash table entry */
1196  for (hentry = *hvector; hentry != NULL; hentry = next_hentry)
1197  {
1198  /* free */
1199  if (rem_func)
1200  {
1201  error_code = (*rem_func) (hentry->key, hentry->data, func_args);
1202  if (error_code != NO_ERROR)
1203  {
1204  return error_code;
1205  }
1206 
1207  hentry->key = NULL;
1208  hentry->data = NULL;
1209  }
1210 
1211  next_hentry = hentry->next;
1212  /* Save the entries for future insertions */
1213  ht->nprealloc_entries++;
1214  hentry->next = ht->prealloc_entries;
1215  ht->prealloc_entries = hentry;
1216  }
1217  *hvector = NULL;
1218  }
1219 
1220  ht->act_head = NULL;
1221  ht->act_tail = NULL;
1222  ht->lru_head = NULL;
1223  ht->lru_tail = NULL;
1224  ht->ncollisions = 0;
1225  ht->nentries = 0;
1226 
1227  return NO_ERROR;
1228 }
1229 
1230 /*
1231  * mht_hls_clear - remove and free all entries of hash table
1232  * return: error code
1233  * ht(in/out): hash table
1234  * rem_func(in): removal function
1235  * func_args(in): removal function arguments
1236  */
1237 int
1238 mht_clear_hls (MHT_HLS_TABLE * ht, int (*rem_func) (const void *key, void *data, void *args), void *func_args)
1239 {
1240  HENTRY_HLS_PTR *hvector; /* Entries of hash table */
1241  HENTRY_HLS_PTR hentry; /* A hash table entry. linked list */
1242  HENTRY_HLS_PTR next_hentry = NULL; /* Next element in linked list */
1243  unsigned int i, error_code;
1244 
1245  assert (ht != NULL);
1246 
1247  /*
1248  * Go over the hash table, removing all entries and setting the vector
1249  * entries to NULL.
1250  */
1251  for (hvector = ht->table, i = 0; i < ht->size; hvector++, i++)
1252  {
1253  /* Go over the linked list for this hash table entry */
1254  for (hentry = *hvector; hentry != NULL; hentry = next_hentry)
1255  {
1256  /* free */
1257  if (rem_func)
1258  {
1259  error_code = (*rem_func) (NULL, hentry->data, func_args);
1260  if (error_code != NO_ERROR)
1261  {
1262  return error_code;
1263  }
1264 
1265  hentry->data = NULL;
1266  }
1267 
1268  next_hentry = hentry->next;
1269  /* Save the entries for future insertions */
1270  ht->nprealloc_entries++;
1271  hentry->next = ht->prealloc_entries;
1272  ht->prealloc_entries = hentry;
1273  }
1274  *hvector = NULL;
1275  }
1276 
1277  ht->ncollisions = 0;
1278  ht->nentries = 0;
1279 
1280  return NO_ERROR;
1281 }
1282 
1283 /*
1284  * mht_dump - display all entries of hash table
1285  * return: TRUE/FALSE
1286  * out_fp(in): FILE stream where to dump; if NULL, stdout
1287  * ht(in): hash table to print
1288  * print_id_opt(in): option for printing hash index vector id
1289  * print_func(in): supplied printing function
1290  * func_args(in): arguments to be passed to print_func
1291  *
1292  * Note: Dump the header of hash table, and for each entry in hash table,
1293  * call function "print_func" on three arguments: the key of the entry,
1294  * the data associated with the key, and args, in order to print the entry
1295  * print_id_opt - Print hash index ? Will run faster if we do not need to
1296  * print this information
1297  */
1298 int
1299 mht_dump (THREAD_ENTRY * thread_p, FILE * out_fp, const MHT_TABLE * ht, const int print_id_opt,
1300  int (*print_func) (THREAD_ENTRY * thread_p, FILE * fp, const void *key, void *data, void *args),
1301  void *func_args)
1302 {
1303  HENTRY_PTR *hvector; /* Entries of hash table */
1304  HENTRY_PTR hentry; /* A hash table entry. linked list */
1305  unsigned int i;
1306  int cont = TRUE;
1307 
1308  assert (ht != NULL);
1309 
1310  if (out_fp == NULL)
1311  {
1312  out_fp = stdout;
1313  }
1314 
1315  fprintf (out_fp,
1316  "HTABLE NAME = %s, SIZE = %d, REHASH_AT = %d,\n" "NENTRIES = %d, NPREALLOC = %d, NCOLLISIONS = %d\n\n",
1317  ht->name, ht->size, ht->rehash_at, ht->nentries, ht->nprealloc_entries, ht->ncollisions);
1318 
1319  if (print_id_opt == -1)
1320  {
1321  /* noting to do */
1322  }
1323  else if (print_id_opt)
1324  {
1325  /* Need to print the index vector id. Therefore, scan the whole table */
1326  for (hvector = ht->table, i = 0; i < ht->size; hvector++, i++)
1327  {
1328  if (*hvector != NULL)
1329  {
1330  fprintf (out_fp, "HASH AT %d\n", i);
1331  /* Go over the linked list */
1332  for (hentry = *hvector; cont == TRUE && hentry != NULL; hentry = hentry->next)
1333  {
1334  cont = (*print_func) (thread_p, out_fp, hentry->key, hentry->data, func_args);
1335  }
1336  }
1337  }
1338  }
1339  else
1340  {
1341  /* Quick scan by following only the active entries */
1342  for (hentry = ht->act_head; cont == TRUE && hentry != NULL; hentry = hentry->act_next)
1343  {
1344  cont = (*print_func) (thread_p, out_fp, hentry->key, hentry->data, func_args);
1345  }
1346  }
1347 
1348  fprintf (out_fp, "\n");
1349 
1350  return (cont);
1351 }
1352 
1353 /*
1354  * mht_dump_hls - display all entries of hash table for HASH LIST SCAN
1355  * return: TRUE/FALSE
1356  * out_fp(in): FILE stream where to dump; if NULL, stdout
1357  * ht(in): hash table to print
1358  * print_id_opt(in): option for printing hash index vector id
1359  * print_func(in): supplied printing function
1360  * func_args(in): arguments to be passed to print_func
1361  *
1362  * Note: Dump the header of hash table, and for each entry in hash table,
1363  * call function "print_func" on three arguments: the key of the entry,
1364  * the data associated with the key, and args, in order to print the entry
1365  * print_id_opt - Print hash index ? Will run faster if we do not need to
1366  * print this information
1367  */
1368 int
1369 mht_dump_hls (THREAD_ENTRY * thread_p, FILE * out_fp, const MHT_HLS_TABLE * ht, const int print_id_opt,
1370  int (*print_func) (THREAD_ENTRY * thread_p, FILE * fp, const void *data, void *args),
1371  void *func_args)
1372 {
1373  HENTRY_HLS_PTR *hvector; /* Entries of hash table */
1374  HENTRY_HLS_PTR hentry; /* A hash table entry. linked list */
1375  unsigned int i;
1376  int cont = TRUE;
1377 
1378  assert (ht != NULL);
1379 
1380  if (out_fp == NULL)
1381  {
1382  out_fp = stdout;
1383  }
1384 
1385  fprintf (out_fp,
1386  "HTABLE NAME = %s, SIZE = %d,\n" "NENTRIES = %d, NPREALLOC = %d, NCOLLISIONS = %d\n\n",
1387  ht->name, ht->size, ht->nentries, ht->nprealloc_entries, ht->ncollisions);
1388 
1389  if (print_id_opt)
1390  {
1391  /* Need to print the index vector id. Therefore, scan the whole table */
1392  for (hvector = ht->table, i = 0; i < ht->size; hvector++, i++)
1393  {
1394  if (*hvector != NULL)
1395  {
1396  fprintf (out_fp, "HASH AT %d\n", i);
1397  /* Go over the linked list */
1398  for (hentry = *hvector; cont == TRUE && hentry != NULL; hentry = hentry->next)
1399  {
1400  cont = (*print_func) (thread_p, out_fp, hentry->data, func_args);
1401  }
1402  }
1403  }
1404  }
1405  fprintf (out_fp, "\n");
1406 
1407  return (cont);
1408 }
1409 
1410 /*
1411  * mht_get - find data associated with key
1412  * return: the data associated with the key, or NULL if not found
1413  * ht(in): hash table
1414  * key(in): hashing key
1415  *
1416  * Note: Find the entry in hash table whose key is the value of the given key
1417  */
1418 void *
1419 mht_get (MHT_TABLE * ht, const void *key)
1420 {
1421  unsigned int hash;
1423 
1424  assert (ht != NULL);
1425  assert (key != NULL);
1426 
1427  /*
1428  * Hash the key and make sure that the return value is between 0 and size
1429  * of hash table
1430  */
1431  hash = (*ht->hash_func) (key, ht->size);
1432  if (hash >= ht->size)
1433  {
1434  hash %= ht->size;
1435  }
1436 
1437  /* now search the linked list */
1438  for (hentry = ht->table[hash]; hentry != NULL; hentry = hentry->next)
1439  {
1440  if (hentry->key == key || (*ht->cmp_func) (hentry->key, key))
1441  {
1442  mht_adjust_lru_list (ht, hentry);
1443 
1444  /* return value */
1445  return hentry->data;
1446  }
1447  }
1448  return NULL;
1449 }
1450 
1451 /*
1452  * mht_adjust_lru_list -
1453  * ht(in): hash table
1454  * hentry(in): hash entry
1455  */
1456 int
1458 {
1459  assert (ht && hentry);
1460 
1461  if (ht && hentry && ht->build_lru_list && ht->lru_tail != hentry)
1462  {
1463  if (ht->lru_head == hentry)
1464  {
1465  ht->lru_head = hentry->lru_next;
1466  }
1467 
1468  /* unlink */
1469  hentry->lru_next->lru_prev = hentry->lru_prev;
1470  if (hentry->lru_prev)
1471  {
1472  hentry->lru_prev->lru_next = hentry->lru_next;
1473  }
1474 
1475  /* add at end */
1476  ht->lru_tail->lru_next = hentry;
1477  hentry->lru_prev = ht->lru_tail;
1478  hentry->lru_next = NULL;
1479  ht->lru_tail = hentry;
1480  }
1481 
1482  return NO_ERROR;
1483 }
1484 
1485 /*
1486  * mht_get2 - Find the next data associated with the key; Search the entry next
1487  * to the last result
1488  * return: the data associated with the key, or NULL if not found
1489  * ht(in):
1490  * key(in):
1491  * last(in/out):
1492  *
1493  * NOTE: This call does not affect the LRU list.
1494  */
1495 void *
1496 mht_get2 (const MHT_TABLE * ht, const void *key, void **last)
1497 {
1498  unsigned int hash;
1500 
1501  assert (ht != NULL && key != NULL);
1502 
1503  /*
1504  * Hash the key and make sure that the return value is between 0 and size
1505  * of hash table
1506  */
1507  hash = (*ht->hash_func) (key, ht->size);
1508  if (hash >= ht->size)
1509  {
1510  hash %= ht->size;
1511  }
1512 
1513  /* now search the linked list */
1514  for (hentry = ht->table[hash]; hentry != NULL; hentry = hentry->next)
1515  {
1516  if (hentry->key == key || (*ht->cmp_func) (hentry->key, key))
1517  {
1518  if (last == NULL)
1519  {
1520  return hentry->data;
1521  }
1522  else if (*((HENTRY_PTR *) last) == NULL)
1523  {
1524  *((HENTRY_PTR *) last) = hentry;
1525  return hentry->data;
1526  }
1527  else if (*((HENTRY_PTR *) last) == hentry)
1528  {
1529  /* found the last result; go forward one more step to get next the above 'if' will be true when the next
1530  * one is found */
1531  *((HENTRY_PTR *) last) = NULL;
1532  }
1533  }
1534  }
1535 
1536  return NULL;
1537 }
1538 
1539 /*
1540  * mht_get_hls - Find the next data associated with the key; Search the entry next
1541  * to the last result
1542  * return: the data associated with the key, or NULL if not found
1543  * ht(in):
1544  * key(in):
1545  * last(in/out):
1546  *
1547  * NOTE: This call does not affect the LRU list.
1548  */
1549 void *
1550 mht_get_hls (const MHT_HLS_TABLE * ht, const void *key, void **last)
1551 {
1552  unsigned int hash;
1554 
1555  assert (ht != NULL && key != NULL);
1556 
1557  /*
1558  * Hash the key and make sure that the return value is between 0 and size of hash table
1559  */
1560  hash = (*ht->hash_func) (key, ht->size);
1561  if (hash >= ht->size)
1562  {
1563  hash %= ht->size;
1564  }
1565 
1566  /* In HASH LIST SCAN, key comparison is performed in executor. */
1567  hentry = ht->table[hash];
1568 
1569  if (hentry != NULL)
1570  {
1571  if (last != NULL)
1572  {
1573  *((HENTRY_HLS_PTR *) last) = hentry;
1574  }
1575  return hentry->data;
1576  }
1577  return NULL;
1578 }
1579 
1580 /*
1581  * mht_put_internal - internal function for mht_put(), mht_put_new(), and
1582  * mht_put_data();
1583  * insert an entry associating key with data
1584  * return:
1585  * For option MHT_OPT_DEFAULT, MHT_OPT_KEEP_KEY, MHT_OPT_INSERT_ONLY,
1586  * returns key if insertion was OK, otherwise, it returns NULL.
1587  * For option MHT_OPT_INSERT_IF_NOT_EXISTS,
1588  * returns existing data if duplicated key was found, or return
1589  * inserted data if insertion was OK, otherwise, it returns NULL.
1590  * ht(in/out): hash table (set as a side effect)
1591  * key(in): hashing key
1592  * data(in): data associated with hashing key
1593  * opt(in): options;
1594  * MHT_OPT_DEFAULT - change data and the key as given of the hash
1595  * entry; replace the old entry with the new one
1596  * if there is an entry with the same key
1597  * MHT_OPT_KEEP_KEY - change data but the key of the hash entry
1598  * MHT_OPT_INSERT_ONLY - do not replace the existing hash entry
1599  * even if there is an etnry with the same key
1600  * MHT_OPT_INSERT_IF_NOT_EXISTS - only insert if the key not exists,
1601  * do nothing if the same key exists.
1602  */
1603 static const void *
1604 mht_put_internal (MHT_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt)
1605 {
1606  unsigned int hash;
1608 
1609  assert (ht != NULL && key != NULL);
1610 
1611  /*
1612  * Hash the key and make sure that the return value is between 0 and size
1613  * of hash table
1614  */
1615  hash = (*ht->hash_func) (key, ht->size);
1616  if (hash >= ht->size)
1617  {
1618  hash %= ht->size;
1619  }
1620 
1621  if (!(opt & MHT_OPT_INSERT_ONLY))
1622  {
1623  /* Now search the linked list.. Is there any entry with the given key ? */
1624  for (hentry = ht->table[hash]; hentry != NULL; hentry = hentry->next)
1625  {
1626  if (hentry->key == key || (*ht->cmp_func) (hentry->key, key))
1627  {
1628  if (opt & MHT_OPT_INSERT_IF_NOT_EXISTS)
1629  {
1630  /* Return data for this option */
1631  return hentry->data;
1632  }
1633 
1634  /* Replace the old data with the new one */
1635  if (!(opt & MHT_OPT_KEEP_KEY))
1636  {
1637  hentry->key = key;
1638  }
1639  hentry->data = data;
1640  return key;
1641  }
1642  }
1643  }
1644 
1645  /* This is a new entry */
1646  if (ht->nprealloc_entries > 0)
1647  {
1648  ht->nprealloc_entries--;
1649  hentry = ht->prealloc_entries;
1651  }
1652  else
1653  {
1654  hentry = (HENTRY_PTR) db_fixed_alloc (ht->heap_id, DB_SIZEOF (HENTRY));
1655  if (hentry == NULL)
1656  {
1657  return NULL;
1658  }
1659  }
1660 
1661  if (ht->build_lru_list)
1662  {
1663  /* link new entry to LRU list */
1664  hentry->lru_next = NULL;
1665  hentry->lru_prev = ht->lru_tail;
1666  if (ht->lru_tail)
1667  {
1668  ht->lru_tail->lru_next = hentry;
1669  }
1670  ht->lru_tail = hentry;
1671  if (ht->lru_head == NULL)
1672  {
1673  ht->lru_head = hentry;
1674  }
1675  }
1676 
1677  /*
1678  * Link the new entry to the double link list of active entries and the
1679  * hash itself. The previous entry should point to new one.
1680  */
1681 
1682  hentry->key = key;
1683  hentry->data = data;
1684  hentry->act_next = NULL;
1685  hentry->act_prev = ht->act_tail;
1686  /* Double link tail entry should point to newly created entry */
1687  if (ht->act_tail != NULL)
1688  {
1689  ht->act_tail->act_next = hentry;
1690  }
1691 
1692  ht->act_tail = hentry;
1693  if (ht->act_head == NULL)
1694  {
1695  ht->act_head = hentry;
1696  }
1697 
1698  hentry->next = ht->table[hash];
1699  if (hentry->next != NULL)
1700  {
1701  ht->ncollisions++;
1702  }
1703 
1704  ht->table[hash] = hentry;
1705  ht->nentries++;
1706 
1707  /*
1708  * Rehash if almost all entries of hash table are used and there are at least
1709  * 5% of collisions
1710  */
1711  if (ht->nentries > ht->rehash_at && ht->ncollisions > (ht->nentries * 0.05))
1712  {
1713  if (mht_rehash (ht) < 0)
1714  {
1715  return NULL;
1716  }
1717  }
1718 
1719  return (opt & MHT_OPT_INSERT_IF_NOT_EXISTS) ? data : key;
1720 }
1721 
1722 const void *
1723 mht_put_new (MHT_TABLE * ht, const void *key, void *data)
1724 {
1725  assert (ht != NULL && key != NULL);
1726  return mht_put_internal (ht, key, data, MHT_OPT_INSERT_ONLY);
1727 }
1728 
1729 const void *
1730 mht_put_hls (MHT_HLS_TABLE * ht, const void *key, void *data)
1731 {
1732  assert (ht != NULL && key != NULL);
1733  return mht_put_hls_internal (ht, key, data, MHT_OPT_INSERT_ONLY);
1734 }
1735 
1736 /*
1737  * mht_put_if_not_exists - insert only if the same key not exists.
1738  * return: Return existing data if duplicated key found,
1739  * or return new insertion data if insertion successful,
1740  * otherwise return NULL.
1741  * ht(in/out): hash table
1742  * key(in): hashing key
1743  * data(in): data associated with hashing key
1744  *
1745  * Insert an entry into a hash table only same key not exists.
1746  * Note that this function different with other put functions, do not return key.
1747  */
1748 const void *
1749 mht_put_if_not_exists (MHT_TABLE * ht, const void *key, void *data)
1750 {
1751  assert (ht != NULL && key != NULL);
1752  return mht_put_internal (ht, key, data, MHT_OPT_INSERT_IF_NOT_EXISTS);
1753 }
1754 
1755 const void *
1756 mht_put_data (MHT_TABLE * ht, const void *key, void *data)
1757 {
1758  assert (ht != NULL && key != NULL);
1759  return mht_put_internal (ht, key, data, MHT_OPT_KEEP_KEY);
1760 }
1761 
1762 /*
1763  * mht_put - insert an entry associating key with data
1764  * return: Returns key if insertion was OK, otherwise, it returns NULL
1765  * ht(in/out): hash table (set as a side effect)
1766  * key(in): hashing key
1767  * data(in): data associated with hashing key
1768  *
1769  * Note: Insert an entry into a hash table, associating the given key
1770  * with the given data. If the entry is duplicated, that is, if
1771  * the key already exist the new entry replaces the old one.
1772  *
1773  * The key and data are NOT COPIED, only its pointers are copied. The
1774  * user must be aware that changes to the key and value are reflected
1775  * into the hash table
1776  */
1777 const void *
1778 mht_put (MHT_TABLE * ht, const void *key, void *data)
1779 {
1780  assert (ht != NULL && key != NULL);
1781  return mht_put_internal (ht, key, data, MHT_OPT_DEFAULT);
1782 }
1783 
1784 /*
1785  * mht_put2_internal - internal function for mht_put2(), mht_put_new2(), and
1786  * mht_put_data2();
1787  * Insert an entry associating key with data;
1788  * Allow mutiple entries with the same key value
1789  * return: Returns key if insertion was OK, otherwise, it returns NULL
1790  * ht(in/out): hash table (set as a side effect)
1791  * key(in): hashing key
1792  * data(in): data associated with hashing key
1793  * opt(in): options;
1794  * MHT_OPT_DEFAULT - change data and the key as given of the hash
1795  * entry; replace the old entry with the new one
1796  * if there is an entry with the same key
1797  * MHT_OPT_KEEP_KEY - change data but the key of the hash entry
1798  * MHT_OPT_INSERT_ONLY - do not replace the existing hash entry
1799  * even if there is an etnry with the same key
1800  */
1801 static const void *
1802 mht_put2_internal (MHT_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt)
1803 {
1804  unsigned int hash;
1806 
1807  assert (ht != NULL && key != NULL);
1808 
1809  /*
1810  * Hash the key and make sure that the return value is between 0 and size
1811  * of hash table
1812  */
1813  hash = (*ht->hash_func) (key, ht->size);
1814  if (hash >= ht->size)
1815  {
1816  hash %= ht->size;
1817  }
1818 
1819  if (!(opt & MHT_OPT_INSERT_ONLY))
1820  {
1821  /* now search the linked list */
1822  for (hentry = ht->table[hash]; hentry != NULL; hentry = hentry->next)
1823  {
1824  if ((hentry->key == key || (*ht->cmp_func) (hentry->key, key)) && hentry->data == data)
1825  {
1826  /* We found the existing entry. Replace the old data with the new one. */
1827  if (!(opt & MHT_OPT_KEEP_KEY))
1828  {
1829  hentry->key = key;
1830  }
1831  hentry->data = data;
1832  return key;
1833  }
1834  }
1835  }
1836 
1837  /* get new entry */
1838  if (ht->nprealloc_entries > 0)
1839  {
1840  ht->nprealloc_entries--;
1841  hentry = ht->prealloc_entries;
1843  }
1844  else
1845  {
1846  hentry = (HENTRY_PTR) db_fixed_alloc (ht->heap_id, DB_SIZEOF (HENTRY));
1847  if (hentry == NULL)
1848  {
1849  return NULL;
1850  }
1851  }
1852 
1853  if (ht->build_lru_list)
1854  {
1855  /* link new entry to LRU list */
1856  hentry->lru_next = NULL;
1857  hentry->lru_prev = ht->lru_tail;
1858  if (ht->lru_tail)
1859  {
1860  ht->lru_tail->lru_next = hentry;
1861  }
1862  ht->lru_tail = hentry;
1863  if (ht->lru_head == NULL)
1864  {
1865  ht->lru_head = hentry;
1866  }
1867  }
1868 
1869  /* link the new entry to the double link list of active entries */
1870  hentry->key = key;
1871  hentry->data = data;
1872  hentry->act_next = NULL;
1873  hentry->act_prev = ht->act_tail;
1874  if (ht->act_tail != NULL)
1875  {
1876  ht->act_tail->act_next = hentry;
1877  }
1878  ht->act_tail = hentry;
1879  if (ht->act_head == NULL)
1880  {
1881  ht->act_head = hentry;
1882  }
1883  /* and link to the hash itself */
1884  if ((hentry->next = ht->table[hash]) != NULL)
1885  {
1886  ht->ncollisions++;
1887  }
1888  ht->table[hash] = hentry;
1889  ht->nentries++;
1890 
1891  /* rehash if almost all entries of hash table are used and there are at least 5% of collisions */
1892  if (ht->nentries > ht->rehash_at && ht->ncollisions > (ht->nentries * 0.05))
1893  {
1894  mht_rehash (ht);
1895  }
1896 
1897  return key;
1898 }
1899 
1900 const void *
1901 mht_put2_new (MHT_TABLE * ht, const void *key, void *data)
1902 {
1903  assert (ht != NULL && key != NULL);
1904  return mht_put2_internal (ht, key, data, MHT_OPT_INSERT_ONLY);
1905 }
1906 
1907 #if defined (ENABLE_UNUSED_FUNCTION)
1908 const void *
1909 mht_put2_data (MHT_TABLE * ht, const void *key, void *data)
1910 {
1911  assert (ht != NULL && key != NULL);
1912  return mht_put2_internal (ht, key, data, MHT_OPT_KEEP_KEY);
1913 }
1914 
1915 /*
1916  * mht_put2 - Insert an entry associating key with data;
1917  * Allow mutiple entries with the same key value
1918  * return: Returns key if insertion was OK, otherwise, it returns NULL
1919  * ht(in/out): hash table (set as a side effect)
1920  * key(in): hashing key
1921  * data(in): data associated with hashing key
1922  *
1923  * Note: Insert an entry into a hash table, associating the given key
1924  * with the given data. If the entry is duplicated, that is, if
1925  * the key already exist the new entry replaces the old one.
1926  *
1927  * The key and data are NOT COPIED, only its pointers are copied. The
1928  * user must be aware that changes to the key and value are reflected
1929  * into the hash table
1930  */
1931 const void *
1932 mht_put2 (MHT_TABLE * ht, const void *key, void *data)
1933 {
1934  assert (ht != NULL && key != NULL);
1935  return mht_put2_internal (ht, key, data, MHT_OPT_DEFAULT);
1936 }
1937 #endif
1938 
1939 /*
1940  * mht_rem - remove a hash entry
1941  * return: error code
1942  * ht(in): hash table (set as a side effect)
1943  * key(in): hashing key
1944  * rem_func(in): supplied function to delete the data and key
1945  * func_args(in): arguments to be passed to rem_func
1946  *
1947  * Note: For each entry in hash table, call function 'rem_func' on three
1948  * arguments: the key of the entry, the data associated with the key,
1949  * and the given args, in order to delete the data and key
1950  */
1951 int
1952 mht_rem (MHT_TABLE * ht, const void *key, int (*rem_func) (const void *key, void *data, void *args), void *func_args)
1953 {
1954  unsigned int hash;
1955  HENTRY_PTR prev_hentry;
1957  int error_code = NO_ERROR;
1958 
1959  assert (ht != NULL && key != NULL);
1960 
1961  /*
1962  * Hash the key and make sure that the return value is between 0 and size
1963  * of hash table
1964  */
1965  hash = (*ht->hash_func) (key, ht->size);
1966  if (hash >= ht->size)
1967  {
1968  hash %= ht->size;
1969  }
1970 
1971  /* Now search the linked list.. Is there any entry with the given key ? */
1972  for (hentry = ht->table[hash], prev_hentry = NULL; hentry != NULL; prev_hentry = hentry, hentry = hentry->next)
1973  {
1974  if (hentry->key == key || (*ht->cmp_func) (hentry->key, key))
1975  {
1976  /*
1977  * We found the entry
1978  * Call "rem_func" (if any) to delete the data and key
1979  * Delete the node from the double link list of active entries.
1980  * Then delete the node from the hash table.
1981  */
1982 
1983  if (rem_func)
1984  {
1985  error_code = (*rem_func) (hentry->key, hentry->data, func_args);
1986  if (error_code != NO_ERROR)
1987  {
1988  return error_code;
1989  }
1990  }
1991 
1992  if (ht->build_lru_list)
1993  {
1994  /* remove from LRU list */
1995  if (ht->lru_head == ht->lru_tail)
1996  {
1997  ht->lru_head = ht->lru_tail = NULL;
1998  }
1999  else if (ht->lru_head == hentry)
2000  {
2001  ht->lru_head = hentry->lru_next;
2002  hentry->lru_next->lru_prev = NULL;
2003  }
2004  else if (ht->lru_tail == hentry)
2005  {
2006  ht->lru_tail = hentry->lru_prev;
2007  hentry->lru_prev->lru_next = NULL;
2008  }
2009  else
2010  {
2011  hentry->lru_prev->lru_next = hentry->lru_next;
2012  hentry->lru_next->lru_prev = hentry->lru_prev;
2013  }
2014  }
2015 
2016  /* Remove from double link list of active entries */
2017  if (ht->act_head == ht->act_tail)
2018  {
2019  /* Single active element */
2020  ht->act_head = ht->act_tail = NULL;
2021  }
2022  else if (ht->act_head == hentry)
2023  {
2024  /* Deleting from the head */
2025  ht->act_head = hentry->act_next;
2026  hentry->act_next->act_prev = NULL;
2027  }
2028  else if (ht->act_tail == hentry)
2029  {
2030  /* Deleting from the tail */
2031  ht->act_tail = hentry->act_prev;
2032  hentry->act_prev->act_next = NULL;
2033  }
2034  else
2035  {
2036  /* Deleting from the middle */
2037  hentry->act_prev->act_next = hentry->act_next;
2038  hentry->act_next->act_prev = hentry->act_prev;
2039  }
2040 
2041  /* Remove from the hash */
2042  if (prev_hentry != NULL)
2043  {
2044  prev_hentry->next = hentry->next;
2045  ht->ncollisions--;
2046  }
2047  else if ((ht->table[hash] = hentry->next) != NULL)
2048  {
2049  ht->ncollisions--;
2050  }
2051  ht->nentries--;
2052  /* Save the entry for future insertions */
2053  ht->nprealloc_entries++;
2054  hentry->next = ht->prealloc_entries;
2055  ht->prealloc_entries = hentry;
2056 
2057  return NO_ERROR;
2058  }
2059  }
2060 
2061  return ER_FAILED;
2062 }
2063 
2064 /*
2065  * mht_rem2 - Remove an hash entry having the specified data
2066  * return: error code
2067  * ht(in): hash table (set as a side effect)
2068  * key(in): hashing key
2069  * data(in):
2070  * rem_func(in): supplied function to delete the data and key
2071  * func_args(in): arguments to be passed to rem_func
2072  *
2073  * Note: For each entry in hash table, call function 'rem_func' on three
2074  * arguments: the key of the entry, the data associated with the key,
2075  * and the given args, in order to delete the data and key
2076  */
2077 int
2078 mht_rem2 (MHT_TABLE * ht, const void *key, const void *data, int (*rem_func) (const void *key, void *data, void *args),
2079  void *func_args)
2080 {
2081  unsigned int hash;
2082  HENTRY_PTR prev_hentry;
2084  int error_code = NO_ERROR;
2085 
2086  assert (ht != NULL && key != NULL);
2087 
2088  /* hash the key and make sure that the return value is between 0 and size of hash table */
2089  hash = (*ht->hash_func) (key, ht->size);
2090  if (hash >= ht->size)
2091  {
2092  hash %= ht->size;
2093  }
2094 
2095  /* now search the linked list */
2096  for (hentry = ht->table[hash], prev_hentry = NULL; hentry != NULL; prev_hentry = hentry, hentry = hentry->next)
2097  {
2098  if ((hentry->key == key || (*ht->cmp_func) (hentry->key, key)) && hentry->data == data)
2099  {
2100  /*
2101  * We found the entry.
2102  * Call "fun" (if any) to delete the data and key.
2103  * Delete the node from the double link list of active entries.
2104  * Then delete the node from the hash table.
2105  */
2106  if (rem_func)
2107  {
2108  error_code = (*rem_func) (hentry->key, hentry->data, func_args);
2109  if (error_code != NO_ERROR)
2110  {
2111  return error_code;
2112  }
2113  }
2114 
2115  if (ht->build_lru_list)
2116  {
2117  /* remove from LRU list */
2118  if (ht->lru_head == ht->lru_tail)
2119  {
2120  ht->lru_head = ht->lru_tail = NULL;
2121  }
2122  else if (ht->lru_head == hentry)
2123  {
2124  ht->lru_head = hentry->lru_next;
2125  hentry->lru_next->lru_prev = NULL;
2126  }
2127  else if (ht->lru_tail == hentry)
2128  {
2129  ht->lru_tail = hentry->lru_prev;
2130  hentry->lru_prev->lru_next = NULL;
2131  }
2132  else
2133  {
2134  hentry->lru_prev->lru_next = hentry->lru_next;
2135  hentry->lru_next->lru_prev = hentry->lru_prev;
2136  }
2137  }
2138 
2139  /* remove from double link list of active entries */
2140  if (ht->act_head == ht->act_tail)
2141  {
2142  ht->act_head = ht->act_tail = NULL;
2143  }
2144  else if (ht->act_head == hentry)
2145  {
2146  ht->act_head = hentry->act_next;
2147  hentry->act_next->act_prev = NULL;
2148  }
2149  else if (ht->act_tail == hentry)
2150  {
2151  ht->act_tail = hentry->act_prev;
2152  hentry->act_prev->act_next = NULL;
2153  }
2154  else
2155  {
2156  hentry->act_prev->act_next = hentry->act_next;
2157  hentry->act_next->act_prev = hentry->act_prev;
2158  }
2159  /* remove from the hash */
2160  if (prev_hentry != NULL)
2161  {
2162  prev_hentry->next = hentry->next;
2163  ht->ncollisions--;
2164  }
2165  else if ((ht->table[hash] = hentry->next) != NULL)
2166  {
2167  ht->ncollisions--;
2168  }
2169  ht->nentries--;
2170  /* save the entry for future insertions */
2171  ht->nprealloc_entries++;
2172  hentry->next = ht->prealloc_entries;
2173  ht->prealloc_entries = hentry;
2174 
2175  return NO_ERROR;
2176  }
2177  }
2178 
2179  return ER_FAILED;
2180 }
2181 
2182 /*
2183  * mht_map - map over hash entries
2184  * return: NO_ERROR or error code - the result of user supplied "map_func"
2185  * ht(in): hash table
2186  * map_func(in): user supplied mapping function
2187  * func_args(in): arguments to be passed to rem_func
2188  *
2189  * Note: For each entry in hash table, call function "map_func" on three
2190  * arguments: the key of the entry, the data associated with the key,
2191  * and the given args. The function that is called should not remove
2192  * (other than the current entry being processed) nor insert entries on
2193  * the given hash table, otherwise, the behavior of the _map is
2194  * unpredictable (e.g., a newly inserted entry may or may not be
2195  * included as part of the map. If "map_func" returns FALSE,
2196  * the mapping is stopped.
2197  */
2198 int
2199 mht_map (const MHT_TABLE * ht, int (*map_func) (const void *key, void *data, void *args), void *func_args)
2200 {
2202  HENTRY_PTR next;
2203  int error_code = NO_ERROR;
2204 
2205  assert (ht != NULL);
2206 
2207  for (hentry = ht->act_head; hentry != NULL; hentry = next)
2208  {
2209  /* Just in case the hentry is removed using mht_rem save the next entry */
2210  next = hentry->act_next;
2211  error_code = (*map_func) (hentry->key, hentry->data, func_args);
2212  if (error_code != NO_ERROR)
2213  {
2214  break;
2215  }
2216  }
2217 
2218  return (error_code);
2219 }
2220 
2221 /*
2222  * mht_map_no_key - map over hash entries;
2223  * Same as mht_map, but "map_func" is called on two arguments:
2224  * data and arguments.
2225  * return: NO_ERROR or error code - the result of user supplied "map_func"
2226  * ht(in): hash table
2227  * map_func(in): user supplied mapping function
2228  * func_args(in): arguments to be passed to rem_func
2229  */
2230 int
2231 mht_map_no_key (THREAD_ENTRY * thread_p, const MHT_TABLE * ht,
2232  int (*map_func) (THREAD_ENTRY * thread_p, void *data, void *args), void *func_args)
2233 {
2235  HENTRY_PTR next;
2236  int error_code = NO_ERROR;
2237 
2238  assert (ht != NULL);
2239 
2240  for (hentry = ht->act_head; hentry != NULL; hentry = next)
2241  {
2242  /* Just in case the hentry is removed using mht_rem save the next entry */
2243  next = hentry->act_next;
2244  error_code = (*map_func) (thread_p, hentry->data, func_args);
2245  if (error_code != NO_ERROR)
2246  {
2247  break;
2248  }
2249  }
2250 
2251  return (error_code);
2252 }
2253 
2254 /*
2255  * mht_count - number of hash entries
2256  * return: number of entries
2257  * ht(in): hash table
2258  */
2259 unsigned int
2260 mht_count (const MHT_TABLE * ht)
2261 {
2262  assert (ht != NULL);
2263  return ht->nentries;
2264 }
2265 
2266 /*
2267  * mht_get_hash_number - get linear hash number or string hash number
2268  * return: the hash value of the hash key
2269  * ht_size(out): hash size
2270  * val(in): DB_VALUE to hash
2271  *
2272  * Note:
2273  */
2274 unsigned int
2275 mht_get_hash_number (const int ht_size, const DB_VALUE * val)
2276 {
2277  unsigned int hashcode = 0;
2278  int i, len;
2279  const char *ptr;
2280 
2281  if (!val || DB_IS_NULL (val) || ht_size <= 1)
2282  {
2283  hashcode = 0;
2284  }
2285  else
2286  {
2287  switch (db_value_type (val))
2288  {
2289  case DB_TYPE_INTEGER:
2290  hashcode = mht_get_shiftmult32 (val->data.i, ht_size);
2291  break;
2292  case DB_TYPE_SMALLINT:
2293  hashcode = mht_get_shiftmult32 (val->data.sh, ht_size);
2294  break;
2295  case DB_TYPE_BIGINT:
2296  {
2297  DB_BIGINT bigint;
2298  unsigned int x, y;
2299 
2300  bigint = db_get_bigint (val);
2301  x = bigint >> 32;
2302  y = (unsigned int) bigint;
2303  hashcode = mht_get_shiftmult32 (x ^ y, ht_size);
2304  break;
2305  }
2306  break;
2307  case DB_TYPE_FLOAT:
2308  {
2309  unsigned int *x, y;
2310  x = (unsigned int *) &val->data.f;
2311  y = (*x) & 0xFFFFFFF0;
2312  hashcode = mht_get_shiftmult32 (y, ht_size);
2313  }
2314  break;
2315  case DB_TYPE_DOUBLE:
2316  case DB_TYPE_MONETARY:
2317  {
2318  unsigned int *x, y, z;
2319  x = (unsigned int *) &val->data.d;
2320  y = (x[0]) & 0xFFFFFFF0;
2321  z = (x[1]) & 0xFFFFFFF0;
2322  hashcode = mht_get_shiftmult32 (y ^ z, ht_size);
2323  }
2324  break;
2325  case DB_TYPE_NUMERIC:
2326  {
2327  unsigned int *buf = (unsigned int *) val->data.num.d.buf;
2328  hashcode = mht_get_shiftmult32 (buf[0] ^ buf[1] ^ buf[2] ^ buf[3], ht_size);
2329  }
2330  break;
2331  case DB_TYPE_DATE:
2332  hashcode = mht_get_shiftmult32 (val->data.date, ht_size);
2333  break;
2334  case DB_TYPE_TIME:
2335  hashcode = mht_get_shiftmult32 (val->data.time, ht_size);
2336  break;
2337  case DB_TYPE_TIMESTAMP:
2338  case DB_TYPE_TIMESTAMPLTZ:
2339  hashcode = mht_get_shiftmult32 (val->data.utime, ht_size);
2340  break;
2341  case DB_TYPE_TIMESTAMPTZ:
2342  hashcode = mht_get_shiftmult32 (val->data.timestamptz.timestamp, ht_size);
2343  break;
2344  case DB_TYPE_DATETIME:
2345  case DB_TYPE_DATETIMELTZ:
2346  hashcode = mht_get_shiftmult32 (val->data.datetime.date ^ val->data.datetime.time, ht_size);
2347  break;
2348  case DB_TYPE_DATETIMETZ:
2349  hashcode =
2351  break;
2352  case DB_TYPE_OID:
2353  {
2354  unsigned int x = (val->data.oid.volid << 16) | (val->data.oid.slotid);
2355  unsigned int y = val->data.oid.pageid;
2356 
2357  hashcode = mht_get_shiftmult32 (x ^ y, ht_size);
2358  }
2359  break;
2360  case DB_TYPE_BIT:
2361  case DB_TYPE_VARBIT:
2362  case DB_TYPE_CHAR:
2363  case DB_TYPE_VARCHAR:
2364  case DB_TYPE_NCHAR:
2365  case DB_TYPE_VARNCHAR:
2366  ptr = db_get_string (val);
2367  if (ptr)
2368  {
2369  len = db_get_string_size (val);
2370  if (len < 0)
2371  {
2372  len = (int) strlen (ptr);
2373  }
2374 
2375  i = len;
2376  for (i--; 0 <= i && ptr[i]; i--)
2377  {
2378  /* only the trailing ASCII space is ignored; the hashing for other characters depend on collation */
2379  if (ptr[i] != 0x20)
2380  {
2381  break;
2382  }
2383  }
2384  i++;
2385  }
2386  if (!ptr || ptr[0] == 0 || i <= 0)
2387  {
2388  hashcode = 0;
2389  }
2390  else
2391  {
2392  hashcode = MHT2STR_COLL (db_get_string_collation (val), (unsigned char *) ptr, i);
2393  hashcode %= ht_size;
2394  }
2395  break;
2396  case DB_TYPE_SET:
2397  case DB_TYPE_MULTISET:
2398  case DB_TYPE_SEQUENCE:
2399  case DB_TYPE_VOBJ:
2400  {
2401  int size = val->data.set->disk_size / 4;
2402  unsigned int x = 0;
2403  int i;
2404 
2405  for (i = 0; i < size; i++)
2406  {
2407  x ^= (unsigned int) (val->data.set->disk_set[i * 4]);
2408  }
2409 
2410  hashcode = mht_get_shiftmult32 (x, ht_size);
2411  }
2412  break;
2413  case DB_TYPE_ENUMERATION:
2414  hashcode = mht_get_shiftmult32 (val->data.enumeration.short_val, ht_size);
2415  break;
2416  case DB_TYPE_JSON:
2417  {
2418  char *json_body = NULL;
2419 
2420  json_body = db_get_json_raw_body (val);
2421 
2422  if (json_body == NULL)
2423  {
2424  hashcode = 0;
2425  }
2426  else
2427  {
2428  len = (int) strlen (json_body);
2429 
2430  hashcode = MHT2STR_COLL (LANG_COLL_BINARY, (unsigned char *) json_body, len);
2431  hashcode %= ht_size;
2432  db_private_free (NULL, json_body);
2433  }
2434  }
2435  break;
2436  default: /* impossible */
2437  /*
2438  * TODO this is actually possible. See the QA scenario:
2439  * sql/_01_object/_09_partition/_006_prunning/cases/1093.sql
2440  * select * from hash_test where test_int = round(11.57);
2441  * The value has type DB_TYPE_DOUBLE in this case.
2442  */
2443  er_log_debug (ARG_FILE_LINE, "mht_get_hash_number: ERROR type = %d" " is Unsupported partition column type.",
2444  db_value_type (val));
2445 #if defined(NDEBUG)
2446  hashcode = 0;
2447 #else /* NDEBUG */
2448  /* debugging purpose */
2449  abort ();
2450 #endif /* NDEBUG */
2451  break;
2452  }
2453  }
2454 
2455  return hashcode;
2456 }
2457 
2458 #if defined (ENABLE_UNUSED_FUNCTION)
2459 /*
2460  * mht_get32_next_power_of_2 -
2461  * return: the next power of 2 greater than ht_size
2462  * ht_size(out): hash size
2463  *
2464  * Note: find first 1's bit of 32bits integer
2465  */
2466 static unsigned int
2467 mht_get32_next_power_of_2 (const unsigned int ht_size)
2468 {
2469  unsigned int map = 0xffff0000, mapsave;
2470  int mi;
2471 
2472  if (ht_size == 0)
2473  {
2474  return 1;
2475  }
2476 
2477  if ((map & ht_size) == 0)
2478  {
2479  map ^= 0xffffffff;
2480  }
2481 
2482  for (mi = 3; mi >= 0; mi--)
2483  {
2484  mapsave = map;
2485  map = (map << (1 << mi)) & mapsave;
2486  if ((map & ht_size) == 0)
2487  {
2488  map = (map ^ 0xffffffff) & mapsave;
2489  }
2490  }
2491 
2492  if (ht_size == map)
2493  {
2494  return map;
2495  }
2496  else
2497  {
2498  return map << 1;
2499  }
2500 }
2501 #endif /* ENABLE_UNUSED_FUNCTION */
2502 
2503 /*
2504  * mht_get_shiftmult32 -
2505  * return: new integer hash value
2506  * key(in): hash key value
2507  * ht_size(in): hash size
2508  *
2509  * Note: Robert Jenkin & Thomas Wang algorithm
2510  */
2511 static unsigned int
2512 mht_get_shiftmult32 (unsigned int key, const unsigned int ht_size)
2513 {
2514  unsigned int c2 = 0x27d4eb2d; /* a prime or an odd constant */
2515 
2516  key = (key ^ 61) ^ (key >> 16);
2517  key += (key << 3);
2518  key ^= (key >> 4);
2519  key *= c2;
2520  key ^= (key >> 15);
2521  return (key % ht_size);
2522 }
2523 
2524 #if defined (ENABLE_UNUSED_FUNCTION)
2525 /*
2526  * mht_get_linear_hash32 - find the next power of 2 greater than hashsize
2527  * return: linear hash value
2528  * key: hash key value
2529  * ht_size: hash size
2530  */
2531 static unsigned int
2532 mht_get_linear_hash32 (const unsigned int key, const unsigned int ht_size)
2533 {
2534  unsigned int np, ret;
2535 
2536  np = mht_get32_next_power_of_2 (ht_size);
2537  ret = key & (np - 1);
2538 
2539  for (ret = key & (np - 1); ret >= ht_size; ret &= (np - 1))
2540  {
2541  if (np % 2)
2542  {
2543  np = np / 2 + 1;
2544  }
2545  else
2546  {
2547  np = np / 2;
2548  }
2549  }
2550  return ret;
2551 }
2552 #endif /* ENABLE_UNUSED_FUNCTION */
2553 
2554 /*
2555  * mht_put_hls_internal
2556  * internal function for mht_put_hls()
2557  * put data in the order.
2558  * eliminates unnecessary logic to improve performance for hash list scan.
2559  *
2560  * return: key
2561  * ht(in/out): hash table (set as a side effect)
2562  * key(in): hashing key
2563  * data(in): data associated with hashing key
2564  * opt(in): options;
2565  */
2566 static const void *
2567 mht_put_hls_internal (MHT_HLS_TABLE * ht, const void *key, void *data, MHT_PUT_OPT opt)
2568 {
2569  unsigned int hash;
2571 
2572  assert (ht != NULL && key != NULL);
2573 
2574  /*
2575  * Hash the key and make sure that the return value is between 0 and size
2576  * of hash table
2577  */
2578  hash = (*ht->hash_func) (key, ht->size);
2579  if (hash >= ht->size)
2580  {
2581  hash %= ht->size;
2582  }
2583 
2584  /* This is a new entry */
2585  if (ht->nprealloc_entries > 0)
2586  {
2587  ht->nprealloc_entries--;
2588  hentry = ht->prealloc_entries;
2590  }
2591  else
2592  {
2594  if (hentry == NULL)
2595  {
2596  return NULL;
2597  }
2598  }
2599 
2600  hentry->data = data;
2601 
2602  /* To input in order, use the tail node. */
2603  if (ht->table[hash] == NULL)
2604  {
2605  ht->table[hash] = hentry;
2606  }
2607  else
2608  {
2609  ht->table[hash]->tail->next = hentry;
2610  ht->ncollisions++;
2611  }
2612  hentry->next = NULL;
2613  ht->table[hash]->tail = hentry;
2614  ht->nentries++;
2615 
2616  return key;
2617 }
DB_C_FLOAT db_get_float(const DB_VALUE *value)
HENTRY_PTR act_next
Definition: memory_hash.h:44
DB_TIME time
Definition: dbtype_def.h:1056
void mht_destroy_hls(MHT_HLS_TABLE *ht)
Definition: memory_hash.c:1160
void * mht_get_hls(const MHT_HLS_TABLE *ht, const void *key, void **last)
Definition: memory_hash.c:1550
static unsigned int mht_calculate_htsize(unsigned int ht_size)
Definition: memory_hash.c:830
static const void * mht_put2_internal(MHT_TABLE *ht, const void *key, void *data, MHT_PUT_OPT opt)
Definition: memory_hash.c:1802
#define NO_ERROR
Definition: error_code.h:46
int mht_map_no_key(THREAD_ENTRY *thread_p, const MHT_TABLE *ht, int(*map_func)(THREAD_ENTRY *thread_p, void *data, void *args), void *func_args)
Definition: memory_hash.c:2231
unsigned int mht_ptrhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:547
unsigned int nprealloc_entries
Definition: memory_hash.h:156
enum mht_put_opt MHT_PUT_OPT
Definition: memory_hash.c:78
short sh
Definition: dbtype_def.h:1050
#define TRUE
Definition: broker_admin.c:49
DB_NUMERIC num
Definition: dbtype_def.h:1069
DB_COLLECTION * db_get_set(const DB_VALUE *value)
int mht_clear(MHT_TABLE *ht, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1180
DB_MIDXKEY * db_get_midxkey(const DB_VALUE *value)
DB_VALUE_COMPARE_RESULT tp_value_compare(const DB_VALUE *value1, const DB_VALUE *value2, int allow_coercion, int total_order)
unsigned int mht_1strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:447
unsigned int mht_4strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:505
int disk_size
Definition: db_set.h:48
HENTRY_PTR lru_next
Definition: memory_hash.h:46
DB_CONST_C_BIT db_get_bit(const DB_VALUE *value, int *length)
int char_tolower(int c)
Definition: chartype.c:146
int db_get_int(const DB_VALUE *value)
DB_TIMESTAMP timestamp
Definition: dbtype_def.h:766
DB_C_DOUBLE db_get_double(const DB_VALUE *value)
#define ER_FAILED
Definition: error_code.h:47
DB_IDENTIFIER oid
Definition: dbtype_def.h:1068
int db_get_string_collation(const DB_VALUE *value)
DB_ENUM_ELEMENT enumeration
Definition: dbtype_def.h:1072
const void * mht_put_if_not_exists(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1749
int mht_rem(MHT_TABLE *ht, const void *key, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1952
#define NPRIMES
Definition: memory_hash.c:808
DB_DATETIME datetime
Definition: dbtype_def.h:1060
const void * mht_put(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1778
char * db_get_json_raw_body(const DB_VALUE *value)
Definition: db_macro.c:5082
static unsigned int mht_5str_pseudo_key(const void *key, int key_size)
Definition: memory_hash.c:376
DB_C_NUMERIC db_get_numeric(const DB_VALUE *value)
unsigned int rehash_at
Definition: memory_hash.h:69
bool build_lru_list
Definition: memory_hash.h:159
DB_DATETIMETZ * db_get_datetimetz(const DB_VALUE *value)
int mht_compare_ints_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:731
HL_HEAPID heap_id
Definition: memory_hash.h:158
int mht_dump_hls(THREAD_ENTRY *thread_p, FILE *out_fp, const MHT_HLS_TABLE *ht, const int print_id_opt, int(*print_func)(THREAD_ENTRY *thread_p, FILE *fp, const void *data, void *args), void *func_args)
Definition: memory_hash.c:1369
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
unsigned int nprealloc_entries
Definition: memory_hash.h:71
int mht_compare_logpageids_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:743
#define er_log_debug(...)
static const unsigned int mht_Primes[NPRIMES]
Definition: memory_hash.c:809
void * mht_get2(const MHT_TABLE *ht, const void *key, void **last)
Definition: memory_hash.c:1496
unsigned int(* hash_func)(const void *key, unsigned int htsize)
Definition: memory_hash.h:149
void * db_fixed_alloc(HL_HEAPID heap_id, size_t size)
Definition: fixed_alloc.c:92
unsigned int size
Definition: memory_hash.h:154
#define MHT2STR_COLL(id, str, size)
Definition: memory_hash.h:36
HL_HEAPID heap_id
Definition: memory_hash.h:73
static const void * mht_put_hls_internal(MHT_HLS_TABLE *ht, const void *key, void *data, MHT_PUT_OPT opt)
Definition: memory_hash.c:2567
void THREAD_ENTRY
#define GET_PTR_FOR_HASH(key)
Definition: memory_hash.c:63
bool build_lru_list
Definition: memory_hash.h:74
static int mht_rehash(MHT_TABLE *ht)
Definition: memory_hash.c:1060
void db_destroy_fixed_heap(HL_HEAPID heap_id)
Definition: fixed_alloc.c:80
static const void * mht_put_internal(MHT_TABLE *ht, const void *key, void *data, MHT_PUT_OPT opt)
Definition: memory_hash.c:1604
DB_TIMESTAMPTZ * db_get_timestamptz(const DB_VALUE *value)
unsigned int nentries
Definition: memory_hash.h:70
#define OID_PSEUDO_KEY(oidp)
Definition: oid.h:130
DB_MONETARY * db_get_monetary(const DB_VALUE *value)
void mht_destroy(MHT_TABLE *ht)
Definition: memory_hash.c:1140
DB_DATA data
Definition: dbtype_def.h:1083
unsigned int DB_TIMESTAMP
Definition: dbtype_def.h:759
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
DB_TIMESTAMP utime
Definition: dbtype_def.h:1058
HENTRY_PTR act_tail
Definition: memory_hash.h:63
#define assert(x)
unsigned int mht_1strlowerhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:420
const char * name
Definition: memory_hash.h:151
unsigned int ncollisions
Definition: memory_hash.h:157
unsigned int size
Definition: memory_hash.h:68
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
DB_TYPE db_value_type(const DB_VALUE *value)
DB_DATETIME datetime
Definition: dbtype_def.h:783
int intl_identifier_casecmp(const char *str1, const char *str2)
unsigned int mht_3strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:483
unsigned int mht_numhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:533
static const float MHT_REHASH_FACTOR
Definition: memory_hash.c:68
DB_OBJECT * db_get_object(const DB_VALUE *value)
unsigned int mht_valhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:561
unsigned char buf[DB_NUMERIC_BUF_SIZE]
Definition: dbtype_def.h:794
#define DB_SIZEOF(val)
Definition: memory_alloc.h:54
INT64 LOG_PAGEID
void * mht_get(MHT_TABLE *ht, const void *key)
Definition: memory_hash.c:1419
#define NULL
Definition: freelistheap.h:34
void * data
Definition: memory_hash.h:50
HENTRY_PTR prealloc_entries
Definition: memory_hash.h:67
DB_DATE date
Definition: dbtype_def.h:1057
const void * mht_put2_new(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1901
int mht_compare_identifiers_equal(const void *key1, const void *key2)
Definition: memory_hash.c:755
DB_TIMESTAMPTZ timestamptz
Definition: dbtype_def.h:1059
HENTRY_HLS_PTR next
Definition: memory_hash.h:141
const void * mht_put_data(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1756
const void * mht_put_hls(MHT_HLS_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1730
HENTRY_PTR * table
Definition: memory_hash.h:60
MHT_TABLE * mht_create(const char *name, int est_size, unsigned int(*hash_func)(const void *key, unsigned int ht_size), int(*cmp_func)(const void *key1, const void *key2))
Definition: memory_hash.c:894
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
HENTRY_PTR act_head
Definition: memory_hash.h:61
unsigned int mht_5strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:521
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
int pr_midxkey_get_element_nocopy(const DB_MIDXKEY *midxkey, int index, DB_VALUE *value, int *prev_indexp, char **prev_ptrp)
#define CEIL_PTVDIV(dividend, divisor)
Definition: memory_alloc.h:50
HENTRY_HLS_PTR tail
Definition: memory_hash.h:140
const char * name
Definition: memory_hash.h:59
int pr_clear_value(DB_VALUE *value)
DB_BIGINT db_get_bigint(const DB_VALUE *value)
int64_t DB_BIGINT
Definition: dbtype_def.h:751
struct hentry * HENTRY_PTR
Definition: memory_hash.h:41
HENTRY_PTR lru_head
Definition: memory_hash.h:65
int mht_compare_ptrs_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:779
int mht_dump(THREAD_ENTRY *thread_p, FILE *out_fp, const MHT_TABLE *ht, const int print_id_opt, int(*print_func)(THREAD_ENTRY *thread_p, FILE *fp, const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1299
static unsigned int mht_get_shiftmult32(unsigned int key, const unsigned int ht_size)
Definition: memory_hash.c:2512
#define ARG_FILE_LINE
Definition: error_manager.h:44
unsigned int mht_get_hash_number(const int ht_size, const DB_VALUE *val)
Definition: memory_hash.c:2275
HENTRY_PTR next
Definition: memory_hash.h:48
OID * db_get_oid(const DB_VALUE *value)
unsigned int nentries
Definition: memory_hash.h:155
const void * mht_put_new(MHT_TABLE *ht, const void *key, void *data)
Definition: memory_hash.c:1723
HENTRY_PTR act_prev
Definition: memory_hash.h:45
void * data
Definition: memory_hash.h:142
unsigned int DB_DATE
Definition: dbtype_def.h:771
unsigned int mht_count(const MHT_TABLE *ht)
Definition: memory_hash.c:2260
static unsigned int mht_3str_pseudo_key(const void *key, int key_size, const unsigned int max_value)
Definition: memory_hash.c:230
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
HENTRY_HLS_PTR * table
Definition: memory_hash.h:152
DB_DATE * db_get_date(const DB_VALUE *value)
const void * key
Definition: memory_hash.h:49
int mht_clear_hls(MHT_HLS_TABLE *ht, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:1238
unsigned int ncollisions
Definition: memory_hash.h:72
unsigned int date
Definition: dbtype_def.h:776
int64_t est_size
Definition: unloaddb.c:54
char * disk_set
Definition: db_set.h:44
int mht_rem2(MHT_TABLE *ht, const void *key, const void *data, int(*rem_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:2078
HENTRY_HLS_PTR prealloc_entries
Definition: memory_hash.h:153
DB_TIMESTAMP * db_get_timestamp(const DB_VALUE *value)
int db_get_string_size(const DB_VALUE *value)
DB_C_SHORT db_get_short(const DB_VALUE *value)
HENTRY_PTR lru_tail
Definition: memory_hash.h:66
int(* cmp_func)(const void *key1, const void *key2)
Definition: memory_hash.h:150
MHT_HLS_TABLE * mht_create_hls(const char *name, int est_size, unsigned int(*hash_func)(const void *key, unsigned int ht_size), int(*cmp_func)(const void *key1, const void *key2))
Definition: memory_hash.c:982
int i
Definition: dynamic_load.c:954
int mht_map(const MHT_TABLE *ht, int(*map_func)(const void *key, void *data, void *args), void *func_args)
Definition: memory_hash.c:2199
int db_make_null(DB_VALUE *value)
HL_HEAPID db_create_fixed_heap(int req_size, int recs_per_chunk)
Definition: fixed_alloc.c:64
#define DB_IS_NULL(value)
Definition: dbtype.h:63
unsigned int(* hash_func)(const void *key, unsigned int htsize)
Definition: memory_hash.h:57
DB_COLLECTION * set
Definition: dbtype_def.h:1063
static unsigned int mht_1str_pseudo_key(const void *key, int key_size)
Definition: memory_hash.c:128
static unsigned int mht_4str_pseudo_key(const void *key, int key_size)
Definition: memory_hash.c:277
union db_numeric::@51 d
struct hentry_hls * HENTRY_HLS_PTR
Definition: memory_hash.h:137
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
unsigned int mht_2str_pseudo_key(const void *key, int key_size)
Definition: memory_hash.c:175
unsigned int mht_2strhash(const void *key, const unsigned int ht_size)
Definition: memory_hash.c:466
static const float MHT_REHASH_TRESHOLD
Definition: memory_hash.c:67
unsigned short short_val
Definition: dbtype_def.h:1023
DB_TIME * db_get_time(const DB_VALUE *value)
DB_C_POINTER db_get_pointer(const DB_VALUE *value)
double amount
Definition: dbtype_def.h:831
int mht_compare_strings_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:767
float f
Definition: dbtype_def.h:1052
mht_put_opt
Definition: memory_hash.c:71
int mht_adjust_lru_list(MHT_TABLE *ht, HENTRY_PTR hentry)
Definition: memory_hash.c:1457
int(* cmp_func)(const void *key1, const void *key2)
Definition: memory_hash.h:58
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
double d
Definition: dbtype_def.h:1053
unsigned int time
Definition: dbtype_def.h:777
int mht_compare_dbvalues_are_equal(const void *key1, const void *key2)
Definition: memory_hash.c:791
DB_DATETIMETZ datetimetz
Definition: dbtype_def.h:1061
HENTRY_PTR lru_prev
Definition: memory_hash.h:47