int wrap_memcached_insert(cachedb_con *con,str* attr, str* value,int expires) { memcached_return_t rc; memcached_con *connection; struct timeval start; start_expire_timer(start,memcache_exec_threshold); connection = (memcached_con *)con->data; rc = memcached_set(connection->memc,attr->s, attr->len , value->s, value->len, (time_t)expires, (uint32_t)0); stop_expire_timer(start,memcache_exec_threshold, "cachedb_memcached insert",attr->s,attr->len,0); if( rc != MEMCACHED_SUCCESS) { LM_ERR("Failed to insert: %s\n",memcached_strerror(connection->memc,rc)); return -1; } return 0; }
static int remove_chunk_f(struct sip_msg* msg, char* glob) { int i; str *pat = (str *)glob; lcache_entry_t* me1, *me2; struct timeval start; if (pat->len+1 > pat_buff_size) { pat_buff = pkg_realloc(pat_buff,pat->len+1); if (pat_buff == NULL) { LM_ERR("No more pkg mem\n"); pat_buff_size = 0; return -1; } pat_buff_size = pat->len +1; } memcpy(pat_buff,pat->s,pat->len); pat_buff[pat->len] = 0; LM_DBG("trying to remove chunk with pattern [%s]\n",pat_buff); start_expire_timer(start,local_exec_threshold); for(i = 0; i< cache_htable_size; i++) { lock_get(&cache_htable[i].lock); me1 = cache_htable[i].entries; me2 = NULL; while(me1) { if (me1->attr.len + 1 > key_buff_size) { key_buff = pkg_realloc(key_buff,me1->attr.len+1); if (key_buff == NULL) { LM_ERR("No more pkg mem\n"); key_buff_size = 0; lock_release(&cache_htable[i].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local remove_chunk",pat->s,pat->len,0); return -1; } key_buff_size = me1->attr.len + 1; } memcpy(key_buff,me1->attr.s,me1->attr.len); key_buff[me1->attr.len] = 0; if(fnmatch(pat_buff,key_buff,0) == 0) { LM_DBG("[%.*s] matches glob [%.*s] - removing from bucket %d\n", me1->attr.len, me1->attr.s,pat_buff_size,pat_buff,i); if(me2) { me2->next = me1->next; shm_free(me1); me1 = me2->next; } else{ cache_htable[i].entries = me1->next; shm_free(me1); me1 = cache_htable[i].entries; } } else { me2 = me1; me1 = me1->next; } } lock_release(&cache_htable[i].lock); } stop_expire_timer(start,local_exec_threshold, "cachedb_local remove_chunk",pat->s,pat->len,0); return 1; }
/*! \brief Finds a tcpconn & sends on it */ static int proto_ws_send(struct socket_info* send_sock, char* buf, unsigned int len, union sockaddr_union* to, int id) { struct tcp_connection *c; struct timeval get; struct ip_addr ip; int port = 0; int fd, n; reset_tcp_vars(tcpthreshold); start_expire_timer(get,tcpthreshold); if (to){ su2ip_addr(&ip, to); port=su_getport(to); n = tcp_conn_get(id, &ip, port, &c, &fd); }else if (id){ n = tcp_conn_get(id, 0, 0, &c, &fd); }else{ LM_CRIT("prot_tls_send called with null id & to\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } if (n<0) { /* error during conn get, return with error too */ LM_ERR("failed to aquire connection\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } /* was connection found ?? */ if (c==0) { if (tcp_no_new_conn) { return -1; } LM_DBG("no open tcp connection found, opening new one\n"); /* create tcp connection */ if ((c=ws_connect(send_sock, to, &fd))==0) { LM_ERR("connect failed\n"); return -1; } goto send_it; } get_time_difference(get, tcpthreshold, tcp_timeout_con_get); /* now we have a connection, let's what we can do with it */ /* BE CAREFUL now as we need to release the conn before exiting !!! */ if (fd==-1) { /* connection is not writable because of its state */ /* return error, nothing to do about it */ tcp_conn_release(c, 0); return -1; } send_it: LM_DBG("sending via fd %d...\n",fd); n = ws_req_write(c, fd, buf, len); stop_expire_timer(get, tcpthreshold, "WS ops",buf,(int)len,1); tcp_conn_set_lifetime( c, tcp_con_lifetime); LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd); if (n<0){ LM_ERR("failed to send\n"); c->state=S_CONN_BAD; if (c->proc_id != process_no) close(fd); tcp_conn_release(c, 0); return -1; } /* only close the FD if not already in the context of our process either we just connected, or main sent us the FD */ if (c->proc_id != process_no) close(fd); tcp_conn_release(c, 0); return n; }
int couchbase_get_counter(cachedb_con *connection,str *attr,int *val) { lcb_t instance; lcb_error_t oprc; lcb_get_cmd_t cmd; const lcb_get_cmd_t *commands[1]; struct timeval start; start_expire_timer(start,couch_exec_threshold); instance = COUCHBASE_CON(connection); commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = attr->s; cmd.v.v0.nkey = attr->len; oprc = lcb_get(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { /* Key not present, record does not exist */ if (oprc == LCB_KEY_ENOENT) { stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter",attr->s,attr->len,0); return -1; } //Attempt reconnect if (couchbase_conditional_reconnect(connection, oprc) != 1) { stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter ",attr->s,attr->len,0); return -2; } //Try Again instance = COUCHBASE_CON(connection); oprc = lcb_get(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { if (oprc == LCB_KEY_ENOENT) { LM_ERR("Get counter command successfully retried\n"); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter",attr->s,attr->len,0); return -1; } LM_ERR("Get counter command retry failed - %s\n", lcb_strerror(instance, oprc)); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter",attr->s,attr->len,0); return -2; } LM_ERR("Get command successfully retried\n"); } //Incase of malloc failure if (!get_res.s) { stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter",attr->s,attr->len,0); return -2; } stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase get counter",attr->s,attr->len,0); if (str2sint((str *)&get_res,val)) { LM_ERR("Failued to convert counter [%.*s] to int\n",get_res.len,get_res.s); pkg_free(get_res.s); get_res.s = NULL; return -1; } pkg_free(get_res.s); get_res.s = NULL; return 1; }
/*! \brief Finds a tcpconn & sends on it */ int tcp_send(struct socket_info* send_sock, int type, char* buf, unsigned len, union sockaddr_union* to, int id) { struct tcp_connection *c; struct tcp_connection *tmp; struct ip_addr ip; int port; int fd; long response[2]; int n; struct timeval get,rcv,snd; port=0; reset_tcp_vars(tcpthreshold); start_expire_timer(get,tcpthreshold); if (to){ su2ip_addr(&ip, to); port=su_getport(to); c=tcpconn_get(id, &ip, port, tcp_con_lifetime); }else if (id){ c=tcpconn_get(id, 0, 0, tcp_con_lifetime); }else{ LM_CRIT("tcp_send called with null id & to\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } if (id){ if (c==0) { if (to){ /* try again w/o id */ c=tcpconn_get(0, &ip, port, tcp_con_lifetime); goto no_id; }else{ LM_ERR("id %d not found, dropping\n", id); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } }else goto get_fd; } no_id: if (c==0){ LM_DBG("no open tcp connection found, opening new one\n"); /* create tcp connection */ if ((c=tcpconn_connect(send_sock, to, type))==0){ LM_ERR("connect failed\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } c->refcnt++; /* safe to do it w/o locking, it's not yet available to the rest of the world */ fd=c->s; /* send the new tcpconn to "tcp main" */ response[0]=(long)c; response[1]=CONN_NEW; n=send_fd(unix_tcp_sock, response, sizeof(response), c->s); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); if (n<=0){ LM_ERR("failed send_fd: %s (%d)\n", strerror(errno), errno); n=-1; goto end; } goto send_it; } get_fd: get_time_difference(get,tcpthreshold,tcp_timeout_con_get); /* todo: see if this is not the same process holding * c and if so send directly on c->fd */ LM_DBG("tcp connection found (%p), acquiring fd\n", c); /* get the fd */ response[0]=(long)c; response[1]=CONN_GET_FD; start_expire_timer(rcv,tcpthreshold); n=send_all(unix_tcp_sock, response, sizeof(response)); if (n<=0){ LM_ERR("failed to get fd(write):%s (%d)\n", strerror(errno), errno); n=-1; get_time_difference(rcv,tcpthreshold,tcp_timeout_receive_fd); goto release_c; } LM_DBG("c= %p, n=%d\n", c, n); tmp=c; n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd, MSG_WAITALL); get_time_difference(rcv,tcpthreshold,tcp_timeout_receive_fd); if (n<=0){ LM_ERR("failed to get fd(receive_fd):" " %s (%d)\n", strerror(errno), errno); n=-1; goto release_c; } if (c!=tmp){ LM_CRIT("got different connection:" " %p (id= %d, refcnt=%d state=%d != " " %p (id= %d, refcnt=%d state=%d (n=%d)\n", c, c->id, c->refcnt, c->state, tmp, tmp->id, tmp->refcnt, tmp->state, n ); n=-1; /* fail */ goto end; } LM_DBG("after receive_fd: c= %p n=%d fd=%d\n",c, n, fd); send_it: LM_DBG("sending...\n"); lock_get(&c->write_lock); #ifdef USE_TLS if (c->type==PROTO_TLS) n=tls_blocking_write(c, fd, buf, len); else #endif /* n=tcp_blocking_write(c, fd, buf, len); */ start_expire_timer(snd,tcpthreshold); n=tsend_stream(fd, buf, len, tcp_send_timeout*1000); get_time_difference(snd,tcpthreshold,tcp_timeout_send); stop_expire_timer(get,tcpthreshold,0,buf,(int)len,1); lock_release(&c->write_lock); LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd); LM_DBG("buf=\n%.*s\n", (int)len, buf); if (n<0){ LM_ERR("failed to send\n"); /* error on the connection , mark it as bad and set 0 timeout */ c->state=S_CONN_BAD; c->timeout=0; /* tell "main" it should drop this (optional it will t/o anyway?)*/ response[0]=(long)c; response[1]=CONN_ERROR; n=send_all(unix_tcp_sock, response, sizeof(response)); /* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/ if (n<=0){ LM_ERR("return failed (write):%s (%d)\n", strerror(errno), errno); } close(fd); return -1; /* error return, no tcpconn_put */ } end: close(fd); release_c: tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */ return n; }
/*! \note WARNING: buf must be 0 terminated (buf[len]=0) or some things might * break (e.g.: modules/textops) */ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) { struct sip_msg* msg; struct timeval start; int rc; char *tmp; str in_buff; in_buff.len = len; in_buff.s = buf; /* the raw processing callbacks can change the buffer, further use in_buff.s and at the end try to free in_buff.s if changed by callbacks */ run_raw_processing_cb(PRE_RAW_PROCESSING,&in_buff); /* update the length for further processing */ len = in_buff.len; msg=pkg_malloc(sizeof(struct sip_msg)); if (msg==0) { LM_ERR("no pkg mem left for sip_msg\n"); goto error; } msg_no++; /* number of vias parsed -- good for diagnostic info in replies */ via_cnt=0; memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */ /* fill in msg */ msg->buf=in_buff.s; msg->len=len; msg->rcv=*rcv_info; msg->id=msg_no; msg->set_global_address=default_global_address; msg->set_global_port=default_global_port; if (parse_msg(in_buff.s,len, msg)!=0){ tmp=ip_addr2a(&(rcv_info->src_ip)); LM_ERR("Unable to parse msg received from [%s:%d]\n", tmp, rcv_info->src_port); /* if a REQUEST msg was detected (first line was succesfully parsed) we should trigger the error route */ if ( msg->first_line.type==SIP_REQUEST && error_rlist.a!=NULL ) run_error_route(msg, 1); goto parse_error; } LM_DBG("After parse_msg...\n"); start_expire_timer(start,execmsgthreshold); /* ... clear branches from previous message */ clear_branches(); if (msg->first_line.type==SIP_REQUEST) { update_stat( rcv_reqs, 1); /* sanity checks */ if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){ /* no via, send back error ? */ LM_ERR("no via found in request\n"); update_stat( err_reqs, 1); goto parse_error; } /* check if necessary to add receive?->moved to forward_req */ /* check for the alias stuff */ #ifdef USE_TCP if (msg->via1->alias && tcp_accept_aliases && (((rcv_info->proto==PROTO_TCP) && !tcp_disable) #ifdef USE_TLS || ((rcv_info->proto==PROTO_TLS) && !tls_disable) #endif ) ){ if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port, rcv_info->proto)!=0){ LM_ERR("tcp alias failed\n"); /* continue */ } } #endif LM_DBG("preparing to run routing scripts...\n"); /* set request route type --bogdan*/ set_route_type( REQUEST_ROUTE ); /* execute pre-script callbacks, if any; * if some of the callbacks said not to continue with * script processing, don't do so; * if we are here basic sanity checks are already done * (like presence of at least one via), so you can count * on via1 being parsed in a pre-script callback --andrei */ rc = exec_pre_req_cb(msg); if (rc == SCB_DROP_MSG) { update_stat( drp_reqs, 1); goto end; /* drop the message */ } /* exec the routing script */ if (rc & SCB_RUN_TOP_ROUTE) run_top_route(rlist[DEFAULT_RT].a, msg); /* execute post request-script callbacks */ if (rc & SCB_RUN_POST_CBS) exec_post_req_cb(msg); } else if (msg->first_line.type==SIP_REPLY) { update_stat( rcv_rpls, 1); /* sanity checks */ if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){ /* no via, send back error ? */ LM_ERR("no via found in reply\n"); update_stat( err_rpls, 1); goto parse_error; } /* set reply route type --bogdan*/ set_route_type( ONREPLY_ROUTE ); /* execute pre-script callbacks, if any ; * if some of the callbacks said not to continue with * script processing, don't do so ; * if we are here, basic sanity checks are already done * (like presence of at least one via), so you can count * on via1 being parsed in a pre-script callback --andrei */ rc = exec_pre_rpl_cb(msg); if (rc == SCB_DROP_MSG) { update_stat( drp_rpls, 1); goto end; /* drop the reply */ } /* exec the onreply routing script */ if (rc & SCB_RUN_TOP_ROUTE && onreply_rlist[DEFAULT_RT].a && (run_top_route(onreply_rlist[DEFAULT_RT].a,msg) & ACT_FL_DROP) && msg->REPLY_STATUS < 200) { LM_DBG("dropping provisional reply %d\n", msg->REPLY_STATUS); update_stat( drp_rpls, 1); goto end; /* drop the message */ } else { /* send the msg */ forward_reply(msg); /* TODO - TX reply stat */ } /* execute post reply-script callbacks */ if (rc & SCB_RUN_POST_CBS) exec_post_rpl_cb(msg); } end: stop_expire_timer( start, execmsgthreshold, "msg processing", msg->buf, msg->len, 0); reset_longest_action_list(execmsgthreshold); /* free possible loaded avps -bogdan */ reset_avps(); LM_DBG("cleaning up\n"); free_sip_msg(msg); pkg_free(msg); if (in_buff.s != buf) pkg_free(in_buff.s); return 0; parse_error: exec_parse_err_cb(msg); free_sip_msg(msg); pkg_free(msg); error: if (in_buff.s != buf) pkg_free(in_buff.s); return -1; }
int couchbase_add(cachedb_con *connection,str *attr,int val,int expires,int *new_val) { lcb_t instance; lcb_error_t oprc; lcb_arithmetic_cmd_t cmd; const lcb_arithmetic_cmd_t *commands[1]; struct timeval start; start_expire_timer(start,couch_exec_threshold); instance = COUCHBASE_CON(connection); commands[0] = &cmd; memset(&cmd, 0, sizeof(cmd)); cmd.v.v0.key = attr->s; cmd.v.v0.nkey = attr->len; cmd.v.v0.delta = val; cmd.v.v0.create = 1; cmd.v.v0.initial = val; cmd.v.v0.exptime = expires; oprc = lcb_arithmetic(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { if (oprc == LCB_KEY_ENOENT) { return -1; stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase add",attr->s,attr->len,0); } LM_ERR("Failed to send the arithmetic query - %s\n", lcb_strerror(instance, oprc)); //Attempt reconnect if (couchbase_conditional_reconnect(connection, oprc) != 1) { stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase add",attr->s,attr->len,0); return -2; } //Try again instance = COUCHBASE_CON(connection); oprc = lcb_arithmetic(instance, NULL, 1, commands); if (oprc != LCB_SUCCESS) { if (oprc == LCB_KEY_ENOENT) { LM_ERR("Arithmetic command successfully retried\n"); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase add",attr->s,attr->len,0); return -1; } LM_ERR("Arithmetic command retry failed - %s\n", lcb_strerror(instance, oprc)); stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase add",attr->s,attr->len,0); return -2; } LM_ERR("Arithmetic command successfully retried\n"); } if (new_val) *new_val = arithmetic_res; stop_expire_timer(start,couch_exec_threshold, "cachedb_couchbase add",attr->s,attr->len,0); return 1; }
/*! \brief Finds a tcpconn & sends on it */ static int proto_tcp_send(struct socket_info* send_sock, char* buf, unsigned int len, union sockaddr_union* to, int id) { struct tcp_connection *c; struct ip_addr ip; int port; struct timeval get,snd; int fd, n; port=0; reset_tcp_vars(tcpthreshold); start_expire_timer(get,tcpthreshold); if (to){ su2ip_addr(&ip, to); port=su_getport(to); n = tcp_conn_get(id, &ip, port, &c, &fd); }else if (id){ n = tcp_conn_get(id, 0, 0, &c, &fd); }else{ LM_CRIT("tcp_send called with null id & to\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } if (n<0) { /* error during conn get, return with error too */ LM_ERR("failed to acquire connection\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } /* was connection found ?? */ if (c==0) { if (tcp_no_new_conn) { return -1; } LM_DBG("no open tcp connection found, opening new one, async = %d\n",tcp_async); /* create tcp connection */ if (tcp_async) { n = tcpconn_async_connect(send_sock, to, buf, len, &c, &fd); if ( n<0 ) { LM_ERR("async TCP connect failed\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } /* connect succeeded, we have a connection */ if (n==0) { /* connect is still in progress, break the sending * flow now (the actual write will be done when * connect will be completed */ LM_DBG("Successfully started async connection \n"); tcp_conn_release(c, 0); return len; } LM_DBG("First connect attempt succeeded in less than %d ms, " "proceed to writing \n",tcp_async_local_connect_timeout); /* our first connect attempt succeeded - go ahead as normal */ } else if ((c=tcp_sync_connect(send_sock, to, &fd))==0) { LM_ERR("connect failed\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } goto send_it; } get_time_difference(get,tcpthreshold,tcp_timeout_con_get); /* now we have a connection, let's see what we can do with it */ /* BE CAREFUL now as we need to release the conn before exiting !!! */ if (fd==-1) { /* connection is not writable because of its state - can we append * data to it for later writting (async writting)? */ if (c->state==S_CONN_CONNECTING) { /* the connection is currently in the process of getting * connected - let's append our send chunk as well - just in * case we ever manage to get through */ LM_DBG("We have acquired a TCP connection which is still " "pending to connect - delaying write \n"); n = add_write_chunk(c,buf,len,1); if (n < 0) { LM_ERR("Failed to add another write chunk to %p\n",c); /* we failed due to internal errors - put the * connection back */ tcp_conn_release(c, 0); return -1; } /* we successfully added our write chunk - success */ tcp_conn_release(c, 0); return len; } else { /* return error, nothing to do about it */ tcp_conn_release(c, 0); return -1; } } send_it: LM_DBG("sending via fd %d...\n",fd); start_expire_timer(snd,tcpthreshold); n = _tcp_write_on_socket(c, fd, buf, len); get_time_difference(snd,tcpthreshold,tcp_timeout_send); stop_expire_timer(get,tcpthreshold,"tcp ops",buf,(int)len,1); tcp_conn_set_lifetime( c, tcp_con_lifetime); LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd); /* LM_DBG("buf=\n%.*s\n", (int)len, buf); */ if (n<0){ LM_ERR("failed to send\n"); c->state=S_CONN_BAD; if (c->proc_id != process_no) close(fd); tcp_conn_release(c, 0); return -1; } /* only close the FD if not already in the context of our process either we just connected, or main sent us the FD */ if (c->proc_id != process_no) close(fd); tcp_conn_release(c, (n<len)?1:0/*pending data in async mode?*/ ); return n; }
/* * return : * 1 - if found * -2 - if not found * -1 - if error * */ int lcache_htable_fetch(cachedb_con *con,str* attr, str* res) { int hash_code; lcache_entry_t* it = NULL, *it_aux = NULL; char* value; struct timeval start; start_expire_timer(start,local_exec_threshold); hash_code= core_hash( attr, 0, cache_htable_size); lock_get(&cache_htable[hash_code].lock); it = cache_htable[hash_code].entries; while(it) { if(it->attr.len == attr->len && (strncmp(it->attr.s, attr->s, attr->len) == 0)) { if( it->expires != 0 && it->expires < get_ticks()) { /* found an expired entry -> delete it */ if(it_aux) it_aux->next = it->next; else cache_htable[hash_code].entries = it->next; shm_free(it); lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local fetch",attr->s,attr->len,0); return -2; } value = (char*)pkg_malloc(it->value.len); if(value == NULL) { LM_ERR("no more memory\n"); lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local fetch",attr->s,attr->len,0); return -1; } memcpy(value, it->value.s, it->value.len); res->len = it->value.len; res->s = value; lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local fetch",attr->s,attr->len,0); return 1; } it_aux = it; it = it->next; } lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local fetch",attr->s,attr->len,0); return -2; }
int lcache_htable_add(cachedb_con *con,str *attr,int val,int expires,int *new_val) { int hash_code; lcache_entry_t *it=NULL,*it_prev=NULL; int old_value; char *new_value; int new_len; str ins_val; struct timeval start; start_expire_timer(start,local_exec_threshold); hash_code = core_hash(attr,0,cache_htable_size); lock_get(&cache_htable[hash_code].lock); it = cache_htable[hash_code].entries; while (it) { if (it->attr.len == attr->len && memcmp(it->attr.s,attr->s,attr->len) == 0) { if (it->expires !=0 && it->expires < get_ticks()) { /* found an expired entry -> delete it */ if(it_prev) it_prev->next = it->next; else cache_htable[hash_code].entries = it->next; shm_free(it); lock_release(&cache_htable[hash_code].lock); ins_val.s = sint2str(val,&ins_val.len); if (lcache_htable_insert(con,attr,&ins_val,expires) < 0) { LM_ERR("failed to insert value\n"); stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return -1; } if (new_val) *new_val = val; stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return 0; } /* found our valid entry */ if (str2sint(&it->value,&old_value) < 0) { LM_ERR("not an integer\n"); lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return -1; } old_value+=val; expires = it->expires; new_value = sint2str(old_value,&new_len); it = shm_realloc(it,sizeof(lcache_entry_t) + attr->len +new_len); if (it == NULL) { LM_ERR("failed to realloc struct\n"); lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return -1; } if (it_prev) it_prev->next = it; else cache_htable[hash_code].entries = it; it->attr.s = (char*)(it + 1); it->value.s =(char *)(it + 1) + attr->len; it->expires = expires; memcpy(it->value.s,new_value,new_len); it->value.len = new_len; lock_release(&cache_htable[hash_code].lock); if (new_val) *new_val = old_value; stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return 0; } it_prev = it; it = it->next; } lock_release(&cache_htable[hash_code].lock); /* not found */ ins_val.s = sint2str(val,&ins_val.len); if (lcache_htable_insert(con,attr,&ins_val,expires) < 0) { LM_ERR("failed to insert value\n"); stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return -1; } if (new_val) *new_val = val; stop_expire_timer(start,local_exec_threshold, "cachedb_local add",attr->s,attr->len,0); return 0; }
static int db_postgres_submit_query(const db_con_t* _con, const str* _s) { int i,ret=0; ExecStatusType result; PGresult *res = NULL; struct timeval start; if(! _con || !_s || !_s->s) { LM_ERR("invalid parameter value\n"); return(-1); } submit_func_called = 1; /* this bit of nonsense in case our connection get screwed up */ switch(PQstatus(CON_CONNECTION(_con))) { case CONNECTION_OK: break; case CONNECTION_BAD: LM_DBG("connection reset\n"); PQreset(CON_CONNECTION(_con)); break; case CONNECTION_STARTED: case CONNECTION_MADE: case CONNECTION_AWAITING_RESPONSE: case CONNECTION_AUTH_OK: case CONNECTION_SETENV: case CONNECTION_SSL_STARTUP: case CONNECTION_NEEDED: default: LM_ERR("%p PQstatus(%s) invalid: %.*s\n", _con, PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s); return -1; } for (i=0;i<2;i++) { /* free any previous query that is laying about */ if(CON_RESULT(_con)) { free_query(_con); } start_expire_timer(start,db_postgres_exec_query_threshold); ret = PQsendQuery(CON_CONNECTION(_con), _s->s); stop_expire_timer(start,db_postgres_exec_query_threshold,"pgsql query",_s->s,_s->len,0); /* exec the query */ if (ret) { LM_DBG("%p PQsendQuery(%.*s)\n", _con, _s->len, _s->s); while (1) { if ((res = PQgetResult(CON_CONNECTION(_con)))) { CON_RESULT(_con) = res; } else { break; } } result = PQresultStatus(CON_RESULT(_con)); if(result==PGRES_FATAL_ERROR) goto reconnect; else return 0; } else { reconnect: /* reconnection attempt - if this is the case */ LM_DBG("%p PQsendQuery failed: %s Query: %.*s\n", _con, PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s); if(PQstatus(CON_CONNECTION(_con))!=CONNECTION_OK) { LM_DBG("connection reset\n"); PQreset(CON_CONNECTION(_con)); } else { /* failure not due to connection loss - no point in retrying */ if(CON_RESULT(_con)) { free_query(_con); } break; } } } LM_ERR("%p PQsendQuery Error: %s Query: %.*s\n", _con, PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s); return -1; }
/*! \brief Finds a tcpconn & sends on it */ static int proto_wss_send(struct socket_info* send_sock, char* buf, unsigned int len, union sockaddr_union* to, int id) { struct tcp_connection *c; struct timeval get; struct ip_addr ip; int port = 0; int fd, n; struct ws_data* d; reset_tcp_vars(tcpthreshold); start_expire_timer(get,tcpthreshold); if (to){ su2ip_addr(&ip, to); port=su_getport(to); n = tcp_conn_get(id, &ip, port, PROTO_WSS, &c, &fd); }else if (id){ n = tcp_conn_get(id, 0, 0, PROTO_NONE, &c, &fd); }else{ LM_CRIT("prot_tls_send called with null id & to\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } if (n<0) { /* error during conn get, return with error too */ LM_ERR("failed to acquire connection\n"); get_time_difference(get,tcpthreshold,tcp_timeout_con_get); return -1; } /* was connection found ?? */ if (c==0) { if (tcp_no_new_conn) { return -1; } if (!to) { LM_ERR("Unknown destination - cannot open new tcp connection\n"); return -1; } LM_DBG("no open tcp connection found, opening new one\n"); /* create tcp connection */ if ((c=ws_connect(send_sock, to, &fd))==0) { LM_ERR("connect failed\n"); return -1; } goto send_it; } get_time_difference(get, tcpthreshold, tcp_timeout_con_get); /* now we have a connection, let's what we can do with it */ /* BE CAREFUL now as we need to release the conn before exiting !!! */ if (fd==-1) { /* connection is not writable because of its state */ /* return error, nothing to do about it */ tcp_conn_release(c, 0); return -1; } send_it: LM_DBG("sending via fd %d...\n",fd); n = ws_req_write(c, fd, buf, len); stop_expire_timer(get, tcpthreshold, "WSS ops",buf,(int)len,1); tcp_conn_set_lifetime( c, tcp_con_lifetime); /* only here we will have all tracing data TLS + WS */ d = c->proto_data; if ( (c->flags&F_CONN_ACCEPTED)==0 && d && d->dest && d->tprot ) { if ( d->message ) { send_trace_message( d->message, t_dst); d->message = NULL; } /* don't allow future traces for this cnection */ d->tprot = 0; d->dest = 0; } LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd); if (n<0){ LM_ERR("failed to send\n"); c->state=S_CONN_BAD; if (c->proc_id != process_no) close(fd); tcp_conn_release(c, 0); return -1; } /* only close the FD if not already in the context of our process either we just connected, or main sent us the FD */ if (c->proc_id != process_no) close(fd); /* mark the ID of the used connection (tracing purposes) */ last_outgoing_tcp_id = c->id; tcp_conn_release(c, 0); return n; }