/*
- include/proto/fd.h
- File descriptors states.
-
- Copyright (C) 2000-2007 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
-*/
+ * include/proto/fd.h
+ * File descriptors states.
+ *
+ * Copyright (C) 2000-2012 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
*/
void run_poller();
-#define EV_FD_SET(fd, ev) (cur_poller.set((fd), (ev)))
-#define EV_FD_CLR(fd, ev) (cur_poller.clr((fd), (ev)))
#define EV_FD_ISSET(fd, ev) (cur_poller.is_set((fd), (ev)))
-#define EV_FD_REM(fd) (cur_poller.rem(fd))
-#define EV_FD_CLO(fd) (cur_poller.clo(fd))
+/* event manipulation primitives for use by I/O callbacks */
+static inline void fd_want_recv(int fd)
+{
+ cur_poller.set(fd, DIR_RD);
+}
+
+static inline void fd_stop_recv(int fd)
+{
+ cur_poller.clr(fd, DIR_RD);
+}
+
+static inline void fd_want_send(int fd)
+{
+ cur_poller.set(fd, DIR_WR);
+}
+
+static inline void fd_stop_send(int fd)
+{
+ cur_poller.clr(fd, DIR_WR);
+}
+
+static inline void fd_stop_both(int fd)
+{
+ cur_poller.rem(fd);
+}
/* Prepares <fd> for being polled */
static inline void fd_insert(int fd)
static inline void si_shutr(struct stream_interface *si)
{
if (stream_int_shutr(si))
- EV_FD_CLR(si_fd(si), DIR_RD);
+ fd_stop_recv(si_fd(si));
}
/* Sends a shutw to the connection using the data layer */
static inline void si_shutw(struct stream_interface *si)
{
if (stream_int_shutw(si))
- EV_FD_CLR(si_fd(si), DIR_WR);
+ fd_stop_send(si_fd(si));
}
/* Calls the data state update on the stream interfaace */
t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
task_queue(t);
}
- EV_FD_SET(fd, DIR_RD); /* prepare for reading reply */
+ fd_want_recv(fd); /* prepare for reading reply */
goto out_nowake;
}
else if (ret == 0 || errno == EAGAIN)
out_wakeup:
task_wakeup(t, TASK_WOKEN_IO);
out_nowake:
- EV_FD_CLR(fd, DIR_WR); /* nothing more to write */
+ fd_stop_send(fd); /* nothing more to write */
fdtab[fd].ev &= ~FD_POLL_OUT;
return 1;
out_poll:
/* Close the connection... */
shutdown(fd, SHUT_RDWR);
- EV_FD_CLR(fd, DIR_RD);
+ fd_stop_recv(fd);
task_wakeup(t, TASK_WOKEN_IO);
fdtab[fd].ev &= ~FD_POLL_IN;
return 1;
fdtab[fd].owner = t;
fdtab[fd].iocb = &check_iocb;
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
- EV_FD_SET(fd, DIR_WR); /* for connect status */
+ fd_want_send(fd); /* for connect status */
#ifdef DEBUG_FULL
assert (!EV_FD_ISSET(fd, DIR_RD));
#endif
*/
void fd_delete(int fd)
{
- EV_FD_CLO(fd);
+ cur_poller.clo(fd);
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
stream_int_retnclose(&s->si[0], &msg); /* forge a 200 response */
s->req->analysers = 0;
s->task->expire = s->rep->wex;
- EV_FD_CLR(cfd, DIR_RD);
+ fd_stop_recv(cfd);
}
else if (unlikely(s->fe->mode == PR_MODE_HEALTH)) { /* health check mode, no client reading */
struct chunk msg;
stream_int_retnclose(&s->si[0], &msg); /* forge an "OK" response */
s->req->analysers = 0;
s->task->expire = s->rep->wex;
- EV_FD_CLR(cfd, DIR_RD);
+ fd_stop_recv(cfd);
}
/* everything's OK, let's go on */
return 1;
fdtab[fd].iocb = conn_fd_handler;
fd_insert(fd);
- EV_FD_SET(fd, DIR_WR); /* for connect status */
+ fd_want_send(fd); /* for connect status */
si->state = SI_ST_CON;
si->flags |= SI_FL_CAP_SPLTCP; /* TCP supports splicing */
*/
conn->flags |= CO_FL_ERROR;
- EV_FD_REM(fd);
+ fd_stop_both(fd);
return 1;
}
{
if (listener->state == LI_LISTEN) {
if (listener->nbconn < listener->maxconn) {
- EV_FD_SET(listener->fd, DIR_RD);
+ fd_want_recv(listener->fd);
listener->state = LI_READY;
} else {
listener->state = LI_FULL;
if (listener->state < LI_READY)
return;
if (listener->state == LI_READY)
- EV_FD_CLR(listener->fd, DIR_RD);
+ fd_stop_recv(listener->fd);
if (listener->state == LI_LIMITED)
LIST_DEL(&listener->wait_queue);
listener->state = LI_LISTEN;
if (l->state == LI_LIMITED)
LIST_DEL(&l->wait_queue);
- EV_FD_CLR(l->fd, DIR_RD);
+ fd_stop_recv(l->fd);
l->state = LI_PAUSED;
return 1;
}
return 1;
}
- EV_FD_SET(l->fd, DIR_RD);
+ fd_want_recv(l->fd);
l->state = LI_READY;
return 1;
}
if (l->state == LI_LIMITED)
LIST_DEL(&l->wait_queue);
- EV_FD_CLR(l->fd, DIR_RD);
+ fd_stop_recv(l->fd);
l->state = LI_FULL;
}
}
{
if (l->state == LI_READY) {
LIST_ADDQ(list, &l->wait_queue);
- EV_FD_CLR(l->fd, DIR_RD);
+ fd_stop_recv(l->fd);
l->state = LI_LIMITED;
}
}
int unbind_listener(struct listener *listener)
{
if (listener->state == LI_READY)
- EV_FD_CLR(listener->fd, DIR_RD);
+ fd_stop_recv(listener->fd);
if (listener->state == LI_LIMITED)
LIST_DEL(&listener->wait_queue);
fdtab[cfd].owner = &s->si[0].conn;
fdtab[cfd].flags = 0;
fdtab[cfd].iocb = conn_fd_handler;
- EV_FD_SET(cfd, DIR_RD);
+ fd_want_recv(cfd);
if (p->accept && (ret = p->accept(s)) <= 0) {
/* Either we had an unrecoverable error (<0) or work is
* place and ask the consumer to hurry.
*/
si->flags |= SI_FL_WAIT_ROOM;
- EV_FD_CLR(fd, DIR_RD);
+ fd_stop_recv(fd);
b->rex = TICK_ETERNITY;
si_chk_snd(b->cons);
return 1;
*/
conn->flags |= CO_FL_ERROR;
- EV_FD_REM(fd);
+ fd_stop_both(fd);
retval = 1;
goto out_wakeup;
}
*/
conn->flags |= CO_FL_ERROR;
- EV_FD_REM(fd);
+ fd_stop_both(fd);
return 1;
}
}
/* otherwise that's just a normal read shutdown */
- EV_FD_CLR(si_fd(si), DIR_RD);
+ fd_stop_recv(si_fd(si));
return;
do_close:
if (!(si->flags & SI_FL_WAIT_ROOM)) {
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
si->flags |= SI_FL_WAIT_ROOM;
- EV_FD_CLR(fd, DIR_RD);
+ fd_stop_recv(fd);
ib->rex = TICK_ETERNITY;
}
}
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_ROOM;
- EV_FD_SET(fd, DIR_RD);
+ fd_want_recv(fd);
if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
ib->rex = tick_add_ifset(now_ms, ib->rto);
}
if (!(si->flags & SI_FL_WAIT_DATA)) {
if ((ob->flags & (BF_FULL|BF_HIJACK|BF_SHUTW_NOW)) == 0)
si->flags |= SI_FL_WAIT_DATA;
- EV_FD_CLR(fd, DIR_WR);
+ fd_stop_send(fd);
ob->wex = TICK_ETERNITY;
}
}
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_DATA;
- EV_FD_SET(fd, DIR_WR);
+ fd_want_send(fd);
if (!tick_isset(ob->wex)) {
ob->wex = tick_add_ifset(now_ms, ob->wto);
if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
/* stop reading */
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
si->flags |= SI_FL_WAIT_ROOM;
- EV_FD_CLR(si_fd(si), DIR_RD);
+ fd_stop_recv(si_fd(si));
}
else {
/* (re)start reading */
si->flags &= ~SI_FL_WAIT_ROOM;
- EV_FD_SET(si_fd(si), DIR_RD);
+ fd_want_recv(si_fd(si));
}
}
*/
si->conn.flags |= CO_FL_ERROR;
fdtab[si_fd(si)].ev &= ~FD_POLL_STICKY;
- EV_FD_REM(si_fd(si));
+ fd_stop_both(si_fd(si));
si->flags |= SI_FL_ERR;
goto out_wakeup;
}
/* Otherwise there are remaining data to be sent in the buffer,
* which means we have to poll before doing so.
*/
- EV_FD_SET(si_fd(si), DIR_WR);
+ fd_want_send(si_fd(si));
si->flags &= ~SI_FL_WAIT_DATA;
if (!tick_isset(ob->wex))
ob->wex = tick_add_ifset(now_ms, ob->wto);
conn->flags |= CO_FL_ERROR;
fdtab[fd].ev &= ~FD_POLL_STICKY;
- EV_FD_REM(fd);
+ fd_stop_both(fd);
goto out_leave;
out_wait:
if (((si->ob->flags & (BF_SHUTW|BF_HIJACK|BF_SHUTW_NOW)) == BF_SHUTW_NOW) &&
(si->state == SI_ST_EST))
stream_int_shutw(si);
- EV_FD_CLR(fd, DIR_WR);
+ fd_stop_send(fd);
si->ob->wex = TICK_ETERNITY;
}
}
if (si->flags & SI_FL_WAIT_ROOM) {
- EV_FD_CLR(fd, DIR_RD);
+ fd_stop_recv(fd);
si->ib->rex = TICK_ETERNITY;
}
else if ((si->ib->flags & (BF_SHUTR|BF_READ_PARTIAL|BF_FULL|BF_DONT_READ|BF_READ_NOEXP)) == BF_READ_PARTIAL) {