/* * File descriptors management functions. * * Copyright 2000-2008 Willy Tarreau * * 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. * */ #include #include #include #include #include #include #include #include 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 */ struct poller pollers[MAX_POLLERS]; struct poller cur_poller; int nbpollers = 0; /* Deletes an FD from the fdsets, and recomputes the maxfd limit. * The file descriptor is also closed. */ void fd_delete(int fd) { EV_FD_CLO(fd); port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port); fdtab[fd].port_range = NULL; close(fd); fdtab[fd].state = FD_STCLOSE; while ((maxfd-1 >= 0) && (fdtab[maxfd-1].state == FD_STCLOSE)) maxfd--; } /* disable the specified poller */ void disable_poller(const char *poller_name) { int p; for (p = 0; p < nbpollers; p++) if (strcmp(pollers[p].name, poller_name) == 0) pollers[p].pref = 0; } /* * Initialize the pollers till the best one is found. * If none works, returns 0, otherwise 1. */ int init_pollers() { int p; struct poller *bp; do { bp = NULL; for (p = 0; p < nbpollers; p++) if (!bp || (pollers[p].pref > bp->pref)) bp = &pollers[p]; if (!bp || bp->pref == 0) break; if (bp->init(bp)) { memcpy(&cur_poller, bp, sizeof(*bp)); return 1; } } while (!bp || bp->pref == 0); return 0; } /* * Deinitialize the pollers. */ void deinit_pollers() { struct poller *bp; int p; for (p = 0; p < nbpollers; p++) { bp = &pollers[p]; if (bp && bp->pref) bp->term(bp); } } /* * Lists the known pollers on . * Should be performed only before initialization. */ int list_pollers(FILE *out) { int p; int last, next; int usable; struct poller *bp; fprintf(out, "Available polling systems :\n"); usable = 0; bp = NULL; last = next = -1; while (1) { for (p = 0; p < nbpollers; p++) { if (!bp || (pollers[p].pref > bp->pref)) bp = &pollers[p]; if ((next < 0 || pollers[p].pref > next) && (last < 0 || pollers[p].pref < last)) next = pollers[p].pref; } if (next == -1) break; for (p = 0; p < nbpollers; p++) { if (pollers[p].pref == next) { fprintf(out, " %10s : ", pollers[p].name); if (pollers[p].pref == 0) fprintf(out, "disabled, "); else fprintf(out, "pref=%3d, ", pollers[p].pref); if (pollers[p].test(&pollers[p])) { fprintf(out, " test result OK"); if (next > 0) usable++; } else fprintf(out, " test result FAILED"); fprintf(out, "\n"); } } last = next; next = -1; }; fprintf(out, "Total: %d (%d usable), will use %s.\n", nbpollers, usable, bp ? bp->name : "none"); return 0; } /* * 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() { if (cur_poller.fork) { if (cur_poller.fork(&cur_poller)) return 1; cur_poller.term(&cur_poller); return 0; } return 1; } /* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * End: */