void b2bl_print_tuple(b2bl_tuple_t* tuple, int log_level)
{
	int index;
	b2bl_entity_id_t* e;

	if(tuple)
	{
		LM_GEN1(log_level, "[%p]->[%.*s] to_del=[%d] lifetime=[%d]"
			" bridge_entities[%p][%p][%p]\n",
			tuple, tuple->key->len, tuple->key->s,
			tuple->to_del, tuple->lifetime,
			tuple->bridge_entities[0], tuple->bridge_entities[1],
			tuple->bridge_entities[2]);
		for (index = 0; index < MAX_B2BL_ENT; index++)
		{
			e = tuple->servers[index];
			if (e) _print_entity(index, e, log_level);
		}
		for (index = 0; index < MAX_B2BL_ENT; index++)
		{
			e = tuple->clients[index];
			if (e) _print_entity(index, e, log_level);
		}
		for (index = 0; index < MAX_BRIDGE_ENT; index++)
		{
			e = tuple->bridge_entities[index];
			if (e)
				LM_GEN1(log_level, ".type=[%d] index=[%d] [%p]"
					" peer=[%p] prev:next=[%p][%p]\n",
					e->type, index, e, e->peer, e->prev, e->next);
		}
	}
}
Example #2
0
/**
 * Clean up on exit. This should be called before exiting.
 * \param show_status set to one to display the mem status
 */
void cleanup(int show_status)
{
	LM_INFO("cleanup\n");
	/*clean-up*/

	/* hack: force-unlock the shared memory lock in case
	   		 some process crashed and let it locked; this will
	   		 allow an almost gracious shutdown */
	if (mem_lock)
#ifdef HP_MALLOC
	{
		int i;

		for (i = 0; i < HP_HASH_SIZE; i++)
			shm_unlock(i);
	}
#else
		shm_unlock();
#endif

	handle_ql_shutdown();
	destroy_modules();
#ifdef USE_TCP
	destroy_tcp();
#endif
#ifdef USE_TLS
	destroy_tls();
#endif
	destroy_timer();
	destroy_stats_collector();
	destroy_script_cb();
	pv_free_extra_list();
	destroy_argv_list();
	destroy_black_lists();
#ifdef PKG_MALLOC
	if (show_status){
		LM_GEN1(memdump, "Memory status (pkg):\n");
		pkg_status();
	}
#endif
#ifdef SHM_MEM
	cleanup_debug();

	if (pt) shm_free(pt);
	pt=0;
	if (show_status){
			LM_GEN1(memdump, "Memory status (shm):\n");
			shm_status();
	}

	/* zero all shmem alloc vars that we still use */
	shm_mem_destroy();
#endif
	if (pid_file) unlink(pid_file);
	if (pgid_file) unlink(pgid_file);
}
Example #3
0
void fm_free(struct fm_block* qm, void* p)
#endif
{
    struct fm_frag* f,*n;

#ifdef DBG_MALLOC
    LM_GEN1(memlog, "%s_free(%p), called from %s: %s(%d)\n", qm->name, p, file,
            func, line);
    if (p && (p > (void *)qm->last_frag || p < (void *)qm->first_frag)) {
        LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
        abort();
    }
#endif
    if (p==0) {
        LM_GEN1(memlog, "free(0) called\n");
        return;
    }
    f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag));

#ifdef DBG_MALLOC
    LM_GEN1(memlog, "freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func,
            f->line);
#endif

join:

    if( qm->large_limit < qm->large_space )
        goto no_join;

    n = FRAG_NEXT(f);

    if (((char*)n < (char*)qm->last_frag) &&  n->prev )
    {

        fm_remove_free(qm, n);
        /* join */
        f->size += n->size + FRAG_OVERHEAD;

#if defined(DBG_MALLOC) || defined(STATISTICS)
        //qm->real_used -= FRAG_OVERHEAD;
        qm->used += FRAG_OVERHEAD;
#endif

        goto join;
    }

no_join:

    fm_insert_free(qm, f);
#if defined(DBG_MALLOC) || defined(STATISTICS)
    qm->fragments -= 1;
#endif
    pkg_threshold_check();
}
Example #4
0
void dump_frag( struct vqm_frag* f, int i )
{
	LM_GEN1(memdump, "    %3d. address=%p  real size=%d bucket=%d\n", i, 
		(char*)f+sizeof(struct vqm_frag), f->size, f->u.inuse.bucket);
#ifdef DBG_QM_MALLOC
	LM_GEN1(memdump, "            demanded size=%d\n", f->demanded_size );
	LM_GEN1(memdump, "            alloc'd from %s: %s(%d)\n",
		f->file, f->func, f->line);
	LM_GEN1(memdump, "        start check=%x, end check= %.*s\n",
			f->check, END_CHECK_PATTERN_LEN, f->end_check );
#endif
}
Example #5
0
/**
 * Exit regulary on a specific signal.
 * This is good for profiling which only works if exited regularly
 * and not by default signal handlers
 * \param signo The signal that should be handled
 */
static void sig_usr(int signo)
{
	int status;
	pid_t pid;
	UNUSED(pid);

	if (is_main){
		if (sig_flag==0) sig_flag=signo;
		else /*  previous sig. not processed yet, ignoring? */
			return; ;
		if (dont_fork)
				/* only one proc, doing everything from the sig handler,
				unsafe, but this is only for debugging mode*/
			handle_sigs();
	}else{
		/* process the important signals */
		switch(signo){
			case SIGPIPE:
					LM_INFO("signal %d received\n", signo);
				break;
			case SIGINT:
			case SIGTERM:
					LM_INFO("signal %d received\n", signo);
					/* print memory stats for non-main too */
					#ifdef PKG_MALLOC
					LM_GEN1(memdump, "Memory status (pkg):\n");
					pkg_status();
					#endif
					exit(0);
					break;
			case SIGUSR1:
					/* statistics -> show only pkg mem */
					#ifdef PKG_MALLOC
					LM_GEN1(memdump, "Memory status (pkg):\n");
					pkg_status();
					#endif
					break;
			case SIGUSR2:
					#ifdef PKG_MALLOC
					set_pkg_stats( get_pkg_status_holder(process_no) );
					#endif
					break;
			case SIGHUP:
					/* ignored*/
					break;
			case SIGCHLD:
					pid = waitpid(-1, &status, WNOHANG);
					LM_DBG("SIGCHLD received from %ld (status=%d), ignoring\n",
						(long)pid,status);
		}
	}
}
Example #6
0
/**
 * Clean up on exit. This should be called before exiting.
 * \param show_status set to one to display the mem status 
 */
void cleanup(int show_status)
{
	LM_INFO("cleanup\n");
	/*clean-up*/
	if (mem_lock) 
		shm_unlock(); /* hack: force-unlock the shared memory lock in case
					 some process crashed and let it locked; this will 
					 allow an almost gracious shutdown */
	handle_ql_shutdown();
	destroy_modules();
#ifdef USE_TCP
	destroy_tcp();
#endif
#ifdef USE_TLS
	destroy_tls();
#endif
	destroy_timer();
	destroy_stats_collector();
	destroy_script_cb();
	pv_free_extra_list();
	destroy_argv_list();
	destroy_black_lists();
#ifdef CHANGEABLE_DEBUG_LEVEL
	if (debug!=&debug_init) {
		reset_proc_debug_level();
		debug_init = *debug;
		shm_free(debug);
		debug = &debug_init;
	}
#endif
#ifdef PKG_MALLOC
	if (show_status){
		LM_GEN1(memdump, "Memory status (pkg):\n");
		pkg_status();
	}
#endif
#ifdef SHM_MEM
	if (pt) shm_free(pt);
	pt=0;
	if (show_status){
			LM_GEN1(memdump, "Memory status (shm):\n");
			shm_status();
	}
	/* zero all shmem alloc vars that we still use */
	shm_mem_destroy();
#endif
	if (pid_file) unlink(pid_file);
	if (pgid_file) unlink(pgid_file);
}
Example #7
0
void siplua_log(int lev, const char *format, ...)
{
  va_list ap;
  char *ret;
  int priority;

  if (!format)
    return;
  if (!(is_printable(lev) | lua_user_debug))
    return;
  va_start(ap, format);
  vasprintf(&ret, format, ap);
  va_end(ap);
  LM_GEN1(lev, "siplua: %s", ret);
  if (lua_user_debug)
    {
      switch (lev)
	{
	case L_ALERT: priority = LOG_ALERT; break;
	case L_CRIT: priority = LOG_CRIT; break;
	case L_ERR: priority = LOG_ERR; break;
	case L_WARN: priority = LOG_WARNING; break;
	case L_NOTICE: priority = LOG_NOTICE; break;
	case L_INFO: priority = LOG_INFO; break;
	case L_DBG: priority = LOG_DEBUG; break;
	default: /* should not happen, no execution path permits it */
	  priority = LOG_ERR;
	}
      syslog(LOG_USER | priority, "siplua: %s", ret);
    }
  free(ret);
}
Example #8
0
int xlog_2(struct sip_msg* msg, char* lev, char* frm)
{
	int log_len;
	long level;
	xl_level_p xlp;
	pv_value_t value;

	xlp = (xl_level_p)lev;
	if(xlp->type==1)
	{
		if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0
			|| value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
		{
			LM_ERR("invalid log level value [%d]\n", value.flags);
			return -1;
		}
		level = (long)value.ri;
	} else {
		level = xlp->v.level;
	}

	if(!is_printable((int)level))
		return 1;

	log_len = xlog_buf_size;

	if(xl_print_log(msg, (pv_elem_t*)frm, &log_len)<0)
		return -1;

	/* log_buf[log_len] = '\0'; */
	LM_GEN1((int)level, "%.*s", log_len, log_buf);

	return 1;
}
Example #9
0
void vqm_status(struct vqm_block* qm)
{
	struct vqm_frag* f;
	unsigned int i,on_list;

	LM_GEN1(memdump, "vqm_status (%p):\n", qm);
	if (!qm) return;
	LM_GEN1(memdump, " heap size= %d, available: %d\n", 
		qm->core_end-qm->init_core, qm->free_core );

	LM_GEN1(memdump, "dumping unfreed fragments:\n");
	for (f=(struct vqm_frag*)qm->init_core, i=0;(char*)f<(char*)qm->core;
		f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag(f, i);

	LM_GEN1(memdump, "dumping unfreed big fragments:\n");
	for (f=(struct vqm_frag*)qm->big_chunks,i=0;(char*)f<(char*)qm->core_end;
		f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag( f, i );

#ifdef DBG_QM_MALLOC
	LM_GEN1(memdump,"dumping bucket statistics:\n");
	for (i=0; i<=BIG_BUCKET(qm); i++) {
		for(on_list=0, f=qm->next_free[i]; f; f=f->u.nxt_free ) on_list++;
		LM_GEN1(memdump,"    %3d. bucket: in use: %ld, on free list: %d\n", 
			i, qm->usage[i], on_list );
	}
#endif
	LM_GEN1(memdump, "-----------------------------\n");
}
Example #10
0
static void _print_entity(int index, b2bl_entity_id_t* e, int log_level)
{
	b2bl_entity_id_t* c = e;

	while (c)
	{
		LM_GEN1(log_level, ".type=[%d] index=[%d] [%p]->[%.*s] state=%d no=%d"
			" dlginfo=[%p] peer=[%p] prev:next=[%p][%p]\n",
			c->type, index, c, c->key.len, c->key.s, c->state, c->no,
			c->dlginfo, c->peer, c->prev, c->next);
		if (c->dlginfo)
			LM_GEN1(log_level, "..........dlginfo=[%p]->[%.*s][%.*s][%.*s]\n",
				c->dlginfo, c->dlginfo->callid.len, c->dlginfo->callid.s,
				c->dlginfo->fromtag.len, c->dlginfo->fromtag.s,
				c->dlginfo->totag.len, c->dlginfo->totag.s);
		c = c->next;
	}
}
Example #11
0
void hp_status(struct hp_block *qm)
{
    struct hp_frag* f;
    unsigned int i,j;
    unsigned int h;
    int unused;
    unsigned long size;

    LM_GEN1(memdump, "hp_status (%p):\n", qm);
    if (!qm) return;

    LM_GEN1(memdump, " heap size= %ld\n", qm->size);

#ifdef STATISTICS
    LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n",
            qm->used, qm->real_used, qm->size-qm->used);
    LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used);
#endif

    LM_GEN1(memdump, "dumping free list:\n");
    for(h=0,i=0,size=0; h<HP_HASH_SIZE; h++) {
        unused=0;
        for (f=qm->free_hash[h].first,j=0; f;
                size+=f->size,f=f->u.nxt_free,i++,j++) { }
        if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t"
                           " bucket size: %9lu - %9lu (first %9lu)\n",
                           h, j, unused, UN_HASH(h),
                           ((h<=HP_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h),
                           qm->free_hash[h].first->size
                          );
        if (j!=qm->free_hash[h].no) {
            LM_CRIT("different free frag. count: %d!=%ld"
                    " for hash %3d\n", j, qm->free_hash[h].no, h);
        }

    }
    LM_GEN1(memdump, "TOTAL: %6d free fragments = %6lu free bytes\n", i, size);
    LM_GEN1(memdump, "TOTAL: %ld large bytes\n", qm->large_space );
    LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD );
    LM_GEN1(memdump, "-----------------------------\n");
}
Example #12
0
static inline void refresh_node( struct ip_node *node)
{
	for( ; node ; node=node->next ) {
		node->hits[PREV_POS] = node->hits[CURR_POS];
		node->hits[CURR_POS] = 0;
		node->leaf_hits[PREV_POS] = node->leaf_hits[CURR_POS];
		node->leaf_hits[CURR_POS] = 0;
		if ( node->flags&NODE_ISRED_FLAG && !is_node_hot_leaf(node) ) {
			node->flags &= ~(NODE_ISRED_FLAG);
			LM_GEN1( pike_log_level,"PIKE - UNBLOCKing node %p\n",node);
		}
		if (node->kids)
			refresh_node( node->kids );
	}
}
Example #13
0
int xdbg(struct sip_msg* msg, char* frm, char* str2)
{
	int log_len;

	if(!is_printable(L_DBG))
		return 1;

	log_len = xlog_buf_size;

	if(xl_print_log(msg, (pv_elem_t*)frm, &log_len)<0)
		return -1;

	/* log_buf[log_len] = '\0'; */
	LM_GEN1(L_DBG, "%.*s", log_len, log_buf);

	return 1;
}
Example #14
0
static int sng_logger(int level, char *fmt, ...)
{
	va_list args;
	static char buffer[256];

	va_start(args, fmt);

	vsnprintf(buffer, 256, fmt, args);

	switch (level) {
	case SNGTC_LOGLEVEL_DEBUG:
		LM_GEN1(L_DBG, fmt, args);
		LM_DBG("%s\n", buffer);
		break;
	case SNGTC_LOGLEVEL_WARN:
		LM_GEN1(L_WARN, fmt, args);
		LM_WARN("%s\n", buffer);
		break;
	case SNGTC_LOGLEVEL_INFO:
		LM_GEN1(L_INFO, fmt, args);
		LM_INFO("%s\n", buffer);
		break;
	case SNGTC_LOGLEVEL_STATS:
		LM_GEN1(L_INFO, fmt, args);
		LM_INFO("%s\n", buffer);
		break;
	case SNGTC_LOGLEVEL_ERROR:
		LM_GEN1(L_ERR, fmt, args);
		LM_ERR("%s\n", buffer);
		break;
	case SNGTC_LOGLEVEL_CRIT:
		LM_GEN1(L_CRIT, fmt, args);
		LM_CRIT("%s\n", buffer);
		break;

	default:
		LM_GEN1(L_WARN, fmt, args);
	}

	va_end(args);

	return 0;
}
Example #15
0
void fm_status(struct fm_block* qm)
{
    struct fm_frag* f;
    unsigned int i,j;
    unsigned int h;
    int unused;
    unsigned long size;

#ifdef DBG_MALLOC
    mem_dbg_htable_t allocd;
    struct mem_dbg_entry *it;
#endif

    LM_GEN1(memdump, "fm_status (%p):\n", qm);
    if (!qm) return;

    LM_GEN1(memdump, " heap size= %ld\n", qm->size);
#if defined(DBG_MALLOC) || defined(STATISTICS)
    LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n",
            qm->used, qm->real_used, qm->size-qm->used);
    LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used);
