/*
 * File descriptors management functions.
 *
 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

/*
 * FIXME:
 * - we still use 'listeners' to check whether we want to stop or not.
 * - the various pollers should be moved to other external files, possibly
 *   dynamic libs.
 */

#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>

#include <common/compat.h>
#include <common/config.h>
#include <common/time.h>

#include <types/fd.h>
#include <types/global.h>

#include <proto/fd.h>
#include <proto/polling.h>
#include <proto/task.h>

struct fdtab *fdtab = NULL;     /* array of all the file descriptors */
int maxfd;                      /* # of the highest fd + 1 */
int totalconn;                  /* total # of terminated sessions */
int actconn;                    /* # of active sessions */

fd_set	*StaticReadEvent, *StaticWriteEvent;
int cfg_polling_mechanism = 0;  /* POLL_USE_{SELECT|POLL|EPOLL} */


/******************************
 * pollers
 ******************************/


#if !defined(CONFIG_HAP_INLINE_FD_SET)
/*
 * Benchmarks performed on a Pentium-M notebook show that using functions
 * instead of the usual macros improve the FD_* performance by about 80%,
 * and that marking them regparm(2) adds another 20%.
 */
REGPRM2 void my_fd_set(const int fd, fd_set *ev)
{
	FD_SET(fd, ev);
}

REGPRM2 void my_fd_clr(const int fd, fd_set *ev)
{
	FD_CLR(fd, ev);
}

REGPRM2 int my_fd_isset(const int fd, const fd_set *ev)
{
	return FD_ISSET(fd, ev);
}
#endif


/*
 * FIXME: this is dirty, but at the moment, there's no other solution to remove
 * the old FDs from outside the loop. Perhaps we should export a global 'poll'
 * structure with pointers to functions such as init_fd() and close_fd(), plus
 * a private structure with several pointers to places such as below.
 */

#if defined(ENABLE_EPOLL)
fd_set *PrevReadEvent = NULL, *PrevWriteEvent = NULL;

#if defined(USE_MY_EPOLL)
#include <errno.h>
#include <sys/syscall.h>
_syscall1 (int, epoll_create, int, size);
_syscall4 (int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event);
_syscall4 (int, epoll_wait, int, epfd, struct epoll_event *, events, int, maxevents, int, timeout);
#endif

/*
 * Main epoll() loop.
 * does 3 actions :
 * 0 (POLL_LOOP_ACTION_INIT)  : initializes necessary private structures
 * 1 (POLL_LOOP_ACTION_RUN)   : runs the loop
 * 2 (POLL_LOOP_ACTION_CLEAN) : cleans up
 *
 * returns 0 if initialization failed, !0 otherwise.
 */

