Add a callback and helper function to handle data expiration.
Update datasets to explicitly not use expiration.
}
}
-static inline bool ContainerValueRangeTimeout(HttpRangeContainerFile *cu, const SCTime_t ts)
+static inline bool ContainerValueRangeTimeout(void *data, const SCTime_t ts)
{
+ HttpRangeContainerFile *cu = data;
// we only timeout if we have no flow referencing us
if (SCTIME_CMP_GT(ts, cu->expire) || cu->error) {
if (SC_ATOMIC_GET(cu->hdata->use_cnt) == 0) {
}
}
- ContainerUrlRangeList.ht =
- THashInit("app-layer.protocols.http.byterange", sizeof(HttpRangeContainerFile),
- ContainerUrlRangeSet, ContainerUrlRangeFree, ContainerUrlRangeHash,
- ContainerUrlRangeCompare, false, memcap, CONTAINER_URLRANGE_HASH_SIZE);
+ ContainerUrlRangeList.ht = THashInit("app-layer.protocols.http.byterange",
+ sizeof(HttpRangeContainerFile), ContainerUrlRangeSet, ContainerUrlRangeFree,
+ ContainerUrlRangeHash, ContainerUrlRangeCompare, ContainerValueRangeTimeout, false,
+ memcap, CONTAINER_URLRANGE_HASH_SIZE);
ContainerUrlRangeList.timeout = timeout;
SCLogDebug("containers started");
switch (type) {
case DATASET_TYPE_MD5:
set->hash = THashInit(cnf_name, sizeof(Md5Type), Md5StrSet, Md5StrFree, Md5StrHash,
- Md5StrCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
+ Md5StrCompare, NULL, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
hashsize > 0 ? hashsize : default_hashsize);
if (set->hash == NULL)
goto out_err;
break;
case DATASET_TYPE_STRING:
set->hash = THashInit(cnf_name, sizeof(StringType), StringSet, StringFree, StringHash,
- StringCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
+ StringCompare, NULL, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
hashsize > 0 ? hashsize : default_hashsize);
if (set->hash == NULL)
goto out_err;
break;
case DATASET_TYPE_SHA256:
set->hash = THashInit(cnf_name, sizeof(Sha256Type), Sha256StrSet, Sha256StrFree,
- Sha256StrHash, Sha256StrCompare, load != NULL ? 1 : 0,
+ Sha256StrHash, Sha256StrCompare, NULL, load != NULL ? 1 : 0,
memcap > 0 ? memcap : default_memcap,
hashsize > 0 ? hashsize : default_hashsize);
if (set->hash == NULL)
break;
case DATASET_TYPE_IPV4:
set->hash = THashInit(cnf_name, sizeof(IPv4Type), IPv4Set, IPv4Free, IPv4Hash,
- IPv4Compare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
+ IPv4Compare, NULL, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
hashsize > 0 ? hashsize : default_hashsize);
if (set->hash == NULL)
goto out_err;
break;
case DATASET_TYPE_IPV6:
set->hash = THashInit(cnf_name, sizeof(IPv6Type), IPv6Set, IPv6Free, IPv6Hash,
- IPv6Compare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
+ IPv6Compare, NULL, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
hashsize > 0 ? hashsize : default_hashsize);
if (set->hash == NULL)
goto out_err;
-/* Copyright (C) 2007-2016 Open Information Security Foundation
+/* Copyright (C) 2007-2024 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
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 *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
+ bool (*DataCompare)(void *, void *), bool (*DataExpired)(void *, SCTime_t),
+ bool reset_memcap, uint64_t memcap, uint32_t hashsize)
{
THashTableContext *ctx = SCCalloc(1, sizeof(*ctx));
BUG_ON(!ctx);
ctx->config.DataFree = DataFree;
ctx->config.DataHash = DataHash;
ctx->config.DataCompare = DataCompare;
+ ctx->config.DataExpired = DataExpired;
/* set defaults */
ctx->config.hash_rand = (uint32_t)RandomGet();
return 0;
}
+/** \brief expire data from the hash
+ * Walk the hash table and remove data that is exprired according to the
+ * DataExpired callback.
+ * \retval cnt number of items successfully expired/removed
+ */
+uint32_t THashExpire(THashTableContext *ctx, const SCTime_t ts)
+{
+ if (ctx->config.DataExpired == NULL)
+ return 0;
+
+ SCLogDebug("timeout: starting");
+ uint32_t cnt = 0;
+
+ for (uint32_t i = 0; i < ctx->config.hash_size; i++) {
+ THashHashRow *hb = &ctx->array[i];
+ if (HRLOCK_TRYLOCK(hb) != 0)
+ continue;
+ /* hash bucket is now locked */
+ THashData *h = hb->head;
+ while (h) {
+ THashData *next = h->next;
+ THashDataLock(h);
+ DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(h->use_cnt) > (uint32_t)INT_MAX);
+ /* only consider items with no references to it */
+ if (SC_ATOMIC_GET(h->use_cnt) == 0 && ctx->config.DataExpired(h->data, ts)) {
+ /* remove from the hash */
+ if (h->prev != NULL)
+ h->prev->next = h->next;
+ if (h->next != NULL)
+ h->next->prev = h->prev;
+ if (hb->head == h)
+ hb->head = h->next;
+ if (hb->tail == h)
+ hb->tail = h->prev;
+ h->next = NULL;
+ h->prev = NULL;
+ SCLogDebug("timeout: removing data %p", h);
+ ctx->config.DataFree(h->data);
+ THashDataUnlock(h);
+ THashDataMoveToSpare(ctx, h);
+ cnt++;
+ } else {
+ THashDataUnlock(h);
+ }
+ h = next;
+ }
+ HRLOCK_UNLOCK(hb);
+ }
+
+ SCLogDebug("timeout: ending: %u entries expired", cnt);
+ return cnt;
+}
+
/** \brief Cleanup the thash engine
*
* Cleanup the thash engine from tag and threshold.
void (*DataFree)(void *);
uint32_t (*DataHash)(void *);
bool (*DataCompare)(void *, void *);
+ bool (*DataExpired)(void *, SCTime_t ts);
} THashConfig;
#define THASH_DATA_SIZE(ctx) (sizeof(THashData) + (ctx)->config.data_size)
THashTableContext *THashInit(const char *cnf_prefix, size_t data_size,
int (*DataSet)(void *dst, void *src), void (*DataFree)(void *),
- uint32_t (*DataHash)(void *), bool (*DataCompare)(void *, void *), bool reset_memcap,
- uint64_t memcap, uint32_t hashsize);
+ uint32_t (*DataHash)(void *), bool (*DataCompare)(void *, void *),
+ bool (*DataExpired)(void *, SCTime_t), bool reset_memcap, uint64_t memcap,
+ uint32_t hashsize);
void THashShutdown(THashTableContext *ctx);
int THashRemoveFromHash (THashTableContext *ctx, void *data);
void THashConsolidateMemcap(THashTableContext *ctx);
void THashDataMoveToSpare(THashTableContext *ctx, THashData *h);
+uint32_t THashExpire(THashTableContext *ctx, const SCTime_t ts);
#endif /* SURICATA_THASH_H */