Hello
I am working on a patch that increases the verbosity of the modules/debugger module . What I am doing is very simple, but in my opinion effective : I am also printing the action being run, not just the type(in the new descr field)
Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=30 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=28 descr= external_module_call(f_ptr<0xb7d4dbf8>, 5, type<10>);
First off all the trace is not very informative because I don't have that of a good example but you get the point.
I know it would be easy to read the cfg and get the line number, but what if you have multiple commands per line. And printing the action type for me is not really usefull (need to get back to header to check the action type).
What do you think, it will be usefull as such? The patch(still some lines to go) if fairly big but fullproof (the print_action() print_expression() in route_struct.c will output data in a static buffer instead of calling DBG()).
Cheers
Marius
Hello (replying on myself)
Sorry for the broken output
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456785@127.0.0.1:10000");
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=33 a=17 descr=if (type<22>) {} else {};
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=30 a=25 descr= external_module_call(f_ptr<0xb7dfc13c>, 0);
I will also check to see why the first line has no config file or line info...
Marius
marius zbihlei wrote:
Hello
I am working on a patch that increases the verbosity of the modules/debugger module . What I am doing is very simple, but in my opinion effective : I am also printing the action being run, not just the type(in the new descr field)
Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=30 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=28 descr= external_module_call(f_ptr<0xb7d4dbf8>, 5, type<10>);
First off all the trace is not very informative because I don't have that of a good example but you get the point.
I know it would be easy to read the cfg and get the line number, but what if you have multiple commands per line. And printing the action type for me is not really usefull (need to get back to header to check the action type).
What do you think, it will be usefull as such? The patch(still some lines to go) if fairly big but fullproof (the print_action() print_expression() in route_struct.c will output data in a static buffer instead of calling DBG()).
Cheers
Marius
Hello,
On 2/9/10 4:00 PM, marius zbihlei wrote:
Hello (replying on myself)
Sorry for the broken output
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456785@127.0.0.1:10000"); Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=33 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=30 a=25 descr= external_module_call(f_ptr<0xb7dfc13c>, 0);
I will also check to see why the first line has no config file or line info...
it is in my roadmap to make it more verbose, but if you can do it is better :-) (so I can say was in my roadmap).
The name of the action is in the structure if it is a module function, for the core functions and statements (if, while, ...) I was thinking on having a mapping table (type, name).
Another idea was to open the cfg, read the respective line and print it next. But would be quite i/o intesive...
When you have the patch ready, send it over. I will look over it and if ok I will tell you to commit.
Thanks, Daniel
Marius
marius zbihlei wrote:
Hello
I am working on a patch that increases the verbosity of the modules/debugger module . What I am doing is very simple, but in my opinion effective : I am also printing the action being run, not just the type(in the new descr field)
Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=30 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32588]: ERROR: *** cfgtrace: c=[../unit/30.cfg] l=26 a=28 descr= external_module_call(f_ptr<0xb7d4dbf8>, 5, type<10>);
First off all the trace is not very informative because I don't have that of a good example but you get the point.
I know it would be easy to read the cfg and get the line number, but what if you have multiple commands per line. And printing the action type for me is not really usefull (need to get back to header to check the action type).
What do you think, it will be usefull as such? The patch(still some lines to go) if fairly big but fullproof (the print_action() print_expression() in route_struct.c will output data in a static buffer instead of calling DBG()).
Cheers
Marius
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Daniel-Constantin Mierla wrote:
Hello,
On 2/9/10 4:00 PM, marius zbihlei wrote:
Hello (replying on myself)
Sorry for the broken output
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456785@127.0.0.1:10000"); Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=33 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=30 a=25 descr= external_module_call(f_ptr<0xb7dfc13c>, 0);
I will also check to see why the first line has no config file or line info...
it is in my roadmap to make it more verbose, but if you can do it is better :-) (so I can say was in my roadmap).
The name of the action is in the structure if it is a module function, for the core functions and statements (if, while, ...) I was thinking on having a mapping table (type, name).
Another idea was to open the cfg, read the respective line and print it next. But would be quite i/o intesive...
When you have the patch ready, send it over. I will look over it and if ok I will tell you to commit.
Thanks, Daniel
Hello Daniel,
I have attacked a patch that enables print_action like printing of module functions, core function and statements . It is usefull if the action line is no longer that 512 characters(it truncates at 512 .. still to test)
The module export is printed like this (call to t_relay) cfgtrace: c=[/home/marius/dev/sip-router/test/unit/30.cfg] l=30 a=25 descr=external_module_call(t_relay)(f_ptr<0xb7ee815c>, 0);
I also liked the file read solution but strangely for some action the file is NULL (*** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456787@127.0.0.1:8000"); )
BTW it is normal for a line like xlog(...) to appear as an action: cfgtrace: c=[/home/marius/dev/sip-router/test/unit/30.cfg] l=30 a=17 descr=if (type<22>external_module_call(xlog)(f_ptr<0xb8062898>, 2, type<10>); drop(1, 1); } else {}; ?
The patch is a little on the long side, and a bit intrusive to my liking , it you have other suggestion please let me now.
Cheers Marius
diff --git a/modules/debugger/debugger_api.c b/modules/debugger/debugger_api.c index 12dc872..eaf19a6 100644 --- a/modules/debugger/debugger_api.c +++ b/modules/debugger/debugger_api.c @@ -140,6 +140,7 @@ typedef struct _dbg_bp */ static dbg_bp_t *_dbg_bp_list = NULL;
+ /** * callback executed for each cfg action */ @@ -151,9 +152,9 @@ int dbg_cfg_trace(void *data) int olen; str pvn; pv_spec_t pvs; - pv_value_t val; + pv_value_t val; void **srevp; - + char *p; srevp = (void**)data;
a = (struct action *)srevp[0]; @@ -166,11 +167,20 @@ int dbg_cfg_trace(void *data) { if(is_printable(_dbg_cfgtrace_level)) { - LOG_(_dbg_cfgtrace_facility, _dbg_cfgtrace_level, + p = print_action_str(a, 1); + if(p){ + LOG_(_dbg_cfgtrace_facility, _dbg_cfgtrace_level, _dbg_cfgtrace_prefix, - " c=[%s] l=%d a=%d\n", - a->cfile, a->cline, a->type - ); + " c=[%s] l=%d a=%d descr=%s\n", + a->cfile, a->cline, a->type, p); + pkg_free(p); + } + else{ + LOG_(_dbg_cfgtrace_facility, _dbg_cfgtrace_level, + _dbg_cfgtrace_prefix, + " c=[%s] l=%d a=%d \n", + a->cfile, a->cline, a->type ); + } } } if(!(_dbg_pid_list[process_no].set&DBG_ABKPOINT_ON)) diff --git a/route_struct.c b/route_struct.c index 85ebcc5..6d94131 100644 --- a/route_struct.c +++ b/route_struct.c @@ -187,120 +187,148 @@ struct action* append_action(struct action* a, struct action* b) return a; }
+#define BLEN 512
- -void print_expr(struct expr* exp) +char* print_expr_str(struct expr* exp, int no_print) { + + char *p, *tmp; + int len; + char *aux = pkg_malloc(512*sizeof(char)); + if(!aux){ + LOG(L_ERR, "Could not allocate memory\n"); + return 0; + } + tmp = aux; if (exp==0){ - LOG(L_CRIT, "ERROR: print_expr: null expression!\n"); - return; + LOG(L_CRIT, "ERROR: print_expr_str: null expression!\n"); + goto error; } if (exp->type==ELEM_T){ switch(exp->l_type){ case METHOD_O: - DBG("method"); + snprintf(tmp, BLEN, "method"); break; case URI_O: - DBG("uri"); + snprintf(tmp, BLEN, "uri"); break; case FROM_URI_O: - DBG("from_uri"); + snprintf(tmp, BLEN, "from_uri"); break; case TO_URI_O: - DBG("to_uri"); + snprintf(tmp, BLEN, "to_uri"); break; case SRCIP_O: - DBG("srcip"); + snprintf(tmp, BLEN, "srcip"); break; case SRCPORT_O: - DBG("srcport"); + snprintf(tmp, BLEN, "srcport"); break; case DSTIP_O: - DBG("dstip"); + snprintf(tmp, BLEN, "dstip"); break; case DSTPORT_O: - DBG("dstport"); + snprintf(tmp, BLEN, "dstport"); break; case PROTO_O: - DBG("proto"); + snprintf(tmp, BLEN, "proto"); break; case AF_O: - DBG("af"); + snprintf(tmp, BLEN, "af"); break; case MSGLEN_O: - DBG("msglen"); + snprintf(tmp, BLEN, "msglen"); break; case ACTION_O: break; case NUMBER_O: break; case AVP_O: - DBG("avp"); + snprintf(tmp, BLEN, "avp"); break; case SNDIP_O: - DBG("sndip"); + snprintf(tmp, BLEN, "sndip"); break; case SNDPORT_O: - DBG("sndport"); + snprintf(tmp, BLEN, "sndport"); break; case TOIP_O: - DBG("toip"); + snprintf(tmp, BLEN, "toip"); break; case TOPORT_O: - DBG("toport"); + snprintf(tmp, BLEN, "toport"); break; case SNDPROTO_O: - DBG("sndproto"); + snprintf(tmp, BLEN, "sndproto"); break; case SNDAF_O: - DBG("sndaf"); + snprintf(tmp, BLEN, "sndaf"); break; case RETCODE_O: - DBG("retcode"); + snprintf(tmp, BLEN, "retcode"); break; case SELECT_O: - DBG("select"); + snprintf(tmp, BLEN, "select"); break; case RVEXP_O: - DBG("rval"); + snprintf(tmp, BLEN, "rval"); break;
default: - DBG("UNKNOWN"); + snprintf(tmp, BLEN, "UNKNOWN"); + } + + if(no_print){ + len = strlen(aux); + tmp = aux + strlen(aux); + } + else{ + len = 0; + DBG("%s", aux); + tmp = aux; } switch(exp->op){ case EQUAL_OP: - DBG("=="); + snprintf(tmp, BLEN - len, "=="); break; case MATCH_OP: - DBG("=~"); + snprintf(tmp, BLEN - len, "=~"); break; case NO_OP: break; case GT_OP: - DBG(">"); + snprintf(tmp, BLEN - len, ">"); break; case GTE_OP: - DBG(">="); + snprintf(tmp, BLEN - len, ">="); break; case LT_OP: - DBG("<"); + snprintf(tmp, BLEN - len, "<"); break; case LTE_OP: - DBG("<="); + snprintf(tmp, BLEN - len, "<="); break; case DIFF_OP: - DBG("!="); + snprintf(tmp, BLEN - len, "!="); break; default: - DBG("<UNKNOWN>"); + snprintf(tmp, BLEN - len, "<UNKNOWN>"); + } + + if(no_print){ + len = strlen(aux); + tmp = aux + len; + }else{ + DBG("%s", aux); + len = 0; + tmp = aux; } switch(exp->r_type){ case NOSUBTYPE: - DBG("N/A"); + snprintf(tmp, BLEN - len, "N/A"); break; case STRING_ST: - DBG(""%s"", ZSW((char*)exp->r.param)); + snprintf(tmp, BLEN - len, ""%s"", ZSW((char*)exp->r.param)); break; case NET_ST: print_net((struct net*)exp->r.param); @@ -309,139 +337,208 @@ void print_expr(struct expr* exp) print_ip("", (struct ip_addr*)exp->r.param, ""); break; case ACTIONS_ST: - print_actions((struct action*)exp->r.param); + p = print_actions_str((struct action*)exp->r.param, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break; case NUMBER_ST: - DBG("%ld",exp->r.numval); + snprintf(tmp, BLEN - len, "%ld",exp->r.numval); break; case MYSELF_ST: - DBG("_myself_"); + snprintf(tmp, BLEN - len, "_myself_"); break; case AVP_ST: - DBG("attr"); + snprintf(tmp, BLEN - len, "attr"); break; case SELECT_ST: - DBG("select"); + snprintf(tmp, BLEN - len, "select"); break; default: - DBG("type<%d>", exp->r_type); + snprintf(tmp, BLEN - len, "type<%d>", exp->r_type); + } + + if(no_print){ + len = strlen(aux); + tmp = aux + len; + }else{ + DBG("%s", aux); + len = 0; + tmp = aux; } }else if (exp->type==EXP_T){ switch(exp->op){ case LOGAND_OP: - DBG("AND( "); - print_expr(exp->l.expr); - DBG(", "); - print_expr(exp->r.expr); - DBG(" )"); + snprintf(tmp, BLEN, "AND( "); + p = print_expr_str(exp->l.expr, no_print); + if(p){ + snprintf(tmp, BLEN - strlen(tmp), "%s", p); + pkg_free(p); + }else goto error; + snprintf(tmp, BLEN, ", "); + p = print_expr_str(exp->r.expr, no_print); + if(p){ + snprintf(tmp, BLEN - strlen(tmp), "%s", p); + pkg_free(p); + }else goto error; + snprintf(tmp, BLEN - strlen(tmp), " )"); break; case LOGOR_OP: - DBG("OR( "); - print_expr(exp->l.expr); - DBG(", "); - print_expr(exp->r.expr); - DBG(" )"); + snprintf(tmp, BLEN, "OR( "); + p = print_expr_str(exp->l.expr, no_print); + if(p){ + snprintf(tmp, BLEN - strlen(tmp), "%s", p); + pkg_free(p); + }else goto error; + snprintf(tmp, BLEN - strlen(tmp), ", "); + p = print_expr_str(exp->r.expr, no_print); + if(p){ + snprintf(tmp, BLEN - strlen(tmp), "%s", p); + pkg_free(p); + }else goto error; + snprintf(tmp, BLEN-strlen(tmp), " )"); break; case NOT_OP: - DBG("NOT( "); - print_expr(exp->l.expr); - DBG(" )"); + snprintf(tmp, BLEN, "NOT( "); + p = print_expr_str(exp->l.expr, no_print); + if(p){ + snprintf(tmp, BLEN - strlen(tmp), "%s", p); + pkg_free(p); + }else goto error; + snprintf(tmp, BLEN - strlen(tmp), " )"); break; default: - DBG("UNKNOWN_EXP "); + snprintf(tmp, BLEN, "UNKNOWN_EXP "); + } + if(no_print) + tmp = aux + strlen(aux); + else{ + DBG("%s", aux); + tmp = aux; }
}else{ - DBG("ERROR:print_expr: unknown type\n"); + snprintf(tmp, BLEN, "ERROR:print_expr: unknown type\n"); + if(no_print) + tmp = aux + strlen(aux); + else{ + DBG("%s", aux); + tmp = aux; + } } + return aux; +error: + pkg_free(aux); + return 0; }
+void print_expr(struct expr* expr) +{ + /* some compilers might complain that result from function is not used */ + if(print_expr_str(expr, 0)); +} +void print_action(struct action* t) +{ + if(print_action_str(t, 0)); +}
+void print_actions(struct action* t) +{ + if(print_actions_str(t, 0)); +}
- -void print_action(struct action* t) +char* print_action_str(struct action* t, int no_print) { + char *aux = pkg_malloc(sizeof(char) * BLEN); + char *tmp = aux; + int len; + char *p; + if(!aux){ + LOG(L_ERR, "Could not allocate memory\n"); + return 0; + } switch(t->type){ case FORWARD_T: - DBG("forward("); + snprintf(tmp, BLEN, "%s", "forward("); break; case FORWARD_TCP_T: - DBG("forward_tcp("); + snprintf(tmp, BLEN, "%s", "forward_tcp("); break; case FORWARD_UDP_T: - DBG("forward_udp("); + snprintf(tmp, BLEN, "%s", "forward_udp("); break; case SEND_T: - DBG("send("); + snprintf(tmp, BLEN, "%s", "send("); break; case SEND_TCP_T: - DBG("send_tcp("); + snprintf(tmp, BLEN, "%s", "send_tcp("); break; case DROP_T: - DBG("drop("); + snprintf(tmp, BLEN, "%s", "drop("); break; case LOG_T: - DBG("log("); + snprintf(tmp, BLEN, "%s", "log("); break; case ERROR_T: - DBG("error("); + snprintf(tmp, BLEN, "%s", "error("); break; case ROUTE_T: - DBG("route("); + snprintf(tmp, BLEN, "%s", "route("); break; case EXEC_T: - DBG("exec("); + snprintf(tmp, BLEN, "%s", "exec("); break; case REVERT_URI_T: - DBG("revert_uri("); + snprintf(tmp, BLEN, "%s", "revert_uri("); break; case STRIP_T: - DBG("strip("); + snprintf(tmp, BLEN, "%s", "strip("); break; case APPEND_BRANCH_T: - DBG("append_branch("); + snprintf(tmp, BLEN, "%s", "append_branch("); break; case PREFIX_T: - DBG("prefix("); + snprintf(tmp, BLEN, "%s", "prefix("); break; case LEN_GT_T: - DBG("len_gt("); + snprintf(tmp, BLEN, "%s", "len_gt("); break; case SETFLAG_T: - DBG("setflag("); + snprintf(tmp, BLEN, "%s", "setflag("); break; case RESETFLAG_T: - DBG("resetflag("); + snprintf(tmp, BLEN, "%s", "resetflag("); break; case ISFLAGSET_T: - DBG("isflagset("); + snprintf(tmp, BLEN, "%s", "isflagset("); break; case AVPFLAG_OPER_T: - DBG("avpflagoper("); + snprintf(tmp, BLEN, "%s", "avpflagoper("); break; case SET_HOST_T: - DBG("sethost("); + snprintf(tmp, BLEN, "%s", "sethost("); break; case SET_HOSTPORT_T: - DBG("sethostport("); + snprintf(tmp, BLEN, "%s", "sethostport("); break; case SET_HOSTPORTTRANS_T: - DBG("sethostporttrans("); + snprintf(tmp, BLEN, "%s", "sethostporttrans("); break; case SET_USER_T: - DBG("setuser("); + snprintf(tmp, BLEN, "%s", "setuser("); break; case SET_USERPASS_T: - DBG("setuserpass("); + snprintf(tmp, BLEN, "%s", "setuserpass("); break; case SET_PORT_T: - DBG("setport("); + snprintf(tmp, BLEN, "%s", "setport("); break; case SET_URI_T: - DBG("seturi("); + snprintf(tmp, BLEN, "%s", "seturi("); break; case IF_T: - DBG("if ("); + snprintf(tmp, BLEN, "%s", "if ("); break; case MODULE_T: case MODULE3_T: @@ -449,141 +546,238 @@ void print_action(struct action* t) case MODULE5_T: case MODULE6_T: case MODULEX_T: - DBG(" external_module_call("); + snprintf(tmp, BLEN, "external_module_call(%s)(", ((union cmd_export_u*)t->val[0].u.data)->c.name); break; case FORCE_RPORT_T: - DBG("force_rport("); + snprintf(tmp, BLEN, "%s", "force_rport("); break; case SET_ADV_ADDR_T: - DBG("set_advertised_address("); + snprintf(tmp, BLEN, "%s", "set_advertised_address("); break; case SET_ADV_PORT_T: - DBG("set_advertised_port("); + snprintf(tmp, BLEN, "%s", "set_advertised_port("); break; case FORCE_TCP_ALIAS_T: - DBG("force_tcp_alias("); + snprintf(tmp, BLEN, "%s", "force_tcp_alias("); break; case LOAD_AVP_T: - DBG("load_avp("); + snprintf(tmp, BLEN, "%s", "load_avp("); break; case AVP_TO_URI_T: - DBG("avp_to_attr"); + snprintf(tmp, BLEN, "%s", "avp_to_attr"); break; case FORCE_SEND_SOCKET_T: - DBG("force_send_socket"); + snprintf(tmp, BLEN, "%s", "force_send_socket"); break; - case ASSIGN_T - : DBG("assign("); + case ASSIGN_T: + snprintf(tmp, BLEN, "%s", "assign("); break; case ADD_T: - DBG("assign_add("); + snprintf(tmp, BLEN, "%s", "assign_add("); break; default: - DBG("UNKNOWN("); + snprintf(tmp, BLEN, "%s", "UNKNOWN("); + } + + if(no_print){ + len = strlen(aux); + tmp = aux + strlen(aux); + }else{ + len = 0; + DBG("%s", aux); + tmp = aux; } switch(t->val[0].type){ case STRING_ST: - DBG(""%s"", ZSW(t->val[0].u.string)); + snprintf(tmp, BLEN - len, ""%s"", ZSW(t->val[0].u.string)); break; case NUMBER_ST: - DBG("%lu",t->val[0].u.number); + snprintf(tmp, BLEN - len, "%lu",t->val[0].u.number); break; case IP_ST: print_ip("", (struct ip_addr*)t->val[0].u.data, ""); break; case EXPR_ST: - print_expr((struct expr*)t->val[0].u.data); + p = print_expr_str((struct expr*)t->val[0].u.data, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break; case ACTIONS_ST: - print_actions((struct action*)t->val[0].u.data); + if((p = print_actions_str((struct action*)t->val[1].u.data, no_print))){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break; case MODEXP_ST: - DBG("f_ptr<%p>",t->val[0].u.data); + snprintf(tmp, BLEN - len, "f_ptr<%p>",t->val[0].u.data); break; case SOCKID_ST: - DBG("%d:%s:%d", + snprintf(tmp, BLEN - len, "%d:%s:%d", ((struct socket_id*)t->val[0].u.data)->proto, ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name), ((struct socket_id*)t->val[0].u.data)->port ); break; case AVP_ST: - DBG("avp(%u,%.*s)", t->val[0].u.attr->type, t->val[0].u.attr->name.s.len, ZSW(t->val[0].u.attr->name.s.s)); + snprintf(tmp, BLEN - len, "avp(%u,%.*s)", t->val[0].u.attr->type, t->val[0].u.attr->name.s.len, ZSW(t->val[0].u.attr->name.s.s)); break; case SELECT_ST: - DBG("select"); + snprintf(tmp, BLEN - len, "select"); break; default: - DBG("type<%d>", t->val[0].type); + snprintf(tmp, BLEN - len, "type<%d>", t->val[0].type); } - if (t->type==IF_T) DBG(") {"); + if(no_print){ + len = strlen(aux); + tmp = aux + len; + }else{ + len = 0; + DBG("%s", aux); + tmp = aux; + } + if (t->type==IF_T) snprintf(tmp, BLEN - len, ") {"); switch(t->val[1].type){ case NOSUBTYPE: break; case STRING_ST: - DBG(", "%s"", ZSW(t->val[1].u.string)); + snprintf(tmp, BLEN - len, ", "%s"", ZSW(t->val[1].u.string)); break; case NUMBER_ST: - DBG(", %lu",t->val[1].u.number); + snprintf(tmp, BLEN - len, ", %lu",t->val[1].u.number); break; case EXPR_ST: - print_expr((struct expr*)t->val[1].u.data); + p = print_expr_str((struct expr*)t->val[1].u.data, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; + break; case ACTION_ST: case ACTIONS_ST: - print_actions((struct action*)t->val[1].u.data); + if((p = print_actions_str((struct action*)t->val[1].u.data, no_print))){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break;
case SOCKID_ST: - DBG("%d:%s:%d", + snprintf(tmp, BLEN - len, "%d:%s:%d", ((struct socket_id*)t->val[0].u.data)->proto, ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name), ((struct socket_id*)t->val[0].u.data)->port ); break; case AVP_ST: - DBG(", avp(%u,%.*s)", t->val[1].u.attr->type, t->val[1].u.attr->name.s.len, ZSW(t->val[1].u.attr->name.s.s)); + snprintf(tmp, BLEN - len, ", avp(%u,%.*s)", t->val[1].u.attr->type, t->val[1].u.attr->name.s.len, ZSW(t->val[1].u.attr->name.s.s)); break; case SELECT_ST: - DBG("select"); + snprintf(tmp, BLEN - len, "select"); break; default: - DBG(", type<%d>", t->val[1].type); + snprintf(tmp, BLEN - len, ", type<%d>", t->val[1].type); + } + if(no_print){ + len = strlen(aux); + tmp = aux + strlen(aux); + }else{ + len = 0; + DBG("%s", aux); + tmp = aux; + } + if (t->type==IF_T) snprintf(tmp, BLEN - len, "} else {"); + if(no_print){ + len = strlen(aux); + tmp = aux + len; + }else{ + len = 0; + DBG("%s", aux); + tmp = aux; } - if (t->type==IF_T) DBG("} else {"); switch(t->val[2].type){ case NOSUBTYPE: break; case STRING_ST: - DBG(", "%s"", ZSW(t->val[2].u.string)); + snprintf(tmp, BLEN - len, ", "%s"", ZSW(t->val[2].u.string)); break; case NUMBER_ST: - DBG(", %lu",t->val[2].u.number); + snprintf(tmp, BLEN - len, ", %lu",t->val[2].u.number); break; case EXPR_ST: - print_expr((struct expr*)t->val[2].u.data); + p = print_expr_str((struct expr*)t->val[2].u.data, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break; case ACTIONS_ST: - print_actions((struct action*)t->val[2].u.data); + p = print_action_str((struct action*)t->val[2].u.data, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + pkg_free(p); + }else goto error; break; case SOCKID_ST: - DBG("%d:%s:%d", + snprintf(tmp, BLEN - len, "%d:%s:%d", ((struct socket_id*)t->val[0].u.data)->proto, ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name), ((struct socket_id*)t->val[0].u.data)->port ); break; default: - DBG(", type<%d>", t->val[2].type); + snprintf(tmp, BLEN - len, ", type<%d>", t->val[2].type); + } + if(no_print){ + len = strlen(aux); + tmp = aux + len; + }else{ + len = 0; + DBG("%s", aux); + tmp = aux; } - if (t->type==IF_T) DBG("}; "); - else DBG("); "); + + if (t->type==IF_T) snprintf(tmp, BLEN - len, "}; "); + else snprintf(tmp, BLEN - len, "); "); + + if(no_print) + tmp = aux + strlen(aux); + else{ + DBG("%s", aux); + tmp = aux; + } + + return aux; +error: + pkg_free(aux); + return 0; }
-void print_actions(struct action* a) +char* print_actions_str(struct action* a, int no_print) { + char *aux = pkg_malloc(sizeof(char)*BLEN); + char *tmp; + char *p; + int len; + if(!aux){ + ERR("No more free memory"); + return 0; + } + tmp = aux; + len = 0; while(a) { - print_action(a); + p = print_action_str(a, no_print); + if(p){ + snprintf(tmp, BLEN - len, "%s", p); + len = strlen(aux); + tmp = aux + len; + pkg_free(p); /* buffer allocated by print_action_str*/ + }else goto error; a = a->next; } + return aux; +error: + pkg_free(aux); + return 0; } diff --git a/route_struct.h b/route_struct.h index 4894bd5..d7181f7 100644 --- a/route_struct.h +++ b/route_struct.h @@ -207,6 +207,14 @@ void print_action(struct action* a); void print_actions(struct action* a); void print_expr(struct expr* exp);
+/* new str function that can return a pointer to a new allocated buffer containing the description */ +/* if flag is 0 then print, else keep data in returned buffer */ +/* returned buffer must be deallocated by user*/ +/* return 0 if error */ +char* print_action_str(struct action* a, int); +char* print_actions_str(struct action* a, int); +char* print_expr_str(struct expr* exp, int); + /** joins to cfg file positions into a new one. */ void cfg_pos_join(struct cfg_pos* res, struct cfg_pos* pos1, struct cfg_pos* pos2);
Hello,
On 2/11/10 5:42 PM, marius zbihlei wrote:
Daniel-Constantin Mierla wrote:
Hello,
On 2/9/10 4:00 PM, marius zbihlei wrote:
Hello (replying on myself)
Sorry for the broken output
Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456785@127.0.0.1:10000"); Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=33 a=17 descr=if (type<22>) {} else {}; Feb 9 16:46:03 marius ../../ser[32584]: ERROR: *** cfgtrace: c=[30.cfg] l=30 a=25 descr= external_module_call(f_ptr<0xb7dfc13c>, 0);
I will also check to see why the first line has no config file or line info...
it is in my roadmap to make it more verbose, but if you can do it is better :-) (so I can say was in my roadmap).
The name of the action is in the structure if it is a module function, for the core functions and statements (if, while, ...) I was thinking on having a mapping table (type, name).
Another idea was to open the cfg, read the respective line and print it next. But would be quite i/o intesive...
When you have the patch ready, send it over. I will look over it and if ok I will tell you to commit.
Thanks, Daniel
Hello Daniel,
I have attacked a patch that enables print_action like printing of module functions, core function and statements . It is usefull if the action line is no longer that 512 characters(it truncates at 512 .. still to test)
The module export is printed like this (call to t_relay) cfgtrace: c=[/home/marius/dev/sip-router/test/unit/30.cfg] l=30 a=25 descr=external_module_call(t_relay)(f_ptr<0xb7ee815c>, 0);
I also liked the file read solution but strangely for some action the file is NULL (*** cfgtrace: c=[(null)] l=0 a=13 descr=seturi("sip:49721123456787@127.0.0.1:8000"); )
I have to check, should be some value there...
BTW it is normal for a line like xlog(...) to appear as an action: cfgtrace: c=[/home/marius/dev/sip-router/test/unit/30.cfg] l=30 a=17 descr=if (type<22>external_module_call(xlog)(f_ptr<0xb8062898>, 2, type<10>); drop(1, 1); } else {}; ?
The patch is a little on the long side, and a bit intrusive to my liking , it you have other suggestion please let me now.
indeed a bit long. I was thinking to have some static tables:
struct action_info { int type; char *name; };
struct action_info _sr_actions_list[] = { {FORWARD_T, "forward"}, {IF_T, "if"}, ... {0, 0} };
Maybe same for expressions, operators, etc. Would become easy everywhere to get the action name (also easy to generate the list of actions for documentation purposes). The core print functions will get simplified a lot, since only few cases need special handling.
What I do not like about printing to buffer now is alloc every time. I was thinking to a less verbose version, just to print the action name, but more details are probably better when debugging.
Cheers, Daniel
Cheers Marius
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Hello,
I don't see a problem with the malloc's as performance is out of the question. I don't think anyone tries to do profiling with the debugger module. It might be a problem with the user that has ownership of the pointer. I've try with some static buffer but this tends to get complicated as recursive calls are made to the printing function.
I don't know about your suggestion for a simplified action_info struct. The problem with the size of the patch is that kamailio support expression is actions, which can have there own action list and such on. Probably it will be better not to touch the route_* files in core, just duplicate the print mechanism in modules/debugger. This will allow for some rather nice optimization (I don't need to handle both the DBG() case and the debugger output case) and support only the necessary bits.
Cheers Marius
The patch is a little on the long side, and a bit intrusive to my liking , it you have other suggestion please let me now.
indeed a bit long. I was thinking to have some static tables:
struct action_info { int type; char *name; };
struct action_info _sr_actions_list[] = { {FORWARD_T, "forward"}, {IF_T, "if"}, ... {0, 0} };
Maybe same for expressions, operators, etc. Would become easy everywhere to get the action name (also easy to generate the list of actions for documentation purposes). The core print functions will get simplified a lot, since only few cases need special handling.
What I do not like about printing to buffer now is alloc every time. I was thinking to a less verbose version, just to print the action name, but more details are probably better when debugging.
Cheers, Daniel
Cheers Marius
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Hello,
On 2/11/10 7:06 PM, Marius Zbihlei wrote:
Hello,
I don't see a problem with the malloc's as performance is out of the question.
not performance, but fragmentation. I wouldn't like chopping the sip worker memory.
I don't think anyone tries to do profiling with the debugger module. It might be a problem with the user that has ownership of the pointer. I've try with some static buffer but this tends to get complicated as recursive calls are made to the printing function.
I don't know about your suggestion for a simplified action_info struct. The problem with the size of the patch is that kamailio support expression is actions, which can have there own action list and such on. Probably it will be better not to touch the route_* files in core, just duplicate the print mechanism in modules/debugger. This will allow for some rather nice optimization (I don't need to handle both the DBG() case and the debugger output case) and support only the necessary bits.
The debugger stops at action evaluation, so I haven't considered printing the expression. The list of action_info was supposed to be in debugger module for what I started, but no time to finish it. You patch extended the idea in my mind to make it available everywhere and use it in core.
Cheers, Daniel
Cheers Marius
The patch is a little on the long side, and a bit intrusive to my liking , it you have other suggestion please let me now.
indeed a bit long. I was thinking to have some static tables:
struct action_info { int type; char *name; };
struct action_info _sr_actions_list[] = { {FORWARD_T, "forward"}, {IF_T, "if"}, ... {0, 0} };
Maybe same for expressions, operators, etc. Would become easy everywhere to get the action name (also easy to generate the list of actions for documentation purposes). The core print functions will get simplified a lot, since only few cases need special handling.
What I do not like about printing to buffer now is alloc every time. I was thinking to a less verbose version, just to print the action name, but more details are probably better when debugging.
Cheers, Daniel
Cheers Marius
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
-- Daniel-Constantin Mierla SIP Server Professional Solutions