📄 refresh.c
字号:
/* * $Id: refresh.c,v 1.47 1999/01/19 23:18:01 wessels Exp $ * * DEBUG: section 22 Refresh Calculation * AUTHOR: Harvest Derived * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * 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. * * 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, USA. * */#ifndef USE_POSIX_REGEX#define USE_POSIX_REGEX /* put before includes; always use POSIX */#endif#include "squid.h"typedef enum { rcHTTP, rcICP, rcCDigest, rcStore, rcCount} refreshCountsEnum;static struct RefreshCounts { const char *proto; int total; int revalidate_stale; int request_max_age_stale; int request_reload2ims_stale; int request_reload_stale; int negative_age_stale; int min_age_override_exp_fresh; int min_age_override_lmt_fresh; int response_expires_stale; int response_expires_fresh; int conf_max_age_stale; int last_modified_factor_fresh; int last_modified_factor_stale; int response_lmt_now_stale; int conf_min_age_fresh; int default_stale; /* maybe-counters -- intermediate decisions that may affect the result */ int request_reload_ignore_maybe; int response_lmt_future_maybe;} refreshCounts[rcCount];/* * Defaults: * MIN NONE * PCT 20% * MAX 3 days */#define REFRESH_DEFAULT_MIN (time_t)0#define REFRESH_DEFAULT_PCT 0.20#define REFRESH_DEFAULT_MAX (time_t)259200static const refresh_t *refreshLimits(const char *);static const refresh_t *refreshUncompiledPattern(const char *);static OBJH refreshStats;static const refresh_t *refreshLimits(const char *url){ const refresh_t *R; for (R = Config.Refresh; R; R = R->next) { if (!regexec(&(R->compiled_pattern), url, 0, 0, 0)) return R; } return NULL;}static const refresh_t *refreshUncompiledPattern(const char *pat){ const refresh_t *R; for (R = Config.Refresh; R; R = R->next) { if (0 == strcmp(R->pattern, pat)) return R; } return NULL;}/* return 1 if the entry must be revalidated within delta seconds * 0 otherwise * * note: request maybe null (e.g. for cache digests build) */static intrefreshCheck(const StoreEntry * entry, request_t * request, time_t delta, struct RefreshCounts *rc){ const refresh_t *R; const char *uri = NULL; time_t min = REFRESH_DEFAULT_MIN; double pct = REFRESH_DEFAULT_PCT; time_t max = REFRESH_DEFAULT_MAX;#if HTTP_VIOLATIONS int override_expire = 0; int override_lastmod = 0; int reload_into_ims = 0; int ignore_reload = 0;#endif const char *pattern = "<none>"; time_t age; double factor; time_t check_time = squid_curtime + delta; if (entry->mem_obj) uri = entry->mem_obj->url; else if (request) uri = urlCanonical(request); debug(22, 3) ("refreshCheck(%s): '%s'\n", rc->proto, uri ? uri : "<none>"); rc->total++; if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE)) { debug(22, 3) ("refreshCheck: YES: Required Authorization\n"); rc->revalidate_stale++; return 1; } if ((R = uri ? refreshLimits(uri) : refreshUncompiledPattern("."))) { min = R->min; pct = R->pct; max = R->max; pattern = R->pattern;#if HTTP_VIOLATIONS override_expire = R->flags.override_expire; override_lastmod = R->flags.override_lastmod; reload_into_ims = R->flags.reload_into_ims; ignore_reload = R->flags.ignore_reload;#endif }#if HTTP_VIOLATIONS if (!reload_into_ims) reload_into_ims = Config.onoff.reload_into_ims;#endif debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n", pattern, (int) min, (int) (100.0 * pct), (int) max); age = check_time - entry->timestamp; debug(22, 3) ("refreshCheck: age = %d\n", (int) age); debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time)); debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp)); /* request-specific checks */ if (request) {#if HTTP_VIOLATIONS if (request->flags.nocache_hack) { if (ignore_reload) { /* The clients no-cache header is ignored */ debug(22, 3) ("refreshCheck: MAYBE: ignore-reload\n"); rc->request_reload_ignore_maybe++; } else if (reload_into_ims) { /* The clients no-cache header is changed into a IMS query */ debug(22, 3) ("refreshCheck: YES: reload-into-ims\n"); rc->request_reload2ims_stale++; return 1; } else { /* The clients no-cache header is not overridden on this request */ debug(22, 3) ("refreshCheck: YES: client reload\n"); request->flags.nocache = 1; rc->request_reload_stale++; return 1; } }#endif if (age < 0) { debug(22, 3) ("refreshCheck: YES: age < 0\n"); rc->negative_age_stale++; return 1; } if (request->cache_control && request->cache_control->max_age > -1) { if (age > request->cache_control->max_age) { debug(22, 3) ("refreshCheck: YES: age > client-max-age\n"); rc->request_max_age_stale++; return 1; } } }#if HTTP_VIOLATIONS if (override_expire && age <= min) { debug(22, 3) ("refreshCheck: NO: age < min && override_expire\n"); rc->min_age_override_exp_fresh++; return 0; }#endif if (entry->expires > -1) { if (entry->expires <= check_time) { debug(22, 3) ("refreshCheck: YES: expires <= curtime\n"); rc->response_expires_stale++; return 1; } else { debug(22, 3) ("refreshCheck: NO: expires > curtime\n"); rc->response_expires_fresh++; return 0; } } if (age > max) { debug(22, 3) ("refreshCheck: YES: age > max\n"); rc->conf_max_age_stale++; return 1; }#if HTTP_VIOLATIONS if (override_lastmod && age <= min) { debug(22, 3) ("refreshCheck: NO: age < min && override_lastmod\n"); rc->min_age_override_lmt_fresh++; return 0; }#endif if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) { factor = (double) age / (double) (entry->timestamp - entry->lastmod); debug(22, 3) ("refreshCheck: factor = %f\n", factor); if (factor < pct) { debug(22, 3) ("refreshCheck: NO: factor < pct\n"); rc->last_modified_factor_fresh++; return 0; } else { debug(22, 3) ("refreshCheck: YES: factor >= pct\n"); rc->last_modified_factor_stale++; return 1; } } else if (entry->lastmod > -1 && entry->timestamp == entry->lastmod) { debug(22, 3) ("refreshCheck: YES: last-modified 'now'\n"); rc->response_lmt_now_stale++; return 1; } else if (entry->lastmod > -1 && entry->timestamp < entry->lastmod) { debug(22, 3) ("refreshCheck: MAYBE: last-modified in the future\n"); rc->response_lmt_future_maybe++; } if (age <= min) { debug(22, 3) ("refreshCheck: NO: age <= min\n"); rc->conf_min_age_fresh++; return 0; } debug(22, 3) ("refreshCheck: YES: default stale\n"); rc->default_stale++; return 1;}intrefreshIsCachable(const StoreEntry * entry){ /* * Don't look at the request to avoid no-cache and other nuisances. * the object should have a mem_obj so the URL will be found there. * 60 seconds delta, to avoid objects which expire almost * immediately, and which can't be refreshed. */ if (!refreshCheck(entry, NULL, 60, &refreshCounts[rcStore])) /* Does not need refresh. This is certainly cachable */ return 1; if (entry->lastmod < 0) /* Last modified is needed to do a refresh */ return 0; if (entry->mem_obj == NULL) /* no mem_obj? */ return 1; if (entry->mem_obj->reply) /* no reply? */ return 1; if (entry->mem_obj->reply->content_length == 0) /* No use refreshing (caching?) 0 byte objects */ return 0; /* This seems to be refreshable. Cache it */ return 1;}/* refreshCheck... functions below are protocol-specific wrappers around * refreshCheck() function above */intrefreshCheckHTTP(const StoreEntry * entry, request_t * request){ return refreshCheck(entry, request, 0, &refreshCounts[rcHTTP]);}intrefreshCheckICP(const StoreEntry * entry, request_t * request){ return refreshCheck(entry, request, 30, &refreshCounts[rcICP]);}intrefreshCheckDigest(const StoreEntry * entry, time_t delta){ return refreshCheck(entry, entry->mem_obj ? entry->mem_obj->request : NULL, delta, &refreshCounts[rcCDigest]);}time_tgetMaxAge(const char *url){ const refresh_t *R; debug(22, 3) ("getMaxAge: '%s'\n", url); if ((R = refreshLimits(url))) return R->max; else return REFRESH_DEFAULT_MAX;}static voidrefreshCountsStats(StoreEntry * sentry, struct RefreshCounts *rc){ int sum = 0; int tot = rc->total; storeAppendPrintf(sentry, "\n\n%s histogram:\n", rc->proto); storeAppendPrintf(sentry, "Category\tCount\t%%Total\n");#define refreshCountsStatsEntry(name) { \ if (rc->name || !strcmp(#name, "total")) \ storeAppendPrintf(sentry, "%s\t%6d\t%6.2f\n", \ #name, rc->name, xpercent(rc->name, tot)); \ sum += rc->name; \} refreshCountsStatsEntry(revalidate_stale); refreshCountsStatsEntry(request_reload2ims_stale); refreshCountsStatsEntry(request_reload_stale); refreshCountsStatsEntry(request_max_age_stale); refreshCountsStatsEntry(min_age_override_exp_fresh); refreshCountsStatsEntry(response_expires_stale); refreshCountsStatsEntry(response_expires_fresh); refreshCountsStatsEntry(conf_max_age_stale); refreshCountsStatsEntry(min_age_override_lmt_fresh); refreshCountsStatsEntry(last_modified_factor_fresh); refreshCountsStatsEntry(last_modified_factor_stale); refreshCountsStatsEntry(response_lmt_now_stale); refreshCountsStatsEntry(conf_min_age_fresh); refreshCountsStatsEntry(default_stale); tot = sum; /* paranoid: "total" line shows 100% if we forgot nothing */ refreshCountsStatsEntry(total); /* maybe counters */ refreshCountsStatsEntry(request_reload_ignore_maybe); refreshCountsStatsEntry(response_lmt_future_maybe);}static voidrefreshStats(StoreEntry * sentry){ int i; int total = 0; /* get total usage count */ for (i = 0; i < rcCount; ++i) total += refreshCounts[i].total; /* protocol usage histogram */ storeAppendPrintf(sentry, "\nRefreshCheck calls per protocol\n\n"); storeAppendPrintf(sentry, "Protocol\t#Calls\t%%Calls\n"); for (i = 0; i < rcCount; ++i) storeAppendPrintf(sentry, "%10s\t%6d\t%6.2f\n", refreshCounts[i].proto, refreshCounts[i].total, xpercent(refreshCounts[i].total, total)); /* per protocol histograms */ storeAppendPrintf(sentry, "\n\nRefreshCheck histograms for various protocols\n"); for (i = 0; i < rcCount; ++i) refreshCountsStats(sentry, &refreshCounts[i]);}voidrefreshInit(){ memset(refreshCounts, 0, sizeof(refreshCounts)); refreshCounts[rcHTTP].proto = "HTTP"; refreshCounts[rcICP].proto = "ICP"; refreshCounts[rcStore].proto = "On Store"; refreshCounts[rcCDigest].proto = "Cache Digests"; cachemgrRegister("refresh", "Refresh Algorithm Statistics", refreshStats, 0, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -