/*
 * include/proto/fd.h
 * File descriptors states.
 *
 * Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, version 2.1
 * exclusively.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _PROTO_FD_H
#define _PROTO_FD_H

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

#include <common/config.h>

#include <types/fd.h>

/* public variables */

extern unsigned int *fd_cache;      // FD events cache
extern int fd_cache_num;            // number of events in the cache
extern unsigned long fd_cache_mask; // Mask of threads with events in the cache

extern THREAD_LOCAL int *fd_updt;  // FD updates list
extern THREAD_LOCAL int fd_nbupdt; // number of updates in the list

__decl_hathreads(extern HA_RWLOCK_T   __attribute__((aligned(64))) fdcache_lock);    /* global lock to protect fd_cache array */
__decl_hathreads(extern HA_SPINLOCK_T __attribute__((aligned(64))) poll_lock);       /* global lock to protect poll info */

/* Deletes an FD from the fdsets.
 * The file descriptor is also closed.
 */
void fd_delete(int fd);

/* Deletes an FD from the fdsets.
 * The file descriptor is kept open.
 */
void fd_remove(int fd);

/* disable the specified poller */
void disable_poller(const char *poller_name);

/*
 * Initialize the pollers till the best one is found.
 * If none works, returns 0, otherwise 1.
 * The pollers register themselves just before main() is called.
 */
int init_pollers();

/*
 * Deinitialize the pollers.
 */
void deinit_pollers();

/*
 * Some pollers may lose their connection after a fork(). It may be necessary
 * to create initialize part of them again. Returns 0 in case of failure,
 * otherwise 1. The fork() function may be NULL if unused. In case of error,
 * the the current poller is destroyed and the caller is responsible for trying
 * another one by calling init_pollers() again.
 */
int fork_poller();

/*
 * Lists the known pollers on <out>.
 * Should be performed only before initialization.
 */
int list_pollers(FILE *out);

/*
 * Runs the polling loop
 */
void run_poller();

/* Scan and process the cached events. This should be called right after
 * the poller.
 */
void fd_process_cached_events();

/* Mark fd <fd> as updated for polling and allocate an entry in the update list
 * for this if it was not already there. This can be done at any time.
 */
static inline void updt_fd_polling(const int fd)
{
	if (fdtab[fd].update_mask & tid_bit)
		/* already scheduled for update */
		return;
	fdtab[fd].update_mask |= tid_bit;
	fd_updt[fd_nbupdt++] = fd;
}


/* Allocates a cache entry for a file descriptor if it does not yet have one.
 * This can be done at any time.
 */
static inline void fd_alloc_cache_entry(const int fd)
{
	HA_RWLOCK_WRLOCK(FDCACHE_LOCK, &fdcache_lock);
	if (fdtab[fd].cache)
		goto end;
	fd_cache_num++;
	fd_cache_mask |= fdtab[fd].thread_mask;
	fdtab[fd].cache = fd_cache_num;
	fd_cache[fd_cache_num-1] = fd;
  end:
	HA_RWLOCK_WRUNLOCK(FDCACHE_LOCK, &fdcache_lock);
}

/* Removes entry used by fd <fd> from the FD cache and replaces it with the
 * last one. The fdtab.cache is adjusted to match the back reference if needed.
 * If the fd has no entry assigned, return immediately.
 */
static inline void fd_release_cache_entry(int fd)
{
	unsigned int pos;

	HA_RWLOCK_WRLOCK(FDCACHE_LOCK, &fdcache_lock);
	pos = fdtab[fd].cache;
	if (!pos)
		goto end;
	fdtab[fd].cache = 0;
	fd_cache_num--;
	if (likely(pos <= fd_cache_num)) {
		/* was not the last entry */
		fd = fd_cache[fd_cache_num];
		fd_cache[pos - 1] = fd;
		fdtab[fd].cache = pos;
	}
  end:
	HA_RWLOCK_WRUNLOCK(FDCACHE_LOCK, &fdcache_lock);
}

/* Computes the new polled status based on the active and ready statuses, for
 * each direction. This is meant to be used by pollers while processing updates.
 */
static inline int fd_compute_new_polled_status(int state)
{
	if (state & FD_EV_ACTIVE_R) {
		if (!(state & FD_EV_READY_R))
			state |= FD_EV_POLLED_R;
	}
	else
		state &= ~FD_EV_POLLED_R;

	if (state & FD_EV_ACTIVE_W) {
		if (!(state & FD_EV_READY_W))
			state |= FD_EV_POLLED_W;
	}
	else
		state &= ~FD_EV_POLLED_W;

	return state;
}

/* This function automatically enables/disables caching for an entry depending
 * on its state, and also possibly creates an update entry so that the poller
 * does its job as well. It is only called on state changes.
 */
static inline void fd_update_cache(int fd)
{
	/* 3 states for each direction require a polling update */
	if ((fdtab[fd].state & (FD_EV_POLLED_R |                 FD_EV_ACTIVE_R)) == FD_EV_POLLED_R ||
	    (fdtab[fd].state & (FD_EV_POLLED_R | FD_EV_READY_R | FD_EV_ACTIVE_R)) == FD_EV_ACTIVE_R ||
	    (fdtab[fd].state & (FD_EV_POLLED_W |                 FD_EV_ACTIVE_W)) == FD_EV_POLLED_W ||
	    (fdtab[fd].state & (FD_EV_POLLED_W | FD_EV_READY_W | FD_EV_ACTIVE_W)) == FD_EV_ACTIVE_W)
		updt_fd_polling(fd);

	/* only READY and ACTIVE states (the two with both flags set) require a cache entry */
	if (((fdtab[fd].state & (FD_EV_READY_R | FD_EV_ACTIVE_R)) == (FD_EV_READY_R | FD_EV_ACTIVE_R)) ||
	    ((fdtab[fd].state & (FD_EV_READY_W | FD_EV_ACTIVE_W)) == (FD_EV_READY_W | FD_EV_ACTIVE_W))) {
		fd_alloc_cache_entry(fd);
	}
	else {
		fd_release_cache_entry(fd);
	}
}

