core_stats.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * Copyright (C) 2006 Voice Sistem SRL
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. *
  20. * History:
  21. * ---------
  22. * 2006-01-23 first version (bogdan)
  23. * 2006-11-28 Added statistics for the number of bad URI's, methods, and
  24. * proxy requests (Jeffrey Magder - SOMA Networks)
  25. */
  26. /*!
  27. * \file
  28. * \brief KEX :: Kamailio Core statistics
  29. * \ingroup kex
  30. */
  31. #include <string.h>
  32. #include "../../lib/kcore/statistics.h"
  33. #include "../../lib/kmi/mi.h"
  34. #include "../../events.h"
  35. #include "../../dprint.h"
  36. #include "../../timer.h"
  37. #include "../../parser/msg_parser.h"
  38. #include "../../script_cb.h"
  39. #include "../../mem/meminfo.h"
  40. #include "../../mem/shm_mem.h"
  41. #include "../../rpc.h"
  42. #include "../../rpc_lookup.h"
  43. #ifdef STATISTICS
  44. stat_var* rcv_reqs; /*!< received requests */
  45. stat_var* rcv_rpls; /*!< received replies */
  46. stat_var* fwd_reqs; /*!< forwarded requests */
  47. stat_var* fwd_rpls; /*!< forwarded replies */
  48. stat_var* drp_reqs; /*!< dropped requests */
  49. stat_var* drp_rpls; /*!< dropped replies */
  50. stat_var* err_reqs; /*!< error requests */
  51. stat_var* err_rpls; /*!< error replies */
  52. stat_var* bad_URIs; /*!< number of bad URIs */
  53. stat_var* unsupported_methods; /*!< unsupported methods */
  54. stat_var* bad_msg_hdr; /*!< messages with bad header */
  55. /*! exported core statistics */
  56. stat_export_t core_stats[] = {
  57. {"rcv_requests" , 0, &rcv_reqs },
  58. {"rcv_replies" , 0, &rcv_rpls },
  59. {"fwd_requests" , 0, &fwd_reqs },
  60. {"fwd_replies" , 0, &fwd_rpls },
  61. {"drop_requests" , 0, &drp_reqs },
  62. {"drop_replies" , 0, &drp_rpls },
  63. {"err_requests" , 0, &err_reqs },
  64. {"err_replies" , 0, &err_rpls },
  65. {"bad_URIs_rcvd", 0, &bad_URIs },
  66. {"unsupported_methods", 0, &unsupported_methods },
  67. {"bad_msg_hdr", 0, &bad_msg_hdr },
  68. {0,0,0}
  69. };
  70. unsigned long shm_stats_get_size(void);
  71. unsigned long shm_stats_get_used(void);
  72. unsigned long shm_stats_get_rused(void);
  73. unsigned long shm_stats_get_mused(void);
  74. unsigned long shm_stats_get_free(void);
  75. unsigned long shm_stats_get_frags(void);
  76. stat_export_t shm_stats[] = {
  77. {"total_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_size },
  78. {"used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_used },
  79. {"real_used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_rused },
  80. {"max_used_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_mused },
  81. {"free_size" , STAT_IS_FUNC, (stat_var**)shm_stats_get_free },
  82. {"fragments" , STAT_IS_FUNC, (stat_var**)shm_stats_get_frags },
  83. {0,0,0}
  84. };
  85. static struct mi_root *mi_get_stats(struct mi_root *cmd, void *param);
  86. static struct mi_root *mi_reset_stats(struct mi_root *cmd, void *param);
  87. static struct mi_root *mi_clear_stats(struct mi_root *cmd, void *param);
  88. static mi_export_t mi_stat_cmds[] = {
  89. { "get_statistics", mi_get_stats, 0 , 0, 0 },
  90. { "reset_statistics", mi_reset_stats, 0 , 0, 0 },
  91. { "clear_statistics", mi_clear_stats, 0 , 0, 0 },
  92. { 0, 0, 0, 0, 0}
  93. };
  94. int stats_proc_stats_init_rpc(void);
  95. int register_mi_stats(void)
  96. {
  97. /* register MI commands */
  98. if (register_mi_mod("core", mi_stat_cmds)<0) {
  99. LM_ERR("unable to register MI cmds\n");
  100. return -1;
  101. }
  102. return 0;
  103. }
  104. static int km_cb_req_stats(struct sip_msg *msg,
  105. unsigned int flags, void *param)
  106. {
  107. update_stat(rcv_reqs, 1);
  108. if(!IS_SIP(msg))
  109. return 1;
  110. if(msg->first_line.u.request.method_value==METHOD_OTHER)
  111. update_stat(unsupported_methods, 1);
  112. return 1;
  113. }
  114. static int km_cb_rpl_stats(struct sip_msg *msg,
  115. unsigned int flags, void *param)
  116. {
  117. update_stat(rcv_rpls, 1);
  118. return 1;
  119. }
  120. static int sts_update_core_stats(void *data)
  121. {
  122. int type;
  123. type = (int)(long)data;
  124. switch(type) {
  125. case 1:
  126. /* fwd_requests */
  127. update_stat(fwd_reqs, 1);
  128. break;
  129. case 2:
  130. /* fwd_replies */
  131. update_stat(fwd_rpls, 1);
  132. break;
  133. case 3:
  134. /* drop_requests */
  135. update_stat(drp_reqs, 1);
  136. break;
  137. case 4:
  138. /* drop_replies */
  139. update_stat(drp_rpls, 1);
  140. break;
  141. case 5:
  142. /* err_requests */
  143. update_stat(err_reqs, 1);
  144. break;
  145. case 6:
  146. /* err_replies */
  147. update_stat(err_rpls, 1);
  148. break;
  149. case 7:
  150. /* bad_URIs_rcvd */
  151. update_stat(bad_URIs, 1);
  152. break;
  153. case 8:
  154. /* bad_msg_hdr */
  155. update_stat(bad_msg_hdr, 1);
  156. break;
  157. }
  158. return 0;
  159. }
  160. int register_core_stats(void)
  161. {
  162. /* register core statistics */
  163. if (register_module_stats( "core", core_stats)!=0 ) {
  164. LM_ERR("failed to register core statistics\n");
  165. return -1;
  166. }
  167. /* register sh_mem statistics */
  168. if (register_module_stats( "shmem", shm_stats)!=0 ) {
  169. LM_ERR("failed to register sh_mem statistics\n");
  170. return -1;
  171. }
  172. if (register_script_cb(km_cb_req_stats, PRE_SCRIPT_CB|REQUEST_CB, 0)<0 ) {
  173. LM_ERR("failed to register PRE request callback\n");
  174. return -1;
  175. }
  176. if (register_script_cb(km_cb_rpl_stats, PRE_SCRIPT_CB|ONREPLY_CB, 0)<0 ) {
  177. LM_ERR("failed to register PRE request callback\n");
  178. return -1;
  179. }
  180. if (stats_proc_stats_init_rpc()<0) return -1;
  181. sr_event_register_cb(SREV_CORE_STATS, sts_update_core_stats);
  182. return 0;
  183. }
  184. /***************************** RPC STUFF *******************************/
  185. /**
  186. * Parameters for RPC callback functions.
  187. */
  188. struct rpc_list_params {
  189. rpc_t* rpc;
  190. void* ctx;
  191. int clear;
  192. };
  193. /**
  194. * Satistic getter RPC callback.
  195. */
  196. static void rpc_get_grp_vars_cbk(void* p, str* g, str* n, counter_handle_t h)
  197. {
  198. struct rpc_list_params *packed_params;
  199. rpc_t* rpc;
  200. void* ctx;
  201. packed_params = p;
  202. rpc = packed_params->rpc;
  203. ctx = packed_params->ctx;
  204. rpc->rpl_printf(ctx, "%.*s:%.*s = %lu",
  205. g->len, g->s, n->len, n->s, counter_get_val(h));
  206. }
  207. /**
  208. * Group statistic getter RPC callback.
  209. */
  210. static void rpc_get_all_grps_cbk(void* p, str* g)
  211. {
  212. counter_iterate_grp_vars(g->s, rpc_get_grp_vars_cbk, p);
  213. }
  214. /**
  215. * All statistic getter RPC callback.
  216. */
  217. static void stats_get_all(rpc_t* rpc, void* ctx, char* stat)
  218. {
  219. int len = strlen(stat);
  220. struct rpc_list_params packed_params;
  221. str s_statistic;
  222. stat_var *s_stat;
  223. if (len==3 && strcmp("all", stat)==0) {
  224. packed_params.rpc = rpc;
  225. packed_params.ctx = ctx;
  226. counter_iterate_grp_names(rpc_get_all_grps_cbk, &packed_params);
  227. }
  228. else if (stat[len-1]==':') {
  229. packed_params.rpc = rpc;
  230. packed_params.ctx = ctx;
  231. stat[len-1] = '\0';
  232. counter_iterate_grp_vars(stat, rpc_get_grp_vars_cbk, &packed_params);
  233. stat[len-1] = ':';
  234. }
  235. else {
  236. s_statistic.s = stat;
  237. s_statistic.len = strlen(stat);
  238. s_stat = get_stat(&s_statistic);
  239. if (s_stat) {
  240. rpc->rpl_printf(ctx, "%s:%s = %lu",
  241. ZSW(get_stat_module(s_stat)), ZSW(get_stat_name(s_stat)),
  242. get_stat_val(s_stat));
  243. }
  244. }
  245. }
  246. /**
  247. * RPC statistics getter.
  248. */
  249. static void rpc_stats_get_statistics(rpc_t* rpc, void* ctx)
  250. {
  251. char* stat;
  252. if (stats_support()==0) {
  253. rpc->fault(ctx, 400, "stats support not enabled");
  254. return;
  255. }
  256. if (rpc->scan(ctx, "s", &stat) < 1) {
  257. rpc->fault(ctx, 400, "Please provide which stats to retrieve");
  258. return;
  259. }
  260. stats_get_all(rpc, ctx, stat);
  261. while((rpc->scan(ctx, "*s", &stat)>0)) {
  262. stats_get_all(rpc, ctx, stat);
  263. }
  264. return;
  265. }
  266. /**
  267. * Satistic reset/clear-er RPC callback..
  268. */
  269. static void rpc_reset_or_clear_grp_vars_cbk(void* p, str* g, str* n, counter_handle_t h)
  270. {
  271. struct rpc_list_params *packed_params;
  272. rpc_t* rpc;
  273. void* ctx;
  274. int clear;
  275. stat_var *s_stat;
  276. long old_val, new_val;
  277. packed_params = p;
  278. rpc = packed_params->rpc;
  279. ctx = packed_params->ctx;
  280. clear = packed_params->clear;
  281. s_stat = get_stat(n);
  282. if (s_stat) {
  283. if (clear) {
  284. old_val=get_stat_val(s_stat);
  285. reset_stat(s_stat);
  286. new_val=get_stat_val(s_stat);
  287. if (old_val==new_val) {
  288. rpc->rpl_printf(ctx, "%s:%s = %lu",
  289. ZSW(get_stat_module(s_stat)), ZSW(get_stat_name(s_stat)),
  290. new_val);
  291. }
  292. else {
  293. rpc->rpl_printf(ctx, "%s:%s = %lu (%lu)",
  294. ZSW(get_stat_module(s_stat)), ZSW(get_stat_name(s_stat)),
  295. new_val, old_val);
  296. }
  297. }
  298. else {
  299. reset_stat(s_stat);
  300. }
  301. }
  302. }
  303. /**
  304. * Group statistics reset/clear-er RPC callback.
  305. */
  306. static void rpc_reset_or_clear_all_grps_cbk(void* p, str* g)
  307. {
  308. counter_iterate_grp_vars(g->s, rpc_reset_or_clear_grp_vars_cbk, p);
  309. }
  310. /**
  311. * All statistics reset/clear-er RPC callback.
  312. */
  313. static void stats_reset_or_clear_all(rpc_t* rpc, void* ctx, char* stat, int clear)
  314. {
  315. int len = strlen(stat);
  316. struct rpc_list_params packed_params;
  317. str s_statistic;
  318. stat_var *s_stat;
  319. long old_val, new_val;
  320. if (len==3 && strcmp("all", stat)==0) {
  321. packed_params.rpc = rpc;
  322. packed_params.ctx = ctx;
  323. packed_params.clear = clear;
  324. counter_iterate_grp_names(rpc_reset_or_clear_all_grps_cbk, &packed_params);
  325. }
  326. else if (stat[len-1]==':') {
  327. packed_params.rpc = rpc;
  328. packed_params.ctx = ctx;
  329. packed_params.clear = clear;
  330. stat[len-1] = '\0';
  331. counter_iterate_grp_vars(stat, rpc_reset_or_clear_grp_vars_cbk, &packed_params);
  332. stat[len-1] = ':';
  333. }
  334. else {
  335. s_statistic.s = stat;
  336. s_statistic.len = strlen(stat);
  337. s_stat = get_stat(&s_statistic);
  338. if (s_stat) {
  339. if (clear) {
  340. old_val=get_stat_val(s_stat);
  341. reset_stat(s_stat);
  342. new_val=get_stat_val(s_stat);
  343. if (old_val==new_val) {
  344. rpc->rpl_printf(ctx, "%s:%s = %lu",
  345. ZSW(get_stat_module(s_stat)), ZSW(get_stat_name(s_stat)),
  346. new_val);
  347. }
  348. else {
  349. rpc->rpl_printf(ctx, "%s:%s = %lu (%lu)",
  350. ZSW(get_stat_module(s_stat)), ZSW(get_stat_name(s_stat)),
  351. new_val, old_val);
  352. }
  353. }
  354. else {
  355. reset_stat(s_stat);
  356. }
  357. }
  358. }
  359. }
  360. /**
  361. * RPC statistics reseter/getter framework.
  362. */
  363. static void stats_reset_or_clear_statistics(rpc_t* rpc, void* ctx, int clear)
  364. {
  365. char* stat;
  366. if (stats_support()==0) {
  367. rpc->fault(ctx, 400, "stats support not enabled");
  368. return;
  369. }
  370. if (rpc->scan(ctx, "s", &stat) < 1) {
  371. rpc->fault(ctx, 400, "Please provide which stats to retrieve");
  372. return;
  373. }
  374. stats_reset_or_clear_all(rpc, ctx, stat, clear);
  375. while((rpc->scan(ctx, "*s", &stat)>0)) {
  376. stats_reset_or_clear_all(rpc, ctx, stat, clear);
  377. }
  378. return;
  379. }
  380. /**
  381. * RPC statistics reseter.
  382. */
  383. static void rpc_stats_reset_statistics(rpc_t* rpc, void* ctx)
  384. {
  385. stats_reset_or_clear_statistics(rpc, ctx, 0);
  386. return;
  387. }
  388. /**
  389. * RPC statistics clearer.
  390. */
  391. static void rpc_stats_clear_statistics(rpc_t* rpc, void* ctx)
  392. {
  393. stats_reset_or_clear_statistics(rpc, ctx, 1);
  394. return;
  395. }
  396. /**
  397. * RPC statistics getter doc.
  398. */
  399. static const char* rpc_stats_get_statistics_doc[2] =
  400. {"get core and modules stats", 0};
  401. /**
  402. * RPC statistics reseter doc.
  403. */
  404. static const char* rpc_stats_reset_statistics_doc[2] =
  405. {"reset core and modules stats (silent operation)", 0};
  406. /**
  407. * RPC statistics clearer doc.
  408. */
  409. static const char* rpc_stats_clear_statistics_doc[2] =
  410. {"clear core and modules stats (verbose operation)", 0};
  411. /**
  412. * Stats RPC commands.
  413. */
  414. rpc_export_t kex_stats_rpc[] =
  415. {
  416. {"stats.get_statistics", rpc_stats_get_statistics,
  417. rpc_stats_get_statistics_doc, RET_ARRAY},
  418. {"stats.reset_statistics", rpc_stats_reset_statistics,
  419. rpc_stats_reset_statistics_doc, 0},
  420. {"stats.clear_statistics", rpc_stats_clear_statistics,
  421. rpc_stats_clear_statistics_doc, 0},
  422. {0, 0, 0, 0}
  423. };
  424. /**
  425. * Stats RPC initializer.
  426. */
  427. int stats_proc_stats_init_rpc(void)
  428. {
  429. if (rpc_register_array(kex_stats_rpc)!=0) {
  430. LM_ERR("failed to register RPC commands\n");
  431. return -1;
  432. }
  433. return 0;
  434. }
  435. /***************************** MI STUFF ********************************/
  436. inline static int mi_add_stat(struct mi_node *rpl, stat_var *stat)
  437. {
  438. struct mi_node *node;
  439. if (stats_support()==0) return -1;
  440. node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu",
  441. ZSW(get_stat_module(stat)),
  442. ZSW(get_stat_name(stat)),
  443. get_stat_val(stat) );
  444. if (node==0)
  445. return -1;
  446. return 0;
  447. }
  448. /* callback for counter_iterate_grp_vars. */
  449. static void mi_add_grp_vars_cbk(void* r, str* g, str* n, counter_handle_t h)
  450. {
  451. struct mi_node *rpl;
  452. rpl = r;
  453. addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu",
  454. g->len, g->s, n->len, n->s, counter_get_val(h));
  455. }
  456. /* callback for counter_iterate_grp_names */
  457. static void mi_add_all_grps_cbk(void* p, str* g)
  458. {
  459. counter_iterate_grp_vars(g->s, mi_add_grp_vars_cbk, p);
  460. }
  461. static struct mi_root *mi_get_stats(struct mi_root *cmd, void *param)
  462. {
  463. struct mi_root *rpl_tree;
  464. struct mi_node *rpl;
  465. struct mi_node *arg;
  466. stat_var *stat;
  467. str val;
  468. if(stats_support()==0)
  469. return init_mi_tree( 404, "Statistics Not Found", 20);
  470. if (cmd->node.kids==NULL)
  471. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  472. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  473. if (rpl_tree==0)
  474. return 0;
  475. rpl = &rpl_tree->node;
  476. for( arg=cmd->node.kids ; arg ; arg=arg->next) {
  477. if (arg->value.len==0)
  478. continue;
  479. val = arg->value;
  480. if ( val.len==3 && memcmp(val.s,"all",3)==0) {
  481. /* add all statistic variables */
  482. /* use direct counters access for that */
  483. counter_iterate_grp_names(mi_add_all_grps_cbk, rpl);
  484. } else if ( val.len>1 && val.s[val.len-1]==':') {
  485. /* add module statistics */
  486. val.len--;
  487. val.s[val.len]=0; /* zero term. */
  488. /* use direct counters access for that */
  489. counter_iterate_grp_vars(val.s, mi_add_grp_vars_cbk, rpl);
  490. val.s[val.len]=':' /* restore */;
  491. } else {
  492. /* add only one statistic */
  493. stat = get_stat( &val );
  494. if (stat==0)
  495. continue;
  496. if (mi_add_stat(rpl,stat)!=0)
  497. goto error;
  498. }
  499. }
  500. if (rpl->kids==0) {
  501. free_mi_tree(rpl_tree);
  502. return init_mi_tree( 404, "Statistics Not Found", 20);
  503. }
  504. return rpl_tree;
  505. error:
  506. free_mi_tree(rpl_tree);
  507. return 0;
  508. }
  509. static struct mi_root *mi_reset_stats(struct mi_root *cmd, void *param)
  510. {
  511. struct mi_root *rpl_tree;
  512. struct mi_node *arg;
  513. stat_var *stat;
  514. int found;
  515. if (cmd->node.kids==NULL)
  516. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  517. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  518. if (rpl_tree==0)
  519. return 0;
  520. found = 0;
  521. for( arg=cmd->node.kids ; arg ; arg=arg->next) {
  522. if (arg->value.len==0)
  523. continue;
  524. stat = get_stat( &arg->value );
  525. if (stat==0)
  526. continue;
  527. reset_stat( stat );
  528. found = 1;
  529. }
  530. if (!found) {
  531. free_mi_tree(rpl_tree);
  532. return init_mi_tree( 404, "Statistics Not Found", 20);
  533. }
  534. return rpl_tree;
  535. }
  536. inline static int mi_reset_and_add_stat(struct mi_node *rpl, stat_var *stat)
  537. {
  538. struct mi_node *node;
  539. long old_val, new_val;
  540. if (stats_support()==0) return -1;
  541. old_val=get_stat_val(stat);
  542. reset_stat(stat);
  543. new_val=get_stat_val(stat);
  544. if (old_val==new_val)
  545. {
  546. node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu",
  547. ZSW(get_stat_module(stat)),
  548. ZSW(get_stat_name(stat)),
  549. new_val);
  550. } else {
  551. node = addf_mi_node_child(rpl, 0, 0, 0, "%s:%s = %lu (%lu)",
  552. ZSW(get_stat_module(stat)),
  553. ZSW(get_stat_name(stat)),
  554. new_val, old_val );
  555. }
  556. if (node==0)
  557. return -1;
  558. return 0;
  559. }
  560. /* callback for counter_iterate_grp_vars to reset counters */
  561. static void mi_add_grp_vars_cbk2(void* r, str* g, str* n, counter_handle_t h)
  562. {
  563. struct mi_node *rpl;
  564. counter_val_t old_val, new_val;
  565. rpl = r;
  566. old_val = counter_get_val(h);
  567. counter_reset(h);
  568. new_val = counter_get_val(h);
  569. if (old_val==new_val)
  570. {
  571. addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu",
  572. g->len, g->s, n->len, n->s, new_val);
  573. } else {
  574. addf_mi_node_child(rpl, 0, 0, 0, "%.*s:%.*s = %lu (%lu)",
  575. g->len, g->s, n->len, n->s, new_val, old_val);
  576. }
  577. }
  578. /* callback for counter_iterate_grp_names to reset counters */
  579. static void mi_add_all_grps_cbk2(void* p, str* g)
  580. {
  581. counter_iterate_grp_vars(g->s, mi_add_grp_vars_cbk2, p);
  582. }
  583. static struct mi_root *mi_clear_stats(struct mi_root *cmd, void *param)
  584. {
  585. struct mi_root *rpl_tree;
  586. struct mi_node *rpl;
  587. struct mi_node *arg;
  588. stat_var *stat;
  589. str val;
  590. if(stats_support()==0)
  591. return init_mi_tree( 404, "Statistics Not Found", 20);
  592. if (cmd->node.kids==NULL)
  593. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  594. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  595. if (rpl_tree==0)
  596. return 0;
  597. rpl = &rpl_tree->node;
  598. for( arg=cmd->node.kids ; arg ; arg=arg->next)
  599. {
  600. if (arg->value.len==0)
  601. continue;
  602. val = arg->value;
  603. if ( val.len==3 && memcmp(val.s,"all",3)==0) {
  604. /* add all statistic variables */
  605. /* use direct counters access for that */
  606. counter_iterate_grp_names(mi_add_all_grps_cbk2, rpl);
  607. } else if ( val.len>1 && val.s[val.len-1]==':') {
  608. /* add module statistics */
  609. val.len--;
  610. val.s[val.len]=0; /* zero term. */
  611. /* use direct counters access for that */
  612. counter_iterate_grp_vars(val.s, mi_add_grp_vars_cbk2, rpl);
  613. val.s[val.len]=':' /* restore */;
  614. } else {
  615. /* reset & return only one statistic */
  616. stat = get_stat( &val );
  617. if (stat==0)
  618. continue;
  619. if (mi_reset_and_add_stat(rpl,stat)!=0)
  620. goto error;
  621. }
  622. }
  623. if (rpl->kids==0) {
  624. free_mi_tree(rpl_tree);
  625. return init_mi_tree( 404, "Statistics Not Found", 20);
  626. }
  627. return rpl_tree;
  628. error:
  629. free_mi_tree(rpl_tree);
  630. return 0;
  631. }
  632. /*** shm stats ***/
  633. static struct mem_info _stats_shm_mi;
  634. static ticks_t _stats_shm_tm = 0;
  635. void stats_shm_update(void)
  636. {
  637. ticks_t t;
  638. t = get_ticks();
  639. if(t!=_stats_shm_tm) {
  640. shm_info(&_stats_shm_mi);
  641. _stats_shm_tm = t;
  642. }
  643. }
  644. unsigned long shm_stats_get_size(void)
  645. {
  646. stats_shm_update();
  647. return _stats_shm_mi.total_size;
  648. }
  649. unsigned long shm_stats_get_used(void)
  650. {
  651. stats_shm_update();
  652. return _stats_shm_mi.used;
  653. }
  654. unsigned long shm_stats_get_rused(void)
  655. {
  656. stats_shm_update();
  657. return _stats_shm_mi.real_used;
  658. }
  659. unsigned long shm_stats_get_mused(void)
  660. {
  661. stats_shm_update();
  662. return _stats_shm_mi.max_used;
  663. }
  664. unsigned long shm_stats_get_free(void)
  665. {
  666. stats_shm_update();
  667. return _stats_shm_mi.free;
  668. }
  669. unsigned long shm_stats_get_frags(void)
  670. {
  671. stats_shm_update();
  672. return _stats_shm_mi.total_frags;
  673. }
  674. #endif