[sr-dev] git:master: debugger: option to set debug level per module

Daniel-Constantin Mierla miconda at gmail.com
Fri May 17 10:34:40 CEST 2013


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

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at 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;
+
+}
 




More information about the sr-dev mailing list