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 121
 	_module_debug_level = f;
119 122
 }
120 123
 
124
+void set_module_debug_facility_cb(get_module_debug_facility_f f)
125
+{
126
+	_module_debug_facility = f;
127
+}
128
+
121 129
 /**
122 130
  * @brief return the log level - the local one if it set,
123 131
  *   otherwise the global value
124 132
  */
125 133
 int get_debug_level(char *mname, int mnlen) {
126
-	int mlevel = L_DBG;
134
+	int mlevel;
127 135
 	/*important -- no LOGs inside, because it will loop */
128 136
 	if(unlikely(_module_debug_level!=NULL && mnlen>0)) {
129 137
 		if(_module_debug_level(mname, mnlen, &mlevel)==0) {
... ...
@@ -134,6 +142,23 @@ int get_debug_level(char *mname, int mnlen) {
134 142
 				_local_debug_level : cfg_get(core, core_cfg, debug);
135 143
 }
136 144
 
145
+/**
146
+ * @brief return the log facility - the local one if it set,
147
+ *   otherwise the global value
148
+ */
149
+int get_debug_facility(char *mname, int mnlen) {
150
+	int mfacility;
151
+	/*important -- no LOGs inside, because it will loop */
152
+	if(unlikely(_module_debug_facility!=NULL && mnlen>0)) {
153
+		if(_module_debug_facility(mname, mnlen, &mfacility)==0) {
154
+			return mfacility;
155
+		}
156
+	}
157
+	return (_local_debug_facility != UNSET_LOCAL_DEBUG_FACILITY) ?
158
+				_local_debug_facility : cfg_get(core, core_cfg, log_facility);
159
+}
160
+
161
+
137 162
 /**
138 163
  * @brief set the local debug log level
139 164
  */
... ...
@@ -150,6 +175,22 @@ void reset_local_debug_level(void)
150 175
 	_local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
151 176
 }
152 177
 
178
+/**
179
+ * @brief set the local debug log facility
180
+ */
181
+void set_local_debug_facility(int facility)
182
+{
183
+	_local_debug_facility = facility;
184
+}
185
+
186
+/**
187
+ * @brief reset the local debug log facility
188
+ */
189
+void reset_local_debug_facility(void)
190
+{
191
+	_local_debug_facility = UNSET_LOCAL_DEBUG_FACILITY;
192
+}
193
+
153 194
 typedef struct log_level_color {
154 195
 	char f;
155 196
 	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 146
 
142 147
 #ifndef NO_SIG_DEBUG
143 148
 /** @brief protection against "simultaneous" printing from signal handlers */
144
-extern volatile int dprint_crit; 
149
+extern volatile int dprint_crit;
145 150
 #endif
146 151
 
147 152
 int str2facility(char *s);
... ...
@@ -210,7 +215,7 @@ void log_prefix_init(void);
210 215
 							syslog(LOG2SYSLOG_LEVEL(level) | \
211 216
 								   (((facility) != DEFAULT_FACILITY) ? \
212 217
 									(facility) : \
213
-									cfg_get(core, core_cfg, log_facility)), \
218
+								    get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
214 219
 									"%s: %s" fmt, \
215 220
 									(lname)?(lname):LOG_LEVEL2NAME(level),\
216 221
 									(prefix), __VA_ARGS__); \
... ...
@@ -227,13 +232,13 @@ void log_prefix_init(void);
227 232
 								syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
228 233
 									   (((facility) != DEFAULT_FACILITY) ? \
229 234
 										(facility) : \
230
-										cfg_get(core, core_cfg, log_facility)),\
235
+								        get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
231 236
 									   "%s" fmt, (prefix), __VA_ARGS__); \
232 237
 							else \
233 238
 								syslog(LOG2SYSLOG_LEVEL(L_DBG) | \
234 239
 									   (((facility) != DEFAULT_FACILITY) ? \
235 240
 										(facility) : \
236
-										cfg_get(core, core_cfg, log_facility)),\
241
+								        get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
237 242
 									   "%s" fmt, (prefix), __VA_ARGS__); \
238 243
 						} \
239 244
 					} \
