Module: sip-router Branch: master Commit: 72f1b495c42933fea96a019e140dc6333fda2eb3 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=72f1b495...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@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; + +}