X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=history%2Fhis.c;fp=history%2Fhis.c;h=0000000000000000000000000000000000000000;hb=b7a32e2d73e3ab1add8208d3e157f7269a31ef4d;hp=aafd14fca8f14289ee1d9e134141cc6204ef36a1;hpb=ac902a8299ff4469b356836f431ead31c3377377;p=inn-innduct.git diff --git a/history/his.c b/history/his.c deleted file mode 100644 index aafd14f..0000000 --- a/history/his.c +++ /dev/null @@ -1,473 +0,0 @@ -/* $Id: his.c 6351 2003-05-19 02:00:06Z rra $ -** -** API to history routines -** -** Copyright (c) 2001, Thus plc -** -** Redistribution and use of the source code in source and binary -** forms, with or without modification, are permitted provided that -** the following 3 conditions are met: -** -** 1. Redistributions of the source code must retain the above -** copyright notice, this list of conditions and the disclaimer -** set out below. -** -** 2. Redistributions of the source code in binary form must -** reproduce the above copyright notice, this list of conditions -** and the disclaimer set out below in the documentation and/or -** other materials provided with the distribution. -** -** 3. Neither the name of the Thus plc nor the names of its -** contributors may be used to endorse or promote products -** derived from this software without specific prior written -** permission from Thus plc. -** -** Disclaimer: -** -** "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DIRECTORS -** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/time.h" -#include -#include - -#include "inn/history.h" -#include "inn/messages.h" -#include "inn/timer.h" -#include "libinn.h" -#include "storage.h" - -#include "hisinterface.h" -#include "hismethods.h" - -struct hiscache { - HASH Hash; /* Hash value of the message-id using Hash() */ - bool Found; /* Whether this entry is in the dbz file yet */ -}; - -struct history { - struct hismethod *methods; - void *sub; - struct hiscache *cache; - size_t cachesize; - const char *error; - struct histstats stats; -}; - -enum HISRESULT {HIScachehit, HIScachemiss, HIScachedne}; - -static const struct histstats nullhist = {0}; - -/* -** Put an entry into the history cache -*/ -static void -his_cacheadd(struct history *h, HASH MessageID, bool Found) -{ - unsigned int i, loc; - - his_logger("HIScacheadd begin", S_HIScacheadd); - if (h->cache != NULL) { - memcpy(&loc, ((char *)&MessageID) + (sizeof(HASH) - sizeof(loc)), - sizeof(loc)); - i = loc % h->cachesize; - memcpy((char *)&h->cache[i].Hash, (char *)&MessageID, sizeof(HASH)); - h->cache[i].Found = Found; - } - his_logger("HIScacheadd end", S_HIScacheadd); -} - -/* -** Lookup an entry in the history cache -*/ -static enum HISRESULT -his_cachelookup(struct history *h, HASH MessageID) -{ - unsigned int i, loc; - - if (h->cache == NULL) - return HIScachedne; - his_logger("HIScachelookup begin", S_HIScachelookup); - memcpy(&loc, ((char *)&MessageID) + (sizeof(HASH) - sizeof(loc)), sizeof(loc)); - i = loc % h->cachesize; - if (memcmp((char *)&h->cache[i].Hash, (char *)&MessageID, sizeof(HASH)) == 0) { - his_logger("HIScachelookup end", S_HIScachelookup); - if (h->cache[i].Found) { - return HIScachehit; - } else { - return HIScachemiss; - } - } else { - his_logger("HIScachelookup end", S_HIScachelookup); - return HIScachedne; - } -} - -/* -** set error status to that indicated by s; doesn't copy the string, -** assumes the caller did that for us -*/ -void -his_seterror(struct history *h, const char *s) -{ - if (h != NULL) { - if (h->error) - free((void *)h->error); - h->error = s; - } - if (s != NULL) - warn("%s", s); -} - -struct history * -HISopen(const char *path, const char *method, int flags) -{ - struct history *h; - int i; - - for (i = 0; i < NUM_HIS_METHODS; ++i) { - if (strcmp(method, his_methods[i].name) == 0) - break; - } - if (i == NUM_HIS_METHODS) { - warn("`%s' isn't a valid history method", method); - return NULL; - } - - /* allocate up our structure and start subordinate history - * manager */ - h = xmalloc(sizeof *h); - h->methods = &his_methods[i]; - h->cache = NULL; - h->error = NULL; - h->cachesize = 0; - h->stats = nullhist; - h->sub = (*h->methods->open)(path, flags, h); - if (h->sub == NULL) { - free(h); - h = NULL; - } - return h; -} - -static bool -his_checknull(struct history *h) -{ - if (h != NULL) - return false; - errno = EBADF; - return true; - -} - -bool -HISclose(struct history *h) -{ - bool r; - - if (his_checknull(h)) - return false; - r = (*h->methods->close)(h->sub); - if (h->cache) { - free(h->cache); - h->cache = NULL; - } - if (h->error) { - free((void *)h->error); - h->error = NULL; - } - free(h); - return r; -} - -bool -HISsync(struct history *h) -{ - bool r = false; - - if (his_checknull(h)) - return false; - TMRstart(TMR_HISSYNC); - r = (*h->methods->sync)(h->sub); - TMRstop(TMR_HISSYNC); - return r; -} - -bool -HISlookup(struct history *h, const char *key, time_t *arrived, - time_t *posted, time_t *expires, TOKEN *token) -{ - bool r; - - if (his_checknull(h)) - return false; - TMRstart(TMR_HISGREP); - r = (*h->methods->lookup)(h->sub, key, arrived, posted, expires, token); - TMRstop(TMR_HISGREP); - return r; -} - -bool -HIScheck(struct history *h, const char *key) -{ - bool r = false; - HASH hash; - - if (his_checknull(h)) - return false; - TMRstart(TMR_HISHAVE); - hash = HashMessageID(key); - switch (his_cachelookup(h, hash)) { - case HIScachehit: - h->stats.hitpos++; - r = true; - break; - - case HIScachemiss: - h->stats.hitneg++; - r = false; - break; - - case HIScachedne: - r = (*h->methods->check)(h->sub, key); - his_cacheadd(h, hash, r); - if (r) - h->stats.misses++; - else - h->stats.dne++; - break; - } - TMRstop(TMR_HISHAVE); - return r; -} - -bool -HISwrite(struct history *h, const char *key, time_t arrived, - time_t posted, time_t expires, const TOKEN *token) -{ - bool r; - - if (his_checknull(h)) - return false; - TMRstart(TMR_HISWRITE); - r = (*h->methods->write)(h->sub, key, arrived, posted, expires, token); - if (r == true) { - HASH hash; - - /* if we successfully wrote it, add it to the cache */ - hash = HashMessageID(key); - his_cacheadd(h, hash, true); - } - TMRstop(TMR_HISWRITE); - - return r; -} - -bool -HISremember(struct history *h, const char *key, time_t arrived) -{ - bool r; - - if (his_checknull(h)) - return false; - TMRstart(TMR_HISWRITE); - r = (*h->methods->remember)(h->sub, key, arrived); - if (r == true) { - HASH hash; - - /* if we successfully wrote it, add it to the cache */ - hash = HashMessageID(key); - his_cacheadd(h, hash, true); - } - TMRstop(TMR_HISWRITE); - - return r; -} - -bool -HISreplace(struct history *h, const char *key, time_t arrived, - time_t posted, time_t expires, const TOKEN *token) -{ - bool r; - - if (his_checknull(h)) - return false; - r = (*h->methods->replace)(h->sub, key, arrived, posted, expires, token); - if (r == true) { - HASH hash; - - /* if we successfully wrote it, add it to the cache */ - hash = HashMessageID(key); - his_cacheadd(h, hash, true); - } - return r; -} - -bool -HISwalk(struct history *h, const char *reason, void *cookie, - bool (*callback)(void *, time_t, time_t, time_t, const TOKEN *)) -{ - bool r; - - if (his_checknull(h)) - return false; - r = (*h->methods->walk)(h->sub, reason, cookie, callback); - return r; -} - -bool -HISexpire(struct history *h, const char *path, const char *reason, - bool writing, void *cookie, time_t threshold, - bool (*exists)(void *, time_t, time_t, time_t, TOKEN *)) -{ - bool r; - - if (his_checknull(h)) - return false; - r = (*h->methods->expire)(h->sub, path, reason, writing, - cookie, threshold, exists); - return r; -} - -void -HISsetcache(struct history *h, size_t size) -{ - if (h == NULL) - return; - if (h->cache) { - free(h->cache); - h->cache = NULL; - } - h->cachesize = size / sizeof(struct hiscache); - if (h->cachesize != 0) - h->cache = xcalloc(h->cachesize, sizeof(struct hiscache)); - h->stats = nullhist; -} - - -/* -** return current history cache stats and zero the counters -*/ -struct histstats -HISstats(struct history *h) -{ - struct histstats r; - - if (h == NULL) - return nullhist; - r = h->stats; - h->stats = nullhist; - return r; -} - - -/* -** return current error status to caller -*/ -const char * -HISerror(struct history *h) -{ - if (h == NULL) - return NULL; - return h->error; -} - - -/* -** control interface to underlying method -*/ -bool -HISctl(struct history *h, int selector, void *val) -{ - bool r; - - if (his_checknull(h)) - return false; - r = (*h->methods->ctl)(h->sub, selector, val); - return r; -} - - -/* -** This code doesn't fit well with the generic history API, it really -** needs migrating to use the new nested timers -*/ - -FILE *HISfdlog = NULL; /* filehandle for history logging purpose */ - -static struct timeval HISstat_start[S_HIS_MAX]; -static struct timeval HISstat_total[S_HIS_MAX]; -static unsigned long HISstat_count[S_HIS_MAX]; - -void HISlogclose(void) { - if (HISfdlog != NULL) - Fclose(HISfdlog); - HISfdlog = NULL; -} - -void HISlogto(const char *s) { - int i; - - HISlogclose(); - if ((HISfdlog = Fopen(s, "a", INND_HISLOG)) == NULL) - syslog(L_FATAL, "cant open %s %m", s); - /* initialize our counters */ - for (i = 0; i < S_HIS_MAX; i++) { - HISstat_start[i].tv_sec = 0; - HISstat_start[i].tv_usec = 0; - HISstat_total[i].tv_sec = 0; - HISstat_total[i].tv_usec = 0; - HISstat_count[i] = 0; - } -} - -void -his_logger(char *s, int code) -{ - struct timeval tv; - struct tm *tm; - - if (HISfdlog == NULL) /* do nothing unless HISlogto() has been called */ - return; - - gettimeofday(&tv, NULL); - tm = localtime((const time_t *)&(tv.tv_sec)); - if (HISstat_start[code].tv_sec != 0) { - fprintf(HISfdlog, "%d/%d/%d %02d:%02d:%02d.%06d: [%d] %s (%.6f)\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec, (int)tv.tv_usec, code, s, (float) tv.tv_sec + - (float) tv.tv_usec / 1000000 - (float) HISstat_start[code].tv_sec - - (float) HISstat_start[code].tv_usec / 1000000); - if (tv.tv_usec < HISstat_start[code].tv_usec) { - HISstat_total[code].tv_sec++; - HISstat_total[code].tv_usec += - tv.tv_usec - HISstat_start[code].tv_usec + 1000000; - } - else - HISstat_total[code].tv_usec += - tv.tv_usec - HISstat_start[code].tv_usec; - HISstat_total[code].tv_sec += tv.tv_sec - HISstat_start[code].tv_sec; - HISstat_count[code]++; - HISstat_start[code].tv_sec = 0; - HISstat_start[code].tv_usec = 0; - } - else { - fprintf(HISfdlog, "%d/%d/%d %02d:%02d:%02d.%06d: [%d] %s\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec, (int)tv.tv_usec, code, s); - HISstat_start[code].tv_sec = tv.tv_sec; - HISstat_start[code].tv_usec = tv.tv_usec; - } -}