예제 #1
0
파일: dbpool.c 프로젝트: Phonebooth/kannel
unsigned int dbpool_decrease(DBPool *p, unsigned int c)
{
    unsigned int i;

    gw_assert(p != NULL && p->pool != NULL && p->db_ops != NULL && p->db_ops->close != NULL);

    /* lock dbpool for updates */
    gwlist_lock(p->pool);

    /*
     * Ensure we don't try to decrease more then available in pool.
     */
    for (i = 0; i < c; i++) {
        DBPoolConn *pc;

        /* gwlist_extract_first doesn't block even if no conn here */
        pc = gwlist_extract_first(p->pool);

        /* no conn availible anymore */
        if (pc == NULL)
            break;

        /* close connections and destroy pool connection */
        dbpool_conn_destroy(pc);
        p->curr_size--;
    }

    /* unlock dbpool for updates */
    gwlist_unlock(p->pool);

    return i;
}
예제 #2
0
파일: dbpool.c 프로젝트: Phonebooth/kannel
unsigned int dbpool_increase(DBPool *p, unsigned int count)
{
    unsigned int i, opened = 0;

    gw_assert(p != NULL && p->conf != NULL && p->db_ops != NULL && p->db_ops->open != NULL);


    /* lock dbpool for updates */
    gwlist_lock(p->pool);

    /* ensure we don't increase more items than the max_size border */
    for (i=0; i < count && p->curr_size < p->max_size; i++) {
        void *conn = p->db_ops->open(p->conf);
        if (conn != NULL) {
            DBPoolConn *pc = gw_malloc(sizeof(DBPoolConn));
            gw_assert(pc != NULL);

            pc->conn = conn;
            pc->pool = p;

            p->curr_size++;
            opened++;
            gwlist_produce(p->pool, pc);
        }
    }

    /* unlock dbpool for updates */
    gwlist_unlock(p->pool);

    return opened;
}
예제 #3
0
파일: bb_boxc.c 프로젝트: Phonebooth/kannel
static void run_wapbox(void *arg)
{
    Boxc *newconn;
    List *newlist;
    long sender;

    gwlist_add_producer(flow_threads);
    newconn = arg;
    newconn->is_wap = 1;
    
    /*
     * create a new incoming list for just that box,
     * and add it to list of list pointers, so we can start
     * to route messages to it.
     */

    debug("bb", 0, "setting up systems for new wapbox");
    
    newlist = gwlist_create();
    /* this is released by the sender/receiver if it exits */
    gwlist_add_producer(newlist);
    
    newconn->incoming = newlist;
    newconn->retry = incoming_wdp;
    newconn->outgoing = outgoing_wdp;

    sender = gwthread_create(boxc_sender, newconn);
    if (sender == -1) {
	    error(0, "Failed to start a new thread, disconnecting client <%s>",
	          octstr_get_cstr(newconn->client_ip));
	    goto cleanup;
    }
    gwlist_append(wapbox_list, newconn);
    gwlist_add_producer(newconn->outgoing);
    boxc_receiver(newconn);

    /* cleanup after receiver has exited */
    
    gwlist_remove_producer(newconn->outgoing);
    gwlist_lock(wapbox_list);
    gwlist_delete_equal(wapbox_list, newconn);
    gwlist_unlock(wapbox_list);

    while (gwlist_producer_count(newlist) > 0)
	    gwlist_remove_producer(newlist);

    newconn->alive = 0;
    
    gwthread_join(sender);

cleanup:
    gw_assert(gwlist_len(newlist) == 0);
    gwlist_destroy(newlist, NULL);
    boxc_destroy(newconn);

    gwlist_remove_producer(flow_threads);
}
예제 #4
0
파일: dbpool.c 프로젝트: Phonebooth/kannel
DBPoolConn *dbpool_conn_consume(DBPool *p)
{
    DBPoolConn *pc;

    gw_assert(p != NULL && p->pool != NULL);
    
    /* check for max connections and if 0 return NULL */
    if (p->max_size < 1)
        return NULL;

    /* check if we have any connection */
    while (p->curr_size < 1) {
        debug("dbpool", 0, "DBPool has no connections, reconnecting up to maximum...");
        /* dbpool_increase ensure max_size is not exceeded so don't lock */
        dbpool_increase(p, p->max_size - p->curr_size);
        if (p->curr_size < 1)
            gwthread_sleep(0.1);
    }

    /* garantee that you deliver a valid connection to the caller */
    while ((pc = gwlist_consume(p->pool)) != NULL) {

        /* 
         * XXX check that the connection is still existing.
         * Is this a performance bottle-neck?!
         */
        if (!pc->conn || (p->db_ops->check && p->db_ops->check(pc->conn) != 0)) {
            /* something was wrong, reinitialize the connection */
            /* lock dbpool for update */
            gwlist_lock(p->pool);
            dbpool_conn_destroy(pc);
            p->curr_size--;
            /* unlock dbpool for update */
            gwlist_unlock(p->pool);
            /*
             * maybe not needed, just try to get next connection, but it
             * can be dangeros if all connections where broken, then we will
             * block here for ever.
             */
            while (p->curr_size < 1) {
                debug("dbpool", 0, "DBPool has too few connections, reconnecting up to maximum...");
                /* dbpool_increase ensure max_size is not exceeded so don't lock */
                dbpool_increase(p, p->max_size - p->curr_size);
                if (p->curr_size < 1)
                    gwthread_sleep(0.1);
            }

        } else {
            break;
        }
    }

    return (pc->conn != NULL ? pc : NULL);
}
예제 #5
0
파일: bb_udp.c 프로젝트: Phonebooth/kannel
/*
 * this function receives an WDP message and adds it to
 * corresponding outgoing_list.
 */