... ...
@@ -298,7 +303,7 @@ void log_prefix_init(void);
298 303
 							syslog(LOG2SYSLOG_LEVEL(__llevel) |\
299 304
 							   (((facility) != DEFAULT_FACILITY) ? \
300 305
 								(facility) : \
301
-								cfg_get(core, core_cfg, log_facility)), \
306
+								get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
302 307
 								"%.*s%s: %s" fmt,\
303 308
 								log_prefix_val->len, log_prefix_val->s, \
304 309
 								(lname)?(lname):LOG_LEVEL2NAME(__llevel),\
... ...
@@ -307,7 +312,7 @@ void log_prefix_init(void);
307 312
 							syslog(LOG2SYSLOG_LEVEL(__llevel) |\
308 313
 							   (((facility) != DEFAULT_FACILITY) ? \
309 314
 								(facility) : \
310
-								cfg_get(core, core_cfg, log_facility)), \
315
+								get_debug_facility(LOG_MNAME, LOG_MNAME_LEN)), \
311 316
 								"%s: %s" fmt,\
312 317
 								(lname)?(lname):LOG_LEVEL2NAME(__llevel),\
313 318
 								(prefix) , ## args); \
... ...
@@ -985,12 +985,44 @@ 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");
992 992
 }
993 993
 
994
+/**
995
+ *
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
+
994 1026
 /**
995 1027
  *
996 1028
  */
... ...
@@ -1032,6 +1064,7 @@ rpc_export_t dbg_rpc[] = {
1032 1064
 	{"dbg.ls",        dbg_rpc_list,      dbg_rpc_list_doc,      0},
1033 1065
 	{"dbg.trace",     dbg_rpc_trace,     dbg_rpc_trace_doc,     0},
1034 1066
 	{"dbg.mod_level", dbg_rpc_mod_level, dbg_rpc_mod_level_doc, 0},
1067
+	{"dbg.mod_facility", dbg_rpc_mod_facility, dbg_rpc_mod_facility_doc, 0},
1035 1068
 	{"dbg.reset_msgid", dbg_rpc_reset_msgid, dbg_rpc_reset_msgid_doc, 0},
1036 1069
 	{0, 0, 0, 0}
1037 1070
 };
... ...
@@ -1056,10 +1089,19 @@ typedef struct _dbg_mod_level {
1056 1089
 	struct _dbg_mod_level *next;
1057 1090
 } dbg_mod_level_t;
1058 1091
 
1092
+typedef struct _dbg_mod_facility {
1093
+	str name;
1094
+	unsigned int hashid;
1095
+	int facility;
1096
+	struct _dbg_mod_facility *next;
1097
+} dbg_mod_facility_t;
1098
+
1059 1099
 typedef struct _dbg_mod_slot
1060 1100
 {
1061 1101
 	dbg_mod_level_t *first;
1062 1102
 	gen_lock_t lock;
1103
+	dbg_mod_facility_t *first_ft;
1104
+	gen_lock_t lock_ft;
1063 1105
 } dbg_mod_slot_t;
1064 1106
 
1065 1107
 static dbg_mod_slot_t *_dbg_mod_table = NULL;
... ...
@@ -1086,13 +1128,15 @@ int dbg_init_mod_levels(int dbg_mod_hash_size)
1086 1128
 
1087 1129
 	for(i=0; i<_dbg_mod_table_size; i++)
