pkg_stats.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
00003  *
00004  * This file is part of Kamailio, a free SIP server.
00005  *
00006  * Kamailio is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * Kamailio is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  *
00020  */
00021 
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 
00033 #include "../../dprint.h"
00034 #include "../../ut.h"
00035 #include "../../pt.h"
00036 #include "../../events.h"
00037 #include "../../mem/mem.h"
00038 #include "../../mem/shm_mem.h"
00039 #include "../../rpc.h"
00040 #include "../../rpc_lookup.h"
00041 
00042 
00046 typedef struct pkg_proc_stats {
00047         int rank;
00048         unsigned int pid;
00049         unsigned int used;
00050         unsigned int available;
00051         unsigned int real_used;
00052 } pkg_proc_stats_t;
00053 
00057 static pkg_proc_stats_t *_pkg_proc_stats_list = NULL;
00058 
00062 static int _pkg_proc_stats_no = 0;
00063 
00067 int pkg_proc_stats_init(void)
00068 {
00069         _pkg_proc_stats_no = get_max_procs();
00070 
00071         if(_pkg_proc_stats_no<=0)
00072                 return -1;
00073         if(_pkg_proc_stats_list!=NULL)
00074                 return -1;
00075         _pkg_proc_stats_list = (pkg_proc_stats_t*)shm_malloc(
00076                         _pkg_proc_stats_no*sizeof(pkg_proc_stats_t));
00077         if(_pkg_proc_stats_list==NULL)
00078                 return -1;
00079         memset(_pkg_proc_stats_list, 0,
00080                         _pkg_proc_stats_no*sizeof(pkg_proc_stats_t));
00081         return 0;
00082 }
00083 
00087 int pkg_proc_stats_myinit(int rank)
00088 {
00089         struct mem_info info;
00090         if(_pkg_proc_stats_list==NULL)
00091                 return -1;
00092         if(process_no>=_pkg_proc_stats_no)
00093                 return -1;
00094         _pkg_proc_stats_list[process_no].pid = (unsigned int)my_pid();
00095         _pkg_proc_stats_list[process_no].rank = rank;
00096 
00097         /* init pkg usage values */
00098         pkg_info(&info);
00099         _pkg_proc_stats_list[process_no].used = info.used;
00100         _pkg_proc_stats_list[process_no].real_used = info.real_used;
00101         return 0;
00102 }
00103 
00107 int pkg_proc_stats_destroy(void)
00108 {
00109         if(_pkg_proc_stats_list==NULL)
00110                 return -1;
00111         shm_free(_pkg_proc_stats_list);
00112         _pkg_proc_stats_list = 0;
00113         _pkg_proc_stats_no = 0;
00114         return 0;
00115 }
00116 
00117 
00121 static int pkg_proc_update_used(void *data)
00122 {
00123         if(_pkg_proc_stats_list==NULL)
00124                 return -1;
00125         if(process_no>=_pkg_proc_stats_no)
00126                 return -1;
00127         _pkg_proc_stats_list[process_no].used = (unsigned int)(long)data;
00128         return 0;
00129 }
00130 
00134 static int pkg_proc_update_real_used(void *data)
00135 {
00136         if(_pkg_proc_stats_list==NULL)
00137                 return -1;
00138         if(process_no>=_pkg_proc_stats_no)
00139                 return -1;
00140         _pkg_proc_stats_list[process_no].real_used = (unsigned int)(long)data;
00141         _pkg_proc_stats_list[process_no].available = pkg_available();
00142         return 0;
00143 }
00144 
00148 int register_pkg_proc_stats(void)
00149 {
00150         sr_event_register_cb(SREV_PKG_SET_USED, pkg_proc_update_used);
00151         sr_event_register_cb(SREV_PKG_SET_REAL_USED, pkg_proc_update_real_used);
00152         return 0;
00153 }
00154 
00158 static const char* rpc_pkg_stats_doc[2] = {
00159         "Private memory (pkg) statistics per process",
00160         0
00161 };
00162 
00166 int pkg_proc_get_pid_index(unsigned int pid)
00167 {
00168         int i;
00169         for(i=0; i<_pkg_proc_stats_no; i++)
00170         {
00171                 if(_pkg_proc_stats_list[i].pid == pid)
00172                         return i;
00173         }
00174         return -1;
00175 }
00176 
00180 static void rpc_pkg_stats(rpc_t* rpc, void* ctx)
00181 {
00182         int i;
00183         int limit;
00184         int cval;
00185         str cname;
00186         void* th;
00187         int mode;
00188 
00189         if(_pkg_proc_stats_list==NULL)
00190         {
00191                 rpc->fault(ctx, 500, "Not initialized");
00192                 return;
00193         }
00194         i = 0;
00195         mode = 0;
00196         cval = 0;
00197         limit = _pkg_proc_stats_no;
00198         if (rpc->scan(ctx, "*S", &cname) == 1)
00199         {
00200                 if(cname.len==3 && strncmp(cname.s, "pid", 3)==0)
00201                         mode = 1;
00202                 else if(cname.len==4 && strncmp(cname.s, "rank", 4)==0)
00203                         mode = 2;
00204                 else if(cname.len==5 && strncmp(cname.s, "index", 5)==0)
00205                         mode = 3;
00206                 else {
00207                         rpc->fault(ctx, 500, "Invalid filter type");
00208                         return;
00209                 }
00210 
00211                 if (rpc->scan(ctx, "d", &cval) < 1)
00212                 {
00213                         rpc->fault(ctx, 500, "One more parameter expected");
00214                         return;
00215                 }
00216                 if(mode==1)
00217                 {
00218                         i = pkg_proc_get_pid_index((unsigned int)cval);
00219                         if(i<0)
00220                         {
00221                                 rpc->fault(ctx, 500, "No such pid");
00222                                 return;
00223                         }
00224                         limit = i + 1;
00225                 } else if(mode==3) {
00226                         i=cval;
00227                         limit = i + 1;
00228                 }
00229         }
00230 
00231         for(; i<limit; i++)
00232         {
00233                 /* add entry node */
00234                 if(mode!=2 || _pkg_proc_stats_list[i].rank==cval)
00235                 {
00236                         if (rpc->add(ctx, "{", &th) < 0)
00237                         {
00238                                 rpc->fault(ctx, 500, "Internal error creating rpc");
00239                                 return;
00240                         }
00241                         if(rpc->struct_add(th, "dddddd",
00242                                                         "entry",     i,
00243                                                         "pid",       _pkg_proc_stats_list[i].pid,
00244                                                         "rank",      _pkg_proc_stats_list[i].rank,
00245                                                         "used",      _pkg_proc_stats_list[i].used,
00246                                                         "free",      _pkg_proc_stats_list[i].available,
00247                                                         "real_used", _pkg_proc_stats_list[i].real_used
00248                                                 )<0)
00249                         {
00250                                 rpc->fault(ctx, 500, "Internal error creating rpc");
00251                                 return;
00252                         }
00253                 }
00254         }
00255 }
00256 
00260 rpc_export_t kex_pkg_rpc[] = {
00261         {"pkg.stats", rpc_pkg_stats,  rpc_pkg_stats_doc,       0},
00262         {0, 0, 0, 0}
00263 };
00264 
00268 int pkg_proc_stats_init_rpc(void)
00269 {
00270         if (rpc_register_array(kex_pkg_rpc)!=0)
00271         {
00272                 LM_ERR("failed to register RPC commands\n");
00273                 return -1;
00274         }
00275         return 0;
00276 }
00277