int udp_addwdp(Msg *msg)
{
    int i;
    Udpc *udpc, *def_udpc;
    Octstr *ip;
    
    def_udpc = NULL;
    if (!udp_running) return -1;
    assert(msg != NULL);
    assert(msg_type(msg) == wdp_datagram);
    
    gwlist_lock(udpc_list);
    /* select in which list to add this */
    for (i=0; i < gwlist_len(udpc_list); i++) {
		udpc = gwlist_get(udpc_list, i);

		if (msg->wdp_datagram.source_port == udp_get_port(udpc->addr)) {
                    def_udpc = udpc;
                    ip = udp_get_ip(udpc->addr);
		    if (octstr_compare(msg->wdp_datagram.source_address, ip) == 0) {
                        octstr_destroy(ip);
	    		gwlist_produce(udpc->outgoing_list, msg);
	    		gwlist_unlock(udpc_list);
	    		return 0;
		    }
                    octstr_destroy(ip);
		}
    }

    if (NULL != def_udpc) {
	gwlist_produce(def_udpc->outgoing_list, msg);
	gwlist_unlock(udpc_list);
	return 0;
    }

    gwlist_unlock(udpc_list);
    return -1;
}
예제 #6
0
파일: bb_boxc.c 프로젝트: Phonebooth/kannel
/*
 * this thread listens to incoming_wdp list
 * and then routs messages to proper wapbox
 */
