Module: sip-router
Branch: master
Commit: 829b7ff2e663c3ab7cc4ea95d2831eabef57b543
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=829b7ff2e663c3ab7cc4ea95d2831eabef57b543

Author: Daniel-Constantin Mierla <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date:   Mon Dec 20 09:51:05 2010 +0100

kex: print private memory usage per process via rpc

- new rpc command pkg.stats that prints used, free and real_used metrics
  per process for private memory (pkg)
- you can see how much pkg each process is eating and how much is still
  available
- should be useful to track pkg memory leaks and/or trigger alerts when
  there is no more pkg available

---

 modules_k/kex/kex_mod.c   |   18 +++-
 modules_k/kex/pkg_stats.c |  249 +++++++++++++++++++++++++++++++++++++++++++++
 modules_k/kex/pkg_stats.h |   39 +++++++
 3 files changed, 305 insertions(+), 1 deletions(-)

diff --git a/modules_k/kex/kex_mod.c b/modules_k/kex/kex_mod.c
index d0d7525..c6b55b4 100644
--- a/modules_k/kex/kex_mod.c
+++ b/modules_k/kex/kex_mod.c
@@ -36,6 +36,7 @@
 #include "km_core.h"
 #include "mi_core.h"
 #include "core_stats.h"
+#include "pkg_stats.h"
 
 
 MODULE_VERSION
@@ -47,6 +48,7 @@ MODULE_VERSION
 int w_is_myself(struct sip_msg *msg, char *uri, str *s2);
 
 static int mod_init(void);
