Module: sip-router
Branch: master
Commit: 72f1b495c42933fea96a019e140dc6333fda2eb3
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=72f1b49…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Fri May 17 09:58:19 2013 +0200
debugger: option to set debug level per module
- new parameters:
- mod_hash_size - size of internal hash table to store levels per
module (used to compute power of two with it)
- mod_level_mode - enable/disable per module log level
- mod_level - specify module log level
modparam("debugger", "mod_hash_size", 5)
modparam("debugger", "mod_level_mode", 1)
modparam("debugger", "mod_level", "core=3");
modparam("debugger", "mod_level", "usrloc=3");
---
modules/debugger/debugger_api.c | 211 +++++++++++++++++++++++++++++++++++++++
modules/debugger/debugger_api.h | 4 +
modules/debugger/debugger_mod.c | 52 ++++++++++-
3 files changed, 266 insertions(+), 1 deletions(-)
diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c
index bbf31a0..7653c95 100644
--- a/modules/debugger/debugger_api.c
+++ b/modules/debugger/debugger_api.c
@@ -35,6 +35,7 @@
#include "../../rpc_lookup.h"
#include "../../route_struct.h"
#include "../../mem/shm_mem.h"
+#include "../../locking.h"
#include "debugger_act.h"
#include "debugger_api.h"
@@ -867,3 +868,213 @@ int dbg_init_rpc(void)
return 0;
}
+
+typedef struct _dbg_mod_level {
+ str name;
+ unsigned int hashid;
+ int level;
+ struct _dbg_mod_level *next;
+} dbg_mod_level_t;
+
+typedef struct _dbg_mod_slot
+{
+ dbg_mod_level_t *first;
+ gen_lock_t lock;
+} dbg_mod_slot_t;
+
+static dbg_mod_slot_t *_dbg_mod_table = NULL;
+static unsigned int _dbg_mod_table_size = 0;
+
+/**
+ *
+ */
+int dbg_init_mod_levels(int dbg_mod_level, int dbg_mod_hash_size)
+{
+ int i;
+ if(dbg_mod_level==0 || dbg_mod_hash_size<=0)
+ return 0;
+ if(_dbg_mod_table!=NULL)
+ return 0;
+ _dbg_mod_table_size = 1 << dbg_mod_hash_size;
+ _dbg_mod_table =
(dbg_mod_slot_t*)shm_malloc(_dbg_mod_table_size*sizeof(dbg_mod_slot_t));
+ if(_dbg_mod_table==NULL)
+ {
+ LM_ERR("no more shm.\n");
+ return -1;
+ }
+ memset(_dbg_mod_table, 0, _dbg_mod_table_size*sizeof(dbg_mod_slot_t));
+
+ for(i=0; i<_dbg_mod_table_size; i++)
+ {
+ if(lock_init(&_dbg_mod_table[i].lock)==0)
+ {
+ LM_ERR("cannot initalize lock[%d]\n", i);
+ i--;
+ while(i>=0)
+ {
+ lock_destroy(&_dbg_mod_table[i].lock);
+ i--;
+ }
+ shm_free(_dbg_mod_table);
+ _dbg_mod_table = NULL;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * case insensitive hashing - clone here to avoid usage of LOG*()
+ * - s1 - str to hash
+ * - s1len - len of s1
+ * return computed hash id
+ */
+#define dbg_ch_h_inc h+=v^(v>>3)
+#define dbg_ch_icase(_c)
(((_c)>='A'&&(_c)<='Z')?((_c)|0x20):(_c))
+static inline unsigned int dbg_compute_hash(char *s1, int s1len)
+{
+ char *p, *end;
+ register unsigned v;
+ register unsigned h;
+
+ h=0;
+
+ end=s1+s1len;
+ for ( p=s1 ; p<=(end-4) ; p+=4 ){
+ v=(dbg_ch_icase(*p)<<24)+(dbg_ch_icase(p[1])<<16)+(dbg_ch_icase(p[2])<<8)
+ + dbg_ch_icase(p[3]);
+ dbg_ch_h_inc;
+ }
+ v=0;
+ for (; p<end ; p++){ v<<=8; v+=dbg_ch_icase(*p);}
+ dbg_ch_h_inc;
+
+ h=((h)+(h>>11))+((h>>13)+(h>>23));
+ return h;
+}
+
+int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel)
+{
+ unsigned int idx;
+ unsigned int hid;
+ dbg_mod_level_t *it;
+ dbg_mod_level_t *itp;
+ dbg_mod_level_t *itn;
+
+ if(_dbg_mod_table==NULL)
+ return -1;
+
+ hid = dbg_compute_hash(mname, mnlen);
+ idx = hid&(_dbg_mod_table_size-1);
+
+ lock_get(&_dbg_mod_table[idx].lock);
+ it = _dbg_mod_table[idx].first;
+ itp = NULL;
+ while(it!=NULL && it->hashid < hid) {
+ itp = it;
+ it = it->next;
+ }
+ while(it!=NULL && it->hashid==hid)
+ {
+ if(mnlen==it->name.len
+ && strncmp(mname, it->name.s, mnlen)==0)
+ {
+ /* found */
+ if(mlevel==NULL) {
+ /* remove */
+ if(itp!=NULL) {
+ itp->next = it->next;
+ } else {
+ _dbg_mod_table[idx].first = it->next;
+ }
+ shm_free(it);
+ } else {
+ /* set */
+ it->level = *mlevel;
+ }
+ lock_release(&_dbg_mod_table[idx].lock);
+ return 0;
+ }
+ itp = it;
+ it = it->next;
+ }
+ /* not found - add */
+ if(mlevel==NULL) {
+ lock_release(&_dbg_mod_table[idx].lock);
+ return 0;
+ }
+ itn = (dbg_mod_level_t*)shm_malloc(sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char));
+ if(itn==NULL) {
+ LM_ERR("no more shm\n");
+ lock_release(&_dbg_mod_table[idx].lock);
+ return -1;
+ }
+ memset(itn, 0, sizeof(dbg_mod_level_t) + (mnlen+1)*sizeof(char));
+ itn->level = *mlevel;
+ itn->hashid = hid;
+ itn->name.s = (char*)(itn) + sizeof(dbg_mod_level_t);
+ itn->name.len = mnlen;
+ strncpy(itn->name.s, mname, mnlen);
+ itn->name.s[itn->name.len] = '\0';
+
+ if(itp==NULL) {
+ itn->next = _dbg_mod_table[idx].first;
+ _dbg_mod_table[idx].first = itn;
+ } else {
+ itn->next = itp->next;
+ itp->next = itn;
+ }
+ lock_release(&_dbg_mod_table[idx].lock);
+ return 0;
+
+}
+
+static int _dbg_get_mod_debug_level = 0;
+int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
+{
+ unsigned int idx;
+ unsigned int hid;
+ dbg_mod_level_t *it;
+ /* no LOG*() usage in this function and those executed insite it
+ * - use fprintf(stderr, ...) if need for troubleshooting
+ * - it will loop otherwise */
+ if(_dbg_mod_table==NULL)
+ return -1;
+
+ if(_dbg_get_mod_debug_level!=0)
+ return -1;
+ _dbg_get_mod_debug_level = 1;
+
+ hid = dbg_compute_hash(mname, mnlen);
+ idx = hid&(_dbg_mod_table_size-1);
+ lock_get(&_dbg_mod_table[idx].lock);
+ it = _dbg_mod_table[idx].first;
+ while(it!=NULL && it->hashid < hid)
+ it = it->next;
+ while(it!=NULL && it->hashid == hid)
+ {
+ if(mnlen==it->name.len
+ && strncmp(mname, it->name.s, mnlen)==0)
+ {
+ /* found */
+ *mlevel = it->level;
+ lock_release(&_dbg_mod_table[idx].lock);
+ _dbg_get_mod_debug_level = 0;
+ return 0;
+ }
+ it = it->next;
+ }
+ lock_release(&_dbg_mod_table[idx].lock);
+ _dbg_get_mod_debug_level = 0;
+ return -1;
+}
+
+/**
+ *
+ */
+void dbg_enable_mod_levels(void)
+{
+ if(_dbg_mod_table==NULL)
+ return;
+ set_module_debug_level_cb(dbg_get_mod_debug_level);
+}
diff --git a/modules/debugger/debugger_api.h b/modules/debugger/debugger_api.h
index e5a5ca2..9af8cf6 100644
--- a/modules/debugger/debugger_api.h
+++ b/modules/debugger/debugger_api.h
@@ -33,5 +33,9 @@ int dbg_init_pid_list(void);
int dbg_init_mypid(void);
int dbg_init_rpc(void);
+int dbg_init_mod_levels(int _dbg_mod_level, int _dbg_mod_hash_size);
+int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel);
+void dbg_enable_mod_levels(void);
+
#endif
diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c
index 8b85afb..98d317b 100644
--- a/modules/debugger/debugger_mod.c
+++ b/modules/debugger/debugger_mod.c
@@ -44,6 +44,7 @@ static void mod_destroy(void);
static int w_dbg_breakpoint(struct sip_msg* msg, char* point, char* str2);
static int fixup_dbg_breakpoint(void** param, int param_no);
+static int dbg_mod_level_param(modparam_t type, void *val);
/* parameters */
extern int _dbg_cfgtrace;
@@ -56,6 +57,9 @@ extern int _dbg_step_loops;
static char * _dbg_cfgtrace_facility_str = 0;
+static int _dbg_mod_hash_size = 0;
+static int _dbg_mod_level = 0;
+
static cmd_export_t cmds[]={
{"dbg_breakpoint", (cmd_function)w_dbg_breakpoint, 1,
fixup_dbg_breakpoint, 0, ANY_ROUTE},
@@ -70,6 +74,9 @@ static param_export_t params[]={
{"log_prefix", STR_PARAM, &_dbg_cfgtrace_prefix},
{"step_usleep", INT_PARAM, &_dbg_step_usleep},
{"step_loops", INT_PARAM, &_dbg_step_loops},
+ {"mod_hash_size", INT_PARAM, &_dbg_mod_hash_size},
+ {"mod_level_mode", INT_PARAM, &_dbg_mod_level},
+ {"mod_level", STR_PARAM|USE_FUNC_PARAM, (void*)dbg_mod_level_param},
{0, 0, 0}
};
@@ -113,6 +120,12 @@ static int mod_init(void)
return -1;
}
+ if(dbg_init_mod_levels(_dbg_mod_level, _dbg_mod_hash_size)<0)
+ {
+ LM_ERR("failed to init per module log level\n");
+ return -1;
+ }
+
return dbg_init_bp_list();
}
@@ -122,8 +135,10 @@ static int mod_init(void)
static int child_init(int rank)
{
LM_DBG("rank is (%d)\n", rank);
- if (rank==PROC_INIT)
+ if (rank==PROC_INIT) {
+ dbg_enable_mod_levels();
return dbg_init_pid_list();
+ }
return dbg_init_mypid();
}
@@ -173,4 +188,39 @@ static int fixup_dbg_breakpoint(void** param, int param_no)
return dbg_add_breakpoint(a, (*p=='0')?0:1);
}
+static int dbg_mod_level_param(modparam_t type, void *val)
+{
+ char *p;
+ str s;
+ int l;
+ if(val==NULL)
+ return -1;
+
+ p = strchr((char*)val, '=');
+ if(p==NULL) {
+ LM_ERR("invalid parameter value: %s\n", (char*)val);
+ return -1;
+ }
+ s.s = p + 1;
+ s.len = strlen(s.s);
+
+ if(str2sint(&s, &l)<0) {
+ LM_ERR("invalid parameter - level value: %s\n", (char*)val);
+ return -1;
+ }
+ s.s = (char*)val;
+ s.len = p - s.s;
+ if(dbg_init_mod_levels(_dbg_mod_level, _dbg_mod_hash_size)<0)
+ {
+ LM_ERR("failed to init per module log level\n");
+ return -1;
+ }
+ if(dbg_set_mod_debug_level(s.s, s.len, &l)<0)
+ {
+ LM_ERR("cannot store parameter: %s\n", (char*)val);
+ return -1;
+ }
+ return 0;
+
+}