modules/counters/counters.c

Go to the documentation of this file.
00001 /*$Id$
00002  *
00003  * Copyright (C) 2010 iptelorg GmbH
00004  *
00005  * Permission to use, copy, modify, and distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00010  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00011  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00012  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00025 /*
00026  * History:
00027  * -------
00028  *  2010-08-06  created by andrei
00029  */
00030 
00031 
00032 #include "../../modparam.h"
00033 #include "../../dprint.h"
00034 #include "../../compiler_opt.h"
00035 #include "../../counters.h"
00036 
00037 MODULE_VERSION
00038 
00039 /* default script counter group name */
00040 static char* cnt_script_grp = "script";
00041 
00042 static int add_script_counter(modparam_t type, void* val);
00043 static int cnt_inc_f(struct sip_msg*, char*, char*);
00044 static int cnt_add_f(struct sip_msg*, char*, char*);
00045 static int cnt_reset_f(struct sip_msg*, char*, char*);
00046 static int cnt_fixup1(void** param, int param_no);
00047 static int cnt_int_fixup(void** param, int param_no);
00048 
00049 
00050 
00051 static cmd_export_t cmds[] = {
00052         {"cnt_inc",    cnt_inc_f,   1,  cnt_fixup1,
00053                         REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
00054         {"cnt_add",    cnt_add_f,   2,  cnt_int_fixup,
00055                         REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
00056         {"cnt_reset", cnt_reset_f,  1, cnt_fixup1,
00057                         REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
00058         {0,0,0,0,0}
00059 };
00060 
00061 static param_export_t params[] = {
00062         {"script_cnt_grp_name", PARAM_STRING, &cnt_script_grp},
00063         {"script_counter", PARAM_STRING|PARAM_USE_FUNC, add_script_counter},
00064         {0,0,0}
00065 };
00066 
00067 
00068 static void cnt_get_rpc(rpc_t* rpc, void* ctx);
00069 static const char* cnt_get_doc[] = {
00070         "get counter value (takes group and counter name as parameters)", 0
00071 };
00072 
00073 static void cnt_reset_rpc(rpc_t* rpc, void* ctx);
00074 static const char* cnt_reset_doc[] = {
00075         "reset counter (takes group and counter name as parameters)", 0
00076 };
00077 
00078 static void cnt_get_raw_rpc(rpc_t* rpc, void* ctx);
00079 static const char* cnt_get_raw_doc[] = {
00080         "get raw counter value (debugging version)", 0
00081 };
00082 
00083 static void cnt_grps_list_rpc(rpc_t* rpc, void* ctx);
00084 static const char* cnt_grps_list_doc[] = {
00085         "list all the counter group names", 0
00086 };
00087 
00088 static void cnt_var_list_rpc(rpc_t* rpc, void* ctx);
00089 static const char* cnt_var_list_doc[] = {
00090         "list all the counters names in a specified group", 0
00091 };
00092 
00093 static void cnt_grp_get_all_rpc(rpc_t* rpc, void* ctx);
00094 static const char* cnt_grp_get_all_doc[] = {
00095         "list all counter names and values in a specified group", 0
00096 };
00097 
00098 static void cnt_help_rpc(rpc_t* rpc, void* ctx);
00099 static const char* cnt_help_doc[] = {
00100         "print the description of a counter (group and counter name required).", 0
00101 };
00102 
00103 
00104 
00105 static rpc_export_t counters_rpc[] = {
00106         {"cnt.get", cnt_get_rpc, cnt_get_doc, 0 },
00107         {"cnt.reset", cnt_reset_rpc, cnt_reset_doc, 0 },
00108         {"cnt.get_raw", cnt_get_raw_rpc, cnt_get_raw_doc, 0 },
00109         {"cnt.grps_list", cnt_grps_list_rpc, cnt_grps_list_doc, RET_ARRAY },
00110         {"cnt.var_list", cnt_var_list_rpc, cnt_var_list_doc, RET_ARRAY },
00111         {"cnt.grp_get_all", cnt_grp_get_all_rpc, cnt_grp_get_all_doc, 0 },
00112         {"cnt.help", cnt_help_rpc, cnt_help_doc, 0},
00113         { 0, 0, 0, 0}
00114 };
00115 
00116 
00117 
00118 struct module_exports exports= {
00119         "counters",
00120         cmds,
00121         counters_rpc,        /* RPC methods */
00122         params,
00123         0, /* module initialization function */
00124         0, /* response function */
00125         0, /* destroy function */
00126         0, /* on_cancel function */
00127         0, /* per-child init function */
00128 };
00129 
00130 
00131 
00140 static int add_script_counter(modparam_t type, void* val)
00141 {
00142         char* name;
00143         counter_handle_t h;
00144         int ret;
00145         char* grp;
00146         char* desc;
00147         char* p;
00148 
00149         if ((type & PARAM_STRING) == 0) {
00150                 BUG("bad parameter type %d\n", type);
00151                 goto error;
00152         }
00153         name = (char*) val;
00154         grp = cnt_script_grp; /* default group */
00155         desc = "custom script counter."; /* default desc. */
00156         if ((p = strchr(name, ':')) != 0 ||
00157                         (p = strchr(name, ' ')) != 0) {
00158                 /* found desc. */
00159                 *p = 0;
00160                 for(p = p+1; *p && (*p == ' ' || *p == '\t'); p++);
00161                 if (*p)
00162                         desc = p;
00163         }
00164         if ((p = strchr(name, '.')) != 0) {
00165                 /* found group */
00166                 grp = name;
00167                 *p = 0;
00168                 name = p+1;
00169         }
00170         ret = counter_register(&h, grp, name, 0, 0, 0, desc, 0);
00171         if (ret < 0) {
00172                 if (ret == -2) {
00173                         ERR("counter %s.%s already registered\n", grp, name);
00174                         return 0;
00175                 }
00176                 ERR("failed to register counter %s.%s\n", grp, name);
00177                 goto error;
00178         }
00179         return 0;
00180 error:
00181         return -1;
00182 }
00183 
00184 
00185 
00186 static int cnt_fixup1(void** param, int param_no)
00187 {
00188         char* name;
00189         char* grp;
00190         char* p;
00191         counter_handle_t h;
00192 
00193         name = (char*)*param;
00194         grp = cnt_script_grp; /* default group */
00195         if ((p = strchr(name, '.')) != 0) {
00196                 /* found group */
00197                 grp = name;
00198                 name = p+1;
00199                 *p = 0;
00200         }
00201         if (counter_lookup(&h, grp, name) < 0) {
00202                 ERR("counter %s.%s does not exist (forgot to define it?)\n",
00203                                 grp, name);
00204                 return -1;
00205         }
00206         *param = (void*)(long)h.id;
00207         return 0;
00208 }
00209 
00210 
00211 
00212 static int cnt_int_fixup(void** param, int param_no)
00213 {
00214         char* name;
00215         char* grp;
00216         char* p;
00217         counter_handle_t h;
00218 
00219         if (param_no == 1) {
00220                 name = (char*)*param;
00221                 grp = cnt_script_grp; /* default group */
00222                 if ((p = strchr(name, '.')) != 0) {
00223                         /* found group */
00224                         grp = name;
00225                         name = p+1;
00226                         *p = 0;
00227                 }
00228                 if (counter_lookup(&h, grp, name) < 0) {
00229                         ERR("counter %s.%s does not exist (forgot to define it?)\n",
00230                                         grp, name);
00231                         return -1;
00232                 }
00233                 *param = (void*)(long)h.id;
00234         } else
00235                 return fixup_var_int_2(param, param_no);
00236         return 0;
00237 }
00238 
00239 
00240 
00241 static int cnt_inc_f(struct sip_msg* msg, char* handle, char* bar)
00242 {
00243         counter_handle_t h;
00244         
00245         h.id = (long)(void*)handle;
00246         counter_inc(h);
00247         return 1;
00248 }
00249 
00250 
00251 
00252 static int cnt_add_f(struct sip_msg* msg, char* handle, char* val)
00253 {
00254         counter_handle_t h;
00255         int v;
00256         
00257         h.id = (long)(void*)handle;
00258         if (unlikely(get_int_fparam(&v, msg, (fparam_t*)val) < 0)) {
00259                 ERR("non integer parameter\n");
00260                 return -1;
00261         }
00262         counter_add(h, v);
00263         return 1;
00264 }
00265 
00266 
00267 
00268 static int cnt_reset_f(struct sip_msg* msg, char* handle, char* bar)
00269 {
00270         counter_handle_t h;
00271         
00272         h.id = (long)(void*)handle;
00273         counter_reset(h);
00274         return 1;
00275 }
00276 
00277 
00278 
00279 static void cnt_grp_get_all(rpc_t* rpc, void* c, char* group);
00280 
00281 
00282 
00283 static void cnt_get_rpc(rpc_t* rpc, void* c)
00284 {
00285         char* group;
00286         char* name;
00287         counter_val_t v;
00288         counter_handle_t h;
00289         
00290         if (rpc->scan(c, "s", &group) < 1)
00291                 return;
00292         if (rpc->scan(c, "*s", &name) < 1)
00293                 return cnt_grp_get_all(rpc, c, group);
00294         /* group & name read */
00295         if (counter_lookup(&h, group, name) < 0) {
00296                 rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
00297                 return;
00298         }
00299         v = counter_get_val(h);
00300         rpc->add(c, "d", (int)v);
00301         return;
00302 }
00303 
00304 
00305 
00306 static void cnt_get_raw_rpc(rpc_t* rpc, void* c)
00307 {
00308         char* group;
00309         char* name;
00310         counter_val_t v;
00311         counter_handle_t h;
00312         
00313         if (rpc->scan(c, "ss", &group, &name) < 2) {
00314                 /* rpc->fault(c, 400, "group and counter name required"); */
00315                 return;
00316         }
00317         if (counter_lookup(&h, group, name) < 0) {
00318                 rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
00319                 return;
00320         }
00321         v = counter_get_raw_val(h);
00322         rpc->add(c, "d", (int)v);
00323         return;
00324 }
00325 
00326 
00327 
00328 static void cnt_reset_rpc(rpc_t* rpc, void* c)
00329 {
00330         char* group;
00331         char* name;
00332         counter_handle_t h;
00333         
00334         if (rpc->scan(c, "ss", &group, &name) < 2) {
00335                 /* rpc->fault(c, 400, "group and counter name required"); */
00336                 return;
00337         }
00338         if (counter_lookup(&h, group, name) < 0) {
00339                 rpc->fault(c, 400, "non-existent counter %s.%s\n", group, name);
00340                 return;
00341         }
00342         counter_reset(h);
00343         return;
00344 }
00345 
00346 
00347 
00348 struct rpc_list_params {
00349         rpc_t* rpc;
00350         void* ctx;
00351 };
00352 
00353 
00354 /* helper callback for iterating groups or names */
00355 static  void rpc_print_name(void* param, str* n)
00356 {
00357         struct rpc_list_params* p;
00358         rpc_t* rpc;
00359         void* ctx;
00360 
00361         p = param;
00362         rpc = p->rpc;
00363         ctx = p->ctx;
00364         rpc->add(ctx, "S", n);
00365 }
00366 
00367 
00368 /* helper callback for iterating on variable names & values*/
00369 static  void rpc_print_name_val(void* param, str* g, str* n,
00370                                                                 counter_handle_t h)
00371 {
00372         struct rpc_list_params* p;
00373         rpc_t* rpc;
00374         void* s;
00375 
00376         p = param;
00377         rpc = p->rpc;
00378         s = p->ctx;
00379         rpc->struct_add(s, "d", n->s, (int)counter_get_val(h));
00380 }
00381 
00382 
00383 
00384 static void cnt_grps_list_rpc(rpc_t* rpc, void* c)
00385 {
00386         struct rpc_list_params packed_params;
00387         
00388         packed_params.rpc = rpc;
00389         packed_params.ctx = c;
00390         counter_iterate_grp_names(rpc_print_name, &packed_params);
00391 }
00392 
00393 
00394 
00395 static void cnt_var_list_rpc(rpc_t* rpc, void* c)
00396 {
00397         char* group;
00398         struct rpc_list_params packed_params;
00399         
00400         if (rpc->scan(c, "s", &group) < 1) {
00401                 /* rpc->fault(c, 400, "group name required"); */
00402                 return;
00403         }
00404         packed_params.rpc = rpc;
00405         packed_params.ctx = c;
00406         counter_iterate_grp_var_names(group, rpc_print_name, &packed_params);
00407 }
00408 
00409 
00410 
00411 static void cnt_grp_get_all(rpc_t* rpc, void* c, char* group)
00412 {
00413         void* s;
00414         struct rpc_list_params packed_params;
00415         
00416         if (rpc->add(c, "{", &s) < 0) return;
00417         packed_params.rpc = rpc;
00418         packed_params.ctx = s;
00419         counter_iterate_grp_vars(group, rpc_print_name_val, &packed_params);
00420 }
00421 
00422 
00423 
00424 static void cnt_grp_get_all_rpc(rpc_t* rpc, void* c)
00425 {
00426         char* group;
00427         
00428         if (rpc->scan(c, "s", &group) < 1) {
00429                 /* rpc->fault(c, 400, "group name required"); */
00430                 return;
00431         }
00432         return cnt_grp_get_all(rpc, c, group);
00433 }
00434 
00435 
00436 
00437 static void cnt_help_rpc(rpc_t* rpc, void* ctx)
00438 {
00439         char* group;
00440         char* name;
00441         char* desc;
00442         counter_handle_t h;
00443         
00444         if (rpc->scan(ctx, "ss", &group, &name) < 2) {
00445                 /* rpc->fault(c, 400, "group and counter name required"); */
00446                 return;
00447         }
00448         if (counter_lookup(&h, group, name) < 0) {
00449                 rpc->fault(ctx, 400, "non-existent counter %s.%s\n", group, name);
00450                 return;
00451         }
00452         desc = counter_get_doc(h);
00453         if (desc)
00454                 rpc->add(ctx, "s", desc);
00455         else
00456                 rpc->fault(ctx, 400, "no description for counter %s.%s\n",
00457                                         group, name);
00458         return;
00459 }
00460 
00461 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */