Beispiel #1
0
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;
}
Beispiel #3
0
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);
	}
}
Beispiel #5
0
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);
	}
}