Browse code

debugger: add support for static and dynamic, module specific, logging facility

Added two new debugger params which will support setting per module logging facility.
This is useful when one might want to change logging for a certain module to a different file.
mod_facility_mode (0/1) is used for enabling this. mod_facility (str) is used for
setting the facility.

Stefan Mititelu authored on 25/05/2015 09:34:25
Showing 7 changed files
... ...
@@ -103,12 +103,15 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val)
103 103
  */
104 104
 
105 105
 /* value for unset local log level  */
106
-#define UNSET_LOCAL_DEBUG_LEVEL	-255
106
+#define UNSET_LOCAL_DEBUG_LEVEL	    -255
107
+#define UNSET_LOCAL_DEBUG_FACILITY  -255
107 108
 
108 109
 /* the local debug log level */
109 110
 static int _local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
111
+static int _local_debug_facility = UNSET_LOCAL_DEBUG_FACILITY;
110 112
 /* callback to get per module debug level */
111 113
 static get_module_debug_level_f _module_debug_level = NULL;
114
+static get_module_debug_facility_f _module_debug_facility = NULL;
112 115
 
113 116
 /**
114 117
  * @brief set callback function for per module debug level
... ...
@@ -118,12 +121,17 @@ void set_module_debug_level_cb(get_module_debug_level_f f)
118 118
 	_module_debug_level = f;
119 119
 }
120 120
 
121
+void set_module_debug_facility_cb(get_module_debug_facility_f f)
122
+{
123
+	_module_debug_facility = f;
124
+}
125
+
121 126
 /**
122 127
  * @brief return the log level - the local one if it set,
123 128
  *   otherwise the global value
124 129
  */