static void wdp_to_wapboxes(void *arg)
{
    List *route_info;
    AddrPar *ap;
    Boxc *conn;
    Msg *msg;
    int i;

    gwlist_add_producer(flow_threads);
    gwlist_add_producer(wapbox_list);

    route_info = gwlist_create();

    
    while(bb_status != BB_DEAD) {

	    gwlist_consume(suspended);	/* block here if suspended */

	    if ((msg = gwlist_consume(incoming_wdp)) == NULL)
	         break;

	    gw_assert(msg_type(msg) == wdp_datagram);

	    conn = route_msg(route_info, msg);
	    if (conn == NULL) {
	        warning(0, "Cannot route message, discard it");
	        msg_destroy(msg);
	        continue;
	    }
	    gwlist_produce(conn->incoming, msg);
    }
    debug("bb", 0, "wdp_to_wapboxes: destroying lists");
    while((ap = gwlist_extract_first(route_info)) != NULL)
	ap_destroy(ap);

    gw_assert(gwlist_len(route_info) == 0);
    gwlist_destroy(route_info, NULL);

    gwlist_lock(wapbox_list);
    for(i=0; i < gwlist_len(wapbox_list); i++) {
	    conn = gwlist_get(wapbox_list, i);
	    gwlist_remove_producer(conn->incoming);
	    conn->alive = 0;
    }
    gwlist_unlock(wapbox_list);

    gwlist_remove_producer(wapbox_list);
    gwlist_remove_producer(flow_threads);
}
예제 #7
0
static Udpc *udpc_find_mapping(Msg *msg, int inbound)
{
    int i;
    Udpc *udpc;
    Octstr *addr;
    
    /* check if there is allready a bound UDP port */
    gwlist_lock(udpc_list);
    for (i=0; i < gwlist_len(udpc_list); i++) {
        udpc = gwlist_get(udpc_list, i);

        /* decide if we compare against inbound or outbound traffic mapping */
        addr = inbound ? udpc->map_addr : udpc->addr;

        if (msg->wdp_datagram.source_port == udp_get_port(addr) &&
            octstr_compare(msg->wdp_datagram.source_address, 
                           udp_get_ip(addr)) == 0) {
            gwlist_unlock(udpc_list);
            return udpc;
        }
    }
    gwlist_unlock(udpc_list);
    return NULL;
}
예제 #8
0
파일: bb_boxc.c 프로젝트: Phonebooth/kannel
int boxc_incoming_wdp_queue(void)
{
    int i, q = 0;
    Boxc *boxc;
    
    if (wapbox_list) {
	    gwlist_lock(wapbox_list);
	    for(i=0; i < gwlist_len(wapbox_list); i++) {
	        boxc = gwlist_get(wapbox_list, i);
	        q += gwlist_len(boxc->incoming);
	    }
	    gwlist_unlock(wapbox_list);
    }
    return q;
}
예제 #9
0
파일: bb_udp.c 프로젝트: Phonebooth/kannel
int udp_outgoing_queue(void)
{
    int i, q = 0;
    Udpc *udpc;

    if (!udp_running || udpc_list == NULL)
	return 0;

    gwlist_lock(udpc_list);
    for (i=0; i < gwlist_len(udpc_list); i++) {
	udpc = gwlist_get(udpc_list, i);
	q += gwlist_len(udpc->outgoing_list);
    }
    gwlist_unlock(udpc_list);
    return q;
}
예제 #10
0
파일: accesslog.c 프로젝트: tphipps/kannel
void alog_close(void)
{

    if (file != NULL) {
        if (markers)
            alog("Log ends");
        gwlist_lock(writers);
        /* wait for writers to complete */
        gwlist_consume(writers);
        fclose(file);
        file = NULL;
        gwlist_unlock(writers);
        gwlist_destroy(writers, NULL);
        writers = NULL;
    }
}
예제 #11
0
int gw_rwlock_rdlock(RWLock *lock)
{
    int ret = 0;
    gw_assert(lock != NULL);

#ifdef HAVE_PTHREAD_RWLOCK
    ret = pthread_rwlock_rdlock(&lock->rwlock);
    if (ret != 0) {
        panic(ret, "Error while pthread_rwlock_rdlock.");
    }
#else
    gwlist_lock(lock->rwlock);
    gwlist_add_producer(lock->rwlock);
    gwlist_unlock(lock->rwlock);
    RWDEBUG("", 0, "------------ gw_rwlock_rdlock(%p) ----------", lock);
#endif

    return ret;
}
예제 #12
0
int gw_rwlock_unlock(RWLock *lock)
{
    int ret = 0;
    gw_assert(lock != NULL);

#ifdef HAVE_PTHREAD_RWLOCK
    ret = pthread_rwlock_unlock(&lock->rwlock);
    if (ret != 0)
        panic(ret, "Error while gw_rwlock_unlock.");
#else
    RWDEBUG("", 0, "------------ gw_rwlock_unlock(%p) ----------", lock);
    if (lock->writer == gwthread_self()) {
        lock->writer = -1;
        gwlist_unlock(lock->rwlock);
    } else 
        gwlist_remove_producer(lock->rwlock);
#endif

    return ret;
}
예제 #13
0
파일: dbpool.c 프로젝트: Phonebooth/kannel
unsigned int dbpool_check(DBPool *p)
{
    long i, len, n = 0, reinit = 0;

    gw_assert(p != NULL && p->pool != NULL && p->db_ops != NULL);

    /*
     * First check if db_ops->check function pointer is here.
     * NOTE: db_ops->check is optional, so if it is not there, then
     * we have nothing todo and we simple return list length.
     */
    if (p->db_ops->check == NULL)
        return gwlist_len(p->pool);

    gwlist_lock(p->pool);
    len = gwlist_len(p->pool);
    for (i = 0; i < len; i++) {
        DBPoolConn *pconn;

        pconn = gwlist_get(p->pool, i);
        if (p->db_ops->check(pconn->conn) != 0) {
            /* something was wrong, reinitialize the connection */
            gwlist_delete(p->pool, i, 1);
            dbpool_conn_destroy(pconn);
            p->curr_size--;
            reinit++;
            len--;
            i--;
        } else {
            n++;
        }
    }
    gwlist_unlock(p->pool);

    /* reinitialize brocken connections */
    if (reinit > 0)
        n += dbpool_increase(p, reinit);


    return n;
}
예제 #14
0
파일: accesslog.c 프로젝트: tphipps/kannel
void alog(const char *fmt, ...)
{
    char buf[FORMAT_SIZE + 1];
    va_list args;

    if (file == NULL)
        return;

    format(buf, fmt);
    va_start(args, fmt);

    gwlist_lock(writers);
    gwlist_add_producer(writers);
    gwlist_unlock(writers);

    vfprintf(file, buf, args);
    fflush(file);

    gwlist_remove_producer(writers);

    va_end(args);
}
예제 #15
0
파일: accesslog.c 프로젝트: tphipps/kannel
void alog_reopen(void)
{
    if (file == NULL)
	return;

    if (markers)
        alog("Log ends");

    gwlist_lock(writers);
    /* wait for writers to complete */
    gwlist_consume(writers);

    fclose(file);
    file = fopen(filename, "a");

    gwlist_unlock(writers);

    if (file == NULL) {
        error(errno, "Couldn't re-open access logfile `%s'.", filename);
    } 
    else if (markers) {
        alog("Log begins");
    }
}
예제 #16
0
파일: wtp_tid.c 프로젝트: Phonebooth/kannel
/*
 * Set tid for an existing initiator. Input a cache item and the new tid.
 */