#endif

#if defined(DBG_MALLOC)
    dbg_ht_init(allocd);

    for (f=qm->first_frag; (char*)f<(char*)qm->last_frag; f=FRAG_NEXT(f))
        if (!f->is_free)
            if (dbg_ht_update(allocd, f->file, f->func, f->line, f->size) < 0) {
                LM_ERR("Unable to update alloc'ed. memory summary\n");
                dbg_ht_free(allocd);
                return;
            }

    LM_GEN1(memdump, " dumping summary of all alloc'ed. fragments:\n");
    for(i=0; i < DBG_HASH_SIZE; i++) {
        it = allocd[i];
        while (it) {
            LM_GEN1(memdump, " %10lu : %lu x [%s: %s, line %lu]\n",
                    it->size, it->no_fragments, it->file, it->func, it->line);
            it = it->next;
        }
    }

    dbg_ht_free(allocd);
#endif

    LM_GEN1(memdump, "dumping free list:\n");
    for(h=0,i=0,size=0; h<F_HASH_SIZE; h++) {
        unused=0;
        for (f=qm->free_hash[h].first,j=0; f;
                size+=f->size,f=f->u.nxt_free,i++,j++) { }
        if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t"
                           " bucket size: %9lu - %9lu (first %9lu)\n",
                           h, j, unused, UN_HASH(h),
                           ((h<=F_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h),
                           qm->free_hash[h].first->size
                          );
        if (j!=qm->free_hash[h].no) {
            LM_CRIT("different free frag. count: %d!=%ld"
                    " for hash %3d\n", j, qm->free_hash[h].no, h);
        }

    }
    LM_GEN1(memdump, "TOTAL: %6d free fragments = %6lu free bytes\n", i, size);
    LM_GEN1(memdump, "TOTAL: %ld large bytes\n", qm->large_space );
    LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD );
    LM_GEN1(memdump, "-----------------------------\n");
}
Example #16
0
void print_action(struct action* t)
{
	switch(t->type){
		case FORWARD_T:
				LM_GEN1(L_DBG, "forward(");
				break;
		case SEND_T:
				LM_GEN1(L_DBG, "send(");
				break;
		case ASSERT_T:
				LM_GEN1(L_DBG, "assert(");
				break;
		case DROP_T:
				LM_GEN1(L_DBG, "drop(");
				break;
		case LOG_T:
				LM_GEN1(L_DBG, "log(");
				break;
		case ERROR_T:
				LM_GEN1(L_DBG, "error(");
				break;
		case ROUTE_T:
				LM_GEN1(L_DBG, "route(");
				break;
		case EXEC_T:
				LM_GEN1(L_DBG, "exec(");
				break;
		case REVERT_URI_T:
				LM_GEN1(L_DBG, "revert_uri(");
				break;
		case STRIP_T:
				LM_GEN1(L_DBG, "strip(");
				break;
		case APPEND_BRANCH_T:
				LM_GEN1(L_DBG, "append_branch(");
				break;
		case PREFIX_T:
				LM_GEN1(L_DBG, "prefix(");
				break;
		case LEN_GT_T:
				LM_GEN1(L_DBG, "len_gt(");
				break;
		case SET_DEBUG_T:
				LM_GEN1(L_DBG, "setdebug(");
				break;
		case SETFLAG_T:
				LM_GEN1(L_DBG, "setflag(");
				break;
		case RESETFLAG_T:
				LM_GEN1(L_DBG, "resetflag(");
				break;
		case ISFLAGSET_T:
				LM_GEN1(L_DBG, "isflagset(");
				break;
		case SETBFLAG_T:
				LM_GEN1(L_DBG, "setbflag(");
				break;
		case RESETBFLAG_T:
				LM_GEN1(L_DBG, "resetbflag(");
				break;
		case ISBFLAGSET_T:
				LM_GEN1(L_DBG, "isbflagset(");
				break;
		case SETSFLAG_T:
				LM_GEN1(L_DBG, "setsflag(");
				break;
		case RESETSFLAG_T:
				LM_GEN1(L_DBG, "resetsflag(");
				break;
		case ISSFLAGSET_T:
				LM_GEN1(L_DBG, "issflagset(");
				break;
		case SET_HOST_T:
				LM_GEN1(L_DBG, "sethost(");
				break;
		case SET_HOSTPORT_T:
				LM_GEN1(L_DBG, "sethostport(");
				break;
		case SET_USER_T:
				LM_GEN1(L_DBG, "setuser(");
				break;
		case SET_USERPASS_T:
				LM_GEN1(L_DBG, "setuserpass(");
				break;
		case SET_PORT_T:
				LM_GEN1(L_DBG, "setport(");
				break;
		case SET_URI_T:
				LM_GEN1(L_DBG, "seturi(");
				break;
		case IF_T:
				LM_GEN1(L_DBG, "if (");
				break;
		case WHILE_T:
				LM_GEN1(L_DBG, "while (");
				break;
		case MODULE_T:
				LM_GEN1(L_DBG, " external_module_call(");
				break;
		case FORCE_RPORT_T:
				LM_GEN1(L_DBG, "force_rport(");
				break;
		case SET_ADV_ADDR_T:
				LM_GEN1(L_DBG, "set_advertised_address(");
				break;
		case SET_ADV_PORT_T:
				LM_GEN1(L_DBG, "set_advertised_port(");
				break;
		case FORCE_TCP_ALIAS_T:
				LM_GEN1(L_DBG, "force_tcp_alias(");
				break;
		case FORCE_SEND_SOCKET_T:
				LM_GEN1(L_DBG, "force_send_socket");
				break;
		case RETURN_T:
				LM_GEN1(L_DBG, "return(");
				break;
		case EXIT_T:
				LM_GEN1(L_DBG, "exit(");
				break;
		case SWITCH_T:
				LM_GEN1(L_DBG, "switch(");
				break;
		case CASE_T:
				LM_GEN1(L_DBG, "case(");
				break;
		case DEFAULT_T:
				LM_GEN1(L_DBG, "default(");
				break;
		case SBREAK_T:
				LM_GEN1(L_DBG, "sbreak(");
				break;
		case EQ_T:
				LM_GEN1(L_DBG, "assign(");
				break;
		default:
				LM_GEN1(L_DBG, "UNKNOWN(");
	}
	switch(t->elem[0].type){
		case STRING_ST:
				LM_GEN1(L_DBG, "\"%s\"", ZSW(t->elem[0].u.string));
				break;
		case NUMBER_ST:
				LM_GEN1(L_DBG, "%lu",t->elem[0].u.number);
				break;
		case SCRIPTVAR_ST:
				LM_GEN1(L_DBG, "scriptvar[%d]",t->elem[0].u.item->type);
				break;
		case IP_ST:
				print_ip("", (struct ip_addr*)t->elem[0].u.data, "");
				break;
		case EXPR_ST:
				print_expr((struct expr*)t->elem[0].u.data);
				break;
		case ACTIONS_ST:
				print_actions((struct action*)t->elem[0].u.data);
				break;
		case CMD_ST:
				LM_GEN1(L_DBG, "f<%s>",((cmd_export_t*)t->elem[0].u.data)->name);
				break;
		case SOCKID_ST:
				LM_GEN1(L_DBG, "%d:%s:%d",
						((struct socket_id*)t->elem[0].u.data)->proto,
						ZSW(((struct socket_id*)t->elem[0].u.data)->name),
						((struct socket_id*)t->elem[0].u.data)->port
						);
				break;
		default:
				LM_GEN1(L_DBG, "type<%d>", t->elem[0].type);
	}
	if (t->type==IF_T) LM_GEN1(L_DBG, ") {");
	switch(t->elem[1].type){
		case NOSUBTYPE:
				break;
		case STRING_ST:
				LM_GEN1(L_DBG, ", \"%s\"", ZSW(t->elem[1].u.string));
				break;
		case NUMBER_ST:
				LM_GEN1(L_DBG, ", %lu",t->elem[1].u.number);
				break;
		case EXPR_ST:
				print_expr((struct expr*)t->elem[1].u.data);
				break;
		case ACTIONS_ST:
				print_actions((struct action*)t->elem[1].u.data);
				break;
		case SOCKID_ST:
				LM_GEN1(L_DBG, "%d:%s:%d",
						((struct socket_id*)t->elem[1].u.data)->proto,
						ZSW(((struct socket_id*)t->elem[1].u.data)->name),
						((struct socket_id*)t->elem[1].u.data)->port
						);
				break;
		default:
				LM_GEN1(L_DBG, ", type<%d>", t->elem[1].type);
	}
	if (t->type==IF_T && t->elem[2].type!=NOSUBTYPE) LM_GEN1(L_DBG, " } else { ");
	switch(t->elem[2].type){
		case NOSUBTYPE:
				break;
		case STRING_ST:
				LM_GEN1(L_DBG, ", \"%s\"", ZSW(t->elem[2].u.string));
				break;
		case NUMBER_ST:
				LM_GEN1(L_DBG, ", %lu",t->elem[2].u.number);
				break;
		case EXPR_ST:
				print_expr((struct expr*)t->elem[2].u.data);
				break;
		case ACTIONS_ST:
				print_actions((struct action*)t->elem[2].u.data);
				break;
		case SOCKID_ST:
				LM_GEN1(L_DBG, "%d:%s:%d",
					((struct socket_id*)t->elem[2].u.data)->proto,
					ZSW(((struct socket_id*)t->elem[2].u.data)->name),
					((struct socket_id*)t->elem[2].u.data)->port
					);
			break;
		default:
			LM_GEN1(L_DBG, ", type<%d>", t->elem[2].type);
	}
	if (t->type==IF_T) LM_GEN1(L_DBG, "}; ");
	else	LM_GEN1(L_DBG, "); ");

}
Example #17
0
static int _bm_log_timer(unsigned int id)
{
	/* BM_CLOCK_REALTIME */
	bm_timeval_t now;
	unsigned long long tdiff;
	benchmark_timer_t *timer;

	if (!timer_active(id))
		return 1;

	if(bm_get_time(&now)<0)
	{
		LM_ERR("error getting current time\n");
		return -1;
	}

	timer = bm_mycfg->tindex[id];
	tdiff = bm_diff_time(timer->start, &now);
	_bm_last_time_diff = (int)tdiff;

	/* What to do
	 * - update min, max, sum
	 * - if granularity hit: Log, reset min/max
	 */

	lock_get(timer->lock);

	timer->sum += tdiff;
	timer->last_sum += tdiff;
	timer->calls++;
	timer->global_calls++;

	if (tdiff < timer->last_min)
		timer->last_min = tdiff;

	if (tdiff > timer->last_max)
		timer->last_max = tdiff;

	if (tdiff < timer->global_min)
		timer->global_min = tdiff;

	if (tdiff > timer->global_max)
		timer->global_max = tdiff;


	if (bm_mycfg->granularity > 0 && timer->calls >= bm_mycfg->granularity)
	{
		LM_GEN1(bm_mycfg->loglevel, "benchmark (timer %s [%d]): %llu ["
			" msgs/total/min/max/avg - LR:"
			" %i/%lld/%lld/%lld/%f | GB: %lld/%lld/%lld/%lld/%f]\n",
			timer->name,
			id,
			tdiff,
			timer->calls,
			timer->last_sum,
			timer->last_min,
			timer->last_max,
			((double)timer->last_sum)/bm_mycfg->granularity,
			timer->global_calls,
			timer->sum,
			timer->global_min,
			timer->global_max,
			((double)timer->sum)/timer->global_calls);

		soft_reset_timer(timer);
	}

	lock_release(timer->lock);

	return 1;
}
Example #18
0
int pike_check_req(struct sip_msg *msg)
{
	struct ip_node *node;
	struct ip_node *father;
	unsigned char flags;
	struct ip_addr* ip;


#ifdef _test
	/* get the ip address from second via */
	if (parse_headers(msg, HDR_VIA1_F, 0)!=0 )
		return -1;
	if (msg->via1==0 )
		return -1;
	/* convert from string to ip_addr */
	ip = str2ip( &msg->via1->host );
	if (ip==0)
		return -1;
#else
	ip = &(msg->rcv.src_ip);
#endif


	/* first lock the proper tree branch and mark the IP with one more hit*/
	lock_tree_branch( ip->u.addr[0] );
	node = mark_node( ip->u.addr, ip->len, &father, &flags);
	if (node==0) {
		unlock_tree_branch( ip->u.addr[0] );
		/* even if this is an error case, we return true in script to avoid
		 * considering the IP as marked (bogdan) */
		return 1;
	}

	LM_DBG("src IP [%s],node=%p; hits=[%d,%d],[%d,%d] node_flags=%d"
		" func_flags=%d\n", ip_addr2a( ip ), node,
		node->hits[PREV_POS],node->hits[CURR_POS],
		node->leaf_hits[PREV_POS],node->leaf_hits[CURR_POS],
		node->flags, flags);

	/* update the timer */
	lock_get(timer_lock);
	if ( flags&NEW_NODE ) {
		/* put this node into the timer list and remove its
		   father only if this has one kid and is not a LEAF_NODE*/
		node->expires =  get_ticks() + timeout;
		append_to_timer( timer, &(node->timer_ll) );
		node->flags |= NODE_INTIMER_FLAG;
		if (father) {
			LM_DBG("father %p: flags=%d kids->next=%p\n",
				father,father->flags,father->kids->next);
			if (!(father->flags&NODE_IPLEAF_FLAG) && !father->kids->next){
				/* debug */
				assert( has_timer_set(&(father->timer_ll))
					&& (father->flags&(NODE_EXPIRED_FLAG|NODE_INTIMER_FLAG)) );
				/* if the node is maked as expired by timer, let the timer
				 * to finish and remove the node */
				if ( !(father->flags&NODE_EXPIRED_FLAG) ) {
					remove_from_timer( timer, &(father->timer_ll) );
					father->flags &= ~NODE_INTIMER_FLAG;
				} else {
					father->flags &= ~NODE_EXPIRED_FLAG;
				}
			}
		}
	} else {
		/* update the timer -> in timer can be only nodes
		 * as IP-leaf(complete address) or tree-leaf */
		if (node->flags&NODE_IPLEAF_FLAG || node->kids==0) {
			/* tree leafs which are not potential red nodes are not update in
			 * order to make them to expire */
			/* debug */
			assert( has_timer_set(&(node->timer_ll))
				&& (node->flags&(NODE_EXPIRED_FLAG|NODE_INTIMER_FLAG)) );
			/* if node exprired, ignore the current hit and let is
			 * expire in timer process */
			if ( !(flags&NO_UPDATE) && !(node->flags&NODE_EXPIRED_FLAG) ) {
				node->expires = get_ticks() + timeout;
				update_in_timer( timer, &(node->timer_ll) );
			}
		} else {
			/* debug */
			assert( !has_timer_set(&(node->timer_ll))
				&& !(node->flags&(NODE_INTIMER_FLAG|NODE_EXPIRED_FLAG)) );
			/* debug */
			assert( !(node->flags&NODE_IPLEAF_FLAG) && node->kids );
		}
	}
	/*print_timer_list( timer );*/ /* debug*/
	lock_release(timer_lock);

	unlock_tree_branch( ip->u.addr[0] );
	/*print_tree( 0 );*/ /* debug */

	if (flags&RED_NODE) {
		if (flags&NEWRED_NODE) {
			LM_GEN1( pike_log_level,
				"PIKE - BLOCKing ip %s, node=%p\n",ip_addr2a(ip),node);
			pike_raise_event(ip_addr2a(ip));
			return -2;
		}
		return -1;
	}
	return 1;
}
Example #19
0
void vqm_free(struct vqm_block* qm, void* p)
#endif
{
	struct vqm_frag *f, *next, *prev, *first_big;
	unsigned char b;

#ifdef DBG_QM_MALLOC
	LM_GEN1(memlog,"params (%p, %p), called from %s: %s(%d)\n", 
		qm, p, file, func, line);
	if (p>(void *)qm->core_end || p<(void*)qm->init_core){
		LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
		abort();
	}
#endif
	if (p==0) {
		LM_WARN("free(0) called\n");
		return;
	}
	f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
	b=f->u.inuse.bucket;
#ifdef DBG_QM_MALLOC
	VQM_DEBUG_FRAG(qm, f);
	if ( ! FRAG_ISUSED(f) ) {
		LM_CRIT("freeing already freed pointer, first freed: %s: %s(%d) "
				"- aborting\n",	f->file, f->func, f->line);
		abort();
	}
	if ( b>MAX_BUCKET ) {
		LM_CRIT("fragment with too high bucket nr: "
				"%d, allocated: %s: %s(%d) - aborting\n",
				b, f->file, f->func, f->line); 
		abort();
	}
	LM_GEN1(memlog,"freeing %d bucket block alloc'ed from %s: %s(%d)\n", 
		f->u.inuse.bucket, f->file, f->func, f->line);
	f->file=file; f->func=func; f->line=line;
	qm->usage[ f->u.inuse.bucket ]--;
#endif
	if (IS_BIGBUCKET(qm,b)) {
		next=FRAG_NEXT(f);
		if  ((char *)next +sizeof( struct vqm_frag) < qm->core_end) {
			VQM_DEBUG_FRAG(qm, next);
			if (! FRAG_ISUSED(next)) { /* coalesce with next fragment */
				LM_DBG("coalesced with next\n");
				vqm_detach_free(qm, next);
				f->size+=next->size;
				FRAG_END(f)->size=f->size;
			}
		}
		first_big = qm->next_free[b];
		if (first_big &&  f>first_big) {
			prev=FRAG_PREV(f);
			VQM_DEBUG_FRAG(qm, prev);
			if (!FRAG_ISUSED(prev)) { /* coalesce with prev fragment */
				LM_DBG("coalesced with prev\n");
				vqm_detach_free(qm, prev );
				prev->size+=f->size;
				f=prev;
				FRAG_END(f)->size=f->size;
			}
		}
		if ((char *)f==qm->big_chunks) { /* release unused core */
			LM_DBG("big chunk released\n");
			qm->free_core+=f->size;
			qm->big_chunks+=f->size;
			return;
		}		
		first_big = qm->next_free[b];
		/* fix reverse link (used only for BIG_BUCKET */
		if (first_big) FRAG_END(first_big)->prv_free=f;
		FRAG_END(f)->prv_free=0;
	} else first_big = qm->next_free[b];
	f->u.nxt_free = first_big; /* also clobbers magic */
	qm->next_free[b] = f;
}
Example #20
0
void print_expr(struct expr* exp)
{
	if (exp==0){
		LM_CRIT("null expression!\n");
		return;
	}
	if (exp->type==ELEM_T){
		switch(exp->left.type){
			case METHOD_O:
				LM_GEN1(L_DBG, "method");
				break;
			case URI_O:
				LM_GEN1(L_DBG, "uri");
				break;
			case FROM_URI_O:
				LM_GEN1(L_DBG, "from_uri");
				break;
			case TO_URI_O:
				LM_GEN1(L_DBG, "to_uri");
				break;
			case SRCIP_O:
				LM_GEN1(L_DBG, "srcip");
				break;
			case SRCPORT_O:
				LM_GEN1(L_DBG, "srcport");
				break;
			case DSTIP_O:
				LM_GEN1(L_DBG, "dstip");
				break;
			case DSTPORT_O:
				LM_GEN1(L_DBG, "dstport");
				break;
			case SCRIPTVAR_O:
				LM_GEN1(L_DBG, "scriptvar[%d]",
					(exp->left.v.spec)?exp->left.v.spec->type:0);
				break;
			case NUMBER_O:
			case NUMBERV_O:
				LM_GEN1(L_DBG, "%d",exp->left.v.n);
				break;
			case STRINGV_O:
				LM_GEN1(L_DBG, "\"%s\"", ZSW((char*)exp->left.v.data));
				break;
			case ACTION_O:
				break;
			case EXPR_O:
				print_expr((struct expr*)exp->left.v.data);
				break;
			default:
				LM_GEN1(L_DBG, "UNKNOWN[%d]", exp->left.type);
		}
		switch(exp->op){
			case EQUAL_OP:
				LM_GEN1(L_DBG, "==");
				break;
			case MATCHD_OP:
			case MATCH_OP:
				LM_GEN1(L_DBG, "=~");
				break;
			case NOTMATCHD_OP:
			case NOTMATCH_OP:
				LM_GEN1(L_DBG, "!~");
				break;
			case GT_OP:
				LM_GEN1(L_DBG, ">");
				break;
			case GTE_OP:
				LM_GEN1(L_DBG, ">=");
				break;
			case LT_OP:
				LM_GEN1(L_DBG, "<");
				break;
			case LTE_OP:
				LM_GEN1(L_DBG, "<=");
				break;
			case DIFF_OP:
				LM_GEN1(L_DBG, "!=");
				break;
			case PLUS_OP:
				LM_GEN1(L_DBG, "+");
				break;
			case MINUS_OP:
				LM_GEN1(L_DBG, "-");
				break;
			case DIV_OP:
				LM_GEN1(L_DBG, "/");
				break;
			case MULT_OP:
				LM_GEN1(L_DBG, "*");
				break;
			case MODULO_OP:
				LM_GEN1(L_DBG, " mod ");
				break;
			case BAND_OP:
				LM_GEN1(L_DBG, "&");
				break;
			case BOR_OP:
				LM_GEN1(L_DBG, "|");
				break;
			case BXOR_OP:
				LM_GEN1(L_DBG, "^");
				break;
			case BLSHIFT_OP:
				LM_GEN1(L_DBG, "<<");
				break;
			case BRSHIFT_OP:
				LM_GEN1(L_DBG, ">>");
				break;
			case BNOT_OP:
				LM_GEN1(L_DBG, "~");
				break;
			case VALUE_OP:
			case NO_OP:
				break;
			default:
				LM_GEN1(L_DBG, "<UNKNOWN[%d]>", exp->op);
		}
		switch(exp->right.type){
			case NOSUBTYPE:
					/* LM_GEN1(L_DBG, "N/A"); */
					break;
			case STRING_ST:
					LM_GEN1(L_DBG, "\"%s\"", ZSW((char*)exp->right.v.data));
					break;
			case NET_ST:
					print_net((struct net*)exp->right.v.data);
					break;
			case IP_ST:
					print_ip("", (struct ip_addr*)exp->right.v.data, "");
					break;
			case ACTIONS_ST:
					print_actions((struct action*)exp->right.v.data);
					break;
			case NUMBER_ST:
					LM_GEN1(L_DBG, "%d",exp->right.v.n);
					break;
			case MYSELF_ST:
					LM_GEN1(L_DBG, "_myself_");
					break;
			case SCRIPTVAR_ST:
					LM_GEN1(L_DBG, "scriptvar[%d]", exp->right.v.spec->type);
					break;
			case NULLV_ST:
					LM_GEN1(L_DBG, "null");
					break;
			case EXPR_ST:
					print_expr((struct expr*)exp->right.v.data);
					break;
			default:
					LM_GEN1(L_DBG, "type<%d>", exp->right.type);
		}
	}else if (exp->type==EXP_T){
		switch(exp->op){
			case AND_OP:
					LM_GEN1(L_DBG, "AND( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case OR_OP:
					LM_GEN1(L_DBG, "OR( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case NOT_OP:
					LM_GEN1(L_DBG, "NOT( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case EVAL_OP:
					LM_GEN1(L_DBG, "EVAL( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case PLUS_OP:
					LM_GEN1(L_DBG, "PLUS( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case MINUS_OP:
					LM_GEN1(L_DBG, "MINUS( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case DIV_OP:
					LM_GEN1(L_DBG, "DIV( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case MULT_OP:
					LM_GEN1(L_DBG, "MULT( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case MODULO_OP:
					LM_GEN1(L_DBG, "MODULO( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BAND_OP:
					LM_GEN1(L_DBG, "BAND( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BOR_OP:
					LM_GEN1(L_DBG, "BOR( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BXOR_OP:
					LM_GEN1(L_DBG, "BXOR( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BLSHIFT_OP:
					LM_GEN1(L_DBG, "BLSHIFT( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BRSHIFT_OP:
					LM_GEN1(L_DBG, "BRSHIFT( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, ", ");
					print_expr(exp->right.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			case BNOT_OP:
					LM_GEN1(L_DBG, "BNOT( ");
					print_expr(exp->left.v.expr);
					LM_GEN1(L_DBG, " )");
					break;
			default:
					LM_GEN1(L_DBG, "UNKNOWN_EXP[%d] ", exp->op);
		}

	}else{
		LM_ERR("unknown type\n");
	}
}
Example #21
0
/* ret= 0! if action -> end of list(e.g DROP), 
      > 0 to continue processing next actions
   and <0 on error */
int do_action(struct action* a, struct sip_msg* msg)
{
	int ret;
	int v;
	int sec,usec;
	union sockaddr_union* to;
	struct proxy_l* p;
	char* tmp;
	char *new_uri, *end, *crt;
	int len,i;
	int user = 0;
	int expires = 0;
	str vals[5];
	str result;
	struct sip_uri uri, next_hop;
	struct sip_uri *u;
	unsigned short port;
	int cmatch;
	struct action *aitem;
	struct action *adefault;
	pv_spec_t *spec;
	pv_elem_p model;
	pv_value_t val;
	pv_elem_t *pve;
	str name_s;
	struct timeval start;
	int end_time;
	action_elem_t *route_params_bak;
	int route_params_number_bak;

	/* reset the value of error to E_UNSPEC so avoid unknowledgable
	   functions to return with error (status<0) and not setting it
	   leaving there previous error; cache the previous value though
	   for functions which want to process it */
	prev_ser_error=ser_error;
	ser_error=E_UNSPEC;

	start_expire_timer(start,execmsgthreshold);

	ret=E_BUG;
	switch ((unsigned char)a->type){
		case DROP_T:
				script_trace("core", "drop", msg, a->line) ;
				action_flags |= ACT_FL_DROP;
		case EXIT_T:
				script_trace("core", "exit", msg, a->line) ;
				ret=0;
				action_flags |= ACT_FL_EXIT;
			break;
		case RETURN_T:
				script_trace("core", "return", msg, a->line) ;
				if (a->elem[0].type == SCRIPTVAR_ST)
				{
					spec = (pv_spec_t*)a->elem[0].u.data;
					if(pv_get_spec_value(msg, spec, &val)!=0
						|| (val.flags&PV_VAL_NULL))
					{
						ret=-1;
					} else {
						if(!(val.flags&PV_VAL_INT))
							ret = 1;
						else
							ret = val.ri;
					}
					pv_value_destroy(&val);
				} else {
					ret=a->elem[0].u.number;
				}
				action_flags |= ACT_FL_RETURN;
			break;
		case FORWARD_T:
			script_trace("core", "forward", msg, a->line) ;
			if (a->elem[0].type==NOSUBTYPE){
				/* parse uri and build a proxy */
				if (msg->dst_uri.len) {
					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
						&next_hop);
					u = &next_hop;
				} else {
					ret = parse_sip_msg_uri(msg);
					u = &msg->parsed_uri;
				}
				if (ret<0) {
					LM_ERR("forward: bad_uri dropping packet\n");
					break;
				}
				/* create a temporary proxy*/
				p=mk_proxy(u->maddr_val.len?&u->maddr_val:&u->host,
					u->port_no, u->proto, (u->type==SIPS_URI_T)?1:0 );
				if (p==0){
					LM_ERR("bad host name in uri, dropping packet\n");
					ret=E_BAD_ADDRESS;
					goto error_fwd_uri;
				}
				ret=forward_request(msg, p);
				free_proxy(p); /* frees only p content, not p itself */
				pkg_free(p);
				if (ret==0) ret=1;
			}else if ((a->elem[0].type==PROXY_ST)) {
				ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data);
				if (ret==0) ret=1;
			}else{
				LM_ALERT("BUG in forward() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
			}
			break;
		case SEND_T:
			script_trace("core", "send", msg, a->line) ;
			if (a->elem[0].type!= PROXY_ST){
				LM_ALERT("BUG in send() type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (a->elem[1].u.data) {
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST){
					LM_ALERT("BUG in send() header type %d\n",a->elem[1].type);
					ret=E_BUG;
					break;
				} else {
					pve = (pv_elem_t *)a->elem[1].u.data;
				}
			} else {
				pve = NULL;
			}
			to=(union sockaddr_union*)
					pkg_malloc(sizeof(union sockaddr_union));
			if (to==0){
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			
			p=(struct proxy_l*)a->elem[0].u.data;
			
			ret=hostent2su(to, &p->host, p->addr_idx,
						(p->port)?p->port:SIP_PORT );
			if (ret==0){
				if (pve) {
					if ( pv_printf_s(msg, pve, &name_s)!=0 || 
							name_s.len == 0 || name_s.s == NULL) {
						LM_WARN("cannot get string for value\n");
						ret=E_UNSPEC;
						break;
					}
					/* build new msg */
					tmp = pkg_malloc(msg->len + name_s.len);
					if (!tmp) {
						LM_ERR("memory allocation failure\n");
						ret = E_OUT_OF_MEM;
						break;
					}
					LM_DBG("searching for first line %d\n",
							msg->first_line.len);
					/* search first line of previous msg */
					/* copy headers */
					len = msg->first_line.len;
					memcpy(tmp, msg->buf, len);
					memcpy(tmp + len, name_s.s, name_s.len);
					memcpy(tmp + len + name_s.len,
							msg->buf + len, msg->len - len);
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							tmp, msg->len + name_s.len);
					pkg_free(tmp);
				} else {
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							msg->buf, msg->len);
				}
				if (ret!=0 && p->host.h_addr_list[p->addr_idx+1])
					p->addr_idx++;
			}
			pkg_free(to);
			if (ret==0)
				ret=1;
			break;
		case LOG_T:
			script_trace("core", "log", msg, a->line) ;
			if ((a->elem[0].type!=NUMBER_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in log() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_GEN1(a->elem[0].u.number, "%s", a->elem[1].u.string);
			ret=1;
			break;
		case APPEND_BRANCH_T:
			script_trace("core", "append_branch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in append_branch %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[0].u.s.s==NULL) {
				ret = append_branch(msg, 0, &msg->dst_uri, &msg->path_vec,
					get_ruri_q(), getb0flags(), msg->force_send_socket);
				/* reset all branch info */
				msg->force_send_socket = 0;
				setb0flags(0);
				set_ruri_q(Q_UNSPECIFIED);
				if(msg->dst_uri.s!=0)
					pkg_free(msg->dst_uri.s);
				msg->dst_uri.s = 0;
				msg->dst_uri.len = 0;
				if(msg->path_vec.s!=0)
					pkg_free(msg->path_vec.s);
				msg->path_vec.s = 0;
				msg->path_vec.len = 0;
			} else {
				ret = append_branch(msg, &a->elem[0].u.s, &msg->dst_uri, 
					&msg->path_vec, a->elem[1].u.number, getb0flags(),
					msg->force_send_socket);
			}
			break;
		case REMOVE_BRANCH_T:
			script_trace("core", "remove_branch", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ST) {
				spec = (pv_spec_t*)a->elem[0].u.data;
				if( pv_get_spec_value(msg, spec, &val)!=0
				|| (val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_INT) ) {
					ret=-1;
					break;
				}
				i = val.ri;
			} else {
				i=a->elem[0].u.number;
			}
			ret = (remove_branch((unsigned int)i)==0)?1:-1;
			break;
		case LEN_GT_T:
			script_trace("core", "len_gt", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST) {
				LM_ALERT("BUG in len_gt type %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			ret = (msg->len >= (unsigned int)a->elem[0].u.number) ? 1 : -1;
			break;
		case SET_DEBUG_T:
			script_trace("core", "set_debug", msg, a->line) ;
			if (a->elem[0].type==NUMBER_ST)
				set_proc_debug_level(a->elem[0].u.number);
			else
				reset_proc_debug_level();
			ret = 1;
			break;
		case SETFLAG_T:
			script_trace("core", "setflag", msg, a->line) ;
			ret = setflag( msg, a->elem[0].u.number );
			break;
		case RESETFLAG_T:
			script_trace("core", "resetflag", msg, a->line) ;
			ret = resetflag( msg, a->elem[0].u.number );
			break;
		case ISFLAGSET_T:
			script_trace("core", "isflagset", msg, a->line) ;
			ret = isflagset( msg, a->elem[0].u.number );
			break;
		case SETSFLAG_T:
			script_trace("core", "setsflag", msg, a->line) ;
			ret = setsflag( a->elem[0].u.number );
			break;
		case RESETSFLAG_T:
			script_trace("core", "resetsflag", msg, a->line) ;
			ret = resetsflag( a->elem[0].u.number );
			break;
		case ISSFLAGSET_T:
			script_trace("core", "issflagset", msg, a->line) ;
			ret = issflagset( a->elem[0].u.number );
			break;
		case SETBFLAG_T:
			script_trace("core", "setbflag", msg, a->line) ;
			ret = setbflag( a->elem[0].u.number, a->elem[1].u.number );
			break;
		case RESETBFLAG_T:
			script_trace("core", "resetbflag", msg, a->line) ;
			ret = resetbflag( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ISBFLAGSET_T:
			script_trace("core", "isbflagset", msg, a->line) ;
			ret = isbflagset( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ERROR_T:
			script_trace("core", "error", msg, a->line) ;
			if ((a->elem[0].type!=STRING_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in error() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_ERR("error(\"%s\", \"%s\") not implemented yet\n",
				a->elem[0].u.string, a->elem[1].u.string);
			ret=1;
			break;
		case ROUTE_T:
			script_trace("route", rlist[a->elem[0].u.number].name, msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in route() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if ((a->elem[0].u.number>RT_NO)||(a->elem[0].u.number<0)){
				LM_ALERT("BUG - invalid routing table number in"
							"route(%lu)\n", a->elem[0].u.number);
				ret=E_CFG;
				break;
			}
			/* check if the route has parameters */
			if (a->elem[1].type != 0) {
				if (a->elem[1].type != NUMBER_ST || a->elem[2].type != SCRIPTVAR_ELEM_ST) {
					LM_ALERT("BUG in route() type %d/%d\n",
							a->elem[1].type, a->elem[2].type);
					ret=E_BUG;
					break;
				}
				route_params_bak = route_params;
				route_params = (action_elem_t *)a->elem[2].u.data;
				route_params_number_bak = route_params_number;
				route_params_number = a->elem[1].u.number;

				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
				route_params = route_params_bak;
				route_params_number = route_params_number_bak;
			} else {
				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
			}
			ret=return_code;
			break;
		case REVERT_URI_T:
			script_trace("core", "revert_uri", msg, a->line) ;
			if (msg->new_uri.s) {
				pkg_free(msg->new_uri.s);
				msg->new_uri.len=0;
				msg->new_uri.s=0;
				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
			};
			ret=1;
			break;
		case SET_HOST_T:
		case SET_HOSTPORT_T:
		case SET_USER_T:
		case SET_USERPASS_T:
		case SET_PORT_T:
		case SET_URI_T:
		case PREFIX_T:
		case STRIP_T:
		case STRIP_TAIL_T:
				script_trace("core", 
					(unsigned char)a->type == SET_HOST_T     ? "set_host" :
					(unsigned char)a->type == SET_HOSTPORT_T ? "set_hostport" : 
					(unsigned char)a->type == SET_USER_T     ? "set_user" :
					(unsigned char)a->type == SET_USERPASS_T ? "set_userpass" : 
					(unsigned char)a->type == SET_PORT_T     ? "set_port" :
					(unsigned char)a->type == SET_URI_T      ? "set_uri" : 
					(unsigned char)a->type == PREFIX_T       ? "prefix" :
					(unsigned char)a->type == STRIP_T  ? "strip" : "strip_tail",
					msg, a->line);
				user=0;
				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
					if (a->elem[0].type!=NUMBER_ST) {
						LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
						break;
					}
				} else if (a->elem[0].type!=STR_ST){
					LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (a->type==SET_URI_T) {
					if (set_ruri( msg, &a->elem[0].u.s) ) {
						LM_ERR("failed to set new RURI\n");
						ret=E_OUT_OF_MEM;
						break;
					}
					ret=1;
					break;
				}
				if (msg->new_uri.s) {
					tmp=msg->new_uri.s;
					len=msg->new_uri.len;
				}else{
					tmp=msg->first_line.u.request.uri.s;
					len=msg->first_line.u.request.uri.len;
				}
				if (parse_uri(tmp, len, &uri)<0){
					LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
					ret=E_UNSPEC;
					break;
				}
				
				new_uri=pkg_malloc(MAX_URI_SIZE);
				if (new_uri==0){
					LM_ERR("memory allocation failure\n");
					ret=E_OUT_OF_MEM;
					break;
				}
				end=new_uri+MAX_URI_SIZE;
				crt=new_uri;
				/* begin copying */
				len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);crt+=len;

				if (a->type==PREFIX_T) {
					if (crt+a->elem[0].u.s.len>end) goto error_uri;
					memcpy( crt, a->elem[0].u.s.s, a->elem[0].u.s.len);
					crt+=a->elem[0].u.s.len;
					/* whatever we had before, with prefix we have username 
					   now */
					user=1;
				}

				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else if (a->type==STRIP_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip asked; "
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s + a->elem[0].u.number;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else if (a->type==STRIP_TAIL_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip_tail asked;"
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else {
					tmp=uri.user.s;
					len=uri.user.len;
				}

				if (len){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					user=1; /* we have an user field so mark it */
				}

				if (a->type==SET_USERPASS_T) tmp=0;
				else tmp=uri.passwd.s;
				/* passwd */
				if (tmp){
					len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* host */
				if (user || tmp){ /* add @ */
					if(crt+1>end) goto error_uri;
					*crt='@'; crt++;
				}
				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.host.s;
					len = uri.host.len;
				}
				if (tmp){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* port */
				if (a->type==SET_HOSTPORT_T) tmp=0;
				else if (a->type==SET_PORT_T) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.port.s;
					len = uri.port.len;
				}
				if (tmp && len>0){
					if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* params */
				tmp=uri.params.s;
				if (tmp){
					/* include in param string the starting ';' */
					len=uri.params.len+1;
					tmp--;
					if(crt+len+1>end) goto error_uri;
					/* if a maddr param is present, strip it out */
					if (uri.maddr.len &&
					(a->type==SET_HOSTPORT_T || a->type==SET_HOST_T)) {
						memcpy(crt,tmp,uri.maddr.s-tmp-1);
						crt+=uri.maddr.s-tmp-1;
						memcpy(crt,uri.maddr_val.s+uri.maddr_val.len,
							tmp+len-uri.maddr_val.s-uri.maddr_val.len);
						crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len;
					} else {
						memcpy(crt,tmp,len);crt+=len;
					}
				}
				/* headers */
				tmp=uri.headers.s;
				if (tmp){
					len=uri.headers.len; if(crt+len+1>end) goto error_uri;
					*crt='?'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				*crt=0; /* null terminate the thing */
				/* copy it to the msg */
				if (msg->new_uri.s) pkg_free(msg->new_uri.s);
				msg->new_uri.s=new_uri;
				msg->new_uri.len=crt-new_uri;
				msg->parsed_uri_ok=0;
				ret=1;
				break;
		case SET_DSTURI_T:
			script_trace("core", "set_dsturi", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in setdsturi() type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if(set_dst_uri(msg, &a->elem[0].u.s)!=0)
				ret = -1;
			else
				ret = 1;
			break;
		case SET_DSTHOST_T:
		case SET_DSTPORT_T:
			script_trace("core", (unsigned char) a->type == SET_DSTHOST_T ?
						 "set_dsturi" : "set_dstport", msg, a->line);
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in domain setting type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}

			tmp = msg->dst_uri.s;
			len = msg->dst_uri.len;

			if (tmp == NULL || len == 0) {
				LM_ERR("failure - null uri\n");
				ret = E_UNSPEC;
				break;
			}
			if (a->type == SET_DSTHOST_T &&
					(a->elem[0].u.s.s == NULL || a->elem[0].u.s.len == 0)) {
				LM_ERR("cannot set a null uri domain\n");
				break;
			}
			if (parse_uri(tmp, len, &uri)<0) {
				LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
				break;
			}
			new_uri=pkg_malloc(MAX_URI_SIZE);
			if (new_uri == NULL) {
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			end=new_uri+MAX_URI_SIZE;
			crt=new_uri;
			len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
			if (crt+len>end) goto error_uri;
			memcpy(crt,tmp,len);
			crt += len;
			/* user */
			tmp = uri.user.s;
			len = uri.user.len;
			if (tmp) {
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);
				crt += len;
				user = 1;
			}
			/* passwd */
			tmp = uri.passwd.s;
			len = uri.passwd.len;
			if (user || tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* host */
			if (a->type==SET_DSTHOST_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.host.s;
				len = uri.host.len;
			}
			if (tmp) {
				if (user) {
					if (crt+1>end) goto error_uri;
					*crt++='@';
				}
				if (crt+len+1>end) goto error_uri;
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* port */
			if (a->type==SET_DSTPORT_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.port.s;
				len = uri.port.len;
			}
			if (tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* params */
			tmp=uri.params.s;
			if (tmp){
				len=uri.params.len; if(crt+len+1>end) goto error_uri;
				*crt++=';';
				memcpy(crt,tmp,len);
				crt += len;
			}
			/* headers */
			tmp=uri.headers.s;
			if (tmp){
				len=uri.headers.len; if(crt+len+1>end) goto error_uri;
				*crt++='?';
				memcpy(crt,tmp,len);
				crt += len;
			}
			*crt=0; /* null terminate the thing */
			/* copy it to the msg */
			pkg_free(msg->dst_uri.s);
			msg->dst_uri.s=new_uri;
			msg->dst_uri.len=crt-new_uri;
			ret = 1;
			break;
		case RESET_DSTURI_T:
			script_trace("core", "reset_dsturi", msg, a->line) ;
			if(msg->dst_uri.s!=0)
				pkg_free(msg->dst_uri.s);
			msg->dst_uri.s = 0;
			msg->dst_uri.len = 0;
			ret = 1;
			break;
		case ISDSTURISET_T:
			script_trace("core", "isdsturiset", msg, a->line) ;
			if(msg->dst_uri.s==0 || msg->dst_uri.len<=0)
				ret = -1;
			else
				ret = 1;
			break;
		case IF_T:
			script_trace("core", "if", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
					/* set return code to expr value */
					if (v<0 || (action_flags&ACT_FL_RETURN)
							|| (action_flags&ACT_FL_EXIT) ){
						if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){ /* hack to quit on DROP*/
							ret=0;
							return_code = 0;
							break;
						}else{
							LM_WARN("error in expression (l=%d)\n", a->line);
						}
					}
					
					ret=1;  /*default is continue */
					if (v>0) {
						if ((a->elem[1].type==ACTIONS_ST)&&a->elem[1].u.data){
							ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
							return_code = ret;
						} else return_code = v;
					}else{
						if ((a->elem[2].type==ACTIONS_ST)&&a->elem[2].u.data){
							ret=run_action_list(
								(struct action*)a->elem[2].u.data,msg);
							return_code = ret;
						} else return_code = v;
					}
				}
			break;
		case WHILE_T:
			script_trace("core", "while", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					len = 0;
					while(1)
					{
						if(len++ >= max_while_loops)
						{
							LM_INFO("max while loops are encountered\n");
							break;
						}
						v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
						/* set return code to expr value */
						if (v<0 || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
							if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
									|| (action_flags&ACT_FL_EXIT) ){
								ret=0;
								return_code = 0;
								break;
							}else{
								LM_WARN("error in expression (l=%d)\n",
										a->line);
							}
						}
					
						ret=1;  /*default is continue */
						if (v>0) {
							if ((a->elem[1].type==ACTIONS_ST)
									&&a->elem[1].u.data){
								ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
								/* check if return was done */
								if ((action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
									break;
								}
								return_code = ret;
							} else {
								/* we should not get here */
								return_code = v;
								break;
							}
						} else {
							/* condition was false */
							return_code = v;
							break;
						}
					}
				}
			break;
		case CACHE_STORE_T:
			script_trace("core", "cache_store", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[2].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - third argument not of type"
						" string%d\n", a->elem[2].type );
				ret=E_BUG;
				break;
			}

			str val_s;

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* parse the value argument */
			pve = (pv_elem_t *)a->elem[2].u.data;
			if ( pv_printf_s(msg, pve, &val_s)!=0 || 
			val_s.len == 0 || val_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* get the expires value */
			if ( a->elem[3].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[3].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_store\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_store expires, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				expires = val.ri;
			}
			else
			if ( a->elem[3].type == NUMBER_ST )
			{
				expires = (int)a->elem[3].u.number;
			}

			ret = cachedb_store( &a->elem[0].u.s, &name_s, &val_s,expires);

			break;
		case CACHE_REMOVE_T:
			script_trace("core", "cache_remove", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			ret = cachedb_remove( &a->elem[0].u.s, &name_s);
			break;
		case CACHE_FETCH_T:
			script_trace("core", "cache_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			str aux = {0, 0};
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_fetch( &a->elem[0].u.s, &name_s, &aux);
			if(ret > 0)
			{
				val.rs = aux;
				val.flags = PV_VAL_STR;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
				pkg_free(aux.s);
			}
			
			break;
		case CACHE_COUNTER_FETCH_T:
			script_trace("core", "cache_counter_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			int aux_counter;
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_counter_fetch( &a->elem[0].u.s, &name_s, &aux_counter);
			if(ret > 0)
			{
				val.ri = aux_counter;
				val.flags = PV_TYPE_INT|PV_VAL_INT;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
			}
			break;
		case CACHE_ADD_T:
			script_trace("core", "cache_add", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int increment=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_add\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_add, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				increment = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				increment = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return the new value to script ? */
			ret = cachedb_add(&a->elem[0].u.s, &name_s, increment,expires,NULL);
			break;
		case CACHE_SUB_T:
			script_trace("core", "cache_sub", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int decrement=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_sub\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_sub, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				decrement = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				decrement = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return new value to script ? */
			ret = cachedb_sub(&a->elem[0].u.s, &name_s, decrement,expires,NULL);
			break;
		case CACHE_RAW_QUERY_T:
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data != NULL && 
				a->elem[2].type!=STR_ST){
				LM_ALERT("BUG in cache_raw_query() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			cdb_raw_entry **cdb_reply;
			int val_number=0,i,j;
			int key_number=0;
			pvname_list_t *cdb_res,*it;
			int_str avp_val;
			int_str avp_name;
			unsigned short avp_type;

			if (a->elem[2].u.data) {
				cdb_res = (pvname_list_t*)a->elem[2].u.data;
				for (it=cdb_res;it;it=it->next)
					val_number++;

				LM_DBG("The query expects %d results back\n",val_number);

				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, &cdb_reply,val_number,&key_number);
				if (ret >= 0 && val_number > 0) {
					for (i=key_number-1; i>=0;i--) {
						it=cdb_res;
						for (j=0;j < val_number;j++) {
							avp_type = 0;
							if (pv_get_avp_name(msg,&it->sname.pvp,&avp_name.n,
								&avp_type) != 0) {
								LM_ERR("cannot get avp name [%d/%d]\n",i,j);
								goto next_avp;
							}
							
							switch (cdb_reply[i][j].type) {
								case CDB_INT:
									avp_val.n = cdb_reply[i][j].val.n; 
									break;
								case CDB_STR:
									avp_type |= AVP_VAL_STR;
									avp_val.s = cdb_reply[i][j].val.s;
									break;
								default:
									LM_WARN("Unknown type %d\n",cdb_reply[i][j].type);
									goto next_avp;
							}
							if (add_avp(avp_type,avp_name.n,avp_val) != 0) {
								LM_ERR("Unable to add AVP\n");
								free_raw_fetch(cdb_reply,val_number,key_number);
								return -1;
							}
next_avp:
							if (it) {
								it = it->next;
								if (it==NULL);
									break;
							}
						}
					}
					free_raw_fetch(cdb_reply,val_number,key_number);
				}
			}
			else
				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, NULL,0,NULL);
			break;
		case XDBG_T:
			script_trace("core", "xdbg", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ELEM_ST)
			{
				if (xdbg(msg, a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print message");
					break;
				}
			}
			else
			{
				LM_ALERT("BUG in xdbg() type %d\n", a->elem[0].type);
				ret=E_BUG;
			}
			break;
		case XLOG_T:
			script_trace("core", "xlog", msg, a->line) ;
			if (a->elem[1].u.data != NULL)
			{
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type);
					ret=E_BUG;
					break;
				}
				if (a->elem[0].type != STR_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}
			else
			{
				if (a->elem[0].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_1(msg,a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}

			break;
		case RAISE_EVENT_T:
			script_trace("core", "raise_event", msg, a->line) ;
			if (a->elem[0].type != NUMBER_ST) {
				LM_ERR("invalid event id\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				/* three parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						a->elem[1].u.data, a->elem[2].u.data);
			} else {
				/* two parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						NULL, a->elem[1].u.data);
			}
			if (ret <= 0) {
				LM_ERR("cannot raise event\n");
				ret=E_UNSPEC;
				break;
			}
			break;
		case SUBSCRIBE_EVENT_T:
			script_trace("core", "subscribe_event", msg, a->line) ;
			if (a->elem[0].type != STR_ST || a->elem[1].type != STR_ST) {
				LM_ERR("BUG in subscribe arguments\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				if (a->elem[2].type != NUMBER_ST) {
					LM_ERR("BUG in subscribe expiration time\n");
					ret=E_BUG;
					break;
				} else {
					i = a->elem[2].u.number;
				}
			} else {
				i = 0;
			}

			name_s.s = a->elem[0].u.data;
			name_s.len = strlen(name_s.s);
			/* result should be the socket */
			result.s = a->elem[1].u.data;
			result.len = strlen(result.s);
			ret = evi_event_subscribe(name_s, result, i, 0);
			break;

		case CONSTRUCT_URI_T:
			script_trace("core", "construct_uri", msg, a->line) ;
			for (i=0;i<5;i++)
			{
				pve = (pv_elem_t *)a->elem[i].u.data;
				if (pve->spec.getf)
				{
					if ( pv_printf_s(msg, pve, &vals[i])!=0 || 
						vals[i].len == 0 || vals[i].s == NULL) 
					{
						LM_WARN("cannot get string for value\n");
						ret=E_BUG;
						return -1;
					}
				}
				else
					vals[i] = pve->text;
			}
			
			result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4],
					&result.len);

			if (result.s)
			{
				int_str res;
				int avp_name;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[5].u.data;
				if (pv_get_avp_name( msg, &(spec->pvp), &avp_name,
						&avp_type)!=0){
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.s = result;
				if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			}

			break;
		case GET_TIMESTAMP_T:
			script_trace("core", "get_timestamp", msg, a->line) ;
			if (get_timestamp(&sec,&usec) == 0) {
				int avp_name;
				int_str res;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[0].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = sec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}

				spec = (pv_spec_t*)a->elem[1].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = usec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			} else {
				LM_ERR("failed to get time\n");
				return -1;
			}
			break;
		case SWITCH_T:
			script_trace("core", "switch", msg, a->line) ;
			if (a->elem[0].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in switch() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			spec = (pv_spec_t*)a->elem[0].u.data;
			if(pv_get_spec_value(msg, spec, &val)!=0)
			{
				LM_ALERT("BUG - no value in switch()\n");
				ret=E_BUG;
				break;
			}

			/* get the value of pvar */
			if(a->elem[1].type!=ACTIONS_ST) {
				LM_ALERT("BUG in switch() actions\n");
				ret=E_BUG;
				break;
			}
			return_code=1;
			adefault = NULL;
			aitem = (struct action*)a->elem[1].u.data;
			cmatch=0;
			while(aitem)
			{
				if((unsigned char)aitem->type==DEFAULT_T)
					adefault=aitem;
				if(cmatch==0)
				{
					if(aitem->elem[0].type==STR_ST)
					{
						if(val.flags&PV_VAL_STR
								&& val.rs.len==aitem->elem[0].u.s.len
								&& strncasecmp(val.rs.s, aitem->elem[0].u.s.s,
									val.rs.len)==0)
							cmatch = 1;
					} else { /* number */
						if(val.flags&PV_VAL_INT && 
								val.ri==aitem->elem[0].u.number)
							cmatch = 1;
					}
				}
				if(cmatch==1)
				{
					if(aitem->elem[1].u.data)
					{
						return_code=run_action_list(
							(struct action*)aitem->elem[1].u.data, msg);
						if ((action_flags&ACT_FL_RETURN) ||
						(action_flags&ACT_FL_EXIT))
							break;
					}
					if(aitem->elem[2].u.number==1)
						break;
				}
				aitem = aitem->next;
			}
			if((cmatch==0) && (adefault!=NULL))
			{
				LM_DBG("switch: running default statement\n");
				if(adefault->elem[0].u.data)
					return_code=run_action_list(
						(struct action*)adefault->elem[0].u.data, msg);
			}
			ret=return_code;
			break;
		case MODULE_T:
			script_trace("module", ((cmd_export_t*)(a->elem[0].u.data))->name,
				msg, a->line) ;
			if ( (a->elem[0].type==CMD_ST) && a->elem[0].u.data ) {
				ret=((cmd_export_t*)(a->elem[0].u.data))->function(msg,
						 (char*)a->elem[1].u.data, (char*)a->elem[2].u.data,
						 (char*)a->elem[3].u.data, (char*)a->elem[4].u.data,
						 (char*)a->elem[5].u.data, (char*)a->elem[6].u.data);
			}else{
				LM_ALERT("BUG in module call\n");
			}
			break;
		case FORCE_RPORT_T:
			script_trace("core", "force_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_RPORT;
			ret=1; /* continue processing */
			break;
		case FORCE_LOCAL_RPORT_T:
			script_trace("core", "force_local_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_LOCAL_RPORT;
			ret=1; /* continue processing */
			break;
		case SET_ADV_ADDR_T:
			script_trace("core", "set_adv_addr", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_address() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			str adv_addr;
			pve = (pv_elem_t *)a->elem[0].u.data;
			if ( pv_printf_s(msg, pve, &adv_addr)!=0 || 
			adv_addr.len == 0 || adv_addr.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			LM_DBG("adv address = [%.*s]\n",adv_addr.len,adv_addr.s);
			msg->set_global_address=adv_addr;
			ret=1; /* continue processing */
			break;
		case SET_ADV_PORT_T:
			script_trace("core", "set_adv_port", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_port() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}

			msg->set_global_port=*((str*)a->elem[0].u.data);
			ret=1; /* continue processing */
			break;
#ifdef USE_TCP
		case FORCE_TCP_ALIAS_T:
			script_trace("core", "force_tcp_alias", msg, a->line) ;
			if ( msg->rcv.proto==PROTO_TCP
#ifdef USE_TLS
					|| msg->rcv.proto==PROTO_TLS
#endif
			   ){
				
				if (a->elem[0].type==NOSUBTYPE)	port=msg->via1->port;
				else if (a->elem[0].type==NUMBER_ST)
					port=(int)a->elem[0].u.number;
				else{
					LM_ALERT("BUG in force_tcp_alias"
							" port type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
						
				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
									msg->rcv.proto)!=0){
					LM_ERR("tcp alias failed\n");
					ret=E_UNSPEC;
					break;
				}
			}
#endif
			ret=1; /* continue processing */
			break;
		case FORCE_SEND_SOCKET_T:
			script_trace("core", "force_send_socket", msg, a->line) ;
			if (a->elem[0].type!=SOCKETINFO_ST){
				LM_ALERT("BUG in force_send_socket argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			msg->force_send_socket=(struct socket_info*)a->elem[0].u.data;
			ret=1; /* continue processing */
			break;
		case SERIALIZE_BRANCHES_T:
			script_trace("core", "serialize_branches", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in serialize_branches argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (serialize_branches(msg,(int)a->elem[0].u.number)!=0) {
				LM_ERR("serialize_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			ret=1; /* continue processing */
			break;
		case NEXT_BRANCHES_T:
			script_trace("core", "next_branches", msg, a->line) ;
			if ((ret=next_branches(msg))<0) {
				LM_ERR("next_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			/* continue processing */
			break;
		case EQ_T:
		case COLONEQ_T:
		case PLUSEQ_T:
		case MINUSEQ_T:
		case DIVEQ_T:
		case MULTEQ_T:
		case MODULOEQ_T:
		case BANDEQ_T:
		case BOREQ_T:
		case BXOREQ_T:
			ret = do_assign(msg, a);
			break;
		case USE_BLACKLIST_T:
			script_trace("core", "use_blacklist", msg, a->line) ;
			mark_for_search((struct bl_head*)a->elem[0].u.data, 1);
			break;
		case UNUSE_BLACKLIST_T:
			script_trace("core", "unuse_blacklist", msg, a->line);
			mark_for_search((struct bl_head*)a->elem[0].u.data, 0);
			break;
		case PV_PRINTF_T:
			script_trace("core", "pv_printf", msg, a->line);
			ret = -1;
			spec = (pv_spec_p)a->elem[0].u.data;
			if(!pv_is_w(spec))
			{
				LM_ERR("read only PV in first parameter of pv_printf\n");
				goto error;
			}

			model = (pv_elem_p)a->elem[1].u.data;

			memset(&val, 0, sizeof(pv_value_t));
			if(pv_printf_s(msg, model, &val.rs)!=0)
			{
				LM_ERR("cannot eval second parameter\n");
				goto error;
			}
			val.flags = PV_VAL_STR;
			if(pv_set_value(msg, spec, EQ_T, &val)<0)
			{
				LM_ERR("setting PV failed\n");
				goto error;
			}
			
			ret = 1;
			break;
		case SCRIPT_TRACE_T:
			script_trace("core", "script_trace", msg, a->line);
			if (a->elem[0].type==NOSUBTYPE) {
				use_script_trace = 0;
			} else {
				
				use_script_trace = 1;
				
				if (a->elem[0].type != NUMBER_ST ||
					a->elem[1].type != SCRIPTVAR_ELEM_ST) {

					LM_ERR("BUG in use_script_trace() arguments\n");
					ret=E_BUG;
					break;
				}

				if (a->elem[2].type!=NOSUBTYPE) {
					script_trace_info = (char *)a->elem[2].u.data;
				} else {
					script_trace_info = NULL;
				}

				script_trace_log_level = (int)a->elem[0].u.number;
				script_trace_elem = *(pv_elem_p)a->elem[1].u.data;
			}

			break;
		default:
			LM_ALERT("BUG - unknown type %d\n", a->type);
			goto error;
	}

	if((unsigned char)a->type!=IF_T && (unsigned char)a->type!=ROUTE_T)
		return_code = ret;
/*skip:*/

	update_longest_action();
	return ret;

error:
	LM_ERR("error at line: %d\n", a->line);
	update_longest_action();
	return ret;
	
error_uri:
	LM_ERR("set*: uri too long\n");
	if (new_uri) pkg_free(new_uri);
	update_longest_action();
	return E_UNSPEC;
error_fwd_uri:
	update_longest_action();
	return ret;
}
Example #22
0
int _bm_log_timer(unsigned int id)
{
    /* BM_CLOCK_REALTIME */
    bm_timeval_t now;
    unsigned long long tdiff;

    if (!timer_active(id))
        return 1;

    if(bm_get_time(&now)<0)
    {
        LM_ERR("error getting current time\n");
        return -1;
    }

    tdiff = bm_diff_time(bm_mycfg->tindex[id]->start, &now);
    _bm_last_time_diff = (int)tdiff;

    /* What to do
     * - update min, max, sum
     * - if granularity hit: Log, reset min/max
     */

    bm_mycfg->tindex[id]->sum += tdiff;
    bm_mycfg->tindex[id]->last_sum += tdiff;
    bm_mycfg->tindex[id]->calls++;

    if (tdiff < bm_mycfg->tindex[id]->last_min)
        bm_mycfg->tindex[id]->last_min = tdiff;

    if (tdiff > bm_mycfg->tindex[id]->last_max)
        bm_mycfg->tindex[id]->last_max = tdiff;

    if (tdiff < bm_mycfg->tindex[id]->global_min)
        bm_mycfg->tindex[id]->global_min = tdiff;

    if (tdiff > bm_mycfg->tindex[id]->global_max)
        bm_mycfg->tindex[id]->global_max = tdiff;


    if ((bm_mycfg->tindex[id]->calls % bm_mycfg->granularity) == 0)
    {
        LM_GEN1(bm_mycfg->loglevel, "benchmark (timer %s [%d]): %llu ["
                " msgs/total/min/max/avg - LR:"
                " %i/%llu/%llu/%llu/%f | GB: %llu/%llu/%llu/%llu/%f]\n",
                bm_mycfg->tindex[id]->name,
                id,
                tdiff,
                bm_mycfg->granularity,
                bm_mycfg->tindex[id]->last_sum,
                bm_mycfg->tindex[id]->last_min,
                bm_mycfg->tindex[id]->last_max,
                ((double)bm_mycfg->tindex[id]->last_sum)/bm_mycfg->granularity,
                bm_mycfg->tindex[id]->calls,
                bm_mycfg->tindex[id]->sum,
                bm_mycfg->tindex[id]->global_min,
                bm_mycfg->tindex[id]->global_max,
                ((double)bm_mycfg->tindex[id]->sum)/bm_mycfg->tindex[id]->calls);

        bm_mycfg->tindex[id]->last_sum = 0;
        bm_mycfg->tindex[id]->last_max = 0;
        bm_mycfg->tindex[id]->last_min = 0xffffffff;
    }

    return 1;
}
Example #23
0
void hp_status(struct hp_block *hpb)
{
	struct hp_frag *f;
	int i, j, si, t = 0;
	int h;

	LM_GEN1(memdump, "hp_status (%p, ROUNDTO=%ld):\n", hpb, ROUNDTO);
	if (!hpb)
		return;

	LM_GEN1(memdump, "%20s : %ld\n", "HP_HASH_SIZE", HP_HASH_SIZE);
	LM_GEN1(memdump, "%20s : %ld\n", "HP_EXTRA_HASH_SIZE", HP_HASH_SIZE);
	LM_GEN1(memdump, "%20s : %ld\n", "HP_TOTAL_SIZE", HP_HASH_SIZE);

	LM_GEN1(memdump, "%20s : %ld\n", "total_size", hpb->size);

#ifdef STATISTICS
	LM_GEN1(memdump, "%20s : %lu\n%20s : %lu\n%20s : %lu\n",
			"used", hpb->used,
			"used+overhead", hpb->real_used,
			"free", hpb->size - hpb->used);

	LM_GEN1(memdump, "%20s : %lu\n\n", "max_used (+overhead)", hpb->max_real_used);
#endif

	LM_GEN1(memdump, "Dumping free fragments:\n");

	for (h = 0; h < HP_HASH_SIZE; h++) {
		if (hpb->free_hash[h].is_optimized) {
			LM_GEN1(memdump, "[ %4d ][ %5d B ][ frags: ", h, h * (int)ROUNDTO);

			for (si = HP_HASH_SIZE + h * shm_secondary_hash_size, j = 0;
				 j < shm_secondary_hash_size; j++, si++, t++) {

				SHM_LOCK(si);
				for (i=0, f=hpb->free_hash[si].first; f; f=f->u.nxt_free, i++, t++)
					;
				SHM_UNLOCK(si);

				LM_GEN1(memdump, "%s%5d ", j == 0 ? "" : "| ", i);
			}

			LM_GEN1(memdump, "]\n");

		} else {
			SHM_LOCK(h);
				for (i=0, f=hpb->free_hash[h].first; f; f=f->u.nxt_free, i++, t++)
					;
			SHM_UNLOCK(h);

			if (i == 0)
				continue;

			if (h > HP_LINEAR_HASH_SIZE) {
				LM_GEN1(memdump, "[ %4d ][ %8d B -> %7d B ][ frags: %5d ]\n",
						h, (int)UN_HASH(h), (int)UN_HASH(h+1) - (int)ROUNDTO, i);
			} else
				LM_GEN1(memdump, "[ %4d ][ %5d B ][ frags: %5d ]\n",
						h, h * (int)ROUNDTO, i);
		}
	}

	LM_GEN1(memdump, "TOTAL: %6d free fragments\n", t);
	LM_GEN1(memdump, "TOTAL: %ld large bytes\n", hpb->large_space );
	LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD );
	LM_GEN1(memdump, "-----------------------------\n");
}
Example #24
0
void* fm_malloc(struct fm_block* qm, unsigned long size)
#endif
{
    struct fm_frag* frag,*n;
    unsigned int hash;

#ifdef DBG_MALLOC
    LM_GEN1(memlog, "%s_malloc(%lu), called from %s: %s(%d)\n", qm->name, size, file, func,
            line);
#endif

    /*size must be a multiple of 8*/
    size=ROUNDUP(size);

    /*search for a suitable free frag*/

    for(hash=GET_HASH(size); hash<F_HASH_SIZE; hash++) {
        frag=qm->free_hash[hash].first;
        for( ; frag; frag = frag->u.nxt_free )
            if ( frag->size >= size ) goto found;
        /* try in a bigger bucket */
    }
    /* not found, bad! */

#if defined(DBG_MALLOC) || defined(STATISTICS)
    LM_ERR(oom_errorf, qm->name, qm->size - qm->real_used,
           qm->name[0] == 'p' ? "M" : "m");
    LM_INFO("attempting defragmentation... (need %lu bytes)\n", size);
#else
    LM_ERR(oom_nostats_errorf, qm->name, qm->name[0] == 'p' ? "M" : "m");
    LM_INFO("attempting defragmentation... (need %lu bytes)\n", size);
#endif

    for( frag = qm->first_frag; (char*)frag < (char*)qm->last_frag;  )
    {
        n = FRAG_NEXT(frag);

        if ( ((char*)n < (char*)qm->last_frag) &&  n->prev && frag->prev )
        {
            /* detach frag*/
            fm_remove_free(qm, frag);

            do
            {
                fm_remove_free(qm, n);
                frag->size += n->size + FRAG_OVERHEAD;

#if defined(DBG_MALLOC) || defined(STATISTICS)
                //qm->real_used -= FRAG_OVERHEAD;
                qm->used += FRAG_OVERHEAD;
#endif

                if( frag->size >size ) {
#ifdef DBG_MALLOC
                    /* mark it as "busy" */
                    frag->is_free = 0;
#endif

                    goto solved;
                }

                n = FRAG_NEXT(frag);
            }
            while
            ( ((char*)n < (char*)qm->last_frag) &&  n->prev);

            fm_insert_free(qm,frag);

        }

        frag = n;
    }

    LM_INFO("unable to alloc a big enough fragment!\n");
    pkg_threshold_check();
    return 0;


found:
    /* we found it!*/

    fm_remove_free(qm,frag);

#ifdef DBG_MALLOC
    /* mark it as "busy" */
    frag->is_free = 0;
#endif

    /*see if we'll use full frag, or we'll split it in 2*/

#ifdef DBG_MALLOC
    fm_split_frag(qm, frag, size, file, func, line);

    frag->file=file;
    frag->func=func;
    frag->line=line;
    frag->check=ST_CHECK_PATTERN;
    LM_GEN1(memlog, "%s_malloc(%lu), returns address %p\n", qm->name, size,
            (char*)frag+sizeof(struct fm_frag));
#else
    fm_split_frag(qm, frag, size);
#endif

solved:

#if defined(DBG_MALLOC) || defined(STATISTICS)
    if (qm->max_real_used<qm->real_used)
        qm->max_real_used=qm->real_used;
    qm->fragments += 1;
#endif

    pkg_threshold_check();
    return (char*)frag+sizeof(struct fm_frag);
}
Example #25
0
/**
 * Signal handler for the server.
 */
void handle_sigs(void)
{
	pid_t  chld;
	int    chld_status;
	int    i;
	int    do_exit;
	const unsigned int shutdown_time = 60; /* one minute close timeout */

	switch(sig_flag){
		case 0: break; /* do nothing*/
		case SIGPIPE:
				/* SIGPIPE might be rarely received on use of
				   exec module; simply ignore it
				 */
				LM_WARN("SIGPIPE received and ignored\n");
				break;
		case SIGINT:
		case SIGTERM:
			/* we end the program in all these cases */
			if (sig_flag==SIGINT)
				LM_DBG("INT received, program terminates\n");
			else
				LM_DBG("SIGTERM received, program terminates\n");
				
			/* first of all, kill the children also */
			kill_all_children(SIGTERM);
			if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) {
				LM_ERR("could not install SIGALARM handler\n");
				/* continue, the process will die anyway if no
				 * alarm is installed which is exactly what we want */
			}
			alarm(shutdown_time);
			while(wait(0) > 0); /* Wait for all the children to terminate */
			signal(SIGALRM, sig_alarm_abort);

			cleanup(1); /* cleanup & show status*/
			alarm(0);
			signal(SIGALRM, SIG_IGN);
			dprint("Thank you for flying " NAME "\n");
			exit(0);
			break;
			
		case SIGUSR1:
#ifdef PKG_MALLOC
			LM_GEN1(memdump, "Memory status (pkg):\n");
			pkg_status();
#endif
#ifdef SHM_MEM
			LM_GEN1(memdump, "Memory status (shm):\n");
			shm_status();
#endif
			break;
			
		case SIGUSR2:
#ifdef PKG_MALLOC
			set_pkg_stats( get_pkg_status_holder(process_no) );
#endif
			break;
			
		case SIGCHLD:
			do_exit = 0;
			while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
				/* is it a process we know about? */
				for( i=0 ; i<counted_processes ; i++ )
					if (pt[i].pid==chld) break;
				if (i==counted_processes) {
					LM_DBG("unkown child process %d ended. Ignoring\n",chld);
					continue;
				}
				do_exit = 1;
				/* process the signal */
				if (WIFEXITED(chld_status)) 
					LM_INFO("child process %d exited normally,"
							" status=%d\n", chld, 
							WEXITSTATUS(chld_status));
				else if (WIFSIGNALED(chld_status)) {
					LM_INFO("child process %d exited by a signal"
							" %d\n", chld, WTERMSIG(chld_status));
#ifdef WCOREDUMP
					LM_INFO("core was %sgenerated\n",
							 WCOREDUMP(chld_status) ?  "" : "not " );
#endif
				}else if (WIFSTOPPED(chld_status)) 
					LM_INFO("child process %d stopped by a"
								" signal %d\n", chld,
								 WSTOPSIG(chld_status));
			}
			if (!do_exit)
				break;
			LM_INFO("terminating due to SIGCHLD\n");
			/* exit */
			kill_all_children(SIGTERM);
			if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) {
				LM_ERR("could not install SIGALARM handler\n");
				/* continue, the process will die anyway if no
				 * alarm is installed which is exactly what we want */
			}
			alarm(shutdown_time);
			while(wait(0) > 0); /* wait for all the children to terminate*/
			signal(SIGALRM, sig_alarm_abort);
			cleanup(1); /* cleanup & show status*/
			alarm(0);
			signal(SIGALRM, SIG_IGN);
			LM_DBG("terminating due to SIGCHLD\n");
			exit(0);
			break;
		
		case SIGHUP: /* ignoring it*/
			LM_DBG("SIGHUP received, ignoring it\n");
			break;
		default:
			LM_CRIT("unhandled signal %d\n", sig_flag);
	}
	sig_flag=0;
}
Example #26
0
void* vqm_malloc(struct vqm_block* qm, unsigned int size)
#endif
{
	struct vqm_frag *new_chunk, *f;
	unsigned char bucket;
	
#ifdef DBG_QM_MALLOC
	unsigned int demanded_size;
	LM_GEN1( memlog, "params (%p, %d) called from %s: %s(%d)\n",
		qm, size, file, func, line);
	demanded_size = size;
#endif
	new_chunk=0;
	/* what's the bucket? what's the total size incl. overhead? */
	bucket = size2bucket( qm, &size );

	if (IS_BIGBUCKET(qm, bucket)) {	/* the kilo-bucket uses first-fit */
#ifdef DBG_QM_MALLOC
		LM_GEN1( memlog, "processing a big fragment\n");
#endif
		for (f=qm->next_free[bucket] ; f; f=f->u.nxt_free ) 
			if (f->size>=size) { /* first-fit */
				new_chunk=f;
				VQM_DEBUG_FRAG(qm, f);
				vqm_detach_free(qm,f);
				break;
			}
	} else if (  (new_chunk=qm->next_free[ bucket ]) ) { /*fixed size bucket*/
			VQM_DEBUG_FRAG(qm, new_chunk);
			/*detach it from the head of bucket's free list*/
			qm->next_free[ bucket ] = new_chunk->u.nxt_free;
	}

	if (!new_chunk) { /* no chunk can be reused; slice one from the core */
		new_chunk=MORE_CORE( qm, bucket, size );
		if (!new_chunk) {
#ifdef DBG_QM_MALLOC
			LM_GEN1(memlog, "params (%p, %d) called from %s: %s(%d)\n", 
				qm, size, file, func, line);
#else
			LM_DBG("params (%p, %d) called from %s: %s(%d)\n", 
				qm, size);
#endif
			return 0;
		}
	}
	new_chunk->u.inuse.magic = FR_USED;
	new_chunk->u.inuse.bucket=bucket;
#ifdef DBG_QM_MALLOC
	new_chunk->file=file;
	new_chunk->func=func;
	new_chunk->line=line;
	new_chunk->demanded_size=demanded_size;
	qm->usage[ bucket ]++;
	LM_GEN1( memlog,"params ( %p, %d ) returns address %p in bucket %d, "
		"real-size %d\n",
		qm, demanded_size, (char*)new_chunk+sizeof(struct vqm_frag), 
		bucket, size );

	new_chunk->end_check=(char*)new_chunk+
							sizeof(struct vqm_frag)+demanded_size;
	memcpy(  new_chunk->end_check, END_CHECK_PATTERN, END_CHECK_PATTERN_LEN );
	new_chunk->check=ST_CHECK_PATTERN;
#endif
	return (char*)new_chunk+sizeof(struct vqm_frag);
}
Example #27
0
int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size)
#endif
{
	unsigned long rest;
	struct qm_frag* n;
	struct qm_frag_end* end;
	
	rest=f->size-new_size;
#ifdef MEM_FRAG_AVOIDANCE
	if ((rest> (FRAG_OVERHEAD+QM_MALLOC_OPTIMIZE))||
		(rest>=(FRAG_OVERHEAD+new_size))){/* the residue fragm. is big enough*/
#else
	if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){
#endif
		f->size=new_size;
		/*split the fragment*/
		end=FRAG_END(f);
		end->size=new_size;
		n=(struct qm_frag*)((char*)end+sizeof(struct qm_frag_end));
		n->size=rest-FRAG_OVERHEAD;
		FRAG_END(n)->size=n->size;
		FRAG_CLEAR_USED(n); /* never used */
		qm->real_used+=FRAG_OVERHEAD;
#ifdef DBG_QM_MALLOC
		end->check1=END_CHECK_PATTERN1;
		end->check2=END_CHECK_PATTERN2;
		/* frag created by malloc, mark it*/
		n->file=file;
		n->func=func;
		n->line=line;
		n->check=ST_CHECK_PATTERN;
#endif
		/* reinsert n in free list*/
		qm_insert_free(qm, n);
		return 0;
	}else{
			/* we cannot split this fragment any more */
		return -1;
	}
}



#ifdef DBG_QM_MALLOC
void* qm_malloc(struct qm_block* qm, unsigned long size,
					const char* file, const char* func, unsigned int line)
#else
void* qm_malloc(struct qm_block* qm, unsigned long size)
#endif
{
	struct qm_frag* f;
	int hash;
	
#ifdef DBG_QM_MALLOC
	unsigned int list_cntr;

	list_cntr = 0;
	LM_GEN1( memlog, "params (%p, %lu), called from %s: %s(%d)\n",
		qm, size, file, func, line);
#endif
	/*size must be a multiple of 8*/
	size=ROUNDUP(size);
	if (size>(qm->size-qm->real_used)) return 0;

	/*search for a suitable free frag*/
#ifdef DBG_QM_MALLOC
	if ((f=qm_find_free(qm, size, &hash, &list_cntr))!=0){
#else
	if ((f=qm_find_free(qm, size, &hash))!=0){
#endif
		/* we found it!*/
		/*detach it from the free list*/
#ifdef DBG_QM_MALLOC
			qm_debug_frag(qm, f);
#endif
		qm_detach_free(qm, f);
		/*mark it as "busy"*/
		f->u.is_free=0;
		qm->free_hash[hash].no--;
		/* we ignore split return */
#ifdef DBG_QM_MALLOC
		split_frag(qm, f, size, file, "fragm. from qm_malloc", line);
#else
		split_frag(qm, f, size);
#endif
		qm->real_used+=f->size;
		qm->used+=f->size;
		if (qm->max_real_used<qm->real_used)
			qm->max_real_used=qm->real_used;
#ifdef DBG_QM_MALLOC
		f->file=file;
		f->func=func;
		f->line=line;
		f->check=ST_CHECK_PATTERN;
		/*  FRAG_END(f)->check1=END_CHECK_PATTERN1;
			FRAG_END(f)->check2=END_CHECK_PATTERN2;*/
		LM_GEN1( memlog, "params (%p, %lu), returns address %p frag. %p "
			"(size=%lu) on %d -th hit\n",
			 qm, size, (char*)f+sizeof(struct qm_frag), f, f->size, list_cntr );
#endif
		return (char*)f+sizeof(struct qm_frag);
	}
	return 0;
}



#ifdef DBG_QM_MALLOC
void qm_free(struct qm_block* qm, void* p, const char* file, const char* func, 
				unsigned int line)
#else
void qm_free(struct qm_block* qm, void* p)
#endif
{
	struct qm_frag* f;
	unsigned long size;
#ifdef QM_JOIN_FREE
	struct qm_frag* next;
	struct qm_frag* prev;
#endif

#ifdef DBG_QM_MALLOC
	LM_GEN1( memlog, "params(%p, %p), called from %s: %s(%d)\n",
		qm, p, file, func, line);
	if (p>(void*)qm->last_frag_end || p<(void*)qm->first_frag){
		LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
		abort();
	}
#endif
	if (p==0) {
		LM_WARN("free(0) called\n");
		return;
	}
#ifdef QM_JOIN_FREE
	prev=next=0;
#endif
	f=(struct qm_frag*) ((char*)p-sizeof(struct qm_frag));
#ifdef DBG_QM_MALLOC
	qm_debug_frag(qm, f);
	if (f->u.is_free){
		LM_CRIT("freeing already freed pointer,"
				" first free: %s: %s(%ld) - aborting\n",
				f->file, f->func, f->line);
		abort();
	}
	LM_GEN1( memlog, "freeing frag. %p alloc'ed from %s: %s(%ld)\n",
			f, f->file, f->func, f->line);
#endif
	size=f->size;
	qm->used-=size;
	qm->real_used-=size;

#ifdef QM_JOIN_FREE
	/* join packets if possible*/
	next=FRAG_NEXT(f);
	if (((char*)next < (char*)qm->last_frag_end) &&( next->u.is_free)){
		/* join */
#ifdef DBG_QM_MALLOC
		qm_debug_frag(qm, next);
#endif
		qm_detach_free(qm, next);
		size+=next->size+FRAG_OVERHEAD;
		qm->real_used-=FRAG_OVERHEAD;
		qm->free_hash[GET_HASH(next->size)].no--; /* FIXME slow */
	}
	
	if (f > qm->first_frag){
		prev=FRAG_PREV(f);
		/*	(struct qm_frag*)((char*)f - (struct qm_frag_end*)((char*)f-
								sizeof(struct qm_frag_end))->size);*/
#ifdef DBG_QM_MALLOC
		qm_debug_frag(qm, prev);
#endif
		if (prev->u.is_free){
			/*join*/
			qm_detach_free(qm, prev);
			size+=prev->size+FRAG_OVERHEAD;
			qm->real_used-=FRAG_OVERHEAD;
			qm->free_hash[GET_HASH(prev->size)].no--; /* FIXME slow */
			f=prev;
		}
	}
	f->size=size;
	FRAG_END(f)->size=f->size;
#endif /* QM_JOIN_FREE*/
#ifdef DBG_QM_MALLOC
	f->file=file;
	f->func=func;
	f->line=line;
#endif
	qm_insert_free(qm, f);
}



#ifdef DBG_QM_MALLOC
void* qm_realloc(struct qm_block* qm, void* p, unsigned long size,
					const char* file, const char* func, unsigned int line)
#else
void* qm_realloc(struct qm_block* qm, void* p, unsigned long size)
#endif
{
	struct qm_frag* f;
	unsigned long diff;
	unsigned long orig_size;
	struct qm_frag* n;
	void* ptr;
	
	
#ifdef DBG_QM_MALLOC
	LM_GEN1( memlog, "params (%p, %p, %lu), called from %s: %s(%d)\n",
		qm, p, size, file, func, line);
	if ((p)&&(p>(void*)qm->last_frag_end || p<(void*)qm->first_frag)){
		LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
		abort();
	}
#endif
	
	if (size==0) {
		if (p)
#ifdef DBG_QM_MALLOC
			qm_free(qm, p, file, func, line);
#else
			qm_free(qm, p);
#endif
		return 0;
	}
	if (p==0)
#ifdef DBG_QM_MALLOC
		return qm_malloc(qm, size, file, func, line);
#else
		return qm_malloc(qm, size);
#endif
	f=(struct qm_frag*) ((char*)p-sizeof(struct qm_frag));
#ifdef DBG_QM_MALLOC
	qm_debug_frag(qm, f);
	LM_GEN1( memlog, "realloc'ing frag %p alloc'ed from %s: %s(%ld)\n",
			f, f->file, f->func, f->line);
	if (f->u.is_free){
		LM_CRIT("trying to realloc an already freed "
				"pointer %p , fragment %p -- aborting\n", p, f);
		abort();
	}
#endif
	/* find first acceptable size */
	size=ROUNDUP(size);
	if (f->size > size){
		orig_size=f->size;
		/* shrink */
#ifdef DBG_QM_MALLOC
		LM_GEN1(memlog,"shrinking from %lu to %lu\n", f->size, size);
		if(split_frag(qm, f, size, file, "fragm. from qm_realloc", line)!=0){
		LM_GEN1(memlog,"shrinked successful\n");
#else
		if(split_frag(qm, f, size)!=0){
#endif
			/* update used sizes: freed the spitted frag */
			qm->real_used-=(orig_size-f->size-FRAG_OVERHEAD);
			qm->used-=(orig_size-f->size);
		}
		
	}else if (f->size < size){
		/* grow */
#ifdef DBG_QM_MALLOC
		LM_GEN1( memlog, "growing from %lu to %lu\n", f->size, size);
#endif
			orig_size=f->size;
			diff=size-f->size;
			n=FRAG_NEXT(f);
			if (((char*)n < (char*)qm->last_frag_end) && 
					(n->u.is_free)&&((n->size+FRAG_OVERHEAD)>=diff)){
				/* join  */
				qm_detach_free(qm, n);
				qm->free_hash[GET_HASH(n->size)].no--; /*FIXME: slow*/
				f->size+=n->size+FRAG_OVERHEAD;
				qm->real_used-=FRAG_OVERHEAD;
				FRAG_END(f)->size=f->size;
				/* end checks should be ok */
				/* split it if necessary */
				if (f->size > size ){
	#ifdef DBG_QM_MALLOC
					split_frag(qm, f, size, file, "fragm. from qm_realloc",
										line);
	#else
					split_frag(qm, f, size);
	#endif
				}
				qm->real_used+=(f->size-orig_size);
				qm->used+=(f->size-orig_size);
			}else{
				/* could not join => realloc */
	#ifdef DBG_QM_MALLOC
				ptr=qm_malloc(qm, size, file, func, line);
	#else
				ptr=qm_malloc(qm, size);
	#endif
				if (ptr) {
					/* copy, need by libssl */
					memcpy(ptr, p, orig_size);
	#ifdef DBG_QM_MALLOC
					qm_free(qm, p, file, func, line);
	#else
					qm_free(qm, p);
	#endif
				}
				p=ptr;
			}
	}else{
		/* do nothing */
#ifdef DBG_QM_MALLOC
		LM_GEN1(memlog,"doing nothing, same size: %lu - %lu\n", f->size, size);
#endif
	}
#ifdef DBG_QM_MALLOC
	LM_GEN1(memlog,"returning %p\n", p);
#endif
	return p;
}




void qm_status(struct qm_block* qm)
{
	struct qm_frag* f;
	int i,j;
	int h;
	int unused;

	LM_GEN1(memdump, "qm_status (%p):\n", qm);
	if (!qm) return;

	LM_GEN1(memdump, " heap size= %lu\n", qm->size);
	LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n",
			qm->used, qm->real_used, qm->size-qm->real_used);
	LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used);
	
	LM_GEN1(memdump, "dumping all alloc'ed. fragments:\n");
	for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;f=FRAG_NEXT(f)
			,i++){
		if (! f->u.is_free){
			LM_GEN1(memdump,"    %3d. %c  address=%p frag=%p size=%lu used=%d\n",
				i, 
				(f->u.is_free)?'a':'N',
				(char*)f+sizeof(struct qm_frag), f, f->size, FRAG_WAS_USED(f));
#ifdef DBG_QM_MALLOC
			LM_GEN1(memdump, "            %s from %s: %s(%ld)\n",
				(f->u.is_free)?"freed":"alloc'd", f->file, f->func, f->line);
			LM_GEN1(memdump, "        start check=%lx, end check= %lx, %lx\n",
				f->check, FRAG_END(f)->check1, FRAG_END(f)->check2);
#endif
		}
	}
	LM_GEN1(memdump, "dumping free list stats :\n");
	for(h=0,i=0;h<QM_HASH_SIZE;h++){
		unused=0;
		for (f=qm->free_hash[h].head.u.nxt_free,j=0; 
				f!=&(qm->free_hash[h].head); f=f->u.nxt_free, i++, j++){
				if (!FRAG_WAS_USED(f)){
					unused++;
#ifdef DBG_QM_MALLOC
					LM_GEN1(memdump, "unused fragm.: hash = %3d, fragment %p,"
						" address %p size %lu, created from %s: %s(%lu)\n",
					    h, f, (char*)f+sizeof(struct qm_frag), f->size,
						f->file, f->func, f->line);
#endif
				}
		}

		if (j) LM_GEN1(memdump, "hash= %3d. fragments no.: %5d, unused: %5d\n"
					"\t\t bucket size: %9lu - %9ld (first %9lu)\n",
					h, j, unused, UN_HASH(h),
					((h<=QM_MALLOC_OPTIMIZE/ROUNDTO)?1:2)*UN_HASH(h),
					qm->free_hash[h].head.u.nxt_free->size
				);
		if (j!=qm->free_hash[h].no){
			LM_CRIT("different free frag. count: %d!=%lu"
				" for hash %3d\n", j, qm->free_hash[h].no, h);
		}

	}
	LM_GEN1(memdump, "-----------------------------\n");
}


/* fills a malloc info structure with info about the block
 * if a parameter is not supported, it will be filled with 0 */
void qm_info(struct qm_block* qm, struct mem_info* info)
{
	int r;
	long total_frags;
	
	total_frags=0;
	memset(info,0, sizeof(*info));
	info->total_size=qm->size;
	info->min_frag=MIN_FRAG_SIZE;
	info->free=qm->size-qm->real_used;
	info->used=qm->used;
	info->real_used=qm->real_used;
	info->max_used=qm->max_real_used;
	for(r=0;r<QM_HASH_SIZE; r++){
		total_frags+=qm->free_hash[r].no;
	}
	info->total_frags=total_frags;
}
Example #28
0
void* fm_realloc(struct fm_block* qm, void* p, unsigned long size)
#endif
{
    struct fm_frag *f;
    unsigned long diff;
    unsigned long orig_size;
    struct fm_frag *n;
    void *ptr;


#ifdef DBG_MALLOC
    LM_GEN1(memlog, "%s_realloc(%p, %lu->%lu), called from %s: %s(%d)\n", qm->name,
            p, p ? ((struct fm_frag*)((char *)p - sizeof(struct fm_frag)))->size:0,
            size, file, func, line);
    if ((p)&&(p>(void*)qm->last_frag || p<(void*)qm->first_frag)) {
        LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p);
        abort();
    }
#endif
    if (size==0) {
        if (p)
#ifdef DBG_MALLOC
            fm_free(qm, p, file, func, line);
#else
            fm_free(qm, p);
#endif
        pkg_threshold_check();
        return 0;
    }
    if (p==0)
#ifdef DBG_MALLOC
        return fm_malloc(qm, size, file, func, line);
#else
        return fm_malloc(qm, size);
#endif
    f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag));
#ifdef DBG_MALLOC
    LM_GEN1(memlog, "realloc'ing frag %p alloc'ed from %s: %s(%ld)\n",
            f, f->file, f->func, f->line);
#endif
    size=ROUNDUP(size);
    orig_size=f->size;
    if (f->size > size) {
        /* shrink */
#ifdef DBG_MALLOC
        LM_GEN1(memlog, "shrinking from %lu to %lu\n", f->size, size);
        fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line);
#else
        fm_split_frag(qm, f, size);
#endif

    } else if (f->size<size) {
        /* grow */

#ifdef DBG_MALLOC
        LM_GEN1(memlog, "growing from %lu to %lu\n", f->size, size);
#endif

        diff=size-f->size;
        n=FRAG_NEXT(f);

        if (((char*)n < (char*)qm->last_frag) &&  n->prev &&
                ((n->size+FRAG_OVERHEAD)>=diff)) {

            fm_remove_free(qm,n);
            /* join */
            f->size += n->size + FRAG_OVERHEAD;

#if defined(DBG_MALLOC) || defined(STATISTICS)
            //qm->real_used -= FRAG_OVERHEAD;
            qm->used += FRAG_OVERHEAD;
#endif

            /* split it if necessary */
            if (f->size > size) {
#ifdef DBG_MALLOC
                fm_split_frag(qm, f, size, file, "fragm. from fm_realloc",
                              line);
#else
                fm_split_frag(qm, f, size);
#endif
            }
        } else {
            /* could not join => realloc */
#ifdef DBG_MALLOC
            ptr=fm_malloc(qm, size, file, func, line);
#else
            ptr = fm_malloc(qm, size);
#endif
            if (ptr) {
                /* copy, need by libssl */
                memcpy(ptr, p, orig_size);
#ifdef DBG_MALLOC
                fm_free(qm, p, file, func, line);
#else
                fm_free(qm, p);
#endif
            }
            p = ptr;
        }
    } else {
        /* do nothing */
#ifdef DBG_MALLOC
        LM_GEN1(memlog, "doing nothing, same size: %lu - %lu\n", f->size, size);
#endif
    }
#ifdef DBG_MALLOC
    LM_GEN1(memlog, "returning %p\n", p);
#endif

#if defined(DBG_MALLOC) || defined(STATISTICS)
    if (qm->max_real_used<qm->real_used)
        qm->max_real_used=qm->real_used;
#endif

    pkg_threshold_check();
    return p;
}