blob: 5ddfebdd0095901c5edc431371782c100e1dd12c [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * File descriptors management functions.
3 *
Willy Tarreau4f60f162007-04-08 16:39:58 +02004 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreau2ff76222007-04-09 19:29:56 +020013#include <stdio.h>
Willy Tarreau4f60f162007-04-08 16:39:58 +020014#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020015#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020016#include <sys/types.h>
17
Willy Tarreau2dd0d472006-06-29 17:53:05 +020018#include <common/compat.h>
19#include <common/config.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020
21#include <types/fd.h>
22#include <types/global.h>
23
Willy Tarreau2a429502006-10-15 14:52:29 +020024#include <proto/fd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
26struct fdtab *fdtab = NULL; /* array of all the file descriptors */
27int maxfd; /* # of the highest fd + 1 */
28int totalconn; /* total # of terminated sessions */
29int actconn; /* # of active sessions */
30
Willy Tarreaubaaee002006-06-26 02:48:02 +020031int cfg_polling_mechanism = 0; /* POLL_USE_{SELECT|POLL|EPOLL} */
32
Willy Tarreau4f60f162007-04-08 16:39:58 +020033struct poller pollers[MAX_POLLERS];
34struct poller cur_poller;
35int nbpollers = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37
Willy Tarreau4f60f162007-04-08 16:39:58 +020038/*********************
39 * generic functions
40 *********************/
Willy Tarreau2a429502006-10-15 14:52:29 +020041
Willy Tarreau4f60f162007-04-08 16:39:58 +020042extern int select_register(struct poller *p);
43#if defined(ENABLE_POLL)
44extern int poll_register(struct poller *p);
Willy Tarreau2a429502006-10-15 14:52:29 +020045#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020046#if defined(ENABLE_EPOLL)
Willy Tarreau4f60f162007-04-08 16:39:58 +020047extern int epoll_register(struct poller *p);
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#endif
Willy Tarreaue1a7a2f2007-04-09 16:11:49 +020049#if defined(ENABLE_KQUEUE)
50extern int kqueue_register(struct poller *p);
51#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreau4f60f162007-04-08 16:39:58 +020054/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
55 * The file descriptor is also closed.
56 */
57void fd_delete(int fd)
Willy Tarreaubaaee002006-06-26 02:48:02 +020058{
Willy Tarreau4f60f162007-04-08 16:39:58 +020059 EV_FD_CLO(fd);
60 close(fd);
61 fdtab[fd].state = FD_STCLOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +020062
Willy Tarreau4f60f162007-04-08 16:39:58 +020063 while ((maxfd-1 >= 0) && (fdtab[maxfd-1].state == FD_STCLOSE))
64 maxfd--;
Willy Tarreaubaaee002006-06-26 02:48:02 +020065}
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67
Willy Tarreau4f60f162007-04-08 16:39:58 +020068/* registers all known pollers */
69void register_pollers()
Willy Tarreaubaaee002006-06-26 02:48:02 +020070{
Willy Tarreau4f60f162007-04-08 16:39:58 +020071 if (select_register(&pollers[nbpollers]))
72 nbpollers++;
73#if defined(ENABLE_POLL)
74 poll_register(&pollers[nbpollers]);
75 nbpollers++;
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020077
Willy Tarreau4f60f162007-04-08 16:39:58 +020078#if defined(ENABLE_EPOLL)
79 epoll_register(&pollers[nbpollers]);
80 nbpollers++;
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#endif
Willy Tarreaue1a7a2f2007-04-09 16:11:49 +020082
83#if defined(ENABLE_KQUEUE)
84 kqueue_register(&pollers[nbpollers]);
85 nbpollers++;
86#endif
Willy Tarreau4f60f162007-04-08 16:39:58 +020087}
Willy Tarreaubaaee002006-06-26 02:48:02 +020088
Willy Tarreau4f60f162007-04-08 16:39:58 +020089/* disable the specified poller */
90void disable_poller(const char *poller_name)
91{
92 int p;
Willy Tarreaubaaee002006-06-26 02:48:02 +020093
Willy Tarreau4f60f162007-04-08 16:39:58 +020094 for (p = 0; p < nbpollers; p++)
95 if (strcmp(pollers[p].name, poller_name) == 0)
96 pollers[p].pref = 0;
97}
Willy Tarreaubaaee002006-06-26 02:48:02 +020098
99/*
Willy Tarreau4f60f162007-04-08 16:39:58 +0200100 * Initialize the pollers till the best one is found.
101 * If none works, returns 0, otherwise 1.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200102 */
Willy Tarreau4f60f162007-04-08 16:39:58 +0200103int init_pollers()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200104{
Willy Tarreau4f60f162007-04-08 16:39:58 +0200105 int p;
106 struct poller *bp;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200107
Willy Tarreaubaaee002006-06-26 02:48:02 +0200108
Willy Tarreau4f60f162007-04-08 16:39:58 +0200109 do {
110 bp = NULL;
111 for (p = 0; p < nbpollers; p++)
112 if (!bp || (pollers[p].pref > bp->pref))
113 bp = &pollers[p];
Willy Tarreaubaaee002006-06-26 02:48:02 +0200114
Willy Tarreau4f60f162007-04-08 16:39:58 +0200115 if (!bp || bp->pref == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116 break;
117
Willy Tarreau4f60f162007-04-08 16:39:58 +0200118 if (bp->init(bp)) {
119 memcpy(&cur_poller, bp, sizeof(*bp));
120 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200121 }
Willy Tarreau4f60f162007-04-08 16:39:58 +0200122 } while (!bp || bp->pref == 0);
123 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200124}
125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126/*
Willy Tarreau2ff76222007-04-09 19:29:56 +0200127 * Lists the known pollers on <out>.
128 * Should be performed only before initialization.
129 */
130int list_pollers(FILE *out)
131{
132 int p;
133 int last, next;
134 int usable;
135 struct poller *bp;
136
137 fprintf(out, "Available polling systems :\n");
138
139 usable = 0;
140 bp = NULL;
141 last = next = -1;
142 while (1) {
143 for (p = 0; p < nbpollers; p++) {
144 if (!bp || (pollers[p].pref > bp->pref))
145 bp = &pollers[p];
146 if ((next < 0 || pollers[p].pref > next)
147 && (last < 0 || pollers[p].pref < last))
148 next = pollers[p].pref;
149 }
150
151 if (next == -1)
152 break;
153
154 for (p = 0; p < nbpollers; p++) {
155 if (pollers[p].pref == next) {
156 fprintf(out, " %10s : ", pollers[p].name);
157 if (pollers[p].pref == 0)
158 fprintf(out, "disabled, ");
159 else
160 fprintf(out, "pref=%3d, ", pollers[p].pref);
161 if (pollers[p].test(&pollers[p])) {
162 fprintf(out, " test result OK");
163 if (next > 0)
164 usable++;
165 } else
166 fprintf(out, " test result FAILED");
167 fprintf(out, "\n");
168 }
169 }
170 last = next;
171 next = -1;
172 };
173 fprintf(out, "Total: %d (%d usable), will use %s.\n", nbpollers, usable, bp ? bp->name : "none");
174 return 0;
175}
176
177/*
178 * Some pollers may lose their connection after a fork(). It may be necessary
179 * to create initialize part of them again. Returns 0 in case of failure,
180 * otherwise 1. The fork() function may be NULL if unused. In case of error,
181 * the the current poller is destroyed and the caller is responsible for trying
182 * another one by calling init_pollers() again.
183 */
184int fork_poller()
185{
186 if (cur_poller.fork) {
187 if (cur_poller.fork(&cur_poller))
188 return 1;
189 cur_poller.term(&cur_poller);
190 return 0;
191 }
192 return 1;
193}
194
195/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 * Local variables:
197 * c-indent-level: 8
198 * c-basic-offset: 8
199 * End:
200 */