int epoll_loop(int action)
{
	int next_time;
	int status;
	int fd;

	int fds, count;
	int pr, pw, sr, sw;
	unsigned rn, ro, wn, wo; /* read new, read old, write new, write old */
	struct epoll_event ev;

	/* private data */
	static struct epoll_event *epoll_events = NULL;
	static int epoll_fd;

	if (action == POLL_LOOP_ACTION_INIT) {
		epoll_fd = epoll_create(global.maxsock + 1);
		if (epoll_fd < 0)
			return 0;
		else {
			epoll_events = (struct epoll_event*)
				calloc(1, sizeof(struct epoll_event) * global.maxsock);
			PrevReadEvent = (fd_set *)
				calloc(1, sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE);
			PrevWriteEvent = (fd_set *)
				calloc(1, sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE);
		}
		return 1;
	}
	else if (action == POLL_LOOP_ACTION_CLEAN) {
		if (PrevWriteEvent) free(PrevWriteEvent);
		if (PrevReadEvent)  free(PrevReadEvent);
		if (epoll_events)   free(epoll_events);
		close(epoll_fd);
		epoll_fd = 0;
		return 1;
	}

	/* OK, it's POLL_LOOP_ACTION_RUN */

	tv_now(&now);

	while (1) {
		next_time = process_runnable_tasks();

		/* stop when there's no connection left and we don't allow them anymore */
		if (!actconn && listeners == 0)
			break;

		for (fds = 0; (fds << INTBITS) < maxfd; fds++) {
	  
			rn = ((int*)StaticReadEvent)[fds];  ro = ((int*)PrevReadEvent)[fds];
			wn = ((int*)StaticWriteEvent)[fds]; wo = ((int*)PrevWriteEvent)[fds];
	  
			if ((ro^rn) | (wo^wn)) {
				for (count = 0, fd = fds << INTBITS; count < (1<<INTBITS) && fd < maxfd; count++, fd++) {
#define FDSETS_ARE_INT_ALIGNED
#ifdef FDSETS_ARE_INT_ALIGNED

#define WE_REALLY_NOW_THAT_FDSETS_ARE_INTS
#ifdef WE_REALLY_NOW_THAT_FDSETS_ARE_INTS
					pr = (ro >> count) & 1;
					pw = (wo >> count) & 1;
					sr = (rn >> count) & 1;
					sw = (wn >> count) & 1;
#else
					pr = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&ro);
					pw = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&wo);
					sr = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&rn);
					sw = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&wn);
#endif
#else
					pr = MY_FD_ISSET(fd, PrevReadEvent);
					pw = MY_FD_ISSET(fd, PrevWriteEvent);
					sr = MY_FD_ISSET(fd, StaticReadEvent);
					sw = MY_FD_ISSET(fd, StaticWriteEvent);
#endif
					if (!((sr^pr) | (sw^pw)))
						continue;

					ev.events = (sr ? EPOLLIN : 0) | (sw ? EPOLLOUT : 0);
					ev.data.fd = fd;

#ifdef EPOLL_CTL_MOD_WORKAROUND
					/* I encountered a rarely reproducible problem with
					 * EPOLL_CTL_MOD where a modified FD (systematically
					 * the one in epoll_events[0], fd#7) would sometimes
					 * be set EPOLL_OUT while asked for a read ! This is
					 * with the 2.4 epoll patch. The workaround is to
					 * delete then recreate in case of modification.
					 * This is in 2.4 up to epoll-lt-0.21 but not in 2.6
					 * nor RHEL kernels.
					 */

					if ((pr | pw) && fdtab[fd].state != FD_STCLOSE)
						epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev);

					if ((sr | sw))
						epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
#else
					if ((pr | pw)) {
						/* the file-descriptor already exists... */
						if ((sr | sw)) {
							/* ...and it will still exist */
							if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev) < 0) {
								// perror("epoll_ctl(MOD)");
								// exit(1);
							}
						} else {
							/* ...and it will be removed */
							if (fdtab[fd].state != FD_STCLOSE &&
							    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev) < 0) {
								// perror("epoll_ctl(DEL)");
								// exit(1);
							}
						}
					} else {
						/* the file-descriptor did not exist, let's add it */
						if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
							// perror("epoll_ctl(ADD)");
							//  exit(1);
						}
					}
#endif // EPOLL_CTL_MOD_WORKAROUND
				}
				((int*)PrevReadEvent)[fds] = rn;
				((int*)PrevWriteEvent)[fds] = wn;
			}		  
		}
      
		/* now let's wait for events */
		status = epoll_wait(epoll_fd, epoll_events, maxfd, next_time);
		tv_now(&now);

		for (count = 0; count < status; count++) {
			fd = epoll_events[count].data.fd;

			if (MY_FD_ISSET(fd, StaticReadEvent)) {
				if (fdtab[fd].state == FD_STCLOSE)
					continue;
				if (epoll_events[count].events & ( EPOLLIN | EPOLLERR | EPOLLHUP ))
					fdtab[fd].cb[DIR_RD].f(fd);
			}

			if (MY_FD_ISSET(fd, StaticWriteEvent)) {
				if (fdtab[fd].state == FD_STCLOSE)
					continue;
				if (epoll_events[count].events & ( EPOLLOUT | EPOLLERR | EPOLLHUP ))
					fdtab[fd].cb[DIR_WR].f(fd);
			}
		}
	}
	return 1;
}
#endif



