Module: sip-router Branch: andrei/counters Commit: 90ba454289fb76ba3ba2badd025e6cd41c581740 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=90ba4542...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Sun Aug 8 19:25:07 2010 +0200
counters: new modules for counters manipulations
New module for manipulating counters via the script, or RPCs.
Script functions: cnt_inc(name) cnt_add(name, val) cnt_reset(name)
Before using a counter in the script it must be declared using: modparam("counters", "script_counter", counter_name)
RPCs: cnt.get grp name - get counter value cnt.reset grp name - reset counter cnt.grps_list - list all the counter groups cnt.var_list grp - list all the counters names in a group cnt.grp_get_all grp - list all the counters and their value, in a group
---
modules/counters/Makefile | 12 ++ modules/counters/counters.c | 368 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 380 insertions(+), 0 deletions(-)
diff --git a/modules/counters/Makefile b/modules/counters/Makefile new file mode 100644 index 0000000..2f325fb --- /dev/null +++ b/modules/counters/Makefile @@ -0,0 +1,12 @@ +# $Id$ +# + +include ../../Makefile.defs +auto_gen= +NAME=counters.so +LIBS= + +DEFS+=-DSER_MOD_INTERFACE + +include ../../Makefile.modules + diff --git a/modules/counters/counters.c b/modules/counters/counters.c new file mode 100644 index 0000000..c163730 --- /dev/null +++ b/modules/counters/counters.c @@ -0,0 +1,368 @@ +/*$Id$ + * + * Copyright (C) 2010 iptelorg GmbH + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/** counters/statistics rpcs and script functions. + * @file counters.c + * @ingroup counters + * Module: counters. + */ +/* + * History: + * ------- + * 2010-08-06 created by andrei + */ + + +#include "../../modparam.h" +#include "../../dprint.h" +#include "../../compiler_opt.h" +#include "../../counters.h" + +MODULE_VERSION + +/* default script counter group name */ +static char* cnt_script_grp = "script"; + +static int add_script_counter(modparam_t type, void* val); +static int cnt_inc_f(struct sip_msg*, char*, char*); +static int cnt_add_f(struct sip_msg*, char*, char*); +static int cnt_reset_f(struct sip_msg*, char*, char*); +static int cnt_fixup1(void** param, int param_no); +static int cnt_int_fixup(void** param, int param_no); + + + +static cmd_export_t cmds[] = { + {"cnt_inc", cnt_inc_f, 1, cnt_fixup1, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE}, + {"cnt_add", cnt_add_f, 2, cnt_int_fixup, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE}, + {"cnt_reset", cnt_reset_f, 1, cnt_fixup1, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE}, + {0,0,0,0,0} +}; + +static param_export_t params[] = { + {"script_cnt_grp_name", PARAM_STRING, &cnt_script_grp}, + {"script_counter", PARAM_STRING|PARAM_USE_FUNC, add_script_counter}, + {0,0,0} +}; + + +static void cnt_get_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_get_doc[] = { + "get counter value (takes group and counter name as parameters)", 0 +}; + +static void cnt_reset_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_reset_doc[] = { + "reset counter (takes group and counter name as parameters)", 0 +}; + +static void cnt_get_raw_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_get_raw_doc[] = { + "get raw counter value (debugging version)", 0 +}; + +static void cnt_grps_list_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_grps_list_doc[] = { + "list all the counter group names", 0 +}; + +static void cnt_var_list_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_var_list_doc[] = { + "list all the counters names in a specified group", 0 +}; + +static void cnt_grp_get_all_rpc(rpc_t* rpc, void* ctx); +static const char* cnt_grp_get_all_doc[] = { + "list all counter names and values in a specified group", 0 +}; + + + + +static rpc_export_t counters_rpc[] = { + {"cnt.get", cnt_get_rpc, cnt_get_doc, 0 }, + {"cnt.reset", cnt_reset_rpc, cnt_reset_doc, 0 }, + {"cnt.get_raw", cnt_get_raw_rpc, cnt_get_raw_doc, 0 }, + {"cnt.grps_list", cnt_grps_list_rpc, cnt_grps_list_doc, RET_ARRAY }, + {"cnt.var_list", cnt_var_list_rpc, cnt_var_list_doc, RET_ARRAY }, + {"cnt.grp_get_all", cnt_grp_get_all_rpc, cnt_grp_get_all_doc, 0 }, + { 0, 0, 0, 0} +}; + + + +struct module_exports exports= { + "counters", + cmds, + counters_rpc, /* RPC methods */ + params, + 0, /* module initialization function */ + 0, /* response function */ + 0, /* destroy function */ + 0, /* on_cancel function */ + 0, /* per-child init function */ +}; + + +static int add_script_counter(modparam_t type, void* val) +{ + char* name; + counter_handle_t h; + int ret; + + if ((type & PARAM_STRING) == 0) { + BUG("bad parameter type %d\n", type); + goto error; + } + name = (char*) val; + ret = counter_register(&h, cnt_script_grp, name, 0, 0, 0, 0); + if (ret < 0) { + if (ret == -2) { + ERR("counter %s.%s already registered\n", cnt_script_grp, name); + return 0; + } + ERR("failed to register counter %s.%s\n", cnt_script_grp, name); + goto error; + } + return 0; +error: + return -1; +} + + + +static int cnt_fixup1(void** param, int param_no) +{ + char* name; + counter_handle_t h; + + name = (char*)*param; + if (counter_lookup(&h, cnt_script_grp, name) < 0) { + ERR("counter %s.%s does not exist (forgot to define it?)\n", + cnt_script_grp, name); + return -1; + } + *param = (void*)(long)h.id; + return 0; +} + + + +static int cnt_int_fixup(void** param, int param_no) +{ + char* name; + counter_handle_t h; + + if (param_no == 1) { + name = (char*)*param; + if (counter_lookup(&h, cnt_script_grp, name) < 0) { + ERR("counter %s.%s does not exist (forgot to define it?)\n", + cnt_script_grp, name); + return -1; + } + *param = (void*)(long)h.id; + } else + return fixup_var_int_2(param, param_no); + return 0; +} + + + +static int cnt_inc_f(struct sip_msg* msg, char* handle, char* bar) +{ + counter_handle_t h; + + h.id = (long)(void*)handle; + counter_inc(h); + return 1; +} + + + +static int cnt_add_f(struct sip_msg* msg, char* handle, char* val) +{ + counter_handle_t h; + int v; + + h.id = (long)(void*)handle; + if (unlikely(get_int_fparam(&v, msg, (fparam_t*)val) < 0)) { + ERR("non integer parameter\n"); + return -1; + } + counter_add(h, v); + return 1; +} + + + +static int cnt_reset_f(struct sip_msg* msg, char* handle, char* bar) +{ + counter_handle_t h; + + h.id = (long)(void*)handle; + counter_reset(h); + return 1; +} + + + +static void cnt_get_rpc(rpc_t* rpc, void* c) +{ + char* group; + char* name; + counter_val_t v; + counter_handle_t h; + + if (rpc->scan(c, "ss", &group, &name) < 2) { + /* rpc->fault(c, 400, "group and counter name required"); */ + return; + } + if (counter_lookup(&h, group, name) < 0) { + rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name); + return; + } + v = counter_get_val(h); + rpc->add(c, "d", (int)v); + return; +} + + + +static void cnt_get_raw_rpc(rpc_t* rpc, void* c) +{ + char* group; + char* name; + counter_val_t v; + counter_handle_t h; + + if (rpc->scan(c, "ss", &group, &name) < 2) { + /* rpc->fault(c, 400, "group and counter name required"); */ + return; + } + if (counter_lookup(&h, group, name) < 0) { + rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name); + return; + } + v = counter_get_raw_val(h); + rpc->add(c, "d", (int)v); + return; +} + + + +static void cnt_reset_rpc(rpc_t* rpc, void* c) +{ + char* group; + char* name; + counter_handle_t h; + + if (rpc->scan(c, "ss", &group, &name) < 2) { + /* rpc->fault(c, 400, "group and counter name required"); */ + return; + } + if (counter_lookup(&h, group, name) < 0) { + rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name); + return; + } + counter_reset(h); + return; +} + + + +struct rpc_list_params { + rpc_t* rpc; + void* ctx; +}; + + +/* helper callback for iterating groups or names */ +static void rpc_print_name(void* param, str* n) +{ + struct rpc_list_params* p; + rpc_t* rpc; + void* ctx; + + p = param; + rpc = p->rpc; + ctx = p->ctx; + rpc->add(ctx, "S", n); +} + + +/* helper callback for iterating on variable names & values*/ +static void rpc_print_name_val(void* param, str* g, str* n, + counter_handle_t h) +{ + struct rpc_list_params* p; + rpc_t* rpc; + void* s; + + p = param; + rpc = p->rpc; + s = p->ctx; + rpc->struct_add(s, "d", n->s, (int)counter_get_val(h)); +} + + + +static void cnt_grps_list_rpc(rpc_t* rpc, void* c) +{ + struct rpc_list_params packed_params; + + packed_params.rpc = rpc; + packed_params.ctx = c; + counter_iterate_grp_names(rpc_print_name, &packed_params); +} + + + +static void cnt_var_list_rpc(rpc_t* rpc, void* c) +{ + char* group; + struct rpc_list_params packed_params; + + if (rpc->scan(c, "s", &group) < 1) { + /* rpc->fault(c, 400, "group name required"); */ + return; + } + packed_params.rpc = rpc; + packed_params.ctx = c; + counter_iterate_grp_var_names(group, rpc_print_name, &packed_params); +} + + + +static void cnt_grp_get_all_rpc(rpc_t* rpc, void* c) +{ + void* s; + char* group; + struct rpc_list_params packed_params; + + if (rpc->scan(c, "s", &group) < 1) { + /* rpc->fault(c, 400, "group name required"); */ + return; + } + if (rpc->add(c, "{", &s) < 0) return; + packed_params.rpc = rpc; + packed_params.ctx = s; + counter_iterate_grp_vars(group, rpc_print_name_val, &packed_params); +} + +/* vi: set ts=4 sw=4 tw=79:ai:cindent: */