X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fhousekeeping.c;h=742291c5a653338e16f48c66f787cf4f59f25b43;hb=c1b1936458ccd0d517148615a6ed753f6a3e30c2;hp=fc878b499280850cebfb204abd76c50071de5777;hpb=8b523510f3c2e34a3654582be2db17f4138582dd;p=citadel.git diff --git a/citadel/housekeeping.c b/citadel/housekeeping.c index fc878b499..742291c5a 100644 --- a/citadel/housekeeping.c +++ b/citadel/housekeeping.c @@ -1,8 +1,8 @@ /* - * This file contains housekeeping tasks which periodically - * need to be executed. It keeps a nice little queue... - * * $Id$ + * + * This file contains miscellaneous housekeeping tasks. + * */ #include "sysdep.h" @@ -10,28 +10,41 @@ #include #include #include -#include + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + #include #include #include #include #include -#include #ifdef HAVE_SYS_SELECT_H #include #endif -#include "tools.h" +#include #include "citadel.h" #include "server.h" +#include "serv_extensions.h" #include "citserver.h" #include "config.h" #include "housekeeping.h" #include "sysdep_decls.h" #include "room_ops.h" +#include "database.h" +#include "msgbase.h" +#include "journaling.h" - -int housepipe[2]; /* This is the queue for housekeeping tasks */ - +#include "ctdl_module.h" +#include "threads.h" /* * Terminate idle sessions. This function pounds through the session table @@ -43,6 +56,8 @@ void terminate_idle_sessions(void) { struct CitContext *ccptr; time_t now; int session_to_kill; + int killed = 0; + int longrunners = 0; now = time(NULL); session_to_kill = 0; @@ -51,132 +66,131 @@ void terminate_idle_sessions(void) { if ( (ccptr!=CC) && (config.c_sleeping > 0) && (now - (ccptr->lastcmd) > config.c_sleeping) ) { - ccptr->kill_me = 1; + if (!ccptr->dont_term) { + ccptr->kill_me = 1; + ++killed; + } + else + longrunners ++; } } end_critical_section(S_SESSION_TABLE); + if (killed > 0) + CtdlLogPrintf(CTDL_INFO, "Terminated %d idle sessions\n", killed); + if (longrunners > 0) + CtdlLogPrintf(CTDL_INFO, "Didn't terminate %d protected idle sessions;\n", killed); } void check_sched_shutdown(void) { if ((ScheduledShutdown == 1) && (ContextList == NULL)) { - lprintf(3, "Scheduled shutdown initiating.\n"); - master_cleanup(); + CtdlLogPrintf(CTDL_NOTICE, "Scheduled shutdown initiating.\n"); + CtdlThreadStopAll(); } } /* - * This is the main loop for the housekeeping thread. It remains active - * during the entire run of the server. + * Check (and fix) floor reference counts. This doesn't need to be done + * very often, since the counts should remain correct during normal operation. */ -void housekeeping_loop(void) { - long flags; - struct timeval tv; - fd_set readfds; - int did_something; - char house_cmd[256]; /* Housekeep cmds are always 256 bytes long */ - char cmd[256]; - - if (pipe(housepipe) != 0) { - lprintf(1, "FATAL ERROR: can't create housekeeping pipe: %s\n", - strerror(errno)); - exit(0); - } +void check_ref_counts_backend(struct ctdlroom *qrbuf, void *data) { - flags = (long) fcntl(housepipe[1], F_GETFL); - flags |= O_NONBLOCK; - fcntl(housepipe[1], F_SETFL, flags); - - while(1) { - do { - did_something = 0; - tv.tv_sec = HOUSEKEEPING_WAKEUP; - tv.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(housepipe[0], &readfds); - select(housepipe[0] + 1, &readfds, NULL, NULL, &tv); - if (FD_ISSET(housepipe[0], &readfds)) { - did_something = 1; - } + int *new_refcounts; - if (did_something) { - read(housepipe[0], house_cmd, 256); - } - else { - memset(house_cmd, 0, 256); - strcpy(house_cmd, "MINUTE"); - } - - extract(cmd, house_cmd, 0); - - /* Do whatever this cmd requires */ - - /* Once-every-minute housekeeper */ - if (!strcmp(cmd, "MINUTE")) { - terminate_idle_sessions(); - } - - /* Scheduled shutdown housekeeper */ - else if (!strcmp(cmd, "SCHED_SHUTDOWN")) { - check_sched_shutdown(); - } + new_refcounts = (int *) data; - /* Unknown */ - else { - lprintf(7, "Unknown housekeeping command\n"); - } - - } while (did_something); - } + ++new_refcounts[(int)qrbuf->QRfloor]; } +void check_ref_counts(void) { + struct floor flbuf; + int a; + int new_refcounts[MAXFLOORS]; + CtdlLogPrintf(CTDL_DEBUG, "Checking floor reference counts\n"); + for (a=0; a 0) { + flbuf.f_flags = flbuf.f_flags | QR_INUSE; + } + else { + flbuf.f_flags = flbuf.f_flags & ~QR_INUSE; + } + lputfloor(&flbuf, a); + CtdlLogPrintf(CTDL_DEBUG, "Floor %d: %d rooms\n", a, new_refcounts[a]); + } +} -void enter_housekeeping_cmd(char *cmd) { - char cmdbuf[256]; +/* + * This is the housekeeping loop. Worker threads come through here after + * processing client requests but before jumping back into the pool. We + * only allow housekeeping to execute once per minute, and we only allow one + * instance to run at a time. + */ +void do_housekeeping(void) { + static int housekeeping_in_progress = 0; + static time_t last_timer = 0L; + int do_housekeeping_now = 0; + int do_perminute_housekeeping_now = 0; + time_t now; + const char *old_name; - lprintf(9, "enter_housekeeping_cmd(%s)\n", cmd); - safestrncpy(cmdbuf, cmd, 256); + /* + * We do it this way instead of wrapping the whole loop in an + * S_HOUSEKEEPING critical section because it eliminates the need to + * potentially have multiple concurrent mutexes in progress. + */ begin_critical_section(S_HOUSEKEEPING); - write(housepipe[1], cmdbuf, 256); + if (housekeeping_in_progress == 0) { + do_housekeeping_now = 1; + housekeeping_in_progress = 1; + now = time(NULL); + if ( (now - last_timer) > (time_t)60 ) { + do_perminute_housekeeping_now = 1; + last_timer = time(NULL); + } + } end_critical_section(S_HOUSEKEEPING); - lprintf(9, "leaving enter_housekeeping_cmd()\n"); -} - - -/* - * Check (and fix) floor reference counts. This doesn't need to be done - * very often, since the counts should remain correct during normal operation. - * NOTE: this function pair should ONLY be called during startup. It is NOT - * thread safe. - */ -void check_ref_counts_backend(struct quickroom *qrbuf, void *data) { - struct floor flbuf; - - getfloor(&flbuf, qrbuf->QRfloor); - ++flbuf.f_ref_count; - flbuf.f_flags = flbuf.f_flags | QR_INUSE; - putfloor(&flbuf, qrbuf->QRfloor); + if (do_housekeeping_now == 0) { + return; } -void check_ref_counts(void) { - struct floor flbuf; - int a; + /* + * Ok, at this point we've made the decision to run the housekeeping + * loop. Everything below this point is real work. + */ - for (a=0; a