static void set_tid_by_item(WTPCached_tid *item, long tid)
{
    gwlist_lock(tid_cache);
    item->tid = tid;
    gwlist_unlock(tid_cache);
}
예제 #17
0
파일: bb_boxc.c 프로젝트: Phonebooth/kannel
static Boxc *route_msg(List *route_info, Msg *msg)
{
    AddrPar *ap;
    Boxc *conn, *best;
    int i, b, len;
    
    ap = gwlist_search(route_info, msg, cmp_route);
    if (ap == NULL) {
	    debug("bb.boxc", 0, "Did not find previous routing info for WDP, "
	    	  "generating new");
route:

	    if (gwlist_len(wapbox_list) == 0)
	        return NULL;

	    gwlist_lock(wapbox_list);

	/* take random wapbox from list, and then check all wapboxes
	 * and select the one with lowest load level - if tied, the first
	 * one
	 */
	    len = gwlist_len(wapbox_list);
	    b = gw_rand() % len;
	    best = gwlist_get(wapbox_list, b);

	    for(i = 0; i < gwlist_len(wapbox_list); i++) {
	        conn = gwlist_get(wapbox_list, (i+b) % len);
	        if (conn != NULL && best != NULL)
		        if (conn->load < best->load)
		            best = conn;
	    }
	    if (best == NULL) {
	        warning(0, "wapbox_list empty!");
	        gwlist_unlock(wapbox_list);
	        return NULL;
	    }
	    conn = best;
	    conn->load++;	/* simulate new client until we get new values */
	
	    ap = gw_malloc(sizeof(AddrPar));
	    ap->address = octstr_duplicate(msg->wdp_datagram.source_address);
	    ap->port = msg->wdp_datagram.source_port;
	    ap->wapboxid = conn->id;
	    gwlist_produce(route_info, ap);

	    gwlist_unlock(wapbox_list);
    } else
	    conn = gwlist_search(wapbox_list, ap, cmp_boxc);

    if (conn == NULL) {
	/* routing failed; wapbox has disappeared!
	 * ..remove routing info and re-route   */

	    debug("bb.boxc", 0, "Old wapbox has disappeared, re-routing");

	    gwlist_delete_equal(route_info, ap);
	    ap_destroy(ap);
	    goto route;
    }
    return conn;
}
예제 #18
0
파일: bb_boxc.c 프로젝트: Phonebooth/kannel
Octstr *boxc_status(int status_type)
{
    Octstr *tmp;
    char *lb, *ws;
    int i, boxes, para = 0;
    time_t orig, t;
    Boxc *bi;

    orig = time(NULL);

    /*
     * XXX: this will cause segmentation fault if this is called
     *    between 'destroy_list and setting list to NULL calls.
     *    Ok, this has to be fixed, but now I am too tired.
     */
    
    if ((lb = bb_status_linebreak(status_type))==NULL)
	    return octstr_create("Un-supported format");

    if (status_type == BBSTATUS_HTML)
	    ws = "&nbsp;&nbsp;&nbsp;&nbsp;";
    else if (status_type == BBSTATUS_TEXT)
	    ws = "    ";
    else
	    ws = "";

    if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
	    para = 1;
    
    if (status_type == BBSTATUS_XML) {
        tmp = octstr_create ("");
        octstr_append_cstr(tmp, "<boxes>\n\t");
    }
    else
        tmp = octstr_format("%sBox connections:%s", para ? "<p>" : "", lb);
    boxes = 0;
    
    if (wapbox_list) {
	    gwlist_lock(wapbox_list);
	    for(i=0; i < gwlist_len(wapbox_list); i++) {
	        bi = gwlist_get(wapbox_list, i);
	        if (bi->alive == 0)
		        continue;
	        t = orig - bi->connect_time;
            if (status_type == BBSTATUS_XML)
	            octstr_format_append(tmp,
		        "<box>\n\t\t<type>wapbox</type>\n\t\t<IP>%s</IP>\n"
                "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n"
                "\t\t<ssl>%s</ssl>\n\t</box>\n",
				octstr_get_cstr(bi->client_ip),
				t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
                conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
#else 
                "not installed"
#endif
                );
            else
	            octstr_format_append(tmp,
		        "%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s",
				ws, octstr_get_cstr(bi->client_ip),
				t/3600/24, t/3600%24, t/60%60, t%60, 
#ifdef HAVE_LIBSSL
                conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
#else
                "",
#endif 
                lb);
	            boxes++;
	       }
	       gwlist_unlock(wapbox_list);
        }
        if (smsbox_list) {
            gw_rwlock_rdlock(smsbox_list_rwlock);
	    for(i=0; i < gwlist_len(smsbox_list); i++) {
	        bi = gwlist_get(smsbox_list, i);
	        if (bi->alive == 0)
		        continue;
	        t = orig - bi->connect_time;
            if (status_type == BBSTATUS_XML)
	            octstr_format_append(tmp, "<box>\n\t\t<type>smsbox</type>\n"
                    "\t\t<id>%s</id>\n\t\t<IP>%s</IP>\n"
                    "\t\t<queue>%ld</queue>\n"
                    "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n"
                    "\t\t<ssl>%s</ssl>\n\t</box>",
                    (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : ""),
		            octstr_get_cstr(bi->client_ip),
		            gwlist_len(bi->incoming) + dict_key_count(bi->sent),
		            t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
                    conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
#else 
                    "not installed"
#endif
                    );
            else
                octstr_format_append(tmp, "%ssmsbox:%s, IP %s (%ld queued), (on-line %ldd %ldh %ldm %lds) %s %s",
                    ws, (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : "(none)"), 
                    octstr_get_cstr(bi->client_ip), gwlist_len(bi->incoming) + dict_key_count(bi->sent),
		            t/3600/24, t/3600%24, t/60%60, t%60, 
#ifdef HAVE_LIBSSL
                    conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
#else
                    "",
#endif 
                    lb);
	       boxes++;
	    }
	    gw_rwlock_unlock(smsbox_list_rwlock);
    }
    if (boxes == 0 && status_type != BBSTATUS_XML) {
	    octstr_destroy(tmp);
	    tmp = octstr_format("%sNo boxes connected", para ? "<p>" : "");
    }
    if (para)
	    octstr_append_cstr(tmp, "</p>");
    if (status_type == BBSTATUS_XML)
        octstr_append_cstr(tmp, "</boxes>\n");
    else
        octstr_append_cstr(tmp, "\n\n");
    return tmp;
}