+static int child_init(int rank);
 static void destroy(void);
 
 static cmd_export_t cmds[]={
@@ -106,7 +108,7 @@ struct module_exports exports= {
        mod_init,   /* module initialization function */
        0,
        (destroy_function) destroy,
-       0           /* per-child init function */
+       child_init  /* per-child init function */
 };
 
 /**
@@ -122,10 +124,24 @@ static int mod_init(void)
        if(register_mi_stats()<0)
                return -1;
 #endif
+       register_pkg_proc_stats();
+       pkg_proc_stats_init_rpc();
        return 0;
 }
 
 /**
+ *
+ */
+static int child_init(int rank)
+{
+       LM_DBG("rank is (%d)\n", rank);
+       if (rank==PROC_INIT)
+               return pkg_proc_stats_init();
+       return pkg_proc_stats_myinit(rank);
+}
+
+
+/**
  * destroy function
  */
 static void destroy(void)
diff --git a/modules_k/kex/pkg_stats.c b/modules_k/kex/pkg_stats.c
new file mode 100644
index 0000000..7a8d9c3
--- /dev/null
+++ b/modules_k/kex/pkg_stats.c
@@ -0,0 +1,249 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Kamailio 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
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+/*!
+ * \file
+ * \brief  Kamailio pkg statistics
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "../../dprint.h"
+#include "../../ut.h"
+#include "../../pt.h"
+#include "../../events.h"
+#include "../../mem/mem.h"
+#include "../../mem/shm_mem.h"
+#include "../../rpc.h"
+#include "../../rpc_lookup.h"
+
+
+/**
+ *
+ */
+typedef struct pkg_proc_stats {
+       int rank;
+       unsigned int pid;
+       unsigned int used;
+       unsigned int available;
+       unsigned int real_used;
+} pkg_proc_stats_t;
+
+/**
+ *
+ */
+static pkg_proc_stats_t *_pkg_proc_stats_list = NULL;
+
+/**
+ *
+ */
+static int _pkg_proc_stats_no = 0;
+
+/**
+ *
+ */
+int pkg_proc_stats_init(void)
+{
+       _pkg_proc_stats_no = get_max_procs();
+
+       if(_pkg_proc_stats_no<=0)
+               return -1;
+       if(_pkg_proc_stats_list!=NULL)
+               return -1;
+       _pkg_proc_stats_list = (pkg_proc_stats_t*)shm_malloc(
+                       _pkg_proc_stats_no*sizeof(pkg_proc_stats_t));
+       if(_pkg_proc_stats_list==NULL)
+               return -1;
+       memset(_pkg_proc_stats_list, 0,
+                       _pkg_proc_stats_no*sizeof(pkg_proc_stats_t));
+       return 0;
+}
+
+/**
+ *
+ */
+int pkg_proc_stats_myinit(int rank)
+{
+       struct mem_info info;
+       if(_pkg_proc_stats_list==NULL)
+               return -1;
+       if(process_no>=_pkg_proc_stats_no)
+               return -1;
+       _pkg_proc_stats_list[process_no].pid = (unsigned int)my_pid();
+       _pkg_proc_stats_list[process_no].rank = rank;
+
+       /* init pkg usage values */
+       pkg_info(&info);
+       _pkg_proc_stats_list[process_no].used = info.used;
+       _pkg_proc_stats_list[process_no].real_used = info.real_used;
+       return 0;
+}
+
+/**
+ *
+ */
+int pkg_proc_stats_destroy(void)
+{
+       if(_pkg_proc_stats_list==NULL)
+               return -1;
+       shm_free(_pkg_proc_stats_list);
+       _pkg_proc_stats_list = 0;
+       _pkg_proc_stats_no = 0;
+       return 0;
+}
+
+
+/**
+ *
+ */
+static int pkg_proc_update_used(void *data)
+{
+       if(_pkg_proc_stats_list==NULL)
+               return -1;
+       if(process_no>=_pkg_proc_stats_no)
+               return -1;
+       _pkg_proc_stats_list[process_no].used = (unsigned int)data;
+       return 0;
+}
+
+/**
+ *
+ */
+static int pkg_proc_update_real_used(void *data)
+{
+       if(_pkg_proc_stats_list==NULL)
+               return -1;
+       if(process_no>=_pkg_proc_stats_no)
+               return -1;
+       _pkg_proc_stats_list[process_no].real_used = (unsigned int)data;
+       _pkg_proc_stats_list[process_no].available = pkg_available();
+       return 0;
+}
+
+/**
+ *
+ */
+int register_pkg_proc_stats(void)
+{
+       sr_event_register_cb(SREV_PKG_SET_USED, pkg_proc_update_used);
+       sr_event_register_cb(SREV_PKG_SET_REAL_USED, pkg_proc_update_real_used);
+       return 0;
+}
+
+/**
+ *
+ */
+static const char* rpc_pkg_stats_doc[2] = {
+       "Private memory (pkg) statistics per process",
+       0
+};
+
+/**
+ *
+ */
+int pkg_proc_get_pid_index(unsigned int pid)
+{
+       int i;
+       for(i=0; i<_pkg_proc_stats_no; i++)
+       {
+               if(_pkg_proc_stats_list[i].pid == pid)
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ *
+ */
+static void rpc_pkg_stats(rpc_t* rpc, void* ctx)
+{
+       int i;
+       int limit;
+       int lpid;
+       void* th;
+
+       if(_pkg_proc_stats_list==NULL)
+       {
+               rpc->fault(ctx, 500, "Not initialized");
+               return;
+       }
+       i = 0;
+       limit = _pkg_proc_stats_no;
+       if (rpc->scan(ctx, "*d", &lpid) == 1)
+       {
+               i = pkg_proc_get_pid_index((unsigned int)lpid);
+               if(i<0)
+               {
+                       rpc->fault(ctx, 500, "No such pid");
+                       return;
+               }
+               limit = i + 1;
+       }
+
+       for(; i<limit; i++)
+       {
+               /* add entry node */
+               if (rpc->add(ctx, "{", &th) < 0)
+               {
+                       rpc->fault(ctx, 500, "Internal error creating rpc");
+                       return;
+               }
+               if(rpc->struct_add(th, "dddddd",
+                                               "entry",     i,
+                                               "pid",       
_pkg_proc_stats_list[i].pid,
+                                               "rank",      
_pkg_proc_stats_list[i].rank,
+                                               "used",      
_pkg_proc_stats_list[i].used,
+                                               "free",      
_pkg_proc_stats_list[i].available,
+                                               "real_used", 
_pkg_proc_stats_list[i].real_used
+                                       )<0)
+               {
+                       rpc->fault(ctx, 500, "Internal error creating rpc");
+                       return;
+               }
+       }
+}
+
+/**
+ *
+ */
+rpc_export_t kex_pkg_rpc[] = {
+       {"pkg.stats", rpc_pkg_stats,  rpc_pkg_stats_doc,       0},
+       {0, 0, 0, 0}
+};
+
+/**
+ *
+ */
+int pkg_proc_stats_init_rpc(void)
+{
+       if (rpc_register_array(kex_pkg_rpc)!=0)
+       {
+               LM_ERR("failed to register RPC commands\n");
+               return -1;
+       }
+       return 0;
+}
+
diff --git a/modules_k/kex/pkg_stats.h b/modules_k/kex/pkg_stats.h
new file mode 100644
index 0000000..4f42758
--- /dev/null
+++ b/modules_k/kex/pkg_stats.h
@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Kamailio 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
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+/*!
+ * \file
+ * \brief  Kamailio pkg statistics
+ */
+
+
+#ifndef _PKG_STATS_H_
+#define _PKG_STATS_H_
+
+int pkg_proc_stats_init(void);
+int pkg_proc_stats_myinit(int rank);
+int pkg_proc_stats_destroy(void);
+int register_pkg_proc_stats(void);
+int pkg_proc_stats_init_rpc(void);
+
+#endif /*_PKG_STATS_H_*/


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to