#include "util-hash-lookup3.h"
#include "util-validate.h"
-static THashData *THashGetUsed(THashTableContext *ctx);
+static THashData *THashGetUsed(THashTableContext *ctx, uint32_t data_size);
static void THashDataEnqueue (THashDataQueue *q, THashData *h);
void THashDataMoveToSpare(THashTableContext *ctx, THashData *h)
}
#endif
-static THashData *THashDataAlloc(THashTableContext *ctx)
+static THashData *THashDataAlloc(THashTableContext *ctx, uint32_t data_size)
{
- const size_t data_size = THASH_DATA_SIZE(ctx);
+ const size_t thash_data_size = THASH_DATA_SIZE(ctx);
- if (!(THASH_CHECK_MEMCAP(ctx, data_size))) {
+ if (!(THASH_CHECK_MEMCAP(ctx, thash_data_size + data_size))) {
return NULL;
}
- (void) SC_ATOMIC_ADD(ctx->memuse, data_size);
+ size_t total_data_size = thash_data_size + data_size;
- THashData *h = SCCalloc(1, data_size);
+ (void)SC_ATOMIC_ADD(ctx->memuse, total_data_size);
+
+ THashData *h = SCCalloc(1, thash_data_size);
if (unlikely(h == NULL))
goto error;
return h;
error:
+ (void)SC_ATOMIC_SUB(ctx->memuse, total_data_size);
return NULL;
}
if (h != NULL) {
DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(h->use_cnt) != 0);
+ uint32_t data_size = 0;
if (h->data != NULL) {
+ if (ctx->config.DataSize) {
+ data_size = ctx->config.DataSize(h->data);
+ }
ctx->config.DataFree(h->data);
}
SCMutexDestroy(&h->m);
SCFree(h);
- (void) SC_ATOMIC_SUB(ctx->memuse, THASH_DATA_SIZE(ctx));
+ (void)SC_ATOMIC_SUB(ctx->memuse, THASH_DATA_SIZE(ctx) + (uint64_t)data_size);
}
}
for (i = 0; i < ctx->config.hash_size; i++) {
HRLOCK_INIT(&ctx->array[i]);
}
- (void) SC_ATOMIC_ADD(ctx->memuse, (ctx->config.hash_size * sizeof(THashHashRow)));
+ (void)SC_ATOMIC_ADD(ctx->memuse, (ctx->config.hash_size * sizeof(THashHashRow)));
/* pre allocate prealloc */
for (i = 0; i < ctx->config.prealloc; i++) {
return -1;
}
- THashData *h = THashDataAlloc(ctx);
+ THashData *h = THashDataAlloc(ctx, 0 /* as we don't have string data here */);
if (h == NULL) {
SCLogError("preallocating data failed: %s", strerror(errno));
return -1;
}
(void) SC_ATOMIC_SUB(ctx->memuse, ctx->config.hash_size * sizeof(THashHashRow));
THashDataQueueDestroy(&ctx->spare_q);
+ DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(ctx->memuse) != 0);
SCFree(ctx);
}
h->next = NULL;
h->prev = NULL;
SCLogDebug("timeout: removing data %p", h);
+ if (ctx->config.DataSize) {
+ uint32_t data_size = ctx->config.DataSize(h->data);
+ if (data_size > 0)
+ (void)SC_ATOMIC_SUB(ctx->memuse, (uint64_t)data_size);
+ }
ctx->config.DataFree(h->data);
THashDataUnlock(h);
THashDataMoveToSpare(ctx, h);
hb->tail = h->prev;
h->next = NULL;
h->prev = NULL;
+ if (ctx->config.DataSize) {
+ uint32_t data_size = ctx->config.DataSize(h->data);
+ if (data_size > 0)
+ (void)SC_ATOMIC_SUB(ctx->memuse, (uint64_t)data_size);
+ }
THashDataMoveToSpare(ctx, h);
h = n;
}
static THashData *THashDataGetNew(THashTableContext *ctx, void *data)
{
THashData *h = NULL;
+ uint32_t data_size = 0;
+ if (ctx->config.DataSize) {
+ data_size = ctx->config.DataSize(data);
+ }
/* get data from the spare queue */
h = THashDataDequeue(&ctx->spare_q);
if (h == NULL) {
/* If we reached the max memcap, we get used data */
- if (!(THASH_CHECK_MEMCAP(ctx, THASH_DATA_SIZE(ctx)))) {
- h = THashGetUsed(ctx);
+ if (!(THASH_CHECK_MEMCAP(ctx, THASH_DATA_SIZE(ctx) + data_size))) {
+ h = THashGetUsed(ctx, data_size);
if (h == NULL) {
return NULL;
}
/* freed data, but it's unlocked */
} else {
/* now see if we can alloc a new data */
- h = THashDataAlloc(ctx);
+ h = THashDataAlloc(ctx, data_size);
if (h == NULL) {
return NULL;
}
}
} else {
/* data has been recycled before it went into the spare queue */
-
/* data is initialized (recycled) but *unlocked* */
+ /* the recycled data was THashData and again does not include
+ * the size of current data to be added */
+ if (data_size > 0) {
+ /* Since it is prealloc'd data, it already has THashData in its memuse */
+ (void)SC_ATOMIC_ADD(ctx->memuse, data_size);
+ if (!(THASH_CHECK_MEMCAP(ctx, data_size))) {
+ if (!SC_ATOMIC_GET(ctx->memcap_reached)) {
+ SC_ATOMIC_SET(ctx->memcap_reached, true);
+ }
+ SCLogError("Adding data will exceed memcap: %" PRIu64 ", current memuse: %" PRIu64,
+ (ctx)->config.memcap, SC_ATOMIC_GET(ctx->memuse));
+ }
+ }
}
// setup the data
BUG_ON(ctx->config.DataSet(h->data, data) != 0);
-
(void) SC_ATOMIC_ADD(ctx->counter, 1);
SCMutexLock(&h->m);
return h;
*
* \retval h data or NULL
*/
-static THashData *THashGetUsed(THashTableContext *ctx)
+static THashData *THashGetUsed(THashTableContext *ctx, uint32_t data_size)
{
uint32_t idx = SC_ATOMIC_GET(ctx->prune_idx) % ctx->config.hash_size;
uint32_t cnt = ctx->config.hash_size;
HRLOCK_UNLOCK(hb);
if (h->data != NULL) {
+ if (ctx->config.DataSize) {
+ uint32_t h_data_size = ctx->config.DataSize(h->data);
+ if (h_data_size > 0) {
+ (void)SC_ATOMIC_SUB(ctx->memuse, (uint64_t)h_data_size);
+ }
+ }
ctx->config.DataFree(h->data);
}
SCMutexUnlock(&h->m);
(void) SC_ATOMIC_ADD(ctx->prune_idx, (ctx->config.hash_size - cnt));
+ if (data_size > 0)
+ (void)SC_ATOMIC_ADD(ctx->memuse, data_size);
return h;
}