#if defined(ENABLE_POLL)
/*
 * Main poll() loop.
 * does 3 actions :
 * 0 (POLL_LOOP_ACTION_INIT)  : initializes necessary private structures
 * 1 (POLL_LOOP_ACTION_RUN)   : runs the loop
 * 2 (POLL_LOOP_ACTION_CLEAN) : cleans up
 *
 * returns 0 if initialization failed, !0 otherwise.
 */

int poll_loop(int action)
{
	int next_time;
	int status;
	int fd, nbfd;

	int fds, count;
	int sr, sw;
	unsigned rn, wn; /* read new, write new */

	/* private data */
	static struct pollfd *poll_events = NULL;

	if (action == POLL_LOOP_ACTION_INIT) {
		poll_events = (struct pollfd*)
			calloc(1, sizeof(struct pollfd) * global.maxsock);
		return 1;
	}
	else if (action == POLL_LOOP_ACTION_CLEAN) {
		if (poll_events)
			free(poll_events);
		return 1;
	}

	/* OK, it's POLL_LOOP_ACTION_RUN */

	tv_now(&now);

	while (1) {
		next_time = process_runnable_tasks();

		/* stop when there's no connection left and we don't allow them anymore */
		if (!actconn && listeners == 0)
			break;

		nbfd = 0;
		for (fds = 0; (fds << INTBITS) < maxfd; fds++) {
	  
			rn = ((int*)StaticReadEvent)[fds];
			wn = ((int*)StaticWriteEvent)[fds];
	  
			if ((rn|wn)) {
				for (count = 0, fd = fds << INTBITS; count < (1<<INTBITS) && fd < maxfd; count++, fd++) {
#define FDSETS_ARE_INT_ALIGNED
#ifdef FDSETS_ARE_INT_ALIGNED

#define WE_REALLY_NOW_THAT_FDSETS_ARE_INTS
#ifdef WE_REALLY_NOW_THAT_FDSETS_ARE_INTS
					sr = (rn >> count) & 1;
					sw = (wn >> count) & 1;
#else
					sr = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&rn);
					sw = MY_FD_ISSET(fd&((1<<INTBITS)-1), (typeof(fd_set*))&wn);
#endif
#else
					sr = MY_FD_ISSET(fd, StaticReadEvent);
					sw = MY_FD_ISSET(fd, StaticWriteEvent);
#endif
					if ((sr|sw)) {
						poll_events[nbfd].fd = fd;
						poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0);
						nbfd++;
					}
				}
			}		  
		}
      
		/* now let's wait for events */
		status = poll(poll_events, nbfd, next_time);
		tv_now(&now);

		for (count = 0; status > 0 && count < nbfd; count++) {
			fd = poll_events[count].fd;
	  
			if (!(poll_events[count].revents & ( POLLOUT | POLLIN | POLLERR | POLLHUP )))
				continue;

			/* ok, we found one active fd */
			status--;

			if (MY_FD_ISSET(fd, StaticReadEvent)) {
				if (fdtab[fd].state == FD_STCLOSE)
					continue;
				if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP ))
					fdtab[fd].cb[DIR_RD].f(fd);
			}
	  
			if (MY_FD_ISSET(fd, StaticWriteEvent)) {
				if (fdtab[fd].state == FD_STCLOSE)
					continue;
				if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP ))
					fdtab[fd].cb[DIR_WR].f(fd);
			}
		}
	}
	return 1;
}
#endif



/*
 * Main select() loop.
 * does 3 actions :
 * 0 (POLL_LOOP_ACTION_INIT)  : initializes necessary private structures
 * 1 (POLL_LOOP_ACTION_RUN)   : runs the loop
 * 2 (POLL_LOOP_ACTION_CLEAN) : cleans up
 *
 * returns 0 if initialization failed, !0 otherwise.
 */