1088 1130
 	{
1089
-		if(lock_init(&_dbg_mod_table[i].lock)==0)
1131
+		if(lock_init(&_dbg_mod_table[i].lock)==0 ||
1132
+		   lock_init(&_dbg_mod_table[i].lock_ft)==0)
1090 1133
 		{
1091 1134
 			LM_ERR("cannot initialize lock[%d]\n", i);
1092 1135
 			i--;
1093 1136
 			while(i>=0)
1094 1137
 			{
1095 1138
 				lock_destroy(&_dbg_mod_table[i].lock);
1139
+				lock_destroy(&_dbg_mod_table[i].lock_ft);
1096 1140
 				i--;
1097 1141
 			}
1098 1142
 			shm_free(_dbg_mod_table);
... ...
@@ -1209,6 +1253,82 @@ int dbg_set_mod_debug_level(char *mname, int mnlen, int *mlevel)
1209 1253
 
1210 1254
 }
1211 1255
 
1256
+int dbg_set_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
+	dbg_mod_facility_t *itp;
1262
+	dbg_mod_facility_t *itn;
1263
+
1264
+	if(_dbg_mod_table==NULL)
1265
+		return -1;
1266
+
1267
+	hid = dbg_compute_hash(mname, mnlen);
1268
+	idx = hid&(_dbg_mod_table_size-1);
1269
+
1270
+	lock_get(&_dbg_mod_table[idx].lock_ft);
1271
+	it = _dbg_mod_table[idx].first_ft;
1272
+	itp = NULL;
1273
+	while(it!=NULL && it->hashid < hid) {
1274
+		itp = it;
1275
+		it = it->next;
1276
+	}
1277
+	while(it!=NULL && it->hashid==hid)
1278
+	{
1279
+		if(mnlen==it->name.len
1280
+				&& strncmp(mname, it->name.s, mnlen)==0)
1281
+		{
1282
+			/* found */
1283
+			if(mfacility==NULL) {
1284
+				/* remove */
1285
+				if(itp!=NULL) {
1286
+					itp->next = it->next;
1287
+				} else {
1288
+					_dbg_mod_table[idx].first_ft = it->next;
1289
+				}
1290
+				shm_free(it);
1291
+			} else {
1292
+				/* set */
1293
+				it->facility = *mfacility;
1294
+			}
1295
+			lock_release(&_dbg_mod_table[idx].lock_ft);
1296
+			return 0;
1297
+		}
1298
+		itp = it;
1299
+		it = it->next;
1300
+	}
1301
+	/* not found - add */
1302
+	if(mfacility==NULL) {
1303
+		lock_release(&_dbg_mod_table[idx].lock_ft);
1304
+		return 0;
1305
+	}
1306
+	itn = (dbg_mod_facility_t*)shm_malloc(sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char));
1307
+	if(itn==NULL) {
1308
+		LM_ERR("no more shm\n");
1309
+		lock_release(&_dbg_mod_table[idx].lock_ft);
1310
+		return -1;
1311
+	}
1312
+	memset(itn, 0, sizeof(dbg_mod_facility_t) + (mnlen+1)*sizeof(char));
1313
+	itn->facility = *mfacility;
1314
+	itn->hashid   = hid;
1315
+	itn->name.s   = (char*)(itn) + sizeof(dbg_mod_facility_t);
1316
+	itn->name.len = mnlen;
1317
+	strncpy(itn->name.s, mname, mnlen);
1318
+	itn->name.s[itn->name.len] = '\0';
1319
+
1320
+	if(itp==NULL) {
1321
+		itn->next = _dbg_mod_table[idx].first_ft;
1322
+		_dbg_mod_table[idx].first_ft = itn;
1323
+	} else {
1324
+		itn->next = itp->next;
1325
+		itp->next = itn;
1326
+	}
1327
+	lock_release(&_dbg_mod_table[idx].lock_ft);
1328
+	return 0;
1329
+
1330
+}
1331
+
1212 1332
 static int _dbg_get_mod_debug_level = 0;
1213 1333
 int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
1214 1334
 {
... ...
@@ -1252,6 +1372,49 @@ int dbg_get_mod_debug_level(char *mname, int mnlen, int *mlevel)
1252 1372
 	return -1;
1253 1373
 }