/*
 * returns the FD's recv state (FD_EV_*)
 */
static inline int fd_recv_state(const int fd)
{
	return ((unsigned)fdtab[fd].state >> (4 * DIR_RD)) & FD_EV_STATUS;
}

/*
 * returns true if the FD is active for recv
 */
static inline int fd_recv_active(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_ACTIVE_R;
}

/*
 * returns true if the FD is ready for recv
 */
static inline int fd_recv_ready(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_READY_R;
}

/*
 * returns true if the FD is polled for recv
 */
static inline int fd_recv_polled(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_POLLED_R;
}

/*
 * returns the FD's send state (FD_EV_*)
 */
static inline int fd_send_state(const int fd)
{
	return ((unsigned)fdtab[fd].state >> (4 * DIR_WR)) & FD_EV_STATUS;
}

/*
 * returns true if the FD is active for send
 */
static inline int fd_send_active(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_ACTIVE_W;
}

/*
 * returns true if the FD is ready for send
 */
static inline int fd_send_ready(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_READY_W;
}

/*
 * returns true if the FD is polled for send
 */
static inline int fd_send_polled(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_POLLED_W;
}

/*
 * returns true if the FD is active for recv or send
 */
static inline int fd_active(const int fd)
{
	return (unsigned)fdtab[fd].state & FD_EV_ACTIVE_RW;
}

/* Disable processing recv events on fd <fd> */
static inline void fd_stop_recv(int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_recv_active(fd)) {
		fdtab[fd].state &= ~FD_EV_ACTIVE_R;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Disable processing send events on fd <fd> */
static inline void fd_stop_send(int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_send_active(fd)) {
		fdtab[fd].state &= ~FD_EV_ACTIVE_W;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Disable processing of events on fd <fd> for both directions. */
static inline void fd_stop_both(int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_active(fd)) {
		fdtab[fd].state &= ~FD_EV_ACTIVE_RW;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Report that FD <fd> cannot receive anymore without polling (EAGAIN detected). */
static inline void fd_cant_recv(const int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_recv_ready(fd)) {
		fdtab[fd].state &= ~FD_EV_READY_R;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Report that FD <fd> can receive anymore without polling. */
static inline void fd_may_recv(const int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (!fd_recv_ready(fd)) {
		fdtab[fd].state |= FD_EV_READY_R;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Disable readiness when polled. This is useful to interrupt reading when it
 * is suspected that the end of data might have been reached (eg: short read).
 * This can only be done using level-triggered pollers, so if any edge-triggered
 * is ever implemented, a test will have to be added here.
 */
static inline void fd_done_recv(const int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_recv_polled(fd) && fd_recv_ready(fd)) {
		fdtab[fd].state &= ~FD_EV_READY_R;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Report that FD <fd> cannot send anymore without polling (EAGAIN detected). */
static inline void fd_cant_send(const int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (fd_send_ready(fd)) {
		fdtab[fd].state &= ~FD_EV_READY_W;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Report that FD <fd> can send anymore without polling (EAGAIN detected). */
static inline void fd_may_send(const int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (!fd_send_ready(fd)) {
		fdtab[fd].state |= FD_EV_READY_W;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Prepare FD <fd> to try to receive */
static inline void fd_want_recv(int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (!fd_recv_active(fd)) {
		fdtab[fd].state |= FD_EV_ACTIVE_R;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Prepare FD <fd> to try to send */
static inline void fd_want_send(int fd)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	if (!fd_send_active(fd)) {
		fdtab[fd].state |= FD_EV_ACTIVE_W;
		fd_update_cache(fd); /* need an update entry to change the state */
	}
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* Update events seen for FD <fd> and its state if needed. This should be called
 * by the poller to set FD_POLL_* flags. */
static inline void fd_update_events(int fd, int evts)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	fdtab[fd].ev &= FD_POLL_STICKY;
	fdtab[fd].ev |= evts;
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);

	if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR))
		fd_may_recv(fd);

	if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
		fd_may_send(fd);
}

/* Prepares <fd> for being polled */
static inline void fd_insert(int fd, unsigned long thread_mask)
{
	HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
	fdtab[fd].ev = 0;
	fdtab[fd].update_mask &= ~tid_bit;
	fdtab[fd].linger_risk = 0;
	fdtab[fd].cloned = 0;
	fdtab[fd].cache = 0;
	fdtab[fd].thread_mask = thread_mask;
	/* note: do not reset polled_mask here as it indicates which poller
	 * still knows this FD from a possible previous round.
	 */
	HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}

/* These are replacements for FD_SET, FD_CLR, FD_ISSET, working on uints */
static inline void hap_fd_set(int fd, unsigned int *evts)
{
	evts[fd / (8*sizeof(*evts))] |= 1U << (fd & (8*sizeof(*evts) - 1));
}

static inline void hap_fd_clr(int fd, unsigned int *evts)
{
	evts[fd / (8*sizeof(*evts))] &= ~(1U << (fd & (8*sizeof(*evts) - 1)));
}

static inline unsigned int hap_fd_isset(int fd, unsigned int *evts)
{
	return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1)));
}


#endif /* _PROTO_FD_H */

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