suricata
util-thash.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "conf.h"
27 
28 #include "util-debug.h"
29 #include "util-thash.h"
30 
31 #include "util-random.h"
32 #include "util-misc.h"
33 #include "util-byte.h"
34 
35 #include "util-hash-lookup3.h"
36 
37 static THashData *THashGetUsed(THashTableContext *ctx);
38 static void THashDataEnqueue (THashDataQueue *q, THashData *h);
39 
40 static void THashDataMoveToSpare(THashTableContext *ctx, THashData *h)
41 {
42  THashDataEnqueue(&ctx->spare_q, h);
43  (void) SC_ATOMIC_SUB(ctx->counter, 1);
44 }
45 
46 static THashDataQueue *THashDataQueueInit (THashDataQueue *q)
47 {
48  if (q != NULL) {
49  memset(q, 0, sizeof(THashDataQueue));
50  HQLOCK_INIT(q);
51  }
52  return q;
53 }
54 
56 {
58  if (q == NULL) {
59  SCLogError(SC_ERR_FATAL, "Fatal error encountered in THashDataQueueNew. Exiting...");
60  exit(EXIT_SUCCESS);
61  }
62  q = THashDataQueueInit(q);
63  return q;
64 }
65 
66 /**
67  * \brief Destroy a queue
68  *
69  * \param q the queue to destroy
70  */
71 static void THashDataQueueDestroy (THashDataQueue *q)
72 {
73  HQLOCK_DESTROY(q);
74 }
75 
76 /**
77  * \brief add to queue
78  *
79  * \param q queue
80  * \param h data
81  */
82 static void THashDataEnqueue (THashDataQueue *q, THashData *h)
83 {
84 #ifdef DEBUG
85  BUG_ON(q == NULL || h == NULL);
86 #endif
87 
88  HQLOCK_LOCK(q);
89 
90  /* more data in queue */
91  if (q->top != NULL) {
92  h->next = q->top;
93  q->top->prev = h;
94  q->top = h;
95  /* only data */
96  } else {
97  q->top = h;
98  q->bot = h;
99  }
100  q->len++;
101 #ifdef DBG_PERF
102  if (q->len > q->dbg_maxlen)
103  q->dbg_maxlen = q->len;
104 #endif /* DBG_PERF */
105  HQLOCK_UNLOCK(q);
106 }
107 
108 /**
109  * \brief remove data from the queue
110  *
111  * \param q queue
112  *
113  * \retval h data or NULL if empty list.
114  */
115 static THashData *THashDataDequeue (THashDataQueue *q)
116 {
117  HQLOCK_LOCK(q);
118 
119  THashData *h = q->bot;
120  if (h == NULL) {
121  HQLOCK_UNLOCK(q);
122  return NULL;
123  }
124 
125  /* more packets in queue */
126  if (q->bot->prev != NULL) {
127  q->bot = q->bot->prev;
128  q->bot->next = NULL;
129  /* just the one we remove, so now empty */
130  } else {
131  q->top = NULL;
132  q->bot = NULL;
133  }
134 
135 #ifdef DEBUG
136  BUG_ON(q->len == 0);
137 #endif
138  if (q->len > 0)
139  q->len--;
140 
141  h->next = NULL;
142  h->prev = NULL;
143 
144  HQLOCK_UNLOCK(q);
145  return h;
146 }
147 
148 #if 0
149 static uint32_t THashDataQueueLen(THashDataQueue *q)
150 {
151  uint32_t len;
152  HQLOCK_LOCK(q);
153  len = q->len;
154  HQLOCK_UNLOCK(q);
155  return len;
156 }
157 #endif
158 
159 static THashData *THashDataAlloc(THashTableContext *ctx)
160 {
161  const size_t data_size = THASH_DATA_SIZE(ctx);
162 
163  if (!(THASH_CHECK_MEMCAP(ctx, data_size))) {
164  return NULL;
165  }
166 
167  (void) SC_ATOMIC_ADD(ctx->memuse, data_size);
168 
169  THashData *h = SCCalloc(1, data_size);
170  if (unlikely(h == NULL))
171  goto error;
172 
173  /* points to data right after THashData block */
174  h->data = (uint8_t *)h + sizeof(THashData);
175 
176 // memset(h, 0x00, data_size);
177 
178  SCMutexInit(&h->m, NULL);
179  SC_ATOMIC_INIT(h->use_cnt);
180  return h;
181 
182 error:
183  return NULL;
184 }
185 
186 static void THashDataFree(THashTableContext *ctx, THashData *h)
187 {
188  if (h != NULL) {
189  if (h->data != NULL) {
190  ctx->config.DataFree(h->data);
191  }
192 
193  SC_ATOMIC_DESTROY(h->use_cnt);
194  SCMutexDestroy(&h->m);
195  SCFree(h);
196  (void) SC_ATOMIC_SUB(ctx->memuse, THASH_DATA_SIZE(ctx));
197  }
198 }
199 
200 #define THASH_DEFAULT_HASHSIZE 4096
201 #define THASH_DEFAULT_MEMCAP 16777216
202 #define THASH_DEFAULT_PREALLOC 1000
203 
204 #define GET_VAR(prefix,name) \
205  snprintf(varname, sizeof(varname), "%s.%s", (prefix), (name))
206 
207 /** \brief initialize the configuration
208  * \warning Not thread safe */
209 static void THashInitConfig(THashTableContext *ctx, const char *cnf_prefix)
210 {
211  char varname[256];
212 
213  SCLogDebug("initializing thash engine...");
214 
215  /* Check if we have memcap and hash_size defined at config */
216  const char *conf_val;
217  uint32_t configval = 0;
218 
219  /** set config values for memcap, prealloc and hash_size */
220  GET_VAR(cnf_prefix, "memcap");
221  if ((ConfGet(varname, &conf_val)) == 1)
222  {
223  if (ParseSizeStringU64(conf_val, &ctx->config.memcap) < 0) {
224  SCLogError(SC_ERR_SIZE_PARSE, "Error parsing %s "
225  "from conf file - %s. Killing engine",
226  varname, conf_val);
227  exit(EXIT_FAILURE);
228  }
229  }
230  GET_VAR(cnf_prefix, "hash-size");
231  if ((ConfGet(varname, &conf_val)) == 1)
232  {
233  if (ByteExtractStringUint32(&configval, 10, strlen(conf_val),
234  conf_val) > 0) {
235  ctx->config.hash_size = configval;
236  }
237  }
238 
239  GET_VAR(cnf_prefix, "prealloc");
240  if ((ConfGet(varname, &conf_val)) == 1)
241  {
242  if (ByteExtractStringUint32(&configval, 10, strlen(conf_val),
243  conf_val) > 0) {
244  ctx->config.prealloc = configval;
245  } else {
246  WarnInvalidConfEntry(varname, "%"PRIu32, ctx->config.prealloc);
247  }
248  }
249 
250  /* alloc hash memory */
251  uint64_t hash_size = ctx->config.hash_size * sizeof(THashHashRow);
252  if (!(THASH_CHECK_MEMCAP(ctx, hash_size))) {
253  SCLogError(SC_ERR_THASH_INIT, "allocating hash failed: "
254  "max hash memcap is smaller than projected hash size. "
255  "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate "
256  "total hash size by multiplying \"hash-size\" with %"PRIuMAX", "
257  "which is the hash bucket size.", ctx->config.memcap, hash_size,
258  (uintmax_t)sizeof(THashHashRow));
259  exit(EXIT_FAILURE);
260  }
261  ctx->array = SCMallocAligned(ctx->config.hash_size * sizeof(THashHashRow), CLS);
262  if (unlikely(ctx->array == NULL)) {
263  SCLogError(SC_ERR_FATAL, "Fatal error encountered in THashInitConfig. Exiting...");
264  exit(EXIT_FAILURE);
265  }
266  memset(ctx->array, 0, ctx->config.hash_size * sizeof(THashHashRow));
267 
268  uint32_t i = 0;
269  for (i = 0; i < ctx->config.hash_size; i++) {
270  HRLOCK_INIT(&ctx->array[i]);
271  }
272  (void) SC_ATOMIC_ADD(ctx->memuse, (ctx->config.hash_size * sizeof(THashHashRow)));
273 
274  /* pre allocate prealloc */
275  for (i = 0; i < ctx->config.prealloc; i++) {
276  if (!(THASH_CHECK_MEMCAP(ctx, THASH_DATA_SIZE(ctx)))) {
277  SCLogError(SC_ERR_THASH_INIT, "preallocating data failed: "
278  "max thash memcap reached. Memcap %"PRIu64", "
279  "Memuse %"PRIu64".", ctx->config.memcap,
280  ((uint64_t)SC_ATOMIC_GET(ctx->memuse) + THASH_DATA_SIZE(ctx)));
281  exit(EXIT_FAILURE);
282  }
283 
284  THashData *h = THashDataAlloc(ctx);
285  if (h == NULL) {
286  SCLogError(SC_ERR_THASH_INIT, "preallocating data failed: %s", strerror(errno));
287  exit(EXIT_FAILURE);
288  }
289  THashDataEnqueue(&ctx->spare_q,h);
290  }
291 
292  return;
293 }
294 
295 THashTableContext* THashInit(const char *cnf_prefix, size_t data_size,
296  int (*DataSet)(void *, void *),
297  void (*DataFree)(void *),
298  uint32_t (*DataHash)(void *),
299  _Bool (*DataCompare)(void *, void *))
300 {
301  THashTableContext *ctx = SCCalloc(1, sizeof(*ctx));
302  BUG_ON(!ctx);
303 
304  ctx->config.data_size = data_size;
305  ctx->config.DataSet = DataSet;
306  ctx->config.DataFree = DataFree;
307  ctx->config.DataHash = DataHash;
308  ctx->config.DataCompare = DataCompare;
309 
310  /* set defaults */
311  ctx->config.hash_rand = (uint32_t)RandomGet();
315 
316  SC_ATOMIC_INIT(ctx->counter);
317  SC_ATOMIC_INIT(ctx->memuse);
318  SC_ATOMIC_INIT(ctx->prune_idx);
319  THashDataQueueInit(&ctx->spare_q);
320 
321  THashInitConfig(ctx, cnf_prefix);
322  return ctx;
323 }
324 
325 /** \brief shutdown the flow engine
326  * \warning Not thread safe */
328 {
329  THashData *h;
330  uint32_t u;
331 
332  /* free spare queue */
333  while ((h = THashDataDequeue(&ctx->spare_q))) {
334  BUG_ON(SC_ATOMIC_GET(h->use_cnt) > 0);
335  THashDataFree(ctx, h);
336  }
337 
338  /* clear and free the hash */
339  if (ctx->array != NULL) {
340  for (u = 0; u < ctx->config.hash_size; u++) {
341  h = ctx->array[u].head;
342  while (h) {
343  THashData *n = h->next;
344  THashDataFree(ctx, h);
345  h = n;
346  }
347 
348  HRLOCK_DESTROY(&ctx->array[u]);
349  }
350  SCFreeAligned(ctx->array);
351  ctx->array = NULL;
352  }
353  (void) SC_ATOMIC_SUB(ctx->memuse, ctx->config.hash_size * sizeof(THashHashRow));
354  THashDataQueueDestroy(&ctx->spare_q);
355 
356  SC_ATOMIC_DESTROY(ctx->prune_idx);
357  SC_ATOMIC_DESTROY(ctx->memuse);
358  SC_ATOMIC_DESTROY(ctx->counter);
359 
360  SCFree(ctx);
361  return;
362 }
363 
364 /** \brief Walk the hash
365  *
366  */
367 int THashWalk(THashTableContext *ctx, THashFormatFunc FormatterFunc, THashOutputFunc OutputterFunc, void *output_ctx)
368 {
369  uint32_t u;
370 
371  if (ctx->array == NULL)
372  return -1;
373 
374  bool err = false;
375  for (u = 0; u < ctx->config.hash_size; u++) {
376  THashHashRow *hb = &ctx->array[u];
377  HRLOCK_LOCK(hb);
378  THashData *h = hb->head;
379  while (h) {
380  char output_string[1024] = "";
381  int size = FormatterFunc(h->data, output_string, sizeof(output_string));
382  if (size > 0) {
383  if (OutputterFunc(output_ctx, (const uint8_t *)output_string, size) < 0) {
384  err = true;
385  break;
386  }
387  }
388  h = h->next;
389  }
390  HRLOCK_UNLOCK(hb);
391  if (err == true)
392  return -1;
393  }
394  return 0;
395 }
396 
397 /** \brief Cleanup the thash engine
398  *
399  * Cleanup the thash engine from tag and threshold.
400  *
401  */
403 {
404  uint32_t u;
405 
406  if (ctx->array == NULL)
407  return;
408 
409  for (u = 0; u < ctx->config.hash_size; u++) {
410  THashHashRow *hb = &ctx->array[u];
411  HRLOCK_LOCK(hb);
412  THashData *h = hb->head;
413  while (h) {
414  if ((SC_ATOMIC_GET(h->use_cnt) > 0)) {
415  h = h->next;
416  } else {
417  THashData *n = h->next;
418  /* remove from the hash */
419  if (h->prev != NULL)
420  h->prev->next = h->next;
421  if (h->next != NULL)
422  h->next->prev = h->prev;
423  if (hb->head == h)
424  hb->head = h->next;
425  if (hb->tail == h)
426  hb->tail = h->prev;
427  h->next = NULL;
428  h->prev = NULL;
429  THashDataMoveToSpare(ctx, h);
430  h = n;
431  }
432  }
433  HRLOCK_UNLOCK(hb);
434  }
435  return;
436 }
437 
438 /* calculate the hash key for this packet
439  *
440  * we're using:
441  * hash_rand -- set at init time
442  * source address
443  */
444 static uint32_t THashGetKey(const THashConfig *cnf, void *data)
445 {
446  uint32_t key;
447 
448  key = cnf->DataHash(data);
449  key %= cnf->hash_size;
450 
451  return key;
452 }
453 
454 static inline int THashCompare(const THashConfig *cnf, void *a, void *b)
455 {
456  if (cnf->DataCompare(a, b) == TRUE)
457  return 1;
458  return 0;
459 }
460 
461 /**
462  * \brief Get new data
463  *
464  * Get new data. We're checking memcap first and will try to make room
465  * if the memcap is reached.
466  *
467  * \retval h *LOCKED* data on succes, NULL on error.
468  */
469 static THashData *THashDataGetNew(THashTableContext *ctx, void *data)
470 {
471  THashData *h = NULL;
472 
473  /* get data from the spare queue */
474  h = THashDataDequeue(&ctx->spare_q);
475  if (h == NULL) {
476  /* If we reached the max memcap, we get used data */
477  if (!(THASH_CHECK_MEMCAP(ctx, THASH_DATA_SIZE(ctx)))) {
478  h = THashGetUsed(ctx);
479  if (h == NULL) {
480  return NULL;
481  }
482 
483  /* freed data, but it's unlocked */
484  } else {
485  /* now see if we can alloc a new data */
486  h = THashDataAlloc(ctx);
487  if (h == NULL) {
488  return NULL;
489  }
490 
491  /* data is initialized but *unlocked* */
492  }
493  } else {
494  /* data has been recycled before it went into the spare queue */
495 
496  /* data is initialized (recylced) but *unlocked* */
497  }
498 
499  // setup the data
500  BUG_ON(ctx->config.DataSet(h->data, data) != 0);
501 
502  (void) SC_ATOMIC_ADD(ctx->counter, 1);
503  SCMutexLock(&h->m);
504  return h;
505 }
506 
507 /*
508  * returns a *LOCKED* data or NULL
509  */
510 
511 struct THashDataGetResult
513 {
514  struct THashDataGetResult res = { .data = NULL, .is_new = false, };
515  THashData *h = NULL;
516 
517  /* get the key to our bucket */
518  uint32_t key = THashGetKey(&ctx->config, data);
519  /* get our hash bucket and lock it */
520  THashHashRow *hb = &ctx->array[key];
521  HRLOCK_LOCK(hb);
522 
523  /* see if the bucket already has data */
524  if (hb->head == NULL) {
525  h = THashDataGetNew(ctx, data);
526  if (h == NULL) {
527  HRLOCK_UNLOCK(hb);
528  return res;
529  }
530 
531  /* data is locked */
532  hb->head = h;
533  hb->tail = h;
534 
535  /* initialize and return */
536  (void) THashIncrUsecnt(h);
537 
538  HRLOCK_UNLOCK(hb);
539  res.data = h;
540  res.is_new = true;
541  return res;
542  }
543 
544  /* ok, we have data in the bucket. Let's find out if it is our data */
545  h = hb->head;
546 
547  /* see if this is the data we are looking for */
548  if (THashCompare(&ctx->config, h->data, data) == 0) {
549  THashData *ph = NULL; /* previous data */
550 
551  while (h) {
552  ph = h;
553  h = h->next;
554 
555  if (h == NULL) {
556  h = ph->next = THashDataGetNew(ctx, data);
557  if (h == NULL) {
558  HRLOCK_UNLOCK(hb);
559  return res;
560  }
561  hb->tail = h;
562 
563  /* data is locked */
564 
565  h->prev = ph;
566 
567  /* initialize and return */
568  (void) THashIncrUsecnt(h);
569 
570  HRLOCK_UNLOCK(hb);
571  res.data = h;
572  res.is_new = true;
573  return res;
574  }
575 
576  if (THashCompare(&ctx->config, h->data, data) != 0) {
577  /* we found our data, lets put it on top of the
578  * hash list -- this rewards active data */
579  if (h->next) {
580  h->next->prev = h->prev;
581  }
582  if (h->prev) {
583  h->prev->next = h->next;
584  }
585  if (h == hb->tail) {
586  hb->tail = h->prev;
587  }
588 
589  h->next = hb->head;
590  h->prev = NULL;
591  hb->head->prev = h;
592  hb->head = h;
593 
594  /* found our data, lock & return */
595  SCMutexLock(&h->m);
596  (void) THashIncrUsecnt(h);
597  HRLOCK_UNLOCK(hb);
598  res.data = h;
599  res.is_new = false;
600  return res;
601  }
602  }
603  }
604 
605  /* lock & return */
606  SCMutexLock(&h->m);
607  (void) THashIncrUsecnt(h);
608  HRLOCK_UNLOCK(hb);
609  res.data = h;
610  res.is_new = false;
611  return res;
612 }
613 
614 /** \brief look up data in the hash
615  *
616  * \param data data to look up
617  *
618  * \retval h *LOCKED* data or NULL
619  */
621 {
622  THashData *h = NULL;
623 
624  /* get the key to our bucket */
625  uint32_t key = THashGetKey(&ctx->config, data);
626  /* get our hash bucket and lock it */
627  THashHashRow *hb = &ctx->array[key];
628  HRLOCK_LOCK(hb);
629 
630  if (hb->head == NULL) {
631  HRLOCK_UNLOCK(hb);
632  return h;
633  }
634 
635  /* ok, we have data in the bucket. Let's find out if it is our data */
636  h = hb->head;
637 
638  /* see if this is the data we are looking for */
639  if (THashCompare(&ctx->config, h->data, data) == 0) {
640  while (h) {
641  h = h->next;
642  if (h == NULL) {
643  HRLOCK_UNLOCK(hb);
644  return h;
645  }
646 
647  if (THashCompare(&ctx->config, h->data, data) != 0) {
648  /* we found our data, lets put it on top of the
649  * hash list -- this rewards active data */
650  if (h->next) {
651  h->next->prev = h->prev;
652  }
653  if (h->prev) {
654  h->prev->next = h->next;
655  }
656  if (h == hb->tail) {
657  hb->tail = h->prev;
658  }
659 
660  h->next = hb->head;
661  h->prev = NULL;
662  hb->head->prev = h;
663  hb->head = h;
664 
665  /* found our data, lock & return */
666  SCMutexLock(&h->m);
667  (void) THashIncrUsecnt(h);
668  HRLOCK_UNLOCK(hb);
669  return h;
670  }
671  }
672  }
673 
674  /* lock & return */
675  SCMutexLock(&h->m);
676  (void) THashIncrUsecnt(h);
677  HRLOCK_UNLOCK(hb);
678  return h;
679 }
680 
681 /** \internal
682  * \brief Get data from the hash directly.
683  *
684  * Called in conditions where the spare queue is empty and memcap is
685  * reached.
686  *
687  * Walks the hash until data can be freed. "prune_idx" atomic int makes
688  * sure we don't start at the top each time since that would clear the top
689  * of the hash leading to longer and longer search times under high
690  * pressure (observed).
691  *
692  * \retval h data or NULL
693  */
694 static THashData *THashGetUsed(THashTableContext *ctx)
695 {
696  uint32_t idx = SC_ATOMIC_GET(ctx->prune_idx) % ctx->config.hash_size;
697  uint32_t cnt = ctx->config.hash_size;
698 
699  while (cnt--) {
700  if (++idx >= ctx->config.hash_size)
701  idx = 0;
702 
703  THashHashRow *hb = &ctx->array[idx];
704 
705  if (HRLOCK_TRYLOCK(hb) != 0)
706  continue;
707 
708  THashData *h = hb->tail;
709  if (h == NULL) {
710  HRLOCK_UNLOCK(hb);
711  continue;
712  }
713 
714  if (SCMutexTrylock(&h->m) != 0) {
715  HRLOCK_UNLOCK(hb);
716  continue;
717  }
718 
719  if (SC_ATOMIC_GET(h->use_cnt) > 0) {
720  HRLOCK_UNLOCK(hb);
721  SCMutexUnlock(&h->m);
722  continue;
723  }
724 
725  /* remove from the hash */
726  if (h->prev != NULL)
727  h->prev->next = h->next;
728  if (h->next != NULL)
729  h->next->prev = h->prev;
730  if (hb->head == h)
731  hb->head = h->next;
732  if (hb->tail == h)
733  hb->tail = h->prev;
734 
735  h->next = NULL;
736  h->prev = NULL;
737  HRLOCK_UNLOCK(hb);
738 
739  SCMutexUnlock(&h->m);
740 
741  (void) SC_ATOMIC_ADD(ctx->prune_idx, (ctx->config.hash_size - cnt));
742  return h;
743  }
744 
745  return NULL;
746 }
#define SCMutexTrylock(mut)
#define HRLOCK_UNLOCK(fb)
Definition: host.h:53
#define GET_VAR(prefix, name)
Definition: util-thash.c:204
#define SCLogDebug(...)
Definition: util-debug.h:335
THashDataQueue * THashDataQueueNew(void)
Definition: util-thash.c:55
#define THASH_DATA_SIZE(ctx)
Definition: util-thash.h:141
void THashShutdown(THashTableContext *ctx)
shutdown the flow engine
Definition: util-thash.c:327
uint32_t hash_size
Definition: util-thash.h:131
uint32_t data_size
Definition: util-thash.h:134
#define BUG_ON(x)
int(* DataSet)(void *dst, void *src)
Definition: util-thash.h:135
#define THASH_DEFAULT_HASHSIZE
Definition: util-thash.c:200
#define HRLOCK_TRYLOCK(fb)
Definition: host.h:52
#define unlikely(expr)
Definition: util-optimize.h:35
struct THashDataGetResult THashGetFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:512
struct THashData_ * next
Definition: util-thash.h:95
long int RandomGet(void)
Definition: util-random.c:129
int THashWalk(THashTableContext *ctx, THashFormatFunc FormatterFunc, THashOutputFunc OutputterFunc, void *output_ctx)
Walk the hash.
Definition: util-thash.c:367
#define HRLOCK_INIT(fb)
Definition: host.h:49
#define HRLOCK_DESTROY(fb)
Definition: host.h:50
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
THashHashRow * array
Definition: util-thash.h:145
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:244
#define THashIncrUsecnt(h)
Definition: util-thash.h:167
#define HQLOCK_LOCK(q)
Definition: host-queue.h:67
#define CLS
void THashCleanup(THashTableContext *ctx)
Cleanup the thash engine.
Definition: util-thash.c:402
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:124
uint32_t prealloc
Definition: util-thash.h:132
THashData * data
Definition: util-thash.h:205
#define TRUE
#define SCMutexLock(mut)
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
#define SC_ATOMIC_DESTROY(name)
Destroy the lock used to protect this variable.
Definition: util-atomic.h:97
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
#define HQLOCK_DESTROY(q)
Definition: host-queue.h:66
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:81
#define SCCalloc(nm, a)
Definition: util-mem.h:253
#define SCMutexUnlock(mut)
struct THashData_ * prev
Definition: util-thash.h:96
int(* THashOutputFunc)(void *output_ctx, const uint8_t *data, const uint32_t data_len)
Definition: util-thash.h:125
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define THASH_DEFAULT_MEMCAP
Definition: util-thash.c:201
#define HQLOCK_INIT(q)
Definition: host-queue.h:65
THashData * bot
Definition: util-thash.h:108
void * data
Definition: util-thash.h:93
THashTableContext * THashInit(const char *cnf_prefix, size_t data_size, int(*DataSet)(void *, void *), void(*DataFree)(void *), uint32_t(*DataHash)(void *), _Bool(*DataCompare)(void *, void *))
Definition: util-thash.c:295
#define SCMutexInit(mut, mutattrs)
uint32_t len
Definition: util-thash.h:109
void(* DataFree)(void *)
Definition: util-thash.h:136
#define HQLOCK_UNLOCK(q)
Definition: host-queue.h:69
SCMutex m
Definition: util-thash.h:88
_Bool(* DataCompare)(void *, void *)
Definition: util-thash.h:138
uint64_t memcap
Definition: util-thash.h:129
THashConfig config
Definition: util-thash.h:153
uint32_t hash_rand
Definition: util-thash.h:130
#define SCMalloc(a)
Definition: util-mem.h:222
uint32_t(* DataHash)(void *)
Definition: util-thash.h:137
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
#define SCMallocAligned(a, b)
wrapper for allocing aligned mem
Definition: util-mem.h:363
#define HRLOCK_LOCK(fb)
Definition: host.h:51
#define WarnInvalidConfEntry(param_name, format, value)
Generic API that can be used by all to log an invalid conf entry.
Definition: util-misc.h:37
#define THASH_CHECK_MEMCAP(ctx, size)
check if a memory alloc would fit in the memcap
Definition: util-thash.h:164
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192
THashData * top
Definition: util-thash.h:107
uint8_t len
THashData * THashLookupFromHash(THashTableContext *ctx, void *data)
look up data in the hash
Definition: util-thash.c:620
#define THASH_DEFAULT_PREALLOC
Definition: util-thash.c:202
THashDataQueue spare_q
Definition: util-thash.h:151
#define SCFreeAligned(a)
Free aligned memory.
Definition: util-mem.h:388
int(* THashFormatFunc)(const void *in_data, char *output, size_t output_size)
Definition: util-thash.h:126
#define SCMutexDestroy