diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2016-01-20 01:10:01 +0000 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2016-01-20 01:10:11 +0000 |
commit | 19d701ddf07d855128ded0cf2b573ce468e3bdd6 (patch) | |
tree | 0edcd3461ca903c76e431bb7c6348c42a0f12488 /framework/src/suricata/src/counters.c | |
parent | fac6fbefbfad1cf837ddd88bc0d330559c8eb6f9 (diff) |
Removing Suricata and Audit from source repo, and updated build.sh to avoid building suricata. Will re-address this in C release via tar balls.
Change-Id: I3710076f8b7f3313cb3cb5260c4eb0a6834d4f6e
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/suricata/src/counters.c')
-rw-r--r-- | framework/src/suricata/src/counters.c | 1500 |
1 files changed, 0 insertions, 1500 deletions
diff --git a/framework/src/suricata/src/counters.c b/framework/src/suricata/src/counters.c deleted file mode 100644 index 887fd7ca..00000000 --- a/framework/src/suricata/src/counters.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* Copyright (C) 2007-2015 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Anoop Saldanha <anoopsaldanha@gmail.com> - * \author Victor Julien <victor@inliniac.net> - * - * Engine stats API - */ - -#include "suricata-common.h" -#include "suricata.h" -#include "counters.h" -#include "threadvars.h" -#include "tm-threads.h" -#include "conf.h" -#include "util-time.h" -#include "util-unittest.h" -#include "util-debug.h" -#include "util-privs.h" -#include "util-signal.h" -#include "unix-manager.h" -#include "output.h" - -/* Time interval for syncing the local counters with the global ones */ -#define STATS_WUT_TTS 3 - -/* Time interval at which the mgmt thread o/p the stats */ -#define STATS_MGMTT_TTS 8 - -/** - * \brief Different kinds of qualifier that can be used to modify the behaviour - * of the counter to be registered - */ -enum { - STATS_TYPE_NORMAL = 1, - STATS_TYPE_AVERAGE = 2, - STATS_TYPE_MAXIMUM = 3, - STATS_TYPE_FUNC = 4, - - STATS_TYPE_MAX = 5, -}; - -/** - * \brief per thread store of counters - */ -typedef struct StatsThreadStore_ { - /** thread name used in output */ - const char *name; - - StatsPublicThreadContext *ctx; - - StatsPublicThreadContext **head; - uint32_t size; - - struct StatsThreadStore_ *next; -} StatsThreadStore; - -/** - * \brief Holds the output interface context for the counter api - */ -typedef struct StatsGlobalContext_ { - /** list of thread stores: one per thread plus one global */ - StatsThreadStore *sts; - SCMutex sts_lock; - int sts_cnt; - - HashTable *counters_id_hash; - - StatsPublicThreadContext global_counter_ctx; -} StatsGlobalContext; - -static void *stats_thread_data = NULL; -static StatsGlobalContext *stats_ctx = NULL; -static time_t stats_start_time; -/** refresh interval in seconds */ -static uint32_t stats_tts = STATS_MGMTT_TTS; -/** is the stats counter enabled? */ -static char stats_enabled = TRUE; - -static int StatsOutput(ThreadVars *tv); -static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *); -void StatsReleaseCounters(StatsCounter *head); - -/** stats table is filled each interval and passed to the - * loggers. Initialized at first use. */ -static StatsTable stats_table = { NULL, NULL, 0, 0, 0, {0 , 0}}; - -static uint16_t counters_global_id = 0; - -static void StatsPublicThreadContextInit(StatsPublicThreadContext *t) -{ - SCMutexInit(&t->m, NULL); -} - -static void StatsPublicThreadContextCleanup(StatsPublicThreadContext *t) -{ - SCMutexLock(&t->m); - StatsReleaseCounters(t->head); - t->head = NULL; - t->perf_flag = 0; - t->curr_id = 0; - SCMutexUnlock(&t->m); - SCMutexDestroy(&t->m); -} - -/** - * \brief Adds a value of type uint64_t to the local counter. - * - * \param id ID of the counter as set by the API - * \param pca Counter array that holds the local counter for this TM - * \param x Value to add to this local counter - */ -void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x) -{ - StatsPrivateThreadContext *pca = &tv->perf_private_ctx; -#ifdef UNITTESTS - if (pca->initialized == 0) - return; -#endif -#ifdef DEBUG - BUG_ON ((id < 1) || (id > pca->size)); -#endif - pca->head[id].value += x; - pca->head[id].updates++; - return; -} - -/** - * \brief Increments the local counter - * - * \param id Index of the counter in the counter array - * \param pca Counter array that holds the local counters for this TM - */ -void StatsIncr(ThreadVars *tv, uint16_t id) -{ - StatsPrivateThreadContext *pca = &tv->perf_private_ctx; -#ifdef UNITTESTS - if (pca->initialized == 0) - return; -#endif -#ifdef DEBUG - BUG_ON ((id < 1) || (id > pca->size)); -#endif - pca->head[id].value++; - pca->head[id].updates++; - return; -} - -/** - * \brief Sets a value of type double to the local counter - * - * \param id Index of the local counter in the counter array - * \param pca Pointer to the StatsPrivateThreadContext - * \param x The value to set for the counter - */ -void StatsSetUI64(ThreadVars *tv, uint16_t id, uint64_t x) -{ - StatsPrivateThreadContext *pca = &tv->perf_private_ctx; -#ifdef UNITTESTS - if (pca->initialized == 0) - return; -#endif -#ifdef DEBUG - BUG_ON ((id < 1) || (id > pca->size)); -#endif - - if ((pca->head[id].pc->type == STATS_TYPE_MAXIMUM) && - (x > pca->head[id].value)) { - pca->head[id].value = x; - } else if (pca->head[id].pc->type == STATS_TYPE_NORMAL) { - pca->head[id].value = x; - } - - pca->head[id].updates++; - - return; -} - -static ConfNode *GetConfig(void) { - ConfNode *stats = ConfGetNode("stats"); - if (stats != NULL) - return stats; - - ConfNode *root = ConfGetNode("outputs"); - ConfNode *node = NULL; - if (root != NULL) { - TAILQ_FOREACH(node, &root->head, next) { - if (strcmp(node->val, "stats") == 0) { - return node->head.tqh_first; - } - } - } - return NULL; -} - -/** - * \brief Initializes stats context - */ -static void StatsInitCtx(void) -{ - SCEnter(); - ConfNode *stats = GetConfig(); - if (stats != NULL) { - const char *enabled = ConfNodeLookupChildValue(stats, "enabled"); - if (enabled != NULL && ConfValIsFalse(enabled)) { - stats_enabled = FALSE; - SCLogDebug("Stats module has been disabled"); - SCReturn; - } - const char *interval = ConfNodeLookupChildValue(stats, "interval"); - if (interval != NULL) - stats_tts = (uint32_t) atoi(interval); - } - - if (!OutputStatsLoggersRegistered()) { - SCLogWarning(SC_WARN_NO_STATS_LOGGERS, "stats are enabled but no loggers are active"); - stats_enabled = FALSE; - SCReturn; - } - - /* Store the engine start time */ - time(&stats_start_time); - - /* init the lock used by StatsThreadStore */ - if (SCMutexInit(&stats_ctx->sts_lock, NULL) != 0) { - SCLogError(SC_ERR_INITIALIZATION, "error initializing sts mutex"); - exit(EXIT_FAILURE); - } - - SCReturn; -} - -/** - * \brief Releases the resources alloted to the output context of the - * Stats API - */ -static void StatsReleaseCtx() -{ - if (stats_ctx == NULL) { - SCLogDebug("Counter module has been disabled"); - return; - } - - StatsThreadStore *sts = NULL; - StatsThreadStore *temp = NULL; - sts = stats_ctx->sts; - - while (sts != NULL) { - if (sts->head != NULL) - SCFree(sts->head); - - temp = sts->next; - SCFree(sts); - sts = temp; - } - - if (stats_ctx->counters_id_hash != NULL) { - HashTableFree(stats_ctx->counters_id_hash); - stats_ctx->counters_id_hash = NULL; - } - - StatsPublicThreadContextCleanup(&stats_ctx->global_counter_ctx); - SCFree(stats_ctx); - stats_ctx = NULL; - - /* free stats table */ - if (stats_table.tstats != NULL) { - SCFree(stats_table.tstats); - stats_table.tstats = NULL; - } - - if (stats_table.stats != NULL) { - SCFree(stats_table.stats); - stats_table.stats = NULL; - } - memset(&stats_table, 0, sizeof(stats_table)); - - return; -} - -/** - * \brief management thread. This thread is responsible for writing the stats - * - * \param arg thread var - * - * \retval NULL This is the value that is always returned - */ -static void *StatsMgmtThread(void *arg) -{ - /* block usr2. usr2 to be handled by the main thread only */ - UtilSignalBlock(SIGUSR2); - - ThreadVars *tv_local = (ThreadVars *)arg; - uint8_t run = 1; - struct timespec cond_time; - - /* Set the thread name */ - if (SCSetThreadName(tv_local->name) < 0) { - SCLogWarning(SC_ERR_THREAD_INIT, "Unable to set thread name"); - } - - if (tv_local->thread_setup_flags != 0) - TmThreadSetupOptions(tv_local); - - /* Set the threads capability */ - tv_local->cap_flags = 0; - - SCDropCaps(tv_local); - - if (stats_ctx == NULL) { - SCLogError(SC_ERR_STATS_NOT_INIT, "Stats API not init" - "StatsInitCounterApi() has to be called first"); - TmThreadsSetFlag(tv_local, THV_CLOSED | THV_RUNNING_DONE); - return NULL; - } - - TmModule *tm = &tmm_modules[TMM_STATSLOGGER]; - BUG_ON(tm->ThreadInit == NULL); - int r = tm->ThreadInit(tv_local, NULL, &stats_thread_data); - if (r != 0 || stats_thread_data == NULL) { - SCLogError(SC_ERR_THREAD_INIT, "Stats API " - "ThreadInit failed"); - TmThreadsSetFlag(tv_local, THV_CLOSED | THV_RUNNING_DONE); - return NULL; - } - SCLogDebug("stats_thread_data %p", &stats_thread_data); - - TmThreadsSetFlag(tv_local, THV_INIT_DONE); - while (run) { - if (TmThreadsCheckFlag(tv_local, THV_PAUSE)) { - TmThreadsSetFlag(tv_local, THV_PAUSED); - TmThreadTestThreadUnPaused(tv_local); - TmThreadsUnsetFlag(tv_local, THV_PAUSED); - } - - cond_time.tv_sec = time(NULL) + stats_tts; - cond_time.tv_nsec = 0; - - /* wait for the set time, or until we are woken up by - * the shutdown procedure */ - SCCtrlMutexLock(tv_local->ctrl_mutex); - SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time); - SCCtrlMutexUnlock(tv_local->ctrl_mutex); - - StatsOutput(tv_local); - - if (TmThreadsCheckFlag(tv_local, THV_KILL)) { - run = 0; - } - } - - TmThreadsSetFlag(tv_local, THV_RUNNING_DONE); - TmThreadWaitForFlag(tv_local, THV_DEINIT); - - r = tm->ThreadDeinit(tv_local, stats_thread_data); - if (r != TM_ECODE_OK) { - SCLogError(SC_ERR_THREAD_DEINIT, "Stats Counter API " - "ThreadDeinit failed"); - } - - TmThreadsSetFlag(tv_local, THV_CLOSED); - return NULL; -} - -/** - * \brief Wake up thread. This thread wakes up every TTS(time to sleep) seconds - * and sets the flag for every ThreadVars' StatsPublicThreadContext - * - * \param arg is NULL always - * - * \retval NULL This is the value that is always returned - */ -static void *StatsWakeupThread(void *arg) -{ - /* block usr2. usr2 to be handled by the main thread only */ - UtilSignalBlock(SIGUSR2); - - ThreadVars *tv_local = (ThreadVars *)arg; - uint8_t run = 1; - ThreadVars *tv = NULL; - PacketQueue *q = NULL; - struct timespec cond_time; - - /* Set the thread name */ - if (SCSetThreadName(tv_local->name) < 0) { - SCLogWarning(SC_ERR_THREAD_INIT, "Unable to set thread name"); - } - - if (tv_local->thread_setup_flags != 0) - TmThreadSetupOptions(tv_local); - - /* Set the threads capability */ - tv_local->cap_flags = 0; - - SCDropCaps(tv_local); - - if (stats_ctx == NULL) { - SCLogError(SC_ERR_STATS_NOT_INIT, "Stats API not init" - "StatsInitCounterApi() has to be called first"); - TmThreadsSetFlag(tv_local, THV_CLOSED | THV_RUNNING_DONE); - return NULL; - } - - TmThreadsSetFlag(tv_local, THV_INIT_DONE); - while (run) { - if (TmThreadsCheckFlag(tv_local, THV_PAUSE)) { - TmThreadsSetFlag(tv_local, THV_PAUSED); - TmThreadTestThreadUnPaused(tv_local); - TmThreadsUnsetFlag(tv_local, THV_PAUSED); - } - - cond_time.tv_sec = time(NULL) + STATS_WUT_TTS; - cond_time.tv_nsec = 0; - - /* wait for the set time, or until we are woken up by - * the shutdown procedure */ - SCCtrlMutexLock(tv_local->ctrl_mutex); - SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time); - SCCtrlMutexUnlock(tv_local->ctrl_mutex); - - tv = tv_root[TVT_PPT]; - while (tv != NULL) { - if (tv->perf_public_ctx.head == NULL) { - tv = tv->next; - continue; - } - - /* assuming the assignment of an int to be atomic, and even if it's - * not, it should be okay */ - tv->perf_public_ctx.perf_flag = 1; - - if (tv->inq != NULL) { - q = &trans_q[tv->inq->id]; - SCCondSignal(&q->cond_q); - } - - tv = tv->next; - } - - /* mgt threads for flow manager */ - tv = tv_root[TVT_MGMT]; - while (tv != NULL) { - if (tv->perf_public_ctx.head == NULL) { - tv = tv->next; - continue; - } - - /* assuming the assignment of an int to be atomic, and even if it's - * not, it should be okay */ - tv->perf_public_ctx.perf_flag = 1; - - tv = tv->next; - } - - if (TmThreadsCheckFlag(tv_local, THV_KILL)) { - run = 0; - } - } - - TmThreadsSetFlag(tv_local, THV_RUNNING_DONE); - TmThreadWaitForFlag(tv_local, THV_DEINIT); - - TmThreadsSetFlag(tv_local, THV_CLOSED); - return NULL; -} - -/** - * \brief Releases a counter - * - * \param pc Pointer to the StatsCounter to be freed - */ -static void StatsReleaseCounter(StatsCounter *pc) -{ - if (pc != NULL) { - SCFree(pc); - } - - return; -} - -/** - * \brief Registers a counter. - * - * \param name Name of the counter, to be registered - * \param tm_name Thread module to which this counter belongs - * \param pctx StatsPublicThreadContext for this tm-tv instance - * \param type_q Qualifier describing the type of counter to be registered - * - * \retval the counter id for the newly registered counter, or the already - * present counter on success - * \retval 0 on failure - */ -static uint16_t StatsRegisterQualifiedCounter(char *name, char *tm_name, - StatsPublicThreadContext *pctx, - int type_q, uint64_t (*Func)(void)) -{ - StatsCounter **head = &pctx->head; - StatsCounter *temp = NULL; - StatsCounter *prev = NULL; - StatsCounter *pc = NULL; - - if (name == NULL || pctx == NULL) { - SCLogDebug("Counter name, StatsPublicThreadContext NULL"); - return 0; - } - - temp = prev = *head; - while (temp != NULL) { - prev = temp; - - if (strcmp(name, temp->name) == 0) { - break; - } - - temp = temp->next; - } - - /* We already have a counter registered by this name */ - if (temp != NULL) - return(temp->id); - - /* if we reach this point we don't have a counter registered by this name */ - if ( (pc = SCMalloc(sizeof(StatsCounter))) == NULL) - return 0; - memset(pc, 0, sizeof(StatsCounter)); - - /* assign a unique id to this StatsCounter. The id is local to this - * thread context. Please note that the id start from 1, and not 0 */ - pc->id = ++(pctx->curr_id); - pc->name = name; - pc->type = type_q; - pc->Func = Func; - - /* we now add the counter to the list */ - if (prev == NULL) - *head = pc; - else - prev->next = pc; - - return pc->id; -} - -/** - * \brief Copies the StatsCounter value from the local counter present in the - * StatsPrivateThreadContext to its corresponding global counterpart. Used - * internally by StatsUpdateCounterArray() - * - * \param pcae Pointer to the StatsPrivateThreadContext which holds the local - * versions of the counters - */ -static void StatsCopyCounterValue(StatsLocalCounter *pcae) -{ - StatsCounter *pc = pcae->pc; - - pc->value = pcae->value; - pc->updates = pcae->updates; - return; -} - -/** - * \brief The output interface for the Stats API - */ -static int StatsOutput(ThreadVars *tv) -{ - const StatsThreadStore *sts = NULL; - const StatsCounter *pc = NULL; - void *td = stats_thread_data; - - if (counters_global_id == 0) - return -1; - - if (stats_table.nstats == 0) { - StatsThreadRegister("Global", &stats_ctx->global_counter_ctx); - - uint32_t nstats = counters_global_id; - - stats_table.nstats = nstats; - stats_table.stats = SCCalloc(stats_table.nstats, sizeof(StatsRecord)); - if (stats_table.stats == NULL) { - stats_table.nstats = 0; - SCLogError(SC_ERR_MEM_ALLOC, "could not alloc memory for stats"); - return -1; - } - - stats_table.ntstats = stats_ctx->sts_cnt; - uint32_t array_size = stats_table.nstats * sizeof(StatsRecord); - stats_table.tstats = SCCalloc(stats_table.ntstats, array_size); - if (stats_table.tstats == NULL) { - stats_table.ntstats = 0; - SCLogError(SC_ERR_MEM_ALLOC, "could not alloc memory for stats"); - return -1; - } - - stats_table.start_time = stats_start_time; - } - - const uint16_t max_id = counters_global_id; - if (max_id == 0) - return -1; - - /** temporary local table to merge the per thread counters, - * especially needed for the average counters */ - struct CountersMergeTable { - int type; - uint64_t value; - uint64_t updates; - } merge_table[max_id]; - memset(&merge_table, 0x00, - max_id * sizeof(struct CountersMergeTable)); - - int thread = stats_ctx->sts_cnt - 1; - StatsRecord *table = stats_table.stats; - - /* Loop through the thread counter stores. The global counters - * are in a separate store inside this list. */ - sts = stats_ctx->sts; - SCLogDebug("sts %p", sts); - while (sts != NULL) { - BUG_ON(thread < 0); - - SCLogDebug("Thread %d %s ctx %p", thread, sts->name, sts->ctx); - - /* temporay table for quickly storing the counters for this - * thread store, so that we can post process them outside - * of the thread store lock */ - struct CountersMergeTable thread_table[max_id]; - memset(&thread_table, 0x00, - max_id * sizeof(struct CountersMergeTable)); - - SCMutexLock(&sts->ctx->m); - pc = sts->ctx->head; - while (pc != NULL) { - SCLogDebug("Counter %s (%u:%u) value %"PRIu64, - pc->name, pc->id, pc->gid, pc->value); - - thread_table[pc->gid].type = pc->type; - switch (pc->type) { - case STATS_TYPE_FUNC: - if (pc->Func != NULL) - thread_table[pc->gid].value = pc->Func(); - break; - case STATS_TYPE_AVERAGE: - default: - thread_table[pc->gid].value = pc->value; - break; - } - thread_table[pc->gid].updates = pc->updates; - table[pc->gid].name = pc->name; - - pc = pc->next; - } - SCMutexUnlock(&sts->ctx->m); - - /* update merge table */ - uint16_t c; - for (c = 0; c < max_id; c++) { - struct CountersMergeTable *e = &thread_table[c]; - /* thread only sets type if it has a counter - * of this type. */ - if (e->type == 0) - continue; - - switch (e->type) { - case STATS_TYPE_MAXIMUM: - if (e->value > merge_table[c].value) - merge_table[c].value = e->value; - break; - case STATS_TYPE_FUNC: - merge_table[c].value = e->value; - break; - case STATS_TYPE_AVERAGE: - default: - merge_table[c].value += e->value; - break; - } - merge_table[c].updates += e->updates; - merge_table[c].type = e->type; - } - - /* update per thread stats table */ - for (c = 0; c < max_id; c++) { - struct CountersMergeTable *e = &thread_table[c]; - /* thread only sets type if it has a counter - * of this type. */ - if (e->type == 0) - continue; - - uint32_t offset = (thread * stats_table.nstats) + c; - StatsRecord *r = &stats_table.tstats[offset]; - r->name = table[c].name; - r->tm_name = sts->name; - - switch (e->type) { - case STATS_TYPE_AVERAGE: - if (e->value > 0 && e->updates > 0) { - r->value = (uint64_t)(e->value / e->updates); - } - break; - default: - r->value = e->value; - break; - } - } - - sts = sts->next; - thread--; - } - - /* transfer 'merge table' to final stats table */ - uint16_t x; - for (x = 0; x < max_id; x++) { - /* xfer previous value to pvalue and reset value */ - table[x].pvalue = table[x].value; - table[x].value = 0; - table[x].tm_name = "Total"; - - struct CountersMergeTable *m = &merge_table[x]; - switch (m->type) { - case STATS_TYPE_MAXIMUM: - if (m->value > table[x].value) - table[x].value = m->value; - break; - case STATS_TYPE_AVERAGE: - if (m->value > 0 && m->updates > 0) { - table[x].value = (uint64_t)(m->value / m->updates); - } - break; - default: - table[x].value += m->value; - break; - } - } - - /* invoke logger(s) */ - OutputStatsLog(tv, td, &stats_table); - return 1; -} - -#ifdef BUILD_UNIX_SOCKET -/** - * \todo reimplement this, probably based on stats-json - */ -TmEcode StatsOutputCounterSocket(json_t *cmd, - json_t *answer, void *data) -{ - json_object_set_new(answer, "message", - json_string("not implemented")); - return TM_ECODE_FAILED; -} -#endif /* BUILD_UNIX_SOCKET */ - -/** - * \brief Initializes the perf counter api. Things are hard coded currently. - * More work to be done when we implement multiple interfaces - */ -void StatsInit(void) -{ - BUG_ON(stats_ctx != NULL); - if ( (stats_ctx = SCMalloc(sizeof(StatsGlobalContext))) == NULL) { - SCLogError(SC_ERR_FATAL, "Fatal error encountered in StatsInitCtx. Exiting..."); - exit(EXIT_FAILURE); - } - memset(stats_ctx, 0, sizeof(StatsGlobalContext)); - - StatsPublicThreadContextInit(&stats_ctx->global_counter_ctx); -} - -void StatsSetupPostConfig(void) -{ - StatsInitCtx(); -} - -/** - * \brief Spawns the wakeup, and the management thread used by the stats api - * - * The threads use the condition variable in the thread vars to control - * their wait loops to make sure the main thread can quickly kill them. - */ -void StatsSpawnThreads(void) -{ - SCEnter(); - - if (!stats_enabled) { - SCReturn; - } - - ThreadVars *tv_wakeup = NULL; - ThreadVars *tv_mgmt = NULL; - - /* spawn the stats wakeup thread */ - tv_wakeup = TmThreadCreateMgmtThread("StatsWakeupThread", - StatsWakeupThread, 1); - if (tv_wakeup == NULL) { - SCLogError(SC_ERR_THREAD_CREATE, "TmThreadCreateMgmtThread " - "failed"); - exit(EXIT_FAILURE); - } - - if (TmThreadSpawn(tv_wakeup) != 0) { - SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed for " - "StatsWakeupThread"); - exit(EXIT_FAILURE); - } - - /* spawn the stats mgmt thread */ - tv_mgmt = TmThreadCreateMgmtThread("StatsMgmtThread", - StatsMgmtThread, 1); - if (tv_mgmt == NULL) { - SCLogError(SC_ERR_THREAD_CREATE, - "TmThreadCreateMgmtThread failed"); - exit(EXIT_FAILURE); - } - - if (TmThreadSpawn(tv_mgmt) != 0) { - SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed for " - "StatsWakeupThread"); - exit(EXIT_FAILURE); - } - - SCReturn; -} - -/** - * \brief Registers a normal, unqualified counter - * - * \param name Name of the counter, to be registered - * \param tv Pointer to the ThreadVars instance for which the counter would - * be registered - * - * \retval id Counter id for the newly registered counter, or the already - * present counter - */ -uint16_t StatsRegisterCounter(char *name, struct ThreadVars_ *tv) -{ - uint16_t id = StatsRegisterQualifiedCounter(name, - (tv->thread_group_name != NULL) ? tv->thread_group_name : tv->name, - &tv->perf_public_ctx, - STATS_TYPE_NORMAL, NULL); - - return id; -} - -/** - * \brief Registers a counter, whose value holds the average of all the values - * assigned to it. - * - * \param name Name of the counter, to be registered - * \param tv Pointer to the ThreadVars instance for which the counter would - * be registered - * - * \retval id Counter id for the newly registered counter, or the already - * present counter - */ -uint16_t StatsRegisterAvgCounter(char *name, struct ThreadVars_ *tv) -{ - uint16_t id = StatsRegisterQualifiedCounter(name, - (tv->thread_group_name != NULL) ? tv->thread_group_name : tv->name, - &tv->perf_public_ctx, - STATS_TYPE_AVERAGE, NULL); - - return id; -} - -/** - * \brief Registers a counter, whose value holds the maximum of all the values - * assigned to it. - * - * \param name Name of the counter, to be registered - * \param tv Pointer to the ThreadVars instance for which the counter would - * be registered - * - * \retval the counter id for the newly registered counter, or the already - * present counter - */ -uint16_t StatsRegisterMaxCounter(char *name, struct ThreadVars_ *tv) -{ - uint16_t id = StatsRegisterQualifiedCounter(name, - (tv->thread_group_name != NULL) ? tv->thread_group_name : tv->name, - &tv->perf_public_ctx, - STATS_TYPE_MAXIMUM, NULL); - - return id; -} - -/** - * \brief Registers a counter, which represents a global value - * - * \param name Name of the counter, to be registered - * \param Func Function Pointer returning a uint64_t - * - * \retval id Counter id for the newly registered counter, or the already - * present counter - */ -uint16_t StatsRegisterGlobalCounter(char *name, uint64_t (*Func)(void)) -{ -#ifdef UNITTESTS - if (stats_ctx == NULL) - return 0; -#else - BUG_ON(stats_ctx == NULL); -#endif - uint16_t id = StatsRegisterQualifiedCounter(name, NULL, - &(stats_ctx->global_counter_ctx), - STATS_TYPE_FUNC, - Func); - return id; -} - -typedef struct CountersIdType_ { - uint16_t id; - const char *string; -} CountersIdType; - -uint32_t CountersIdHashFunc(HashTable *ht, void *data, uint16_t datalen) -{ - CountersIdType *t = (CountersIdType *)data; - uint32_t hash = 0; - int i = 0; - - int len = strlen(t->string); - - for (i = 0; i < len; i++) - hash += tolower((unsigned char)t->string[i]); - - hash = hash % ht->array_size; - - return hash; -} - -char CountersIdHashCompareFunc(void *data1, uint16_t datalen1, - void *data2, uint16_t datalen2) -{ - CountersIdType *t1 = (CountersIdType *)data1; - CountersIdType *t2 = (CountersIdType *)data2; - int len1 = 0; - int len2 = 0; - - if (t1 == NULL || t2 == NULL) - return 0; - - if (t1->string == NULL || t2->string == NULL) - return 0; - - len1 = strlen(t1->string); - len2 = strlen(t2->string); - - if (len1 == len2 && memcmp(t1->string, t2->string, len1) == 0) { - return 1; - } - - return 0; -} - -void CountersIdHashFreeFunc(void *data) -{ - SCFree(data); -} - - -/** \internal - * \brief Adds a TM to the clubbed TM table. Multiple instances of the same TM - * are stacked together in a PCTMI container. - * - * \param tm_name Name of the tm to be added to the table - * \param pctx StatsPublicThreadContext associated with the TM tm_name - * - * \retval 1 on success, 0 on failure - */ -static int StatsThreadRegister(const char *thread_name, StatsPublicThreadContext *pctx) -{ - if (stats_ctx == NULL) { - SCLogDebug("Counter module has been disabled"); - return 0; - } - - StatsThreadStore *temp = NULL; - - if (thread_name == NULL || pctx == NULL) { - SCLogDebug("supplied argument(s) to StatsThreadRegister NULL"); - return 0; - } - - SCMutexLock(&stats_ctx->sts_lock); - if (stats_ctx->counters_id_hash == NULL) { - stats_ctx->counters_id_hash = HashTableInit(256, CountersIdHashFunc, - CountersIdHashCompareFunc, - CountersIdHashFreeFunc); - BUG_ON(stats_ctx->counters_id_hash == NULL); - } - StatsCounter *pc = pctx->head; - while (pc != NULL) { - CountersIdType t = { 0, pc->name }, *id = NULL; - id = HashTableLookup(stats_ctx->counters_id_hash, &t, sizeof(t)); - if (id == NULL) { - id = SCCalloc(1, sizeof(*id)); - BUG_ON(id == NULL); - id->id = counters_global_id++; - id->string = pc->name; - BUG_ON(HashTableAdd(stats_ctx->counters_id_hash, id, sizeof(*id)) < 0); - } - pc->gid = id->id; - pc = pc->next; - } - - - if ( (temp = SCMalloc(sizeof(StatsThreadStore))) == NULL) { - SCMutexUnlock(&stats_ctx->sts_lock); - return 0; - } - memset(temp, 0, sizeof(StatsThreadStore)); - - temp->ctx = pctx; - temp->name = thread_name; - - temp->next = stats_ctx->sts; - stats_ctx->sts = temp; - stats_ctx->sts_cnt++; - SCLogDebug("stats_ctx->sts %p", stats_ctx->sts); - - SCMutexUnlock(&stats_ctx->sts_lock); - return 1; -} - -/** \internal - * \brief Returns a counter array for counters in this id range(s_id - e_id) - * - * \param s_id Counter id of the first counter to be added to the array - * \param e_id Counter id of the last counter to be added to the array - * \param pctx Pointer to the tv's StatsPublicThreadContext - * - * \retval a counter-array in this(s_id-e_id) range for this TM instance - */ -static int StatsGetCounterArrayRange(uint16_t s_id, uint16_t e_id, - StatsPublicThreadContext *pctx, - StatsPrivateThreadContext *pca) -{ - StatsCounter *pc = NULL; - uint32_t i = 0; - - if (pctx == NULL || pca == NULL) { - SCLogDebug("pctx/pca is NULL"); - return -1; - } - - if (s_id < 1 || e_id < 1 || s_id > e_id) { - SCLogDebug("error with the counter ids"); - return -1; - } - - if (e_id > pctx->curr_id) { - SCLogDebug("end id is greater than the max id for this tv"); - return -1; - } - - if ( (pca->head = SCMalloc(sizeof(StatsLocalCounter) * (e_id - s_id + 2))) == NULL) { - return -1; - } - memset(pca->head, 0, sizeof(StatsLocalCounter) * (e_id - s_id + 2)); - - pc = pctx->head; - while (pc->id != s_id) - pc = pc->next; - - i = 1; - while ((pc != NULL) && (pc->id <= e_id)) { - pca->head[i].pc = pc; - pca->head[i].id = pc->id; - pc = pc->next; - i++; - } - pca->size = i - 1; - - pca->initialized = 1; - return 0; -} - -/** \internal - * \brief Returns a counter array for all counters registered for this tm - * instance - * - * \param pctx Pointer to the tv's StatsPublicThreadContext - * - * \retval pca Pointer to a counter-array for all counter of this tm instance - * on success; NULL on failure - */ -static int StatsGetAllCountersArray(StatsPublicThreadContext *pctx, StatsPrivateThreadContext *private) -{ - if (pctx == NULL || private == NULL) - return -1; - - return StatsGetCounterArrayRange(1, pctx->curr_id, pctx, private); -} - - -int StatsSetupPrivate(ThreadVars *tv) -{ - StatsGetAllCountersArray(&(tv)->perf_public_ctx, &(tv)->perf_private_ctx); - - StatsThreadRegister(tv->name, &(tv)->perf_public_ctx); - return 0; -} - -/** - * \brief Syncs the counter array with the global counter variables - * - * \param pca Pointer to the StatsPrivateThreadContext - * \param pctx Pointer the the tv's StatsPublicThreadContext - * - * \retval 0 on success - * \retval -1 on error - */ -int StatsUpdateCounterArray(StatsPrivateThreadContext *pca, StatsPublicThreadContext *pctx) -{ - StatsLocalCounter *pcae = NULL; - uint32_t i = 0; - - if (pca == NULL || pctx == NULL) { - SCLogDebug("pca or pctx is NULL inside StatsUpdateCounterArray"); - return -1; - } - - pcae = pca->head; - - SCMutexLock(&pctx->m); - for (i = 1; i <= pca->size; i++) { - StatsCopyCounterValue(&pcae[i]); - } - SCMutexUnlock(&pctx->m); - - pctx->perf_flag = 0; - - return 1; -} - -/** - * \brief Get the value of the local copy of the counter that hold this id. - * - * \param tv threadvars - * \param id The counter id. - * - * \retval 0 on success. - * \retval -1 on error. - */ -uint64_t StatsGetLocalCounterValue(ThreadVars *tv, uint16_t id) -{ - StatsPrivateThreadContext *pca = &tv->perf_private_ctx; -#ifdef DEBUG - BUG_ON ((id < 1) || (id > pca->size)); -#endif - return pca->head[id].value; -} - -/** - * \brief Releases the resources alloted by the Stats API - */ -void StatsReleaseResources() -{ - StatsReleaseCtx(); - - return; -} - -/** - * \brief Releases counters - * - * \param head Pointer to the head of the list of perf counters that have to - * be freed - */ -void StatsReleaseCounters(StatsCounter *head) -{ - StatsCounter *pc = NULL; - - while (head != NULL) { - pc = head; - head = head->next; - StatsReleaseCounter(pc); - } - - return; -} - -/** - * \brief Releases the StatsPrivateThreadContext allocated by the user, for storing and - * updating local counter values - * - * \param pca Pointer to the StatsPrivateThreadContext - */ -void StatsReleasePrivateThreadContext(StatsPrivateThreadContext *pca) -{ - if (pca != NULL) { - if (pca->head != NULL) { - SCFree(pca->head); - pca->head = NULL; - pca->size = 0; - } - pca->initialized = 0; - } - - return; -} - -void StatsThreadCleanup(ThreadVars *tv) -{ - StatsPublicThreadContextCleanup(&tv->perf_public_ctx); - StatsReleasePrivateThreadContext(&tv->perf_private_ctx); -} - -/*----------------------------------Unit_Tests--------------------------------*/ - -#ifdef UNITTESTS -/** \internal - * \brief Registers a normal, unqualified counter - * - * \param name Name of the counter, to be registered - * \param tm_name Name of the engine module under which the counter has to be - * registered - * \param type Datatype of this counter variable - * \param pctx StatsPublicThreadContext corresponding to the tm_name key under which the - * key has to be registered - * - * \retval id Counter id for the newly registered counter, or the already - * present counter - */ -static uint16_t RegisterCounter(char *name, char *tm_name, - StatsPublicThreadContext *pctx) -{ - uint16_t id = StatsRegisterQualifiedCounter(name, tm_name, pctx, - STATS_TYPE_NORMAL, NULL); - return id; -} - -static int StatsTestCounterReg02() -{ - StatsPublicThreadContext pctx; - - memset(&pctx, 0, sizeof(StatsPublicThreadContext)); - - return RegisterCounter(NULL, NULL, &pctx); -} - -static int StatsTestCounterReg03() -{ - StatsPublicThreadContext pctx; - int result; - - memset(&pctx, 0, sizeof(StatsPublicThreadContext)); - - result = RegisterCounter("t1", "c1", &pctx); - - StatsReleaseCounters(pctx.head); - - return result; -} - -static int StatsTestCounterReg04() -{ - StatsPublicThreadContext pctx; - int result; - - memset(&pctx, 0, sizeof(StatsPublicThreadContext)); - - RegisterCounter("t1", "c1", &pctx); - RegisterCounter("t2", "c2", &pctx); - RegisterCounter("t3", "c3", &pctx); - - result = RegisterCounter("t1", "c1", &pctx); - - StatsReleaseCounters(pctx.head); - - return result; -} - -static int StatsTestGetCntArray05() -{ - ThreadVars tv; - int id; - - memset(&tv, 0, sizeof(ThreadVars)); - - id = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - if (id != 1) { - printf("id %d: ", id); - return 0; - } - - int r = StatsGetAllCountersArray(NULL, &tv.perf_private_ctx); - return (r == -1) ? 1 : 0; -} - -static int StatsTestGetCntArray06() -{ - ThreadVars tv; - int id; - int result; - - memset(&tv, 0, sizeof(ThreadVars)); - - id = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - if (id != 1) - return 0; - - int r = StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - - result = (r == 0) ? 1 : 0; - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(&tv.perf_private_ctx); - - return result; -} - -static int StatsTestCntArraySize07() -{ - ThreadVars tv; - StatsPrivateThreadContext *pca = NULL; - int result; - - memset(&tv, 0, sizeof(ThreadVars)); - - //pca = (StatsPrivateThreadContext *)&tv.perf_private_ctx; - - RegisterCounter("t1", "c1", &tv.perf_public_ctx); - RegisterCounter("t2", "c2", &tv.perf_public_ctx); - - StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - pca = &tv.perf_private_ctx; - - StatsIncr(&tv, 1); - StatsIncr(&tv, 2); - - result = pca->size; - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(pca); - - return result; -} - -static int StatsTestUpdateCounter08() -{ - ThreadVars tv; - StatsPrivateThreadContext *pca = NULL; - int id; - int result; - - memset(&tv, 0, sizeof(ThreadVars)); - - id = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - - StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - pca = &tv.perf_private_ctx; - - StatsIncr(&tv, id); - StatsAddUI64(&tv, id, 100); - - result = pca->head[id].value; - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(pca); - - return result; -} - -static int StatsTestUpdateCounter09() -{ - ThreadVars tv; - StatsPrivateThreadContext *pca = NULL; - uint16_t id1, id2; - int result; - - memset(&tv, 0, sizeof(ThreadVars)); - - id1 = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - RegisterCounter("t2", "c2", &tv.perf_public_ctx); - RegisterCounter("t3", "c3", &tv.perf_public_ctx); - RegisterCounter("t4", "c4", &tv.perf_public_ctx); - id2 = RegisterCounter("t5", "c5", &tv.perf_public_ctx); - - StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - pca = &tv.perf_private_ctx; - - StatsIncr(&tv, id2); - StatsAddUI64(&tv, id2, 100); - - result = (pca->head[id1].value == 0) && (pca->head[id2].value == 101); - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(pca); - - return result; -} - -static int StatsTestUpdateGlobalCounter10() -{ - ThreadVars tv; - StatsPrivateThreadContext *pca = NULL; - - int result = 1; - uint16_t id1, id2, id3; - - memset(&tv, 0, sizeof(ThreadVars)); - - id1 = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - id2 = RegisterCounter("t2", "c2", &tv.perf_public_ctx); - id3 = RegisterCounter("t3", "c3", &tv.perf_public_ctx); - - StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - pca = &tv.perf_private_ctx; - - StatsIncr(&tv, id1); - StatsAddUI64(&tv, id2, 100); - StatsIncr(&tv, id3); - StatsAddUI64(&tv, id3, 100); - - StatsUpdateCounterArray(pca, &tv.perf_public_ctx); - - result = (1 == tv.perf_public_ctx.head->value); - result &= (100 == tv.perf_public_ctx.head->next->value); - result &= (101 == tv.perf_public_ctx.head->next->next->value); - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(pca); - - return result; -} - -static int StatsTestCounterValues11() -{ - ThreadVars tv; - StatsPrivateThreadContext *pca = NULL; - - int result = 1; - uint16_t id1, id2, id3, id4; - - memset(&tv, 0, sizeof(ThreadVars)); - - id1 = RegisterCounter("t1", "c1", &tv.perf_public_ctx); - id2 = RegisterCounter("t2", "c2", &tv.perf_public_ctx); - id3 = RegisterCounter("t3", "c3", &tv.perf_public_ctx); - id4 = RegisterCounter("t4", "c4", &tv.perf_public_ctx); - - StatsGetAllCountersArray(&tv.perf_public_ctx, &tv.perf_private_ctx); - pca = &tv.perf_private_ctx; - - StatsIncr(&tv, id1); - StatsAddUI64(&tv, id2, 256); - StatsAddUI64(&tv, id3, 257); - StatsAddUI64(&tv, id4, 16843024); - - StatsUpdateCounterArray(pca, &tv.perf_public_ctx); - - result &= (1 == tv.perf_public_ctx.head->value); - - result &= (256 == tv.perf_public_ctx.head->next->value); - - result &= (257 == tv.perf_public_ctx.head->next->next->value); - - result &= (16843024 == tv.perf_public_ctx.head->next->next->next->value); - - StatsReleaseCounters(tv.perf_public_ctx.head); - StatsReleasePrivateThreadContext(pca); - - return result; -} - -#endif - -void StatsRegisterTests() -{ -#ifdef UNITTESTS - UtRegisterTest("StatsTestCounterReg02", StatsTestCounterReg02, 0); - UtRegisterTest("StatsTestCounterReg03", StatsTestCounterReg03, 1); - UtRegisterTest("StatsTestCounterReg04", StatsTestCounterReg04, 1); - UtRegisterTest("StatsTestGetCntArray05", StatsTestGetCntArray05, 1); - UtRegisterTest("StatsTestGetCntArray06", StatsTestGetCntArray06, 1); - UtRegisterTest("StatsTestCntArraySize07", StatsTestCntArraySize07, 2); - UtRegisterTest("StatsTestUpdateCounter08", StatsTestUpdateCounter08, 101); - UtRegisterTest("StatsTestUpdateCounter09", StatsTestUpdateCounter09, 1); - UtRegisterTest("StatsTestUpdateGlobalCounter10", - StatsTestUpdateGlobalCounter10, 1); - UtRegisterTest("StatsTestCounterValues11", StatsTestCounterValues11, 1); -#endif -} |