int conn_close_with_my(conn_t *c) {//这个操作很重,会干掉mysql的连接,已经客户端连接等所有数据!!!! int res = 0; list_del_init(&(c->link)); if(c->my){ if( (res = my_conn_close(c->my)) < 0 ){ log(g_log, "my conn close error\n"); } c->my = NULL; } if( (res = cli_conn_close(c->cli)) < 0 ){ log(g_log, "cli conn close error\n"); } c->cli = NULL; if( (res = conn_release(c)) < 0 ){ log(g_log, "conn release error\n"); } debug(g_log, "conn:%u connection close\n", c->connid); return res; }
int conn_close(conn_t *c) { int res = 0; list_del_init(&(c->link)); if(c->my){ if( (res = my_conn_put(c->my, 1)) < 0 ){ log(g_log, "put my conn error\n"); } c->my = NULL; } if( (res = cli_conn_close(c->cli)) < 0 ){ log(g_log, "cli conn close error\n"); } c->cli = NULL; if( (res = conn_release(c)) < 0 ){ log(g_log, "conn release error\n"); } debug(g_log, "conn:%u connection close\n", c->connid); return res; }
void closeclient(int epfd, int fd) { close(fd); conn_release(fd); // kernel 2.6.9 +, event can be set to NULL epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); }
conn_t *conn_open(int fd, uint32_t ip, uint16_t port) {//分配conn_t和cli_conn_t, 并挂接起来 int res = 0; conn_t *c; if( (c = conn_alloc()) == NULL ){//这个连接其实是个中间搭桥的连接。 log(g_log, "conn alloc error\n"); return NULL; } if( (res = cli_conn_open(c, fd, ip, port)) < 0 ){//将c跟当前的fd连接起来,建立一个客户端连接结构 log(g_log, "cli conn open error\n"); conn_release(c); return NULL; } return c; }
struct task_act * task_select (int *secs_p) { struct connection * cn; struct connection * cn_tmp; struct connection **next_cn; struct task_act * tk; struct task_act **next_tk; struct oper_act * on; int timeout_tmp; char process_edbs = TRUE; char do_timeout; int suspended = FALSE; int xi = 0; struct task_act * ret_tk = NULLTASK; extern char startup_update; struct oper_act * newop = NULLOPER; time (&timenow); (*secs_p) = NOTOK; conns_used = 0; /* DLOG(log_dsap, LLOG_DEBUG, ("task_select connections:")); conn_list_log(connlist); */ for(cn=connlist; cn!=NULLCONN; cn=cn_tmp) { cn_tmp = cn->cn_next; /* Nasty but necessary in conn_extract() manages to get itself called somehow */ do_timeout = FALSE; #ifdef DEBUG conn_log(cn,LLOG_DEBUG); #endif next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { if(tk->tk_timed) { if(tk->tk_timeout <= timenow) { #ifdef DEBUG struct UTCtime ut; struct UTCtime ut2; DLOG(log_dsap, LLOG_TRACE, ("task has timelimit of %ld", tk->tk_timeout)); tm2ut(gmtime(&(tk->tk_timeout)), &ut); DLOG(log_dsap, LLOG_DEBUG, ("converted timelimit = %s", utct2str(&(ut)))); tm2ut(gmtime(&(timenow)), &ut2); DLOG(log_dsap, LLOG_DEBUG, ("time now = %s", utct2str(&(ut2)))); #endif (*next_tk) = tk->tk_next; timeout_task(tk); continue; } else { timeout_tmp = (int) tk->tk_timeout - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } next_tk = &(tk->tk_next); } if(cn->cn_state == CN_OPEN) { next_tk = &(cn->cn_tasklist); for(tk=cn->cn_tasklist; tk!=NULLTASK; tk=(*next_tk)) { next_tk = &(tk->tk_next); if(tk->tk_state == TK_ACTIVE) { if( (ret_tk == NULLTASK) || (tk->tk_prio > ret_tk->tk_prio) || ( (tk->tk_prio == ret_tk->tk_prio) && ( (!ret_tk->tk_timed) || ( (tk->tk_timed) && (tk->tk_timeout < ret_tk->tk_timeout) ) ) ) ) { ret_tk = tk; } } if(tk->tk_state == TK_SUSPEND) { /* * A task suspended to allow the network to be polled. * Set suspended to force polling. */ tk->tk_state = TK_ACTIVE; suspended = TRUE; } } if(cn->cn_tasklist == NULLTASK) { if(cn->cn_initiator) { if(cn->cn_operlist == NULLOPER) { if((cn->cn_last_used + conn_timeout) <= timenow) { do_timeout = TRUE; } else { timeout_tmp = (int) (cn->cn_last_used + conn_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } else { timeout_tmp = conn_timeout; /* safety catch */ if ((tk = cn->cn_operlist->on_task) != NULLTASK) { if (tk->tk_timed) { timeout_tmp = (int) tk->tk_timeout - timenow; if (timeout_tmp < 0) timeout_tmp = 0; } } if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } cn->cn_last_used = timenow; } } } else { cn->cn_last_used = timenow; process_edbs = FALSE; } } else { if((cn->cn_last_used + nsap_timeout) <= timenow) { if ((cn->cn_state == CN_CONNECTING1) || (cn->cn_state == CN_CONNECTING2)) conn_retry(cn,1); else if (cn->cn_state == CN_CLOSING) { if (conn_release_retry(cn) == NOTOK) { /* had its chance - abort */ conn_rel_abort (cn); do_ds_unbind(cn); conn_extract(cn); } } else if ( (cn->cn_state == CN_OPENING) || (cn->cn_state == CN_PRE_OPENING) ) { /* something started to associate - then gave up !!! */ conn_rel_abort (cn); conn_extract (cn); } (*secs_p) = nsap_timeout; } else { timeout_tmp = (int) (cn->cn_last_used + nsap_timeout) - timenow; if(((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) { (*secs_p) = timeout_tmp; } } } if(do_timeout) { LLOG(log_dsap, LLOG_TRACE, ("Timing out connection %d",cn->cn_ad)); if (conn_release(cn) == NOTOK) { (*secs_p) = nsap_timeout; conns_used++; } } else { conns_used++; } } /* * Open the connection with the highest priority operation * waiting on it... * * Get DSA Info operations are highest priority, followed by * BIND_COMPARE, and X500, and finally GetEDB operations. */ next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= MAX_CONNS) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type == ON_TYPE_GET_DSA_INFO) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI)) break; for(on=cn->cn_operlist; on!=NULLOPER; on=on->on_next_conn) { if(on->on_type != ON_TYPE_GET_EDB) { (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } break; } } if(on == NULLOPER) next_cn = &(cn->cn_next); } next_cn = &(connwaitlist); for(cn=connwaitlist; cn!=NULLCONN; cn=(*next_cn)) { if(conns_used >= (MAX_CONNS - CONNS_RESERVED_DI - CONNS_RESERVED_X500)) break; (*next_cn) = cn->cn_next; if(conn_request(cn) == OK) { conns_used++; cn->cn_next = connlist; connlist = cn; cn->cn_last_used = timenow; /* Do something with the operations */ } else { /* Do something with the operations */ } } if(process_edbs && !quipu_shutdown) { /* * Nothing is happening that would be disturbed by writing back * a retrieved EDB so it is a good time to process them. */ if (!get_edb_ops && pending_ops) { get_edb_ops = pending_ops; pending_ops = NULLOPER; if(oper_chain(get_edb_ops) != OK) { LLOG(log_dsap, LLOG_TRACE, ("Could not chain a pending operation")); (*secs_p) = 0; /* service network and then try next one */ pending_ops = get_edb_ops -> on_next_task; get_edb_ops -> on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; } } else if (get_edb_ops) { if (get_edb_ops->on_state == ON_COMPLETE) { if (get_edb_ops->on_type == ON_TYPE_GET_EDB) process_edb(get_edb_ops,&newop); else { /* ON_TYPE_SHADOW */ process_shadow(get_edb_ops); ds_res_free (&get_edb_ops-> on_resp.di_result.dr_res.dcr_dsres); } if (newop) { newop->on_next_task = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); if (oper_send_invoke (newop) != OK) { LLOG(log_dsap, LLOG_EXCEPTIONS, ("oper_send getedb next failed")); oper_free (newop); get_edb_ops = NULLOPER; } get_edb_ops = newop; } else if (get_edb_ops) { pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_conn_extract(get_edb_ops); oper_free(get_edb_ops); get_edb_ops = NULLOPER; } (*secs_p) = 0; /* Schedule next one ! */ } else if (get_edb_ops->on_state == ON_ABANDONED) { LLOG (log_dsap,LLOG_TRACE,("Get edb has been abandoned")); pending_ops = get_edb_ops->on_next_task; get_edb_ops->on_next_task = NULLOPER; oper_free(get_edb_ops); get_edb_ops = NULLOPER; (*secs_p) = 0; /* Schedule next one ! */ } } else if (startup_update) { /* see if cache timer has expired - if so resend edb ops... */ if ( (timenow - lastedb_update) >= slave_timeout ) slave_update(); } } if ((get_edb_ops == NULLOPER) && startup_update ) { /* make sure we are awake for the next EDB update */ if ((timeout_tmp = lastedb_update + slave_timeout - timenow) >= 0) if (((*secs_p) == NOTOK) || ((*secs_p) > timeout_tmp)) (*secs_p) = timeout_tmp; } if(suspended) { /* * A task suspended in order for the network to be checked. * Force this to happen by setting the selected task to NULL * and the polling time of the network to 0 secs. */ ret_tk = NULLTASK; (*secs_p) = 0; } for(cn=connwaitlist; cn!=NULLCONN; cn=cn->cn_next) xi++; /* If someting is waiting, see if we can shut a connection down */ /* Make arbitary choice for now */ for(cn=connlist; (xi!=0 || quipu_shutdown) && (cn!=NULLCONN); cn=cn_tmp) { cn_tmp = cn->cn_next; if ((cn->cn_state == CN_OPEN) && (cn->cn_tasklist == NULLTASK) && (cn->cn_initiator) && (cn->cn_operlist == NULLOPER)) { LLOG(log_dsap, LLOG_TRACE, ("Releasing connection %d early (%d waiting)",cn->cn_ad,xi)); if (conn_release(cn) == NOTOK) conns_used++; else xi--; (*secs_p) = 0; /* let connection be re-used */ } } #ifndef NO_STATS if ( (timenow - last_log_close) >= LOGOPENTIME ) { ll_close (log_stat); last_log_close = timenow; } else { if ( (ret_tk == NULLTASK) && (*secs_p >= LOGOPENTIME)) *secs_p = LOGOPENTIME; /* Wake to close log! */ } #endif if(process_edbs && quipu_shutdown) *secs_p = NOTOK; return(ret_tk); }