/* lookup the digest of a given peer */ lookup_t peerDigestLookup(peer * p, request_t * request) { #if USE_CACHE_DIGESTS const cache_key *key = request ? storeKeyPublicByRequest(request) : NULL; assert(p); assert(request); debug(15, 5) ("peerDigestLookup: peer %s\n", p->name); /* does the peeer have a valid digest? */ if (!p->digest) { debug(15, 5) ("peerDigestLookup: gone!\n"); return LOOKUP_NONE; } else if (!peerHTTPOkay(p, request)) { debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n"); return LOOKUP_NONE; } else if (!p->digest->flags.needed) { debug(15, 5) ("peerDigestLookup: note need\n"); peerDigestNeeded(p->digest); return LOOKUP_NONE; } else if (!p->digest->flags.usable) { debug(15, 5) ("peerDigestLookup: !ready && %srequested\n", p->digest->flags.requested ? "" : "!"); return LOOKUP_NONE; } debug(15, 5) ("peerDigestLookup: OK to lookup peer %s\n", p->name); assert(p->digest->cd); /* does digest predict a hit? */ if (!cacheDigestTest(p->digest->cd, key)) return LOOKUP_MISS; debug(15, 5) ("peerDigestLookup: peer %s says HIT!\n", p->name); return LOOKUP_HIT; #endif return LOOKUP_NONE; }
/* select best peer based on cache digests */ peer * neighborsDigestSelect(request_t * request) { peer *best_p = NULL; #if USE_CACHE_DIGESTS const cache_key *key; int best_rtt = 0; int choice_count = 0; int ichoice_count = 0; peer *p; int p_rtt; int i; if (!request->flags.hierarchical) return NULL; key = storeKeyPublicByRequest(request); 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; lookup = peerDigestLookup(p, request); if (lookup == LOOKUP_NONE) continue; choice_count++; if (lookup == LOOKUP_MISS) continue; p_rtt = netdbHostRtt(p->host); debug(15, 5) ("neighborsDigestSelect: peer %s rtt: %d\n", p->name, p_rtt); /* is this peer better than others in terms of rtt ? */ if (!best_p || (p_rtt && p_rtt < best_rtt)) { best_p = p; best_rtt = p_rtt; if (p_rtt) /* informative choice (aka educated guess) */ ichoice_count++; debug(15, 4) ("neighborsDigestSelect: peer %s leads with rtt %d\n", p->name, 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; }
/* ask store for a digest */ static void peerDigestRequest(PeerDigest * pd) { peer *p = pd->peer; StoreEntry *e, *old_e; char *url; const cache_key *key; request_t *req; DigestFetchState *fetch = NULL; pd->req_result = NULL; pd->flags.requested = 1; /* compute future request components */ if (p->digest_url) url = xstrdup(p->digest_url); else url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestFileName); req = urlParse(METHOD_GET, url); assert(req); key = storeKeyPublicByRequest(req); debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key)); /* add custom headers */ assert(!req->header.len); httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr); httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html"); if (p->login) xstrncpy(req->login, p->login, MAX_LOGIN_SZ); /* create fetch state structure */ CBDATA_INIT_TYPE(DigestFetchState); fetch = cbdataAlloc(DigestFetchState); fetch->request = requestLink(req); fetch->pd = pd; fetch->offset = 0; /* update timestamps */ fetch->start_time = squid_curtime; pd->times.requested = squid_curtime; pd_last_req_time = squid_curtime; req->flags.cachable = 1; /* the rest is based on clientProcessExpired() */ req->flags.refresh = 1; old_e = fetch->old_entry = storeGet(key); if (old_e) { debug(72, 5) ("peerDigestRequest: found old entry\n"); storeLockObject(old_e); storeCreateMemObject(old_e, url, url); fetch->old_sc = storeClientRegister(old_e, fetch); } e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method); assert(EBIT_TEST(e->flags, KEY_PRIVATE)); fetch->sc = storeClientRegister(e, fetch); /* set lastmod to trigger IMS request if possible */ if (old_e) e->lastmod = old_e->lastmod; /* push towards peer cache */ debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n"); fwdStart(-1, e, req); cbdataLock(fetch); cbdataLock(fetch->pd); storeClientCopy(fetch->sc, e, 0, 0, 4096, memAllocate(MEM_4K_BUF), peerDigestFetchReply, fetch); }