1254 1374
 
1375
+static int _dbg_get_mod_debug_facility = 0;
1376
+int dbg_get_mod_debug_facility(char *mname, int mnlen, int *mfacility)
1377
+{
1378
+	unsigned int idx;
1379
+	unsigned int hid;
1380
+	dbg_mod_facility_t *it;
1381
+	/* no LOG*() usage in this function and those executed insite it
1382
+	 * - use fprintf(stderr, ...) if need for troubleshooting
1383
+	 * - it will loop otherwise */
1384
+	if(_dbg_mod_table==NULL)
1385
+		return -1;
1386
+
1387
+	if(cfg_get(dbg, dbg_cfg, mod_facility_mode)==0)
1388
+		return -1;
1389
+
1390
+	if(_dbg_get_mod_debug_facility!=0)
1391
+		return -1;
1392
+	_dbg_get_mod_debug_facility = 1;
1393
+
1394
+	hid = dbg_compute_hash(mname, mnlen);
1395
+	idx = hid&(_dbg_mod_table_size-1);
1396
+	lock_get(&_dbg_mod_table[idx].lock_ft);
1397
+	it = _dbg_mod_table[idx].first_ft;
1398
+	while(it!=NULL && it->hashid < hid)
1399
+		it = it->next;
1400
+	while(it!=NULL && it->hashid == hid)
1401
+	{
1402
+		if(mnlen==it->name.len
1403
+				&& strncmp(mname, it->name.s, mnlen)==0)
1404
+		{
1405
+			/* found */
1406
+			*mfacility = it->facility;
1407
+		    lock_release(&_dbg_mod_table[idx].lock_ft);
1408
+			_dbg_get_mod_debug_facility = 0;
1409
+			return 0;
1410
+		}
1411
+		it = it->next;
1412
+	}
1413
+	lock_release(&_dbg_mod_table[idx].lock_ft);
1414
+	_dbg_get_mod_debug_facility = 0;
1415
+	return -1;
1416
+}
1417
+
1255 1418
 /**
1256 1419
  *
1257 1420
  */
... ...
@@ -1262,6 +1425,13 @@ void dbg_enable_mod_levels(void)
1262 1425
 	set_module_debug_level_cb(dbg_get_mod_debug_level);
1263 1426
 }
1264 1427
 
1428
+void dbg_enable_mod_facilities(void)
1429
+{
1430
+	if(_dbg_mod_table==NULL)
1431
+		return;
1432
+	set_module_debug_facility_cb(dbg_get_mod_debug_facility);
1433
+}
1434
+
1265 1435
 #define DBG_PVCACHE_SIZE 32
1266 1436
 
1267 1437
 typedef struct _dbg_pvcache {
... ...
@@ -1423,7 +1593,7 @@ void dbg_enable_log_assign(void)
1423 1593
 	set_log_assign_action_cb(dbg_log_assign);
1424 1594
 }
1425 1595
 
