/*
- * $Id: client_side.cc,v 1.264 1998/04/08 21:38:36 wessels Exp $
+ * $Id: client_side.cc,v 1.265 1998/04/08 22:51:13 rousskov Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
assert(H->alg == PEER_SA_NONE);
}
if (/* we used ICP or CD for peer selecton */
- H->alg != PEER_SA_NONE &&
- /* a CD lookup found peers with digests */
- H->cd_lookup != LOOKUP_NONE &&
+ http->request->hier.alg != PEER_SA_NONE &&
+ /* a successful CD lookup was made */
+ http->request->hier.cd_lookup != LOOKUP_NONE &&
+ /* it was not a CD miss (we go direct on CD MISSes) */
+ !(http->request->hier.alg == PEER_SA_DIGEST && http->request->hier.cd_lookup == LOOKUP_MISS) &&
/* paranoid: we have a reply pointer */
(reply = storeEntryReply(http->entry))) {
const char *x_cache_fld = httpHeaderGetLastStr(&reply->header, HDR_X_CACHE);
const int real_hit = x_cache_fld && !strncmp(x_cache_fld, "HIT", 3);
- const int guess_hit = H->cd_lookup == LOOKUP_HIT;
- peer *peer = peerFindByName(H->host);
+ const int guess_hit = LOOKUP_HIT == http->request->hier.cd_lookup;
+ peer *peer = peerFindByName(http->request->hier.cd_host);
+ debug(33,2) ("clientUpdateCounters: peer %s real/guess: %d/%d for %s!\n",
+ http->request->hier.cd_host, real_hit, guess_hit, http->request->host);
cacheDigestGuessStatsUpdate(&Counter.cd.guess, real_hit, guess_hit);
if (peer)
cacheDigestGuessStatsUpdate(&peer->digest.stats.guess,
real_hit, guess_hit);
- else
- debug(33,1) ("clientUpdateCounters: lost peer: %s!\n", storeUrl(http->entry));
+ else {
+ debug(33,2) ("clientUpdateCounters: lost peer %s for %s!\n",
+ http->request->hier.cd_host, http->request->host);
+ fatal_dump("lost peer");
+ }
}
#endif
}
ROUNDROBIN_PARENT,
#if SQUID_PEER_DIGEST
CACHE_DIGEST_HIT,
+ CACHE_DIGEST_MISS_DIRECT,
#endif
HIER_MAX
} hier_code;
/*
- * $Id: neighbors.cc,v 1.194 1998/04/07 23:44:17 rousskov Exp $
+ * $Id: neighbors.cc,v 1.195 1998/04/08 22:51:14 rousskov Exp $
*
* DEBUG: section 15 Neighbor Routines
* AUTHOR: Harvest Derived
return peers_pinged;
}
+/* lookup the digest of a given peer */
+lookup_t
+peerDigestLookup(peer *p, request_t * request, StoreEntry * entry)
+{
+#if SQUID_PEER_DIGEST
+ const cache_key *key = storeKeyPublic(storeUrl(entry), request->method);
+ assert(p);
+ debug(15, 5) ("neighborsDigestPeerLookup: peer %s\n", p->host);
+ /* does the peeer have a valid digest? */
+ if (EBIT_TEST(p->digest.flags, PD_DISABLED)) {
+ return LOOKUP_NONE;
+ } else
+ if (!peerAllowedToUse(p, request)) {
+ return LOOKUP_NONE;
+ } else
+ if (EBIT_TEST(p->digest.flags, PD_USABLE)) {
+ /* fall through; put here to have common case on top */;
+ } else
+ if (!EBIT_TEST(p->digest.flags, PD_INITED)) {
+ peerDigestInit(p);
+ return LOOKUP_NONE;
+ } else {
+ assert(EBIT_TEST(p->digest.flags, PD_REQUESTED));
+ return LOOKUP_NONE;
+ }
+ debug(15, 5) ("neighborsDigestPeerLookup: OK to lookup peer %s\n", p->host);
+ assert(p->digest.cd);
+ /* does digest predict a hit? */
+ if (!cacheDigestTest(p->digest.cd, key))
+ return LOOKUP_MISS;
+ debug(15, 5) ("neighborsDigestPeerLookup: peer %s says HIT!\n", p->host);
+ return LOOKUP_HIT;
+#endif
+ return LOOKUP_NONE;
+}
+
+/* select best peer based on cache digests */
peer *
neighborsDigestSelect(request_t * request, StoreEntry * entry)
{
key = storeKeyPublic(storeUrl(entry), request->method);
for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
+ lookup_t lookup;
if (!p)
p = Config.peers;
if (i == 1)
first_ping = p;
- debug(15, 5) ("neighborsDigestSelect: considering peer %s\n", p->host);
- /* does the peeer have a valid digest? */
- if (EBIT_TEST(p->digest.flags, PD_DISABLED)) {
- continue;
- } else
- if (EBIT_TEST(p->digest.flags, PD_USABLE)) {
- ;
- } else
- if (!EBIT_TEST(p->digest.flags, PD_INITED)) {
- peerDigestInit(p);
+ lookup = peerDigestLookup(p, request, entry);
+ if (lookup == LOOKUP_NONE)
continue;
- } else {
- assert(EBIT_TEST(p->digest.flags, PD_REQUESTED));
- continue;
- }
choice_count++;
- debug(15, 5) ("neighborsDigestSelect: peer %s is a candidate\n", p->host);
- assert(p->digest.cd);
- /* does digest predict a hit? */
- if (!cacheDigestTest(p->digest.cd, key))
+ if (lookup == LOOKUP_MISS)
continue;
- p_rtt = netdbHostPeerRtt(request->host, p);
- debug(15, 5) ("neighborsDigestSelect: peer %s says hit with rtt %d\n",
+ p_rtt = netdbHostRtt(p->host);
+ debug(15, 5) ("neighborsDigestSelect: peer %s rtt: %d\n",
p->host, p_rtt);
/* is this peer better than others in terms of rtt ? */
if (!best_p || (p_rtt && p_rtt < best_rtt)) {
p->host, best_rtt);
}
}
- debug(15, 5) ("neighborsDigestSelect: selected peer %s, rtt: %d\n",
- best_p ? best_p->host : "<none>", best_rtt);
+ debug(15, 4) ("neighborsDigestSelect: choices: %d (%d)\n",
+ choice_count, ichoice_count);
+ peerNoteDigestLookup(request, best_p,
+ best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
request->hier.n_choices = choice_count;
request->hier.n_ichoices = ichoice_count;
#endif
return best_p;
}
+void
+peerNoteDigestLookup(request_t * request, peer *p, lookup_t lookup)
+{
+#if SQUID_PEER_DIGEST
+ if (p)
+ strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host));
+ else
+ *request->hier.cd_host = '\0';
+ request->hier.cd_lookup = lookup;
+ debug(15, 4) ("peerNoteDigestLookup: peer %s, lookup: %s\n",
+ p ? p->host : "<none>", lookup_t_str[lookup]);
+#endif
+}
+
static void
neighborAlive(peer * p, const MemObject * mem, const icp_common_t * header)
{
/*
- * $Id: peer_select.cc,v 1.46 1998/04/08 19:28:48 wessels Exp $
+ * $Id: peer_select.cc,v 1.47 1998/04/08 22:51:15 rousskov Exp $
*
* DEBUG: section 44 Peer Selection Algorithm
* AUTHOR: Duane Wessels
"ROUNDROBIN_PARENT",
#if SQUID_PEER_DIGEST
"CACHE_DIGEST_HIT",
+ "CACHE_DIGEST_MISS",
#endif
"INVALID CODE"
};
} else if (peerSelectIcpPing(request, direct, entry)) {
assert(entry->ping_status == PING_NONE);
#if SQUID_PEER_DIGEST
- /* always check digests if any */
- /* @?@ optimize: track if there are any digested peers at all (global counter) */
- if (1) {
- p = neighborsDigestSelect(request, entry);
- if (p) {
- request->hier.cd_lookup = LOOKUP_HIT;
- } else
- if (request->hier.n_choices) {
- request->hier.cd_lookup = LOOKUP_MISS;
- } else {
- request->hier.cd_lookup = LOOKUP_NONE;
- }
- debug(44, 3) ("peerSelect: %s digest lookup: %s choices: %d (%d)\n",
- p ? p->host : "",
- lookup_t_str[request->hier.cd_lookup],
- request->hier.n_choices, request->hier.n_ichoices);
- }
- /* @?@ TEST: randomly choose a peer selection algorithm */
- if (request->hier.cd_lookup != LOOKUP_NONE && (squid_random() & 1)) {
+ /* which algorithm to use? */
+ if (squid_random() & 1) {
debug(44, 3) ("peerSelect: Using Cache Digest\n");
request->hier.alg = PEER_SA_DIGEST;
- if (request->hier.cd_lookup == LOOKUP_HIT) {
+ if (1 /* global_digested_peer_count */)
+ p = neighborsDigestSelect(request, entry);
+ code = DIRECT; /* default @?@: CACHE_DIGEST_NONE */
+ switch (request->hier.cd_lookup) {
+ case LOOKUP_HIT:
assert(p);
code = CACHE_DIGEST_HIT;
debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
hierarchyNote(&request->hier, code, &psstate->icp, p->host);
+ peerSelectCallback(psstate, p); /* @?@: p used to be NULL */
+ return;
+ case LOOKUP_MISS:
+ code = CACHE_DIGEST_MISS_DIRECT;
+ /* fall through */
+ case LOOKUP_NONE:
+ /* go direct */
+ debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
+ hierarchyNote(&request->hier, code, &psstate->icp, request->host);
peerSelectCallback(psstate, NULL);
return;
+ default:
+ assert(0); /* invalid lookup code */
}
+ assert(0); /* never reached */
} else {
request->hier.alg = PEER_SA_ICP;
#endif
debug(44, 3) ("peerHandleIcpReply: %s %s\n",
icp_opcode_str[op],
storeUrl(psstate->entry));
+#if SQUID_PEER_DIGEST
+ /* do cd lookup to count false misses */
+ peerNoteDigestLookup(request, p,
+ peerDigestLookup(p, request, psstate->entry));
+#endif
psstate->icp.n_recv++;
if (op == ICP_MISS || op == ICP_DECHO) {
if (type == PEER_PARENT)
extern peer *peerFindByName(const char *);
extern peer *getDefaultParent(request_t * request);
extern peer *getRoundRobinParent(request_t * request);
+extern lookup_t peerDigestLookup(peer *p, request_t * request, StoreEntry * entry);
extern peer *neighborsDigestSelect(request_t * request, StoreEntry * entry);
+extern void peerNoteDigestLookup(request_t * request, peer *p, lookup_t lookup);
extern int neighborUp(const peer * e);
extern void peerDestroy(peer * e);
extern char *neighborTypeStr(const peer * e);
extern void peerSelectInit(void);
/* peer_digest.c */
-extern void peerDigestValidate(peer * p);
-extern void peerDigestRequest(peer * p);
+void peerDigestInit(peer *p);
extern void protoDispatch(int, StoreEntry *, request_t *);
/*
- * $Id: stat.cc,v 1.226 1998/04/08 19:28:50 wessels Exp $
+ * $Id: stat.cc,v 1.227 1998/04/08 22:51:16 rousskov Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
static OBJH statFiledescriptors;
static OBJH statCounters;
static OBJH statPeerSelect;
+static OBJH statDigestBlob;
static OBJH statAvg5min;
static OBJH statAvg60min;
static OBJH statUtilization;
cachemgrRegister("peer_select",
"Peer Selection Algorithms",
statPeerSelect, 0);
+ cachemgrRegister("digest_stats",
+ "Cache Digest and ICP blob",
+ statDigestBlob, 0);
cachemgrRegister("5min",
"5 Minute Average of Counters",
statAvg5min, 0);
#endif
}
+static void
+statDigestBlob(StoreEntry * sentry)
+{
+#if SQUID_PEER_DIGEST
+ StatCounters *f = &CountHist[0];
+ StatCounters *l = &CountHist[5];
+ double x;
+
+ storeAppendPrintf(sentry, "\nicp.query_svc_time histogram:\n");
+ statHistDump(&f->icp.query_svc_time, sentry, NULL);
+ storeAppendPrintf(sentry, "\nicp.reply_svc_time histogram:\n");
+ statHistDump(&f->icp.reply_svc_time, sentry, NULL);
+ storeAppendPrintf(sentry, "\nicp.client_svc_time histogram:\n");
+ statHistDump(&f->icp.client_svc_time, sentry, NULL);
+ storeAppendPrintf(sentry, "\ncd.client_svc_time histogram:\n");
+ statHistDump(&f->cd.client_svc_time, sentry, NULL);
+
+ storeAppendPrintf(sentry, "\nMedian service times:\n");
+ x = statHistDeltaMedian(&l->cd.client_svc_time,
+ &f->cd.client_svc_time);
+ storeAppendPrintf(sentry, "cd.client_median_svc_time = %f seconds\n",
+ x / 1000.0);
+ x = statHistDeltaMedian(&l->icp.client_svc_time,
+ &f->icp.client_svc_time);
+ storeAppendPrintf(sentry, "icp.client_median_svc_time = %f seconds\n",
+ x / 1000.0);
+
+ storeAppendPrintf(sentry, "\nTraffic:\n");
+ storeAppendPrintf(sentry, "icp.times_used = %d\n",
+ f->icp.times_used);
+ storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
+ f->icp.pkts_sent);
+ storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
+ f->icp.pkts_recv);
+ storeAppendPrintf(sentry, "icp.replies_queued = %d\n",
+ f->icp.replies_queued);
+ storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n",
+ (int) f->icp.kbytes_sent.kb);
+ storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n",
+ (int) f->icp.kbytes_recv.kb);
+ storeAppendPrintf(sentry, "cd.times_used = %d\n",
+ f->cd.times_used);
+ storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n",
+ (int) f->cd.kbytes_sent.kb);
+ storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n",
+ (int) f->cd.kbytes_recv.kb);
+ storeAppendPrintf(sentry, "cd.peer_memory = %d\n",
+ (int) f->cd.memory.kb);
+ storeAppendPrintf(sentry, "cd.store_memory = %d\n",
+ (int) (store_digest ? store_digest->mask_size/1024 : 0));
+#endif
+ statPeerSelect(sentry);
+ storeDigestReport(sentry);
+}
+
static void
statCounters(StoreEntry * e)
{
/*
- * $Id: store_digest.cc,v 1.4 1998/04/07 23:26:46 rousskov Exp $
+ * $Id: store_digest.cc,v 1.5 1998/04/08 22:51:17 rousskov Exp $
*
* DEBUG: section 71 Store Digest Manager
* AUTHOR: Alex Rousskov
*/
/* how often we want to rebuild the digest, seconds */
-static const time_t StoreDigestRebuildPeriod = 60 * 60;
+static const time_t StoreDigestRebuildPeriod = 6 * 60;
/* how often we want to rewrite the digest, seconds */
-static const time_t StoreDigestRewritePeriod = 60 * 60;
+static const time_t StoreDigestRewritePeriod = 6 * 60;
/* how many bytes to swap out at a time */
static const int StoreDigestSwapOutChunkSize = SM_PAGE_SIZE;
/* portion (0,1] of a hash table to be rescanned at a time */
char host[SQUIDHOSTNAMELEN];
icp_ping_data icp;
#if SQUID_PEER_DIGEST
+ char cd_host[SQUIDHOSTNAMELEN]; /* the host of selected by cd peer */
peer_select_alg_t alg; /* peer selection algorithm */
lookup_t cd_lookup; /* cd prediction: none, miss, hit */
int n_choices; /* #peers we selected from (cd only) */
#if SQUID_PEER_DIGEST
struct {
int times_used;
- kb_t kbtes_sent;
- kb_t kbtes_recv;
+ kb_t kbytes_sent;
+ kb_t kbytes_recv;
kb_t memory;
cd_guess_stats guess;
StatHist client_svc_time;