X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fhousekeeping.c;h=f4d930d64802631a320086be954b50f409255f58;hb=aa8b1021b70043469d32645ea2961794fbccaa32;hp=e8c060c7bf0d075fa0e075fc81f02a332ea111b4;hpb=701a7e49b52ce0aeeae0561f89aab038b04b179c;p=citadel.git diff --git a/citadel/housekeeping.c b/citadel/housekeeping.c index e8c060c7b..f4d930d64 100644 --- a/citadel/housekeeping.c +++ b/citadel/housekeeping.c @@ -1,107 +1,167 @@ /* - * This file contains housekeeping tasks which periodically - * need to be executed. + * This file contains miscellaneous housekeeping tasks. * - * $Id$ + * Copyright (c) 1987-2011 by the citadel.org team + * + * This program is open source 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "sysdep.h" #include #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 +#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" -/* - * Terminate idle sessions. This function pounds through the session table - * comparing the current time to each session's time-of-last-command. If an - * idle session is found it is terminated, then the search restarts at the - * beginning because the pointer to our place in the list becomes invalid. - */ -void terminate_idle_sessions(void) { - struct CitContext *ccptr; - time_t now; - -START_OVER: - now = time(NULL); - for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { - if ( (ccptr!=CC) - && (config.c_sleeping > 0) - && (now - (ccptr->lastcmd) > config.c_sleeping) ) { - lprintf(3, "Session %d timed out. Terminating it...\n", - ccptr->cs_pid); - kill_session(ccptr->cs_pid); - lprintf(9, "...done terminating it.\n"); - goto START_OVER; - } - } - } - - -/* - * Main housekeeping function. This gets run whenever a session terminates. - */ -void do_housekeeping(void) { - - lprintf(9, "--- begin housekeeping ---\n"); - begin_critical_section(S_HOUSEKEEPING); - /* - * Terminate idle sessions. - */ - lprintf(7, "Calling terminate_idle_sessions()\n"); - terminate_idle_sessions(); - lprintf(9, "Done with terminate_idle_sessions()\n"); +#include "ctdl_module.h" +#include "threads.h" - /* - * If the server is scheduled to shut down the next time all - * users are logged out, now's the time to do it. - */ +void check_sched_shutdown(void) { if ((ScheduledShutdown == 1) && (ContextList == NULL)) { - lprintf(3, "Scheduled shutdown initiating.\n"); - master_cleanup(); - } - end_critical_section(S_HOUSEKEEPING); - lprintf(9, "--- end housekeeping ---\n"); + syslog(LOG_NOTICE, "Scheduled shutdown initiating.\n"); + server_shutting_down = 1; } +} /* * 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) { - struct floor flbuf; +void check_ref_counts_backend(struct ctdlroom *qrbuf, void *data) { - lgetfloor(&flbuf, qrbuf->QRfloor); - ++flbuf.f_ref_count; - flbuf.f_flags = flbuf.f_flags | QR_INUSE; - lputfloor(&flbuf, qrbuf->QRfloor); - } + int *new_refcounts; + + new_refcounts = (int *) data; + + ++new_refcounts[(int)qrbuf->QRfloor]; +} void check_ref_counts(void) { struct floor flbuf; int a; + int new_refcounts[MAXFLOORS]; + + syslog(LOG_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); + syslog(LOG_DEBUG, "Floor %d: %d rooms\n", a, new_refcounts[a]); + } +} + +/* + * 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; + + /* + * 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); + 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); + + if (do_housekeeping_now == 0) { + return; + } - ForEachRoom(check_ref_counts_backend); - } + /* + * Ok, at this point we've made the decision to run the housekeeping + * loop. Everything below this point is real work. + */ + /* First, do the "as often as needed" stuff... */ + JournalRunQueue(); + PerformSessionHooks(EVT_HOUSE); + + /* Then, do the "once per minute" stuff... */ + if (do_perminute_housekeeping_now) { + cdb_check_handles(); /* suggested by Justin Case */ + PerformSessionHooks(EVT_TIMER); /* Run any timer hooks */ + } + + /* + * All done. + */ + housekeeping_in_progress = 0; +}