125 130
 int get_debug_level(char *mname, int mnlen) {
126
-	int mlevel = L_DBG;
131
+	int mlevel;
127 132
 	/*important -- no LOGs inside, because it will loop */
128 133
 	if(unlikely(_module_debug_level!=NULL && mnlen>0)) {
129 134
 		if(_module_debug_level(mname, mnlen, &mlevel)==0) {
... ...
@@ -135,6 +143,23 @@ int get_debug_level(char *mname, int mnlen) {
135 135
 }
136 136
 
137 137
 /**
138
+ * @brief return the log facility - the local one if it set,
139
+ *   otherwise the global value
140
+ */
141
+int get_debug_facility(char *mname, int mnlen) {
142
+	int mfacility;
143
+	/*important -- no LOGs inside, because it will loop */
144
+	if(unlikely(_module_debug_facility!=NULL && mnlen>0)) {
145
+		if(_module_debug_facility(mname, mnlen, &mfacility)==0) {
146
+			return mfacility;
147
+		}
148
+	}
149
+	return (_local_debug_facility != UNSET_LOCAL_DEBUG_FACILITY) ?
150
+				_local_debug_facility : cfg_get(core, core_cfg, log_facility);
151
+}
152
+
153
+
154
+/**
138 155
  * @brief set the local debug log level
139 156
  */
140 157
 void set_local_debug_level(int level)
... ...
@@ -150,6 +175,22 @@ void reset_local_debug_level(void)
150 150
 	_local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
151 151
 }
152 152
 
153
+/**
154
+ * @brief set the local debug log facility
155
+ */
156
+void set_local_debug_facility(int facility)
157
+{
158
+	_local_debug_facility = facility;
159
+}
160
+
161
+/**
162
+ * @brief reset the local debug log facility
163
+ */
164
+void reset_local_debug_facility(void)
165
+{
166
+	_local_debug_facility = UNSET_LOCAL_DEBUG_FACILITY;
167
+}
168
+
153 169
 typedef struct log_level_color {
154 170
 	char f;
155 171
 	char b;
... ...
@@ -130,10 +130,15 @@ struct log_level_info {
130 130
 
131 131
 /** @brief per process debug level handling */
132 132
 int get_debug_level(char *mname, int mnlen);
133
+int get_debug_facility(char *mname, int mnlen);
133 134
 void set_local_debug_level(int level);
135
+void set_local_debug_facility(int facility);
134 136
 void reset_local_debug_level(void);
137
+void reset_local_debug_facility(void);
135 138
 typedef int (*get_module_debug_level_f)(char *mname, int mnlen, int *mlevel);
139
+typedef int (*get_module_debug_facility_f)(char *mname, int mnlen, int *mfacility);
136 140
 void set_module_debug_level_cb(get_module_debug_level_f f);
141
+void set_module_debug_facility_cb(get_module_debug_facility_f f);
137 142
 
138 143
 #define is_printable(level) (get_debug_level(LOG_MNAME, LOG_MNAME_LEN)>=(level))
139 144
 extern struct log_level_info log_level_info[];
... ...
@@ -141,7 +146,7 @@ extern char *log_name;
141 141
 
142 142
 #ifndef NO_SIG_DEBUG
143 143
 /** @brief protection against "simultaneous" printing from signal handlers */
144
-extern volatile int dprint_crit; 
144
+extern volatile int dprint_crit;
145 145
 #endif
146 146
 
147 147
 int str2facility(char *s);
... ...
@@ -210,7 +215,7 @@ void log_prefix_init(void);
210 210
 							syslog(LOG2SYSLOG_LEVEL(level) | \
211 211
 								   (((facility) != DEFAULT_FACILITY) ? \
212 212
 									(facility) : \
213
-									cfg_get(core, core_cfg, log_facility)), \
213
+								    get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
214 214
 									"%s: %s" fmt, \
215 215
 									(lname)?(lname):LOG_LEVEL2NAME(level),\
216 216
 									(prefix), __VA_ARGS__); \
... ...
@@ -227,13 +232,13 @@ void log_prefix_init(void);
227 227
 								syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
228 228
 									   (((facility) != DEFAULT_FACILITY) ? \
229 229
 										(facility) : \
230
-										cfg_get(core, core_cfg, log_facility)),\
230
+								        get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
231 231
 									   "%s" fmt, (prefix), __VA_ARGS__); \
232 232
 							else \
233 233
 								syslog(LOG2SYSLOG_LEVEL(L_DBG) | \
234 234
 									   (((facility) != DEFAULT_FACILITY) ? \
235 235
 										(facility) : \
236
-										cfg_get(core, core_cfg, log_facility)),\
236
+								        get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
237 237
 									   "%s" fmt, (prefix), __VA_ARGS__); \
238 238
 						} \
239 239
 					} \
... ...
@@ -298,7 +303,7 @@ void log_prefix_init(void);
298 298
 							syslog(LOG2SYSLOG_LEVEL(__llevel) |\
299 299
 							   (((facility) != DEFAULT_FACILITY) ? \
300 300
 								(facility) : \
301
-								cfg_get(core, core_cfg, log_facility)), \
301
+								get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
302 302
 								"%.*s%s: %s" fmt,\
303 303
 								log_prefix_val->len, log_prefix_val->s, \
304 304
 								(lname)?(lname):LOG_LEVEL2NAME(__llevel),\
... ...
@@ -307,7 +312,7 @@ void log_prefix_init(void);
307 307
 							syslog(LOG2SYSLOG_LEVEL(__llevel) |\
308 308
 							   (((facility) != DEFAULT_FACILITY) ? \
309 309
 								(facility) : \
310
-								cfg_get(core, core_cfg, log_facility)), \
310
+								get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
311 311
 								"%s: %s" fmt,\
312 312
 								(lname)?(lname):LOG_LEVEL2NAME(__llevel),\
313 313
 								(prefix) , ## args); \
... ...
@@ -985,7 +985,7 @@ static void dbg_rpc_mod_level(rpc_t* rpc, void* ctx){
985 985
 
986 986
 	if(dbg_set_mod_debug_level(value.s, value.len, &l)<0)
987 987
 	{
988
-		rpc->fault(ctx, 500, "cannot store parameter\n");
988
+		rpc->fault(ctx, 500, "cannot store parameter");
989 989
 		return;
990 990
 	}
991 991
 	rpc->add(ctx, "s", "200 ok");
... ...
@@ -994,6 +994,38 @@ static void dbg_rpc_mod_level(rpc_t* rpc, void* ctx){
994 994
 /**
995 995
  *
996 996
  */
997
+static const char* dbg_rpc_mod_facility_doc[2] = {
998
+	"Specify module log facility",
999
+	0
1000
+};
1001
+
1002
+static void dbg_rpc_mod_facility(rpc_t* rpc, void* ctx) {
1003
+	int fl;
1004
+	str value = {0, 0};
1005
+	str facility = {0, 0};
1006
+
1007
+	if (rpc->scan(ctx, "SS", &value, &facility) < 1)
1008
+	{
1009
+	    rpc->fault(ctx, 500, "invalid parameters");
1010
+	    return;
1011
+	}
1012
+
1013
+	if ((fl = str2facility(facility.s)) == -1) {
1014
+	    rpc->fault(ctx, 500, "facility not found");
1015
+	    return;
1016
+	}
1017
+
1018
+	if(dbg_set_mod_debug_facility(value.s, value.len, &fl) < 0)
1019
+	{
1020
+	    rpc->fault(ctx, 500, "cannot store parameter");
1021
+	    return;
1022
+	}
1023
+	rpc->add(ctx, "s", "200 ok");
1024
+}
1025
+
1026
+/**
1027
+ *
1028
+ */
997 1029
 static const char* dbg_rpc_reset_msgid_doc[2] = {
998 1030
 	"Reset msgid on all process",
999 1031
 	0
... ...
@@ -1032,6 +1064,7 @@ rpc_export_t dbg_rpc[] = {
1032 1032
 	{"dbg.ls",        dbg_rpc_list,      dbg_rpc_list_doc,      0},
1033 1033
 	{"dbg.trace",     dbg_rpc_trace,     dbg_rpc_trace_doc,     0},
1034 1034
 	{"dbg.mod_level", dbg_rpc_mod_level, dbg_rpc_mod_level_doc, 0},
1035
+	{"dbg.mod_facility", dbg_rpc_mod_facility, dbg_rpc_mod_facility_doc, 0},
1035 1036
 	{"dbg.reset_msgid", dbg_rpc_reset_msgid, dbg_rpc_reset_msgid_doc, 0},
1036 1037
 	{0, 0, 0, 0}
1037 1038
 };
... ...
@@ -1056,10 +1089,19 @@ typedef struct _dbg_mod_level {
1056 1056
 	struct _dbg_mod_level *next;
1057 1057
 } dbg_mod_level_t;
1058 1058
 
1059
+typedef struct _dbg_mod_facility {
1060
+	str name;
1061
+	unsigned int hashid;
1062
+	int facility;
1063
+	struct _dbg_mod_facility *next;
1064
+} dbg_mod_facility_t;
1065
+
1059 1066
 typedef struct _dbg_mod_slot
1060 1067
 {
1061 1068
 	dbg_mod_level_t *first;
1062 1069
 	gen_lock_t lock;
1070
+	dbg_mod_facility_t *first_ft;
1071
+	gen_lock_t lock_ft;
1063 1072
 } dbg_mod_slot_t;
1064 1073
 
1065 1074
 static dbg_mod_slot_t *_dbg_mod_table = NULL;
... ...
@@ -1086,13 +1128,15 @@ int dbg_init_mod_levels(int dbg_mod_hash_size)
1086 1086
 
1087 1087
 	for(i=0; i<_dbg_mod_table_size; i++)
1088 1088
 	{
1089
-		if(lock_init(&_dbg_mod_table[i].lock)==0)
1089
+		if(lock_init(&_dbg_mod_table[i].lock)==0 ||
1090
+		   lock_init(&_dbg_mod_table[i].lock_ft)==0)
1090 1091
 		{
1091 1092
 			LM_ERR("cannot initialize lock[%d]\n", i);
1092 1093
 			i--;
1093 1094
 			while(i>=0)
1094 1095
 			{
1095 1096
 				lock_destroy(&_dbg_mod_table[i].lock);
1097
+				lock_destroy(&_dbg_mod_table[i].lock_ft);
1096 1098
 				i--;
1097 1099
 			}
1098 1100
 			shm_free(_dbg_mod_table);
... ...
@@ -1209,6 +1253,82 @@ int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel)
1209 1209
 
1210 1210
 }
1211 1211
 
1212
+int dbg_set_mod_debug_facility(char *mname, int mnlen, int *mfacility)
1213
+{
1214
+	unsigned int idx;
1215
+	unsigned int hid;
1216
+	dbg_mod_facility_t *it;
1217
+	dbg_mod_facility_t *itp;
1218
+	dbg_mod_facility_t *itn;
1219
+
1220
+	if(_dbg_mod_table==NULL)
1221
+		return -1;
1222
+
1223
+	hid = dbg_compute_hash(mname, mnlen);
1224
+	idx = hid&(_dbg_mod_table_size-1);
1225
+
1226
+	lock_get(&_dbg_mod_table[idx].lock_ft);
1227
+	it = _dbg_mod_table[idx].first_ft;
1228
+	itp = NULL;
1229
+	while(it!=NULL && it->hashid < hid) {
1230
+		itp = it;
1231
+		it = it->next;
1232
+	}
1233
+	while(it!=NULL && it->hashid==hid)
1234
+	{
1235
+		if(mnlen==it->name.len
1236
+				&& strncmp(mname, it->name.s, mnlen)==0)
1237
+		{
1238
+			/* found */
1239
+			if(mfacility==NULL) {
1240
+				/* remove */
1241
+				if(itp!=NULL) {
1242
+					itp->next = it->next;
1243
+				} else {
1244
+					_dbg_mod_table[idx].first_ft = it->next;
1245
+				}
1246
+				shm_free(it);
1247
+			} else {
1248
+				/* set */
1249
+				it->facility = *mfacility;
1250
+			}
1251
+			lock_release(&_dbg_mod_table[idx].lock_ft);
1252
+			return 0;
1253
+		}
1254
+		itp = it;
1255
+		it = it->next;
1256
+	}
1257
+	/* not found - add */
1258
+	if(mfacility==NULL) {
1259
+		lock_release(&_dbg_mod_table[idx].lock_ft);
1260
+		return 0;
1261
+	}
1262
+	itn = (dbg_mod_facility_t*)shm_malloc(sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char));
1263
+	if(itn==NULL) {
1264
+		LM_ERR("no more shm\n");
1265
+		lock_release(&_dbg_mod_table[idx].lock_ft);
1266
+		return -1;
1267
+	}
1268
+	memset(itn, 0, sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char));
1269
+	itn->facility = *mfacility;
1270
+	itn->hashid   = hid;
1271
+	itn->name.s   = (char*)(itn) + sizeof(dbg_mod_facility_t);
1272
+	itn->name.len = mnlen;
1273
+	strncpy(itn->name.s, mname, mnlen);
1274
+	itn->name.s[itn->name.len] = '\0';
1275
+
1276
+	if(itp==NULL) {
1277
+		itn->next = _dbg_mod_table[idx].first_ft;
1278
+		_dbg_mod_table[idx].first_ft = itn;
1279
+	} else {
1280
+		itn->next = itp->next;
1281
+		itp->next = itn;
1282
+	}
1283
+	lock_release(&_dbg_mod_table[idx].lock_ft);
1284
+	return 0;
1285
+
1286
+}
1287
+
1212 1288
 static int _dbg_get_mod_debug_level = 0;
1213 1289
 int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
1214 1290
 {
... ...
@@ -1252,6 +1372,49 @@ int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
1252 1252
 	return -1;
1253 1253
 }
1254 1254
 
1255
+static int _dbg_get_mod_debug_facility = 0;
1256
+int dbg_get_mod_debug_facility(char *mname, int mnlen, int *mfacility)
1257
+{
1258
+	unsigned int idx;
1259
+	unsigned int hid;
1260
+	dbg_mod_facility_t *it;
1261
+	/* no LOG*() usage in this function and those executed insite it
1262
+	 * - use fprintf(stderr, ...) if need for troubleshooting
1263
+	 * - it will loop otherwise */
1264
+	if(_dbg_mod_table==NULL)
1265
+		return -1;
1266
+
1267
+	if(cfg_get(dbg, dbg_cfg, mod_facility_mode)==0)
1268
+		return -1;
1269
+
1270
+	if(_dbg_get_mod_debug_facility!=0)
1271
+		return -1;
1272
+	_dbg_get_mod_debug_facility = 1;
1273
+
1274
+	hid = dbg_compute_hash(mname, mnlen);
1275
+	idx = hid&(_dbg_mod_table_size-1);
1276
+	lock_get(&_dbg_mod_table[idx].lock_ft);
1277
+	it = _dbg_mod_table[idx].first_ft;
1278
+	while(it!=NULL && it->hashid < hid)
1279
+		it = it->next;
1280
+	while(it!=NULL && it->hashid == hid)
1281
+	{
1282
+		if(mnlen==it->name.len
1283
+				&& strncmp(mname, it->name.s, mnlen)==0)
1284
+		{
1285
+			/* found */
1286
+			*mfacility = it->facility;
1287
+		    lock_release(&_dbg_mod_table[idx].lock_ft);
1288
+			_dbg_get_mod_debug_facility = 0;
1289
+			return 0;
1290
+		}
1291
+		it = it->next;
1292
+	}
1293
+	lock_release(&_dbg_mod_table[idx].lock_ft);
1294
+	_dbg_get_mod_debug_facility = 0;
1295
+	return -1;
1296
+}
1297
+
1255 1298
 /**
1256 1299
  *
1257 1300
  */
... ...
@@ -1262,6 +1425,13 @@ void dbg_enable_mod_levels(void)
1262 1262
 	set_module_debug_level_cb(dbg_get_mod_debug_level);
1263 1263
 }
1264 1264
 
1265
+void dbg_enable_mod_facilities(void)
1266
+{
1267
+	if(_dbg_mod_table==NULL)
1268
+		return;
1269
+	set_module_debug_facility_cb(dbg_get_mod_debug_facility);
1270
+}
1271
+
1265 1272
 #define DBG_PVCACHE_SIZE 32
1266 1273
 
1267 1274
 typedef struct _dbg_pvcache {
... ...
@@ -1423,7 +1593,7 @@ void dbg_enable_log_assign(void)
1423 1423
 	set_log_assign_action_cb(dbg_log_assign);
1424 1424
 }
1425 1425
 
1426
-int dbg_level_mode_fixup(void *temp_handle,
1426
+int dbg_mode_fixup(void *temp_handle,
1427 1427
 	str *group_name, str *var_name, void **value){
1428 1428
 	if(_dbg_mod_table==NULL)
1429 1429
 	{
... ...
@@ -35,7 +35,9 @@ int dbg_init_rpc(void);
35 35
 
36 36
 int dbg_init_mod_levels(int _dbg_mod_hash_size);
37 37
 int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel);
38
+int dbg_set_mod_debug_facility(char *mname, int mnlen, int *mfacility);
38 39
 void dbg_enable_mod_levels(void);
40
+void dbg_enable_mod_facilities(void);
39 41
 
40 42
 int dbg_init_pvcache(void);
41 43
 void dbg_enable_log_assign(void);
... ...
@@ -32,6 +32,7 @@
32 32
 
33 33
 struct cfg_group_dbg	default_dbg_cfg = {
34 34
 	0, /* level_mode */
35
+	0, /* facility_mode */
35 36
 	0  /* hash_size */
36 37
 };
37 38
 
... ...
@@ -39,8 +40,11 @@ void *dbg_cfg = &default_dbg_cfg;
39 39
 
40 40
 cfg_def_t dbg_cfg_def[] = {
41 41
 	{"mod_level_mode", CFG_VAR_INT|CFG_ATOMIC, 0, 1,
42
-		dbg_level_mode_fixup, 0,
42
+		dbg_mode_fixup, 0,
43 43
 		"Enable or disable per module log level (0 - disabled, 1 - enabled)"},
44
+	{"mod_facility_mode", CFG_VAR_INT|CFG_ATOMIC, 0, 1,
45
+		dbg_mode_fixup, 0,
46
+		"Enable or disable per module log facility (0 - disabled, 1 - enabled)"},
44 47
 	{"mod_hash_size", CFG_VAR_INT|CFG_READONLY, 0, 0,
45 48
 		0, 0,
46 49
 		"power of two as size of internal hash table to store levels per module"},
... ...
@@ -34,6 +34,7 @@
34 34
 
35 35
 struct cfg_group_dbg {
36 36
 	unsigned int mod_level_mode;
37
+	unsigned int mod_facility_mode;
37 38
 	unsigned int mod_hash_size;
38 39
 };
39 40
 
... ...
@@ -41,6 +42,6 @@ extern struct cfg_group_dbg	default_dbg_cfg;
41 41
 extern void	*dbg_cfg;
42 42
 extern cfg_def_t dbg_cfg_def[];
43 43
 
44
-extern int dbg_level_mode_fixup(void *temp_handle,
44
+extern int dbg_mode_fixup(void *temp_handle,
45 45
 	str *group_name, str *var_name, void **value);
46 46
 #endif
... ...
@@ -47,6 +47,7 @@ static void mod_destroy(void);
47 47
 static int w_dbg_breakpoint(struct sip_msg* msg, char* point, char* str2);
48 48
 static int fixup_dbg_breakpoint(void** param, int param_no);
49 49
 static int dbg_mod_level_param(modparam_t type, void *val);
50
+static int dbg_mod_facility_param(modparam_t type, void *val);
50 51
 
51 52
 static int fixup_dbg_pv_dump(void** param, int param_no);
52 53
 static int w_dbg_dump(struct sip_msg* msg, char* mask, char* level);
... ...
@@ -91,6 +92,8 @@ static param_export_t params[]={
91 91
 	{"mod_hash_size",     INT_PARAM, &default_dbg_cfg.mod_hash_size},
92 92
 	{"mod_level_mode",    INT_PARAM, &default_dbg_cfg.mod_level_mode},
93 93
 	{"mod_level",         PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_level_param},
94
+	{"mod_facility_mode", INT_PARAM, &default_dbg_cfg.mod_facility_mode},
95
+	{"mod_facility",      PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_facility_param},
94 96
 	{"reset_msgid",       INT_PARAM, &_dbg_reset_msgid},
95 97
 	{"cfgpkgcheck",       INT_PARAM, &_dbg_cfgpkgcheck},
96 98
 	{0, 0, 0}
... ...
@@ -141,8 +144,9 @@ static int mod_init(void)
141 141
 		LM_ERR("Fail to declare the configuration\n");
142 142
 		return -1;
143 143
 	}
144
-	LM_DBG("cfg level_mode:%d hash_size:%d\n",
144
+	LM_DBG("cfg level_mode:%d facility_mode:%d hash_size:%d\n",
145 145
 		cfg_get(dbg, dbg_cfg, mod_level_mode),
146
+		cfg_get(dbg, dbg_cfg, mod_facility_mode),
146 147
 		cfg_get(dbg, dbg_cfg, mod_hash_size));
147 148
 
148 149
 	if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
... ...
@@ -179,6 +183,7 @@ static int child_init(int rank)
179 179
 	LM_DBG("rank is (%d)\n", rank);
180 180
 	if (rank==PROC_INIT) {
181 181
 		dbg_enable_mod_levels();
182
+		dbg_enable_mod_facilities();
182 183
 		dbg_enable_log_assign();
183 184
 		return dbg_init_pid_list();
184 185
 	}
... ...
@@ -328,3 +333,43 @@ static int dbg_mod_level_param(modparam_t type, void *val)
328 328
 
329 329
 }
330 330
 
331
+static int dbg_mod_facility_param(modparam_t type, void *val)
332
+{
333
+	char *p;
334
+	str s;
335
+	int fl;
336
+	if(val==NULL)
337
+		return -1;
338
+
339
+	p = strchr((char*)val, '=');
340
+	if(p==NULL) {
341
+		LM_ERR("invalid parameter value: %s\n", (char*)val);
342
+		return -1;
343
+	}
344
+	s.s = p + 1;
345
+	s.len = strlen(s.s);
346
+
347
+	if ((fl = str2facility(s.s)) == -1) {
348
+		LM_ERR("invalid parameter - facility value: %s\n", (char*)val);
349
+		return -1;
350
+	}
351
+
352
+	s.s = (char*)val;
353
+	s.len = p - s.s;
354
+	LM_DBG("cfg facility_mode:%d hash_size:%d\n",
355
+		cfg_get(dbg, dbg_cfg, mod_facility_mode),
356
+		cfg_get(dbg, dbg_cfg, mod_hash_size));
357
+	if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
358
+	{
359
+		LM_ERR("failed to init per module log level\n");
360
+		return -1;
361
+	}
362
+	if(dbg_set_mod_debug_facility(s.s, s.len, &fl)<0)
363
+	{
364
+		LM_ERR("cannot store parameter: %s\n", (char*)val);
365
+		return -1;
366
+	}
367
+	return 0;
368
+
369
+}
370
+