]>
Commit | Line | Data |
---|---|---|
641941c0 | 1 | |
062e2281 | 2 | /* |
0c511722 | 3 | * $Id: peer_select.cc,v 1.52 1998/04/22 16:24:14 rousskov Exp $ |
062e2281 | 4 | * |
5 | * DEBUG: section 44 Peer Selection Algorithm | |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
9 | * -------------------------------------------------------- | |
10 | * | |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
13 | * National Laboratory for Applied Network Research and funded by | |
14 | * the National Science Foundation. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | * | |
30 | */ | |
31 | ||
32 | #include "squid.h" | |
33 | ||
429fdbec | 34 | const char *hier_strings[] = |
35 | { | |
36 | "NONE", | |
37 | "DIRECT", | |
38 | "SIBLING_HIT", | |
39 | "PARENT_HIT", | |
40 | "DEFAULT_PARENT", | |
41 | "SINGLE_PARENT", | |
42 | "FIRST_UP_PARENT", | |
43 | "NO_PARENT_DIRECT", | |
44 | "FIRST_PARENT_MISS", | |
45 | "CLOSEST_PARENT_MISS", | |
46 | "CLOSEST_DIRECT", | |
47 | "NO_DIRECT_FAIL", | |
48 | "SOURCE_FASTEST", | |
429fdbec | 49 | "ROUNDROBIN_PARENT", |
b123df92 | 50 | #if SQUID_PEER_DIGEST |
c127134a | 51 | "CACHE_DIGEST_HIT", |
285f75ea | 52 | "NO_CACHE_DIGEST_DIRECT", |
c127134a | 53 | #endif |
429fdbec | 54 | "INVALID CODE" |
55 | }; | |
56 | ||
85034133 | 57 | static struct { |
75e88d56 | 58 | int timeouts; |
85034133 | 59 | } PeerStats; |
062e2281 | 60 | |
f9e5a344 | 61 | static char *DirectStr[] = |
62 | { | |
63 | "DIRECT_NO", | |
64 | "DIRECT_MAYBE", | |
65 | "DIRECT_YES" | |
7b665aeb | 66 | }; |
75e88d56 | 67 | |
f5b8bbc4 | 68 | static void peerSelectFoo(ps_state *); |
de7ba689 | 69 | static void peerSelectCheckAS(ps_state *); |
f5b8bbc4 | 70 | static void peerPingTimeout(void *data); |
71 | static void peerSelectCallbackFail(ps_state * psstate); | |
b3264694 | 72 | static IRCB peerHandleIcpReply; |
de7ba689 | 73 | static IPH peerSelectCheckASDone; |
f5b8bbc4 | 74 | static void peerSelectStateFree(ps_state * psstate); |
75 | static void peerIcpParentMiss(peer *, icp_common_t *, ps_state *); | |
76 | static int peerCheckNetdbDirect(ps_state * psstate); | |
348b2031 | 77 | |
78 | static void | |
79 | peerSelectStateFree(ps_state * psstate) | |
80 | { | |
81 | if (psstate->acl_checklist) { | |
51fdcbd5 | 82 | debug(44, 1) ("calling aclChecklistFree() from peerSelectStateFree\n"); |
348b2031 | 83 | aclChecklistFree(psstate->acl_checklist); |
84 | } | |
85 | requestUnlink(psstate->request); | |
8407afee | 86 | psstate->request = NULL; |
87 | cbdataFree(psstate); | |
348b2031 | 88 | } |
062e2281 | 89 | |
90 | int | |
91 | peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry) | |
92 | { | |
7b665aeb | 93 | int n; |
93775f90 | 94 | if (entry == NULL) |
95 | return 0; | |
9fb13bb6 | 96 | debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry)); |
062e2281 | 97 | if (entry->ping_status != PING_NONE) |
98 | return 0; | |
9bd6a36d | 99 | assert(direct != DIRECT_YES); |
79a15e0a | 100 | if (!EBIT_TEST(entry->flag, HIERARCHICAL) && direct != DIRECT_NO) |
062e2281 | 101 | return 0; |
79a15e0a | 102 | if (EBIT_TEST(entry->flag, KEY_PRIVATE) && !neighbors_do_private_keys) |
062e2281 | 103 | if (direct != DIRECT_NO) |
104 | return 0; | |
7b665aeb | 105 | n = neighborsCount(request); |
f9e5a344 | 106 | debug(44, 3) ("peerSelectIcpPing: counted %d neighbors\n", n); |
7b665aeb | 107 | return n; |
062e2281 | 108 | } |
109 | ||
110 | ||
111 | peer * | |
112 | peerGetSomeParent(request_t * request, hier_code * code) | |
113 | { | |
114 | peer *p; | |
de7ba689 | 115 | debug(44, 3) ("peerGetSomeParent: called.\n"); |
062e2281 | 116 | if ((p = getDefaultParent(request))) { |
429fdbec | 117 | *code = DEFAULT_PARENT; |
062e2281 | 118 | return p; |
119 | } | |
062e2281 | 120 | if ((p = getRoundRobinParent(request))) { |
429fdbec | 121 | *code = ROUNDROBIN_PARENT; |
062e2281 | 122 | return p; |
123 | } | |
124 | if ((p = getFirstUpParent(request))) { | |
429fdbec | 125 | *code = FIRSTUP_PARENT; |
062e2281 | 126 | return p; |
127 | } | |
128 | return NULL; | |
129 | } | |
130 | ||
131 | void | |
93775f90 | 132 | peerSelect(request_t * request, |
b6c0e933 | 133 | StoreEntry * entry, |
582b6456 | 134 | PSC * callback, |
135 | PSC * fail_callback, | |
b6c0e933 | 136 | void *callback_data) |
75e88d56 | 137 | { |
b6c0e933 | 138 | ps_state *psstate = xcalloc(1, sizeof(ps_state)); |
86b389fc | 139 | if (entry) |
9fb13bb6 | 140 | debug(44, 3) ("peerSelect: %s\n", storeUrl(entry)); |
86b389fc | 141 | else |
f9e5a344 | 142 | debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]); |
3f6c0fb2 | 143 | cbdataAdd(psstate, MEM_NONE); |
b6c0e933 | 144 | psstate->request = requestLink(request); |
145 | psstate->entry = entry; | |
146 | psstate->callback = callback; | |
147 | psstate->fail_callback = fail_callback; | |
148 | psstate->callback_data = callback_data; | |
39edba21 | 149 | #if SQUID_PEER_DIGEST |
150 | request->hier.peer_select_start = current_time; | |
151 | #endif | |
395b813e | 152 | cbdataLock(callback_data); |
153 | peerSelectCheckAS(psstate); | |
de7ba689 | 154 | } |
155 | ||
156 | static void | |
157 | peerSelectCheckASDone(const ipcache_addrs * ia, void *data) | |
158 | { | |
159 | ps_state *psstate = data; | |
b6c0e933 | 160 | peerSelectFoo(psstate); |
75e88d56 | 161 | } |
162 | ||
de7ba689 | 163 | static void |
164 | peerSelectCheckAS(ps_state * psstate) | |
165 | { | |
166 | request_t *request = psstate->request; | |
167 | ||
168 | /* XXXX Just a quick hack to get the destination address to the | |
169 | * ipcache, because peerSelectIcpPing requires non-blocking ACL | |
170 | * check. | |
171 | * We should handle AS acl's differently than cache_host ones. */ | |
172 | ||
173 | ipcache_nbgethostbyname(request->host, | |
174 | peerSelectCheckASDone, | |
175 | psstate); | |
176 | return; | |
177 | } | |
178 | ||
179 | ||
75e88d56 | 180 | static void |
181 | peerCheckNeverDirectDone(int answer, void *data) | |
182 | { | |
b6c0e933 | 183 | ps_state *psstate = data; |
348b2031 | 184 | psstate->acl_checklist = NULL; |
a3d5953d | 185 | debug(44, 3) ("peerCheckNeverDirectDone: %d\n", answer); |
b6c0e933 | 186 | psstate->never_direct = answer ? 1 : -1; |
187 | peerSelectFoo(psstate); | |
75e88d56 | 188 | } |
189 | ||
190 | static void | |
191 | peerCheckAlwaysDirectDone(int answer, void *data) | |
192 | { | |
b6c0e933 | 193 | ps_state *psstate = data; |
348b2031 | 194 | psstate->acl_checklist = NULL; |
a3d5953d | 195 | debug(44, 3) ("peerCheckAlwaysDirectDone: %d\n", answer); |
7b665aeb | 196 | psstate->always_direct = answer ? 1 : -1; |
b6c0e933 | 197 | peerSelectFoo(psstate); |
75e88d56 | 198 | } |
199 | ||
93775f90 | 200 | static void |
b6c0e933 | 201 | peerSelectCallback(ps_state * psstate, peer * p) |
93775f90 | 202 | { |
b6c0e933 | 203 | StoreEntry *entry = psstate->entry; |
8407afee | 204 | void *data = psstate->callback_data; |
b6c0e933 | 205 | if (entry) { |
9fb13bb6 | 206 | debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry)); |
b6c0e933 | 207 | if (entry->ping_status == PING_WAITING) |
208 | eventDelete(peerPingTimeout, psstate); | |
209 | entry->ping_status = PING_DONE; | |
210 | } | |
ee1679df | 211 | psstate->icp.stop = current_time; |
8407afee | 212 | if (cbdataValid(data)) |
365e5b34 | 213 | psstate->callback(p, data); |
8407afee | 214 | cbdataUnlock(data); |
348b2031 | 215 | peerSelectStateFree(psstate); |
93775f90 | 216 | } |
217 | ||
218 | static void | |
b6c0e933 | 219 | peerSelectCallbackFail(ps_state * psstate) |
93775f90 | 220 | { |
b6c0e933 | 221 | request_t *request = psstate->request; |
8407afee | 222 | void *data = psstate->callback_data; |
9fb13bb6 | 223 | const char *url = psstate->entry ? storeUrl(psstate->entry) : urlCanonical(request, NULL); |
a3d5953d | 224 | debug(44, 1) ("Failed to select source for '%s'\n", url); |
225 | debug(44, 1) (" always_direct = %d\n", psstate->always_direct); | |
226 | debug(44, 1) (" never_direct = %d\n", psstate->never_direct); | |
227 | debug(44, 1) (" timeout = %d\n", psstate->icp.timeout); | |
8407afee | 228 | if (cbdataValid(data)) |
365e5b34 | 229 | psstate->fail_callback(NULL, data); |
8407afee | 230 | cbdataUnlock(data); |
348b2031 | 231 | peerSelectStateFree(psstate); |
063347b4 | 232 | /* XXX When this happens, the client request just hangs */ |
93775f90 | 233 | } |
234 | ||
b3264694 | 235 | static int |
236 | peerCheckNetdbDirect(ps_state * psstate) | |
237 | { | |
238 | peer *p = psstate->closest_parent_miss; | |
239 | int myrtt; | |
240 | int myhops; | |
241 | if (p == NULL) | |
242 | return 0; | |
243 | myrtt = netdbHostRtt(psstate->request->host); | |
437e2060 | 244 | debug(44, 3) ("peerCheckNetdbDirect: MY RTT = %d\n", myrtt); |
245 | debug(44, 3) ("peerCheckNetdbDirect: closest_parent_miss RTT = %d\n", | |
b3264694 | 246 | psstate->icp.p_rtt); |
247 | if (myrtt && myrtt < psstate->icp.p_rtt) | |
248 | return 1; | |
249 | myhops = netdbHostHops(psstate->request->host); | |
437e2060 | 250 | debug(44, 3) ("peerCheckNetdbDirect: MY hops = %d\n", myhops); |
251 | debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_hops = %d\n", | |
b3264694 | 252 | Config.minDirectHops); |
253 | if (myhops && myhops <= Config.minDirectHops) | |
254 | return 1; | |
255 | return 0; | |
256 | } | |
257 | ||
93775f90 | 258 | static void |
b6c0e933 | 259 | peerSelectFoo(ps_state * psstate) |
062e2281 | 260 | { |
261 | peer *p; | |
262 | hier_code code; | |
b6c0e933 | 263 | StoreEntry *entry = psstate->entry; |
264 | request_t *request = psstate->request; | |
75e88d56 | 265 | int direct; |
7b665aeb | 266 | debug(44, 3) ("peerSelectFoo: '%s %s'\n", |
b6c0e933 | 267 | RequestMethodStr[request->method], |
268 | request->host); | |
eeeb6107 | 269 | if (psstate->never_direct == 0 && Config.accessList.NeverDirect) { |
348b2031 | 270 | psstate->acl_checklist = aclChecklistCreate( |
271 | Config.accessList.NeverDirect, | |
75e88d56 | 272 | request, |
273 | request->client_addr, | |
274 | NULL, /* user agent */ | |
348b2031 | 275 | NULL); /* ident */ |
276 | aclNBCheck(psstate->acl_checklist, | |
75e88d56 | 277 | peerCheckNeverDirectDone, |
b6c0e933 | 278 | psstate); |
75e88d56 | 279 | return; |
b6c0e933 | 280 | } else if (psstate->never_direct > 0) { |
75e88d56 | 281 | direct = DIRECT_NO; |
eeeb6107 | 282 | } else if (psstate->always_direct == 0 && Config.accessList.AlwaysDirect) { |
348b2031 | 283 | psstate->acl_checklist = aclChecklistCreate( |
284 | Config.accessList.AlwaysDirect, | |
75e88d56 | 285 | request, |
286 | request->client_addr, | |
287 | NULL, /* user agent */ | |
348b2031 | 288 | NULL); /* ident */ |
289 | aclNBCheck(psstate->acl_checklist, | |
75e88d56 | 290 | peerCheckAlwaysDirectDone, |
b6c0e933 | 291 | psstate); |
75e88d56 | 292 | return; |
b6c0e933 | 293 | } else if (psstate->always_direct > 0) { |
75e88d56 | 294 | direct = DIRECT_YES; |
295 | } else { | |
296 | direct = DIRECT_MAYBE; | |
297 | } | |
7b665aeb | 298 | debug(44, 3) ("peerSelectFoo: direct = %s\n", DirectStr[direct]); |
062e2281 | 299 | if (direct == DIRECT_YES) { |
7b665aeb | 300 | debug(44, 3) ("peerSelectFoo: DIRECT\n"); |
a4394ebd | 301 | hierarchyNote(&request->hier, DIRECT, &psstate->icp, request->host); |
b6c0e933 | 302 | peerSelectCallback(psstate, NULL); |
062e2281 | 303 | return; |
304 | } | |
a369131d | 305 | psstate->single_parent = getSingleParent(request); |
a369131d | 306 | if (psstate->single_parent != NULL) { |
307 | debug(44, 3) ("peerSelect: found single parent, skipping ICP query\n"); | |
308 | } else if (peerSelectIcpPing(request, direct, entry)) { | |
9bd6a36d | 309 | assert(entry->ping_status == PING_NONE); |
b123df92 | 310 | #if SQUID_PEER_DIGEST |
26b164ac | 311 | /* which algorithm to use? */ |
312 | if (squid_random() & 1) { | |
0c511722 | 313 | debug(44, 2) ("peerSelect: Using Cache Digest\n"); |
b123df92 | 314 | request->hier.alg = PEER_SA_DIGEST; |
26b164ac | 315 | if (1 /* global_digested_peer_count */) |
316 | p = neighborsDigestSelect(request, entry); | |
2920225f | 317 | /* update counters */ |
318 | statHistCount(&Counter.cd.peer_choice_count, request->hier.n_choices); | |
319 | statHistCount(&Counter.cd.peer_ichoice_count, request->hier.n_ichoices); | |
320 | code = DIRECT; | |
26b164ac | 321 | switch (request->hier.cd_lookup) { |
322 | case LOOKUP_HIT: | |
b123df92 | 323 | assert(p); |
c127134a | 324 | code = CACHE_DIGEST_HIT; |
0c511722 | 325 | debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host); |
c127134a | 326 | hierarchyNote(&request->hier, code, &psstate->icp, p->host); |
26b164ac | 327 | peerSelectCallback(psstate, p); /* @?@: p used to be NULL */ |
328 | return; | |
329 | case LOOKUP_MISS: | |
285f75ea | 330 | code = NO_CACHE_DIGEST_DIRECT; |
26b164ac | 331 | /* fall through */ |
332 | case LOOKUP_NONE: | |
333 | /* go direct */ | |
0c511722 | 334 | debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], request->host); |
26b164ac | 335 | hierarchyNote(&request->hier, code, &psstate->icp, request->host); |
c127134a | 336 | peerSelectCallback(psstate, NULL); |
b123df92 | 337 | return; |
26b164ac | 338 | default: |
339 | assert(0); /* invalid lookup code */ | |
c127134a | 340 | } |
26b164ac | 341 | assert(0); /* never reached */ |
c127134a | 342 | } else { |
b123df92 | 343 | request->hier.alg = PEER_SA_ICP; |
c127134a | 344 | #endif |
345 | debug(44, 3) ("peerSelect: Doing ICP pings\n"); | |
346 | psstate->icp.start = current_time; | |
347 | psstate->icp.n_sent = neighborsUdpPing(request, | |
348 | entry, | |
349 | peerHandleIcpReply, | |
b6c0e933 | 350 | psstate, |
c127134a | 351 | &psstate->icp.n_replies_expected); |
352 | if (psstate->icp.n_sent == 0) | |
353 | debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n"); | |
354 | if (psstate->icp.n_replies_expected > 0) { | |
355 | entry->ping_status = PING_WAITING; | |
356 | eventAdd("peerPingTimeout", | |
357 | peerPingTimeout, | |
358 | psstate, | |
359 | Config.neighborTimeout); | |
360 | return; | |
361 | } | |
b123df92 | 362 | #if SQUID_PEER_DIGEST |
062e2281 | 363 | } |
c127134a | 364 | #endif |
062e2281 | 365 | } |
de7ba689 | 366 | debug(44, 3) ("peerSelectFoo: After peerSelectIcpPing.\n"); |
b3264694 | 367 | if (peerCheckNetdbDirect(psstate)) { |
368 | code = CLOSEST_DIRECT; | |
369 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host); | |
370 | hierarchyNote(&request->hier, code, &psstate->icp, request->host); | |
371 | peerSelectCallback(psstate, NULL); | |
a200bbd2 | 372 | } else if ((p = psstate->closest_parent_miss) != NULL) { |
b3264694 | 373 | code = CLOSEST_PARENT_MISS; |
374 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); | |
375 | hierarchyNote(&request->hier, code, &psstate->icp, p->host); | |
376 | peerSelectCallback(psstate, p); | |
a200bbd2 | 377 | } else if ((p = psstate->first_parent_miss) != NULL) { |
429fdbec | 378 | code = FIRST_PARENT_MISS; |
a3d5953d | 379 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); |
a4394ebd | 380 | hierarchyNote(&request->hier, code, &psstate->icp, p->host); |
b6c0e933 | 381 | peerSelectCallback(psstate, p); |
a369131d | 382 | } else if ((p = psstate->single_parent)) { |
383 | code = SINGLE_PARENT; | |
384 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); | |
385 | hierarchyNote(&request->hier, code, &psstate->icp, p->host); | |
386 | peerSelectCallback(psstate, p); | |
93775f90 | 387 | } else if (direct != DIRECT_NO) { |
429fdbec | 388 | code = DIRECT; |
a3d5953d | 389 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host); |
a4394ebd | 390 | hierarchyNote(&request->hier, code, &psstate->icp, request->host); |
b6c0e933 | 391 | peerSelectCallback(psstate, NULL); |
93775f90 | 392 | } else if ((p = peerGetSomeParent(request, &code))) { |
a3d5953d | 393 | debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); |
a4394ebd | 394 | hierarchyNote(&request->hier, code, &psstate->icp, p->host); |
b6c0e933 | 395 | peerSelectCallback(psstate, p); |
93775f90 | 396 | } else { |
429fdbec | 397 | code = NO_DIRECT_FAIL; |
a4394ebd | 398 | hierarchyNote(&request->hier, code, &psstate->icp, NULL); |
b6c0e933 | 399 | peerSelectCallbackFail(psstate); |
062e2281 | 400 | } |
401 | } | |
402 | ||
d9586c3c | 403 | static void |
93775f90 | 404 | peerPingTimeout(void *data) |
062e2281 | 405 | { |
b6c0e933 | 406 | ps_state *psstate = data; |
407 | StoreEntry *entry = psstate->entry; | |
86b389fc | 408 | if (entry) |
9fb13bb6 | 409 | debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry)); |
93775f90 | 410 | entry->ping_status = PING_TIMEOUT; |
75e88d56 | 411 | PeerStats.timeouts++; |
b6c0e933 | 412 | psstate->icp.timeout = 1; |
413 | peerSelectFoo(psstate); | |
85034133 | 414 | } |
415 | ||
416 | void | |
417 | peerSelectInit(void) | |
418 | { | |
75e88d56 | 419 | memset(&PeerStats, '\0', sizeof(PeerStats)); |
9bdbfe33 | 420 | assert(sizeof(hier_strings) == (HIER_MAX + 1) * sizeof(char *)); |
062e2281 | 421 | } |
93775f90 | 422 | |
b3264694 | 423 | static void |
424 | peerIcpParentMiss(peer * p, icp_common_t * header, ps_state * ps) | |
425 | { | |
426 | int rtt; | |
427 | int hops; | |
428 | if (Config.onoff.query_icmp) { | |
79a15e0a | 429 | if (header->flags & ICP_FLAG_SRC_RTT) { |
b3264694 | 430 | rtt = header->pad & 0xFFFF; |
431 | hops = (header->pad >> 16) & 0xFFFF; | |
432 | if (rtt > 0 && rtt < 0xFFFF) | |
433 | netdbUpdatePeer(ps->request, p, rtt, hops); | |
434 | if (rtt && (ps->icp.p_rtt == 0 || rtt < ps->icp.p_rtt)) { | |
435 | ps->closest_parent_miss = p; | |
436 | ps->icp.p_rtt = rtt; | |
437 | } | |
438 | } | |
439 | } | |
440 | /* if closest-only is set, the don't allow FIRST_PARENT_MISS */ | |
79a15e0a | 441 | if (EBIT_TEST(p->options, NEIGHBOR_CLOSEST_ONLY)) |
b3264694 | 442 | return; |
443 | /* set FIRST_MISS if thre is no CLOSEST parent */ | |
444 | if (ps->closest_parent_miss != NULL) | |
445 | return; | |
446 | rtt = tvSubMsec(ps->icp.start, current_time) / p->weight; | |
447 | if (ps->icp.w_rtt == 0 || rtt < ps->icp.w_rtt) { | |
448 | ps->first_parent_miss = p; | |
449 | ps->icp.w_rtt = rtt; | |
450 | } | |
451 | } | |
93775f90 | 452 | |
b6c0e933 | 453 | static void |
b3264694 | 454 | peerHandleIcpReply(peer * p, peer_t type, icp_common_t * header, void *data) |
93775f90 | 455 | { |
b6c0e933 | 456 | ps_state *psstate = data; |
b3264694 | 457 | icp_opcode op = header->opcode; |
b6c0e933 | 458 | request_t *request = psstate->request; |
f9e5a344 | 459 | debug(44, 3) ("peerHandleIcpReply: %s %s\n", |
27cd7235 | 460 | icp_opcode_str[op], |
9fb13bb6 | 461 | storeUrl(psstate->entry)); |
26b164ac | 462 | #if SQUID_PEER_DIGEST |
463 | /* do cd lookup to count false misses */ | |
3ab66981 | 464 | if (p && request) |
465 | peerNoteDigestLookup(request, p, | |
466 | peerDigestLookup(p, request, psstate->entry)); | |
26b164ac | 467 | #endif |
b6c0e933 | 468 | psstate->icp.n_recv++; |
27cd7235 | 469 | if (op == ICP_MISS || op == ICP_DECHO) { |
b3264694 | 470 | if (type == PEER_PARENT) |
471 | peerIcpParentMiss(p, header, psstate); | |
a7c05555 | 472 | } else if (op == ICP_HIT) { |
a4394ebd | 473 | hierarchyNote(&request->hier, |
429fdbec | 474 | type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT, |
b6c0e933 | 475 | &psstate->icp, |
93775f90 | 476 | p->host); |
b6c0e933 | 477 | peerSelectCallback(psstate, p); |
93775f90 | 478 | return; |
27cd7235 | 479 | } else if (op == ICP_SECHO) { |
a4394ebd | 480 | hierarchyNote(&request->hier, |
429fdbec | 481 | SOURCE_FASTEST, |
b6c0e933 | 482 | &psstate->icp, |
483 | request->host); | |
4f92c80c | 484 | peerSelectCallback(psstate, NULL); |
93775f90 | 485 | return; |
486 | } | |
b6c0e933 | 487 | if (psstate->icp.n_recv < psstate->icp.n_replies_expected) |
93775f90 | 488 | return; |
b6c0e933 | 489 | peerSelectFoo(psstate); |
93775f90 | 490 | } |