int select_loop(int action)
{
	int next_time;
	int status;
	int fd,i;
	struct timeval delta;
	int readnotnull, writenotnull;
	static fd_set	*ReadEvent = NULL, *WriteEvent = NULL;

	if (action == POLL_LOOP_ACTION_INIT) {
		ReadEvent = (fd_set *)
			calloc(1, sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE);
		WriteEvent = (fd_set *)
			calloc(1, sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE);
		return 1;
	}
	else if (action == POLL_LOOP_ACTION_CLEAN) {
		if (WriteEvent)       free(WriteEvent);
		if (ReadEvent)        free(ReadEvent);
		return 1;
	}

	/* OK, it's POLL_LOOP_ACTION_RUN */

	tv_now(&now);

	while (1) {
		next_time = process_runnable_tasks();

		/* stop when there's no connection left and we don't allow them anymore */
		if (!actconn && listeners == 0)
			break;

		if (next_time > 0) {  /* FIXME */
			/* Convert to timeval */
			/* to avoid eventual select loops due to timer precision */
			next_time += SCHEDULER_RESOLUTION;
			delta.tv_sec  = next_time / 1000; 
			delta.tv_usec = (next_time % 1000) * 1000;
		}
		else if (next_time == 0) { /* allow select to return immediately when needed */
			delta.tv_sec = delta.tv_usec = 0;
		}


		/* let's restore fdset state */

		readnotnull = 0; writenotnull = 0;
		for (i = 0; i < (maxfd + FD_SETSIZE - 1)/(8*sizeof(int)); i++) {
			readnotnull |= (*(((int*)ReadEvent)+i) = *(((int*)StaticReadEvent)+i)) != 0;
			writenotnull |= (*(((int*)WriteEvent)+i) = *(((int*)StaticWriteEvent)+i)) != 0;
		}

		//	/* just a verification code, needs to be removed for performance */
		//	for (i=0; i<maxfd; i++) {
		//	    if (MY_FD_ISSET(i, ReadEvent) != MY_FD_ISSET(i, StaticReadEvent))
		//		abort();
		//	    if (MY_FD_ISSET(i, WriteEvent) != MY_FD_ISSET(i, StaticWriteEvent))
		//		abort();
		//	    
		//	}

		status = select(maxfd,
				readnotnull ? ReadEvent : NULL,
				writenotnull ? WriteEvent : NULL,
				NULL,
				(next_time >= 0) ? &delta : NULL);
      
		/* this is an experiment on the separation of the select work */
		// status  = (readnotnull  ? select(maxfd, ReadEvent, NULL, NULL, (next_time >= 0) ? &delta : NULL) : 0);
		// status |= (writenotnull ? select(maxfd, NULL, WriteEvent, NULL, (next_time >= 0) ? &delta : NULL) : 0);
      
		tv_now(&now);

		if (status > 0) { /* must proceed with events */

			int fds;
			char count;
	  
			for (fds = 0; (fds << INTBITS) < maxfd; fds++)
				if ((((int *)(ReadEvent))[fds] | ((int *)(WriteEvent))[fds]) != 0)
					for (count = 1<<INTBITS, fd = fds << INTBITS; count && fd < maxfd; count--, fd++) {
		      
						/* if we specify read first, the accepts and zero reads will be
						 * seen first. Moreover, system buffers will be flushed faster.
						 */
						if (MY_FD_ISSET(fd, ReadEvent)) {
							if (fdtab[fd].state == FD_STCLOSE)
								continue;
							fdtab[fd].cb[DIR_RD].f(fd);
						}

						if (MY_FD_ISSET(fd, WriteEvent)) {
							if (fdtab[fd].state == FD_STCLOSE)
								continue;
							fdtab[fd].cb[DIR_WR].f(fd);
						}
					}
		}
		else {
			//	  fprintf(stderr,"select returned %d, maxfd=%d\n", status, maxfd);
		}
	}
	return 1;
}



/*********************
 * generic functions
 *********************/


/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
 * The file descriptor is also closed.
 */
void fd_delete(int fd)
{
	MY_FD_CLR(fd, StaticReadEvent);
	MY_FD_CLR(fd, StaticWriteEvent);
#if defined(ENABLE_EPOLL)
	if (PrevReadEvent) {
		MY_FD_CLR(fd, PrevReadEvent);
		MY_FD_CLR(fd, PrevWriteEvent);
	}
#endif

	close(fd);
	fdtab[fd].state = FD_STCLOSE;

	while ((maxfd-1 >= 0) && (fdtab[maxfd-1].state == FD_STCLOSE))
		maxfd--;
}


/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 */