1426
-int dbg_level_mode_fixup(void *temp_handle,
1596
+int dbg_mode_fixup(void *temp_handle,
1427 1597
 	str *group_name, str *var_name, void **value){
1428 1598
 	if(_dbg_mod_table==NULL)
1429 1599
 	{
... ...
@@ -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 40
 
40 41
 cfg_def_t dbg_cfg_def[] = {
41 42
 	{"mod_level_mode", CFG_VAR_INT|CFG_ATOMIC, 0, 1,
42
-		dbg_level_mode_fixup, 0,
43
+		dbg_mode_fixup, 0,
43 44
 		"Enable or disable per module log level (0 - disabled, 1 - enabled)"},
45
+	{"mod_facility_mode", CFG_VAR_INT|CFG_ATOMIC, 0, 1,
46
+		dbg_mode_fixup, 0,
47
+		"Enable or disable per module log facility (0 - disabled, 1 - enabled)"},
44 48
 	{"mod_hash_size", CFG_VAR_INT|CFG_READONLY, 0, 0,
45 49
 		0, 0,
46 50
 		"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 42
 extern void	*dbg_cfg;
42 43
 extern cfg_def_t dbg_cfg_def[];
43 44
 
44
-extern int dbg_level_mode_fixup(void *temp_handle,
45
+extern int dbg_mode_fixup(void *temp_handle,
45 46
 	str *group_name, str *var_name, void **value);
46 47
 #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 92
 	{"mod_hash_size",     INT_PARAM, &default_dbg_cfg.mod_hash_size},
92 93
 	{"mod_level_mode",    INT_PARAM, &default_dbg_cfg.mod_level_mode},
93 94
 	{"mod_level",         PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_level_param},
95
+	{"mod_facility_mode", INT_PARAM, &default_dbg_cfg.mod_facility_mode},
96
+	{"mod_facility",      PARAM_STRING|USE_FUNC_PARAM, (void*)dbg_mod_facility_param},
94 97
 	{"reset_msgid",       INT_PARAM, &_dbg_reset_msgid},
95 98
 	{"cfgpkgcheck",       INT_PARAM, &_dbg_cfgpkgcheck},
96 99
 	{0, 0, 0}
... ...
@@ -141,8 +144,9 @@ static int mod_init(void)
141 144
 		LM_ERR("Fail to declare the configuration\n");
142 145
 		return -1;
143 146
 	}
144
-	LM_DBG("cfg level_mode:%d hash_size:%d\n",
147
+	LM_DBG("cfg level_mode:%d facility_mode:%d hash_size:%d\n",
145 148
 		cfg_get(dbg, dbg_cfg, mod_level_mode),
149
+		cfg_get(dbg, dbg_cfg, mod_facility_mode),
146 150
 		cfg_get(dbg, dbg_cfg, mod_hash_size));
147 151
 
148 152
 	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 183
 	LM_DBG("rank is (%d)\n", rank);
180 184
 	if (rank==PROC_INIT) {
181 185
 		dbg_enable_mod_levels();
186
+		dbg_enable_mod_facilities();
182 187
 		dbg_enable_log_assign();
183 188
 		return dbg_init_pid_list();
184 189
 	}
... ...
@@ -328,3 +333,43 @@ static int dbg_mod_level_param(modparam_t type, void *val)
328 333
 
329 334
 }
330 335
 
336
+static int dbg_mod_facility_param(modparam_t type, void *val)
337
+{
338
+	char *p;
339
+	str s;
340
+	int fl;
341
+	if(val==NULL)
342
+		return -1;
343
+
344
+	p = strchr((char*)val, '=');
345
+	if(p==NULL) {
346
+		LM_ERR("invalid parameter value: %s\n", (char*)val);
347
+		return -1;
348
+	}
349
+	s.s = p + 1;
350
+	s.len = strlen(s.s);
351
+
352
+	if ((fl = str2facility(s.s)) == -1) {
353
+		LM_ERR("invalid parameter - facility value: %s\n", (char*)val);
354
+		return -1;
355
+	}
356
+
357
+	s.s = (char*)val;
358
+	s.len = p - s.s;
359
+	LM_DBG("cfg facility_mode:%d hash_size:%d\n",
360
+		cfg_get(dbg, dbg_cfg, mod_facility_mode),
361
+		cfg_get(dbg, dbg_cfg, mod_hash_size));
362
+	if(dbg_init_mod_levels(cfg_get(dbg, dbg_cfg, mod_hash_size))<0)
363
+	{
364
+		LM_ERR("failed to init per module log level\n");
365
+		return -1;
366
+	}
367
+	if(dbg_set_mod_debug_facility(s.s, s.len, &fl)<0)
368
+	{
369
+		LM_ERR("cannot store parameter: %s\n", (char*)val);
370
+		return -1;
371
+	}
372
+	return 0;
373
+
374
+}
375
+