int main(int argc, char **argv){ serv_init(argc, argv); Server serv; Fdevents fdes; const Fdevents::events_t *events; fdes.set(serv_link->fd(), FDEVENT_IN, FRONT_LISTEN_LINK, serv_link); uint32_t last_timer_ticks = g_ticks; while(!quit){ events = fdes.wait(TICK_INTERVAL); if(events == NULL){ log_fatal("events.wait error: %s", strerror(errno)); break; } uint32_t curr_ticks = g_ticks; if(last_timer_ticks < curr_ticks){ uint32_t elapsed_ticks = (uint32_t)(curr_ticks - last_timer_ticks); last_timer_ticks = curr_ticks; if(elapsed_ticks > 5 * 1000/TICK_INTERVAL){ // 5 seconds // something blocks too long elapsed_ticks = 0; }else{ for(int i=0; i<elapsed_ticks; i++){ serv.tick(); } } } for(int i=0; i<(int)events->size(); i++){ const Fdevent *fde = events->at(i); int type = fde->data.num; UdpLink *link = (UdpLink *)fde->data.ptr; if(type == FRONT_LISTEN_LINK){ UdpLink *new_link = serv.proc_listen_link(link, &fdes); if(new_link){ fdes.set(new_link->fd(), FDEVENT_IN, FRONT_CLIENT_LINK, new_link); } }else if(type == FRONT_CLIENT_LINK){ int ret = serv.proc_client_link(link, &fdes); if(ret == -1){ fdes.del(link->fd()); log_debug("close link: %d", link->fd()); delete link; } }else if(type == ADMIN_LISTEN_LINK){ // }else if(type == ADMIN_CLIENT_LINK){ // } } } serv_free(); return 0; }
int proc_result(ProcJob &job, Fdevents &select, ready_list_t &ready_list){ Link *link = job.link; if(job.result == PROC_ERROR){ log_info("fd: %d, proc error, delete link", link->fd()); select.del(link->fd()); delete link; return PROC_ERROR; } if(job.cmd){ job.cmd->calls += 1; job.cmd->time_wait += job.time_wait; job.cmd->time_proc += job.time_proc; } if(!link->output->empty()){ //log_trace("add %d to select.out", link->fd()); select.set(link->fd(), FDEVENT_OUT, 1, link); if(select.isset(link->fd(), FDEVENT_IN)){ //log_trace("delete %d from select.in", link->fd()); select.clr(link->fd(), FDEVENT_IN); } }else{ if(link->input->empty()){ if(!select.isset(link->fd(), FDEVENT_IN)){ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } }else{ if(select.isset(link->fd(), FDEVENT_IN)){ //log_trace("delete %d from select.in", link->fd()); select.clr(link->fd(), FDEVENT_IN); } ready_list.push_back(link); } } return PROC_OK; }
void* Slave::_run_thread(void *arg){ Slave *slave = (Slave *)arg; const std::vector<Bytes> *req; Fdevents select; const Fdevents::events_t *events; int idle = 0; bool reconnect = false; #define RECV_TIMEOUT 200 #define MAX_RECV_TIMEOUT 300 * 1000 #define MAX_RECV_IDLE MAX_RECV_TIMEOUT/RECV_TIMEOUT while(!slave->thread_quit){ if(reconnect){ slave->status = DISCONNECTED; reconnect = false; select.del(slave->link->fd()); delete slave->link; slave->link = NULL; sleep(1); } if(!slave->connected()){ if(slave->connect() != 1){ usleep(100 * 1000); }else{ select.set(slave->link->fd(), FDEVENT_IN, 0, NULL); } continue; } events = select.wait(RECV_TIMEOUT); if(events == NULL){ log_error("events.wait error: %s", strerror(errno)); sleep(1); continue; }else if(events->empty()){ if(idle++ >= MAX_RECV_IDLE){ log_error("the master hasn't responsed for awhile, reconnect..."); idle = 0; reconnect = true; } continue; } idle = 0; if(slave->link->read() <= 0){ log_error("link.read error: %s, reconnecting to master", strerror(errno)); reconnect = true; continue; } while(1){ req = slave->link->recv(); if(req == NULL){ log_error("link.recv error: %s, reconnecting to master", strerror(errno)); reconnect = true; break; }else if(req->empty()){ break; }else if(req->at(0) == "noauth"){ log_error("authentication required"); reconnect = true; sleep(1); break; }else{ if(slave->proc(*req) == -1){ goto err; } } } } // end while log_info("Slave thread quit"); return (void *)NULL; err: log_fatal("Slave thread exit unexpectedly"); exit(0); return (void *)NULL;; }
void run(int argc, char **argv){ ready_list_t ready_list; ready_list_t ready_list_2; ready_list_t::iterator it; const Fdevents::events_t *events; Server serv(ssdb); Fdevents select; select.set(serv_link->fd(), FDEVENT_IN, 0, serv_link); select.set(serv.writer.fd(), FDEVENT_IN, 0, &serv.writer); int link_count = 0; while(!quit){ bool write_pending = false; ready_list.clear(); ready_list_2.clear(); if(write_pending || !ready_list.empty()){ // give links that are not in ready_list a chance events = select.wait(0); }else{ events = select.wait(50); } if(events == NULL){ log_fatal("events.wait error: %s", strerror(errno)); break; } for(int i=0; i<(int)events->size(); i++){ const Fdevent *fde = events->at(i); if(fde->data.ptr == serv_link){ Link *link = serv_link->accept(); if(link == NULL){ log_error("accept fail!"); continue; } link_count ++; log_info("new link from %s:%d, fd: %d, link_count: %d", link->remote_ip, link->remote_port, link->fd(), link_count); link->nodelay(); link->noblock(); link->create_time = millitime(); link->active_time = link->create_time; select.set(link->fd(), FDEVENT_IN, 1, link); }else if(fde->data.ptr == &serv.writer){ ProcJob job; if(serv.writer.pop(&job) == 0){ log_fatal("reading result from workers error!"); exit(0); } if(proc_result(job, select, ready_list_2) == PROC_ERROR){ link_count --; } }else{ Link *link = (Link *)fde->data.ptr; // 不能同时监听读和写事件, 只能监听其中一个 if(fde->events & FDEVENT_ERR){ log_info("fd: %d error, delete link", link->fd()); link_count --; select.del(link->fd()); delete link; }else if(fde->events & FDEVENT_IN){ int len = link->read(); //log_trace("fd: %d read: %d", link->fd(), len); if(len <= 0){ log_info("fd: %d, read: %d, delete link", link->fd(), len); link_count --; select.del(link->fd()); delete link; }else{ ready_list.push_back(link); } }else if(fde->events & FDEVENT_OUT){ int len = link->write(); //log_trace("fd: %d write: %d", link->fd(), len); if(len <= 0){ log_info("fd: %d, write: %d, delete link", link->fd(), len); link_count --; select.del(link->fd()); delete link; }else if(link->output->empty()){ //log_trace("delete %d from select.out", link->fd()); select.clr(link->fd(), FDEVENT_OUT); if(!link->input->empty()){ ready_list.push_back(link); }else{ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } }else{ write_pending = true; } } } } for(it = ready_list.begin(); it != ready_list.end(); it ++){ Link *link = *it; const Request *req = link->recv(); if(req == NULL){ log_warn("fd: %d, link parse error, delete link", link->fd()); link_count --; select.del(link->fd()); delete link; continue; } if(req->empty()){ if(!select.isset(link->fd(), FDEVENT_IN)){ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } continue; } ProcJob job; job.link = link; serv.proc(&job); if(job.result == PROC_BACKEND){ select.del(link->fd()); continue; } link->active_time = millitime(); if(proc_result(job, select, ready_list_2) == PROC_ERROR){ link_count --; } } // end foreach ready link ready_list.swap(ready_list_2); } }
void run(int argc, char **argv){ typedef std::vector<Link *> ready_list_t; ready_list_t ready_list; ready_list_t ready_list_2; ready_list_t::iterator it; const Fdevents::events_t *events; Fdevents select; select.set(serv_link->fd(), FDEVENT_IN, 0, serv_link); CommandProc proc(ssdb); while(!quit){ if(!ready_list.empty()){ // give links that are not in ready_list a chance events = select.wait(0); }else{ events = select.wait(200); } if(events == NULL){ log_fatal("events.wait error: %s", strerror(errno)); break; } for(int i=0; i<(int)events->size(); i++){ const Fdevent *fde = events->at(i); if(fde->data.ptr == serv_link){ Link *link = serv_link->accept(); if(link == NULL){ log_error("accept fail!"); continue; } // link->nodelay(); link->noblock(); // select.set(link->fd(), FDEVENT_IN, 1, link); log_info("new link: %d", link->fd()); }else{ Link *link = (Link *)fde->data.ptr; // 不能同时监听读和写事件, 只能监听其中一个 if(fde->events & FDEVENT_IN){ int len = link->read(); log_trace("fd: %d read: %d", link->fd(), len); if(len <= 0){ log_info("fd: %d, read: %d, delete link", link->fd(), len); select.del(link->fd()); delete link; }else{ ready_list.push_back(link); } }else if(fde->events & FDEVENT_OUT){ int len = link->write(); log_trace("fd: %d write: %d", link->fd(), len); if(len < 0){ log_info("fd: %d, write: %d, delete link", link->fd(), len); select.del(link->fd()); delete link; }else if(link->output->empty()){ //log_trace("delete %d from select.out", link->fd()); select.clr(link->fd(), FDEVENT_OUT); if(!link->input->empty()){ ready_list.push_back(link); }else{ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } } } } } ready_list_2.clear(); for(it = ready_list.begin(); it != ready_list.end(); it ++){ Link *link = *it; const Request *req = link->recv(); if(req == NULL){ log_warn("fd: %d, link parse error, delete link", link->fd()); select.del(link->fd()); delete link; continue; } if(req->empty()){ if(!select.isset(link->fd(), FDEVENT_IN)){ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } continue; } Response resp; int status = proc.proc(*link, *req, &resp); if(status == PROC_ERROR){ log_info("fd: %d, proc error, delete link", link->fd()); select.del(link->fd()); delete link; continue; }else if(status == PROC_BACKEND){ select.del(link->fd()); continue; } if(link->send(resp) == -1){ log_info("fd: %d, send error, delete link", link->fd()); select.del(link->fd()); delete link; continue; } if(!link->output->empty()){ //log_trace("add %d to select.out", link->fd()); select.set(link->fd(), FDEVENT_OUT, 1, link); if(select.isset(link->fd(), FDEVENT_IN)){ //log_trace("delete %d from select.in", link->fd()); select.clr(link->fd(), FDEVENT_IN); } }else{ if(link->input->empty()){ if(!select.isset(link->fd(), FDEVENT_IN)){ //log_trace("add %d to select.in", link->fd()); select.set(link->fd(), FDEVENT_IN, 1, link); } }else{ if(select.isset(link->fd(), FDEVENT_IN)){ //log_trace("delete %d from select.in", link->fd()); select.clr(link->fd(), FDEVENT_IN); } ready_list_2.push_back(link); } } } // end foreach ready link ready_list.swap(ready_list_2); } }