"Fossies" - the Fresh Open Source Software Archive

Member "citadel/housekeeping.c" (5 Jun 2021, 5157 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "housekeeping.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.01_vs_902.

    1 /*
    2  * This file contains miscellaneous housekeeping tasks.
    3  *
    4  * Copyright (c) 1987-2021 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License, version 3.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  */
   14 
   15 #include <stdio.h>
   16 #include <libcitadel.h>
   17 
   18 #include "ctdl_module.h"
   19 #include "serv_extensions.h"
   20 #include "room_ops.h"
   21 #include "internet_addressing.h"
   22 #include "config.h"
   23 #include "journaling.h"
   24 #include "citadel_ldap.h"
   25 
   26 void check_sched_shutdown(void) {
   27     if ((ScheduledShutdown == 1) && (ContextList == NULL)) {
   28         syslog(LOG_NOTICE, "housekeeping: scheduled shutdown initiating");
   29         server_shutting_down = 1;
   30     }
   31 }
   32 
   33 
   34 /*
   35  * Check (and fix) floor reference counts.  This doesn't need to be done
   36  * very often, since the counts should remain correct during normal operation.
   37  */
   38 void check_ref_counts_backend(struct ctdlroom *qrbuf, void *data) {
   39 
   40     int *new_refcounts;
   41 
   42     new_refcounts = (int *) data;
   43 
   44     ++new_refcounts[(int)qrbuf->QRfloor];
   45 }
   46 
   47 
   48 void check_ref_counts(void) {
   49     struct floor flbuf;
   50     int a;
   51 
   52     int new_refcounts[MAXFLOORS];
   53 
   54     syslog(LOG_DEBUG, "housekeeping: checking floor reference counts");
   55     for (a=0; a<MAXFLOORS; ++a) {
   56         new_refcounts[a] = 0;
   57     }
   58 
   59     cdb_begin_transaction();
   60     CtdlForEachRoom(check_ref_counts_backend, (void *)new_refcounts );
   61     cdb_end_transaction();
   62 
   63     for (a=0; a<MAXFLOORS; ++a) {
   64         lgetfloor(&flbuf, a);
   65         flbuf.f_ref_count = new_refcounts[a];
   66         if (new_refcounts[a] > 0) {
   67             flbuf.f_flags = flbuf.f_flags | QR_INUSE;
   68         }
   69         else {
   70             flbuf.f_flags = flbuf.f_flags & ~QR_INUSE;
   71         }
   72         lputfloor(&flbuf, a);
   73         syslog(LOG_DEBUG, "housekeeping: floor %d has %d rooms", a, new_refcounts[a]);
   74     }
   75 }
   76 
   77 
   78 /*
   79  * Provide hints as to whether we have any memory leaks
   80  */
   81 void keep_an_eye_on_memory_usage(void) {
   82     static void *original_brk = NULL;
   83     if (!original_brk) original_brk = sbrk(0);  // Remember the original program break so we can test for leaks
   84     syslog(LOG_DEBUG, "original_brk=%lx, current_brk=%lx, addl=%ld", (long)original_brk, (long)sbrk(0), (long)(sbrk(0)-original_brk));  // FIXME not so noisy please
   85 }
   86 
   87 
   88 /*
   89  * This is the housekeeping loop.  Worker threads come through here after
   90  * processing client requests but before jumping back into the pool.  We
   91  * only allow housekeeping to execute once per minute, and we only allow one
   92  * instance to run at a time.
   93  */
   94 static int housekeeping_in_progress = 0;
   95 static int housekeeping_disabled = 0;
   96 static time_t last_timer = 0L;
   97 
   98 void do_housekeeping(void) {
   99     int do_housekeeping_now = 0;
  100     int do_perminute_housekeeping_now = 0;
  101     time_t now;
  102 
  103     if (housekeeping_disabled) {
  104         return;
  105     }
  106 
  107     /*
  108      * We do it this way instead of wrapping the whole loop in an
  109      * S_HOUSEKEEPING critical section because it eliminates the need to
  110      * potentially have multiple concurrent mutexes in progress.
  111      */
  112     begin_critical_section(S_HOUSEKEEPING);
  113     if (housekeeping_in_progress == 0) {
  114         do_housekeeping_now = 1;
  115         housekeeping_in_progress = 1;
  116     }
  117     end_critical_section(S_HOUSEKEEPING);
  118 
  119     now = time(NULL);
  120     if ( (do_housekeeping_now == 0) && (!CtdlIsSingleUser()) ) {
  121         if ( (now - last_timer) > (time_t)300 ) {
  122             syslog(LOG_WARNING,
  123                 "housekeeping: WARNING: housekeeping loop has not run for %ld minutes.  Is something stuck?",
  124                 ((now - last_timer) / 60)
  125             );
  126         }
  127         return;
  128     }
  129 
  130     /*
  131      * Ok, at this point we've made the decision to run the housekeeping
  132      * loop.  Everything below this point is real work.
  133      */
  134 
  135     if ( (now - last_timer) > (time_t)60 ) {
  136         do_perminute_housekeeping_now = 1;
  137         last_timer = time(NULL);
  138     }
  139 
  140     /* First, do the "as often as needed" stuff... */
  141     JournalRunQueue();
  142     PerformSessionHooks(EVT_HOUSE);
  143 
  144     /* Then, do the "once per minute" stuff... */
  145     if (do_perminute_housekeeping_now) {
  146         cdb_check_handles();
  147         PerformSessionHooks(EVT_TIMER);     // Run all registered TIMER hooks
  148 
  149 #ifdef HAVE_LDAP                    // LDAP sync isn't in a module so we can put it here
  150         static time_t last_ldap_sync = 0L;
  151         if ( (now - last_ldap_sync) > (time_t)CtdlGetConfigLong("c_ldap_sync_freq") ) {
  152             CtdlSynchronizeUsersFromLDAP();
  153             last_ldap_sync = time(NULL);
  154         }
  155 #endif
  156 
  157     keep_an_eye_on_memory_usage();
  158     }
  159 
  160     /*
  161      * All done.
  162      */
  163     begin_critical_section(S_HOUSEKEEPING);
  164     housekeeping_in_progress = 0;
  165     end_critical_section(S_HOUSEKEEPING);
  166 }
  167 
  168 
  169 void CtdlDisableHouseKeeping(void) {
  170     syslog(LOG_INFO, "housekeeping: trying to disable");
  171     while ( (!housekeeping_disabled) && (!server_shutting_down) && (!housekeeping_in_progress) ) {
  172 
  173         if (housekeeping_in_progress) {
  174             sleep(1);
  175         }
  176         else {
  177             begin_critical_section(S_HOUSEKEEPING);
  178             if (!housekeeping_in_progress) {
  179                 housekeeping_disabled = 1;
  180             }
  181             end_critical_section(S_HOUSEKEEPING);
  182         }
  183     }
  184     syslog(LOG_INFO, "housekeeping: disabled now");
  185 }
  186 
  187 
  188 void CtdlEnableHouseKeeping(void) {
  189     begin_critical_section(S_HOUSEKEEPING);
  190     housekeeping_in_progress = 0;
  191     end_critical_section(S_HOUSEKEEPING);
  192 }