]> git.ipfire.org Git - thirdparty/squid.git/blame - src/neighbors.cc
use integer flag for init
[thirdparty/squid.git] / src / neighbors.cc
CommitLineData
fa966b74 1/* $Id: neighbors.cc,v 1.10 1996/04/06 00:53:06 wessels Exp $ */
019dd986 2
3/*
4 * DEBUG: Section 15 neighbors:
5 */
090089c4 6
44a47c6e 7#include "squid.h"
090089c4 8
44a47c6e 9static neighbors *friends = NULL;
090089c4 10
11static struct neighbor_cf *Neighbor_cf = NULL;
12
13static icp_common_t echo_hdr;
14static short echo_port;
15FILE *cache_hierarchy_log = NULL;
16
17static char *hier_strings[] =
18{
19 "NONE",
20 "DIRECT",
21 "NEIGHBOR_HIT",
22 "PARENT_HIT",
23 "SINGLE_PARENT",
24 "NO_PARENT_DIRECT",
25 "FIRST_PARENT_MISS",
26 "LOCAL_IP_DIRECT",
27 "DEAD_PARENT",
28 "DEAD_NEIGHBOR",
29 "REVIVE_PARENT",
30 "REVIVE_NEIGHBOR",
31 "NO_DIRECT_FAIL",
32 "SOURCE_FASTEST",
33 "INVALID CODE"
34};
35
36
37edge *whichEdge(header, from)
38 icp_common_t *header;
39 struct sockaddr_in *from;
40{
22e4fa85 41 int j;
090089c4 42 int port;
43 struct in_addr ip;
44 edge *e = NULL;
45
46 port = ntohs(from->sin_port);
47 ip = from->sin_addr;
48
019dd986 49 debug(15, 3, "whichEdge: from %s port %d\n", inet_ntoa(ip), port);
090089c4 50
51 for (e = friends->edges_head; e; e = e->next) {
52 for (j = 0; j < e->n_addresses; j++) {
53 if (ip.s_addr == e->addresses[j].s_addr && port == e->udp_port) {
54 return e;
55 }
56 }
57 }
58 return (NULL);
59}
60
61
62void hierarchy_log_append(url, code, timeout, cache_host)
63 char *url;
64 hier_code code;
65 int timeout;
66 char *cache_host;
67{
68 static time_t last_time = 0;
69 static char time_str[128];
70 char *s = NULL;
71
72 if (!cache_hierarchy_log)
73 return;
74
75 if (code > HIER_MAX)
76 code = HIER_MAX;
77
78 if (emulate_httpd_log) {
79 if (cached_curtime != last_time) {
80 s = mkhttpdlogtime(&cached_curtime);
81 strcpy(time_str, s);
82 last_time = cached_curtime;
83 }
84 if (cache_host) {
85 fprintf(cache_hierarchy_log, "[%s] %s %s%s %s\n",
86 time_str,
87 url,
88 timeout ? "TIMEOUT_" : "",
89 hier_strings[code],
90 cache_host);
91 } else {
92 fprintf(cache_hierarchy_log, "[%s] %s %s%s\n",
93 time_str,
94 url,
95 timeout ? "TIMEOUT_" : "",
96 hier_strings[code]);
97 }
98 } else {
99 if (cache_host) {
22e4fa85 100 fprintf(cache_hierarchy_log, "%d %s %s%s %s\n",
101 (int) cached_curtime,
090089c4 102 url,
103 timeout ? "TIMEOUT_" : "",
104 hier_strings[code],
105 cache_host);
106 } else {
22e4fa85 107 fprintf(cache_hierarchy_log, "%d %s %s%s\n",
108 (int) cached_curtime,
090089c4 109 url,
110 timeout ? "TIMEOUT_" : "",
111 hier_strings[code]);
112 }
113 }
114 if (unbuffered_logs)
115 fflush(cache_hierarchy_log);
116}
117
118static int edgeWouldBePinged(e, host)
119 edge *e;
120 char *host;
121{
122 int offset;
123 dom_list *d = NULL;
124 int do_ping = 1;
125
126 if (e->domains == NULL)
127 return do_ping;
128
129 do_ping = 0;
130 for (d = e->domains; d; d = d->next) {
131 if ((offset = strlen(host) - strlen(d->domain)) < 0) {
132 do_ping = !d->do_ping;
133 continue;
134 }
135 if (strcasecmp(d->domain, host + offset) == 0) {
136 /* found a match, no need to check any more domains */
137 do_ping = d->do_ping;
138 break;
139 } else {
140 do_ping = !d->do_ping;
141 }
142 }
143 return do_ping;
144}
145
146edge *getSingleParent(host, n)
147 char *host;
148 int *n;
149{
150 edge *p = NULL;
151 edge *e = NULL;
090089c4 152 int count = 0;
153
154 if (n == NULL && friends->n_parent < 1)
155 return NULL;
156 for (e = friends->edges_head; e; e = e->next) {
157 if (edgeWouldBePinged(e, host)) {
158 count++;
159 if (e->type != is_a_parent) {
160 /* we matched a neighbor, not a parent. There
161 * can be no single parent */
162 if (n == NULL)
163 return NULL;
164 continue;
165 }
166 if (p) {
167 /* already have a parent, this makes the second,
168 * so there can be no single parent */
169 if (n == NULL)
170 return NULL;
171 continue;
172 }
173 p = e;
174 }
175 }
176 /* Ok, all done checking the edges. If only one parent matched, then
177 * p will already point to it */
178 if (n)
179 *n = count;
180 if (count == 1)
181 return p;
182 return NULL;
183}
184
185edge *getFirstParent(host)
186 char *host;
187{
188 edge *e = NULL;
090089c4 189 if (friends->n_parent < 1)
190 return NULL;
191 for (e = friends->edges_head; e; e = e->next) {
192 if (e->type != is_a_parent)
193 continue;
194 if (edgeWouldBePinged(e, host))
195 return e;
196 }
197 return NULL;
198}
199
200edge *getNextEdge(edge * e)
201{
202 return e->next;
203}
204
205edge *getFirstEdge()
206{
207 return friends->edges_head;
208}
209
210void neighbors_install(host, type, ascii_port, udp_port, proxy_only, domains)
211 char *host;
212 char *type;
213 int ascii_port;
214 int udp_port;
215 int proxy_only;
216 dom_list *domains;
217{
090089c4 218 edge *e;
219
019dd986 220 debug(15, 1, "Adding a %s: %s\n", type, host);
090089c4 221
222 e = (edge *) xcalloc(1, sizeof(edge));
223
224 e->ack_deficit = 0;
225 e->ascii_port = ascii_port;
226 e->udp_port = udp_port;
227 e->proxy_only = proxy_only;
228 e->host = xstrdup(host);
229 e->domains = domains;
230 e->num_pings = 0;
231 e->pings_sent = 0;
232 e->pings_acked = 0;
233 e->neighbor_up = 1;
234 e->hits = 0;
235 e->misses = 0;
236
237 if (!strcmp(type, "parent")) {
238 friends->n_parent++;
239 e->type = is_a_parent;
240 } else {
241 friends->n_neighbor++;
242 e->type = is_a_neighbor;
243 }
244
245 /* Append edge */
246 if (!friends->edges_head)
247 friends->edges_head = e;
248 if (friends->edges_tail)
249 friends->edges_tail->next = e;
250 friends->edges_tail = e;
251
252 friends->n++;
253}
254
255void neighbors_open(fd)
256 int fd;
257{
22e4fa85 258 int j;
090089c4 259 struct sockaddr_in our_socket_name;
260 struct sockaddr_in *ap;
261 int sock_name_length = sizeof(our_socket_name);
262 int log_fd;
263 char *fname = NULL;
264 char **list = NULL;
265 edge *e = NULL;
266 struct in_addr *ina = NULL;
267
268 if (getsockname(fd, (struct sockaddr *) &our_socket_name,
269 &sock_name_length) == -1) {
019dd986 270 debug(15, 1, "getsockname(%d,%p,%p) failed.\n",
090089c4 271 fd, &our_socket_name, &sock_name_length);
272 }
273 friends->fd = fd;
274
275 /* open log file */
276 if ((fname = getHierarchyLogFile())) {
277 log_fd = file_open(fname, NULL, O_WRONLY | O_CREAT | O_APPEND);
278 if (log_fd < 0) {
019dd986 279 debug(15, 1, "%s: %s\n", fname, xstrerror());
280 debug(15, 1, "Hierachical logging is disabled.\n");
090089c4 281 } else if (!(cache_hierarchy_log = fdopen(log_fd, "a"))) {
019dd986 282 debug(15, 1, "%s: %s\n", fname, xstrerror());
283 debug(15, 1, "Hierachical logging is disabled.\n");
090089c4 284 }
285 }
286 /* Prepare neighbor connections, one at a time */
287 for (e = friends->edges_head; e; e = e->next) {
019dd986 288 debug(15, 2, "Finding IP addresses for '%s'\n", e->host);
090089c4 289 if ((list = getAddressList(e->host)) == NULL) {
290 sprintf(tmp_error_buf, "DNS lookup for '%s' failed! Cannot continue.\n",
291 e->host);
292 fatal(tmp_error_buf);
293 }
294 e->n_addresses = 0;
295 for (j = 0; *list && j < EDGE_MAX_ADDRESSES; j++) {
296 ina = &e->addresses[j];
297 memcpy(&(ina->s_addr), *list, 4);
298 list++;
299 e->n_addresses++;
300 }
301 if (e->n_addresses < 1) {
302 sprintf(tmp_error_buf, "No IP addresses found for '%s'; Cannot continue.\n", e->host);
303 fatal(tmp_error_buf);
304 }
305 for (j = 0; j < e->n_addresses; j++) {
019dd986 306 debug(15, 2, "--> IP address #%d: %s\n", j, inet_ntoa(e->addresses[j]));
090089c4 307 }
308 e->rtt = 1000;
309
310 /* Prepare query packet for future use */
311 e->header.opcode = ICP_OP_QUERY;
312 e->header.version = ICP_VERSION_CURRENT;
313 e->header.length = 0;
314 e->header.reqnum = 0;
315 memset(e->header.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE);
316 e->header.shostid = our_socket_name.sin_addr.s_addr;
317
318 ap = &e->in_addr;
319 memset(ap, '\0', sizeof(struct sockaddr_in));
320 ap->sin_family = AF_INET;
321 ap->sin_addr = e->addresses[0];
322 ap->sin_port = htons(e->udp_port);
323
324 if (e->type == is_a_parent) {
019dd986 325 debug(15, 3, "parent_install: host %s addr %s port %d\n",
090089c4 326 e->host, inet_ntoa(ap->sin_addr),
327 e->udp_port);
328 e->neighbor_up = 1;
329 } else {
019dd986 330 debug(15, 3, "neighbor_install: host %s addr %s port %d\n",
090089c4 331 e->host, inet_ntoa(ap->sin_addr),
332 e->udp_port);
333 e->neighbor_up = 1;
334 }
335
336 /* do this only the first time thru */
337 if (0 == echo_hdr.opcode) {
338 struct servent *sep;
339
340 echo_hdr.opcode = ICP_OP_SECHO;
341 echo_hdr.version = ICP_VERSION_CURRENT;
342 echo_hdr.length = 0;
343 echo_hdr.reqnum = 0;
344 memset(echo_hdr.auth, '\0', sizeof(u_num32) * ICP_AUTH_SIZE);
345 echo_hdr.shostid = our_socket_name.sin_addr.s_addr;
346
347 sep = getservbyname("echo", "udp");
0af42d4b 348 echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
090089c4 349 }
350 }
351}
352
353neighbors *neighbors_create()
354{
355 neighbors *f;
356
357 f = (neighbors *) xcalloc(1, sizeof(neighbors));
358 f->n = 0;
359 f->n_parent = 0;
360 f->n_neighbor = 0;
361 f->edges_head = (edge *) NULL;
362 f->edges_tail = (edge *) NULL;
363 f->first_ping = (edge *) NULL;
364 return (friends = f);
365}
366
367
368int neighborsUdpPing(proto)
369 protodispatch_data *proto;
370{
371 char *t = NULL;
372 char *host = proto->host;
373 char *url = proto->url;
374 StoreEntry *entry = proto->entry;
375 struct hostent *hep = NULL;
376 struct sockaddr_in to_addr;
377 edge *e = NULL;
378 int i;
379
22e4fa85 380 entry->mem_obj->e_pings_n_pings = 0;
381 entry->mem_obj->e_pings_n_acks = 0;
382 entry->mem_obj->e_pings_first_miss = NULL;
090089c4 383
384 if (friends->edges_head == (edge *) NULL)
385 return 0;
386
387 for (i = 0, e = friends->first_ping; i++ < friends->n; e = e->next) {
388 if (e == (edge *) NULL)
389 e = friends->edges_head;
019dd986 390 debug(15, 5, "neighborsUdpPing: Edge %s\n", e->host);
090089c4 391
392 /* Don't resolve refreshes through neighbors because we don't resolve
393 * misses through neighbors */
394 if ((e->type == is_a_neighbor) && (entry->flag & REFRESH_REQUEST))
395 continue;
396
397 /* skip dumb caches where we failed to connect() w/in the last 60s */
398 if (e->udp_port == echo_port &&
399 (cached_curtime - e->last_fail_time < 60))
400 continue;
401
402 if (!edgeWouldBePinged(e, host))
403 continue; /* next edge */
404
019dd986 405 debug(15, 4, "neighborsUdpPing: pinging cache %s for <URL:%s>\n",
090089c4 406 e->host, url);
407
6eb42cae 408 /* e->header.reqnum++; */
409 e->header.reqnum = atoi(entry->key);
410 debug(15, 1, "neighborsUdpPing: key = '%s'\n", entry->key);
411 debug(15, 1, "neighborsUdpPing: reqnum = %d\n", e->header.reqnum);
090089c4 412
413 if (e->udp_port == echo_port) {
019dd986 414 debug(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
090089c4 415 icpUdpSend(friends->fd, url, &echo_hdr, &e->in_addr, ICP_OP_DECHO);
416 } else {
417 icpUdpSend(friends->fd, url, &e->header, &e->in_addr, ICP_OP_QUERY);
418 }
419
420 e->ack_deficit++;
421 e->num_pings++;
422 e->pings_sent++;
423
424 if (e->ack_deficit < HIER_MAX_DEFICIT) {
425 /* consider it's alive. count it */
426 e->neighbor_up = 1;
22e4fa85 427 entry->mem_obj->e_pings_n_pings++;
090089c4 428 } else {
429 /* consider it's dead. send a ping but don't count it. */
430 e->neighbor_up = 0;
431 if (e->ack_deficit > (HIER_MAX_DEFICIT << 1))
432 /* do this to prevent wrap around but we still want it
433 * to move a bit so we can debug it easier. */
434 e->ack_deficit = HIER_MAX_DEFICIT + 1;
019dd986 435 debug(15, 6, "cache %s is considered dead but send PING anyway, hope it comes up soon.\n",
090089c4 436 inet_ntoa(e->in_addr.sin_addr));
437 /* log it once at the threshold */
438 if ((e->ack_deficit == HIER_MAX_DEFICIT)) {
439 if (e->type == is_a_neighbor) {
440 hierarchy_log_append("Detect: ",
441 HIER_DEAD_NEIGHBOR, 0,
442 e->host);
443 } else {
444 hierarchy_log_append("Detect: ",
445 HIER_DEAD_PARENT, 0,
446 e->host);
447 }
448 }
449 }
450 friends->first_ping = e->next;
451 }
452
453 /* only do source_ping if we have neighbors */
454 if (echo_hdr.opcode) {
455 if (proto->source_ping && (hep = ipcache_gethostbyname(host))) {
019dd986 456 debug(15, 6, "neighborsUdpPing: Send to original host\n");
457 debug(15, 6, "neighborsUdpPing: url=%s, host=%s, t=%d\n",
090089c4 458 url, host, t);
459 to_addr.sin_family = AF_INET;
460 memcpy(&to_addr.sin_addr, hep->h_addr, hep->h_length);
461 to_addr.sin_port = echo_port;
462 echo_hdr.reqnum = cached_curtime;
019dd986 463 debug(15, 6, "neighborsUdpPing - url: %s to url-host %s \n",
090089c4 464 url, inet_ntoa(to_addr.sin_addr));
465 /* send to original site */
466 icpUdpSend(friends->fd, url, &echo_hdr, &to_addr, ICP_OP_SECHO);
467 } else {
019dd986 468 debug(15, 6, "neighborsUdpPing: Source Ping is disabled.\n");
090089c4 469 }
470 }
22e4fa85 471 return (entry->mem_obj->e_pings_n_pings);
090089c4 472}
473
474
475/* I should attach these records to the entry. We take the first
476 * hit we get our wait until everyone misses. The timeout handler
477 * call needs to nip this shopping list or call one of the misses.
478 *
479 * If a hit process is already started, then sobeit
480 */
481void neighborsUdpAck(fd, url, header, from, entry)
482 int fd;
483 char *url;
484 icp_common_t *header;
485 struct sockaddr_in *from;
486 StoreEntry *entry;
487{
488 edge *e = NULL;
489
019dd986 490 debug(15, 6, "neighborsUdpAck: url=%s (%d chars), header=0x%x, from=0x%x, ent=0x%x\n",
090089c4 491 url, strlen(url), header, from, entry);
019dd986 492 debug(15, 6, " hdr: opcode=%d, ver=%d, shostid=%x, len=%d, rn=0x%x\n",
090089c4 493 header->opcode, header->version, header->shostid,
494 header->length, header->reqnum);
019dd986 495 debug(15, 6, " from: fam=%d, port=%d, addr=0x%x\n",
fa966b74 496 ntohs(from->sin_family),
497 ntohs(from->sin_port),
498 ntohl(from->sin_addr.s_addr));
090089c4 499
500 /* look up for neighbor/parent entry */
501 e = whichEdge(header, from);
502
503 if (e) {
504 /* reset the deficit. It's alive now. */
505 /* Don't care about exact count. */
506 if ((e->ack_deficit >= HIER_MAX_DEFICIT)) {
507 if (e->type == is_a_neighbor) {
508 hierarchy_log_append("Detect: ",
509 HIER_REVIVE_NEIGHBOR, 0, e->host);
510 } else {
511 hierarchy_log_append("Detect: ",
512 HIER_REVIVE_PARENT, 0, e->host);
513 }
514 }
515 e->ack_deficit = 0;
516 e->neighbor_up = 1;
517 e->pings_acked++;
518 }
519 /* check if someone is already fetching it */
6eb42cae 520 if (BIT_TEST(entry->flag, ENTRY_DISPATCHED) || (entry->ping_status != WAITING)) {
090089c4 521 if (entry->ping_status == DONE) {
019dd986 522 debug(15, 5, "There is already a cache/source dispatched for this object\n");
523 debug(15, 5, "--> <URL:%s>\n", entry->url);
6eb42cae 524 debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %d\n",
525 BIT_TEST(entry->flag, ENTRY_DISPATCHED));
019dd986 526 debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status);
090089c4 527 } else {
019dd986 528 debug(15, 5, "The ping already timed out.\n");
529 debug(15, 5, "--> <URL:%s>\n", entry->url);
6eb42cae 530 debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %lx\n",
531 BIT_TEST(entry->flag, ENTRY_DISPATCHED));
019dd986 532 debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status);
090089c4 533 }
534 return;
535 }
019dd986 536 debug(15, 6, "neighborsUdpAck - url: %s to us %s \n",
090089c4 537 url, e ? inet_ntoa(e->in_addr.sin_addr) : "url-host");
538
539 if (header->opcode == ICP_OP_SECHO) {
540 /* receive ping back from source or from non-cached cache */
541 if (e) {
019dd986 542 debug(15, 6, "Got SECHO from non-cached cache:%s\n",
090089c4 543 inet_ntoa(e->in_addr.sin_addr));
019dd986 544 debug(15, 6, "This is not supposed to happen. Ignored.\n");
090089c4 545 } else {
546 /* if we reach here, source is the one has the fastest respond. */
547 /* fetch directly from source */
019dd986 548 debug(15, 6, "Source is the first to respond.\n");
090089c4 549 hierarchy_log_append(entry->url,
550 HIER_SOURCE_FASTEST,
551 0,
552 inet_ntoa(from->sin_addr));
6eb42cae 553 BIT_SET(entry->flag, ENTRY_DISPATCHED);
090089c4 554 entry->ping_status = DONE;
555 getFromOrgSource(0, entry);
556 }
557 return;
558 }
559 if (header->opcode == ICP_OP_HIT) {
560 /* If an edge is not found, count it as a MISS message. */
561 if (!e) {
562 /* count it as a MISS message */
22e4fa85 563 entry->mem_obj->e_pings_n_acks++;
090089c4 564 return;
565 }
566 /* GOT a HIT here */
019dd986 567 debug(15, 6, "HIT: Getting %s from host: %s\n", entry->url, e->host);
090089c4 568 if (e->type == is_a_neighbor) {
569 hierarchy_log_append(entry->url, HIER_NEIGHBOR_HIT, 0, e->host);
570 } else {
571 hierarchy_log_append(entry->url, HIER_PARENT_HIT, 0, e->host);
572 }
6eb42cae 573 BIT_SET(entry->flag, ENTRY_DISPATCHED);
090089c4 574 entry->ping_status = DONE;
575 getFromCache(0, entry, e);
576 e->hits++;
577 return;
578 } else if ((header->opcode == ICP_OP_MISS) || (header->opcode == ICP_OP_DECHO)) {
579 /* everytime we get here, count it as a miss */
22e4fa85 580 entry->mem_obj->e_pings_n_acks++;
090089c4 581 if (e)
582 e->misses++;
583
584 if (header->opcode == ICP_OP_DECHO) {
585 /* receive ping back from non-cached cache */
586
587 if (e) {
019dd986 588 debug(15, 6, "Got DECHO from non-cached cache:%s\n",
090089c4 589 inet_ntoa(e->in_addr.sin_addr));
019dd986 590 debug(15, 6, "Good.");
090089c4 591
592 if (e->type == is_a_parent) {
22e4fa85 593 if (entry->mem_obj->e_pings_first_miss == NULL) {
019dd986 594 debug(15, 6, "OK. We got dumb-cached parent as the first miss here.\n");
22e4fa85 595 entry->mem_obj->e_pings_first_miss = e;
090089c4 596 }
597 } else {
019dd986 598 debug(15, 6, "Dumb Cached as a neighbor does not make sense.\n");
599 debug(15, 6, "Count it anyway.\n");
090089c4 600 }
601
602
603 } else {
019dd986 604 debug(15, 6, "Got DECHO from non-cached cache: But the host is not in the list.\n");
605 debug(15, 6, "Count it anyway.\n");
090089c4 606 }
607
608 } else {
609 /* ICP_OP_MISS from a cache */
22e4fa85 610 if ((entry->mem_obj->e_pings_first_miss == NULL) && e && e->type == is_a_parent) {
611 entry->mem_obj->e_pings_first_miss = e;
090089c4 612
613 }
614 }
615
22e4fa85 616 if (entry->mem_obj->e_pings_n_acks == entry->mem_obj->e_pings_n_pings) {
6eb42cae 617 BIT_SET(entry->flag, ENTRY_DISPATCHED);
090089c4 618 entry->ping_status = DONE;
019dd986 619 debug(15, 6, "Receive MISSes from all neighbors and parents\n");
090089c4 620 /* pass in fd=0 here so getFromCache() looks up the real FD
621 * and resets the timeout handler */
622 getFromDefaultSource(0, entry);
623 return;
624 }
625 } else {
019dd986 626 debug(15, 0, "neighborsUdpAck: WHY ARE WE HERE? header->opcode = %d\n",
090089c4 627 header->opcode);
628 }
629}
630
631void neighbors_cf_add(host, type, ascii_port, udp_port, proxy_only)
632 char *host;
633 char *type;
634 int ascii_port;
635 int udp_port;
636 int proxy_only;
637{
638 struct neighbor_cf *t, *u;
639
640 t = (struct neighbor_cf *) xcalloc(sizeof(struct neighbor_cf), 1);
641 t->host = xstrdup(host);
642 t->type = xstrdup(type);
643 t->ascii_port = ascii_port;
644 t->udp_port = udp_port;
645 t->proxy_only = proxy_only;
646 t->next = (struct neighbor_cf *) NULL;
647
648 if (Neighbor_cf == (struct neighbor_cf *) NULL) {
649 Neighbor_cf = t;
650 } else {
651 for (u = Neighbor_cf; u->next; u = u->next);
652 u->next = t;
653 }
654}
655
656int neighbors_cf_domain(host, domain)
657 char *host;
658 char *domain;
659{
660 struct neighbor_cf *t;
661 dom_list *l;
662 dom_list **L;
663
664 for (t = Neighbor_cf; t; t = t->next) {
665 if (strcmp(t->host, host) == 0)
666 break;
667 }
668
669 if (t == NULL)
670 return 0;
671
672 l = (dom_list *) xmalloc(sizeof(dom_list));
673 l->do_ping = 1;
674 if (*domain == '!') { /* check for !.edu */
675 l->do_ping = 0;
676 domain++;
677 }
678 l->domain = xstrdup(domain);
679 l->next = NULL;
680 for (L = &(t->domains); *L; L = &((*L)->next));
681 *L = l;
682
683 return 1;
684}
685
686void neighbors_init()
687{
688 struct neighbor_cf *t, *next;
689
690 for (t = Neighbor_cf; t; t = next) {
691 next = t->next;
44a47c6e 692 if (strncmp(t->host, getMyHostname(), SQUIDHOSTNAMELEN) ||
090089c4 693 t->ascii_port != getAsciiPortNum()) {
694 neighbors_install(t->host, t->type,
695 t->ascii_port, t->udp_port, t->proxy_only,
696 t->domains);
697 } else {
019dd986 698 debug(15, 0, "neighbors_init: skipping cache_host %s %s %d %d\n",
090089c4 699 t->type, t->host, t->ascii_port, t->udp_port);
019dd986 700 debug(15, 0, "neighbors_init: because it seems to be identical to this cached\n");
090089c4 701 }
702 xfree(t->host);
703 xfree(t->type);
704 xfree(t);
705 }
706}
707
708void neighbors_rotate_log()
709{
710 int i;
711 static char from[MAXPATHLEN];
712 static char to[MAXPATHLEN];
713 char *fname = NULL;
714 int log_fd;
715
716 if ((fname = getHierarchyLogFile()) == NULL)
717 return;
718
019dd986 719 debug(15, 1, "neighbors_rotate_log: Rotating.\n");
090089c4 720
721 /* Rotate numbers 0 through N up one */
722 for (i = getLogfileRotateNumber(); i > 1;) {
723 i--;
724 sprintf(from, "%s.%d", fname, i - 1);
725 sprintf(to, "%s.%d", fname, i);
726 rename(from, to);
727 }
728 /* Rotate the current log to .0 */
729 if (getLogfileRotateNumber() > 0) {
730 sprintf(to, "%s.%d", fname, 0);
731 rename(fname, to);
732 }
733 /* Close and reopen the log. It may have been renamed "manually"
734 * before HUP'ing us. */
735 fclose(cache_hierarchy_log);
736 log_fd = file_open(fname, NULL, O_WRONLY | O_CREAT | O_APPEND);
737 if (log_fd < 0) {
019dd986 738 debug(15, 0, "rotate_logs: %s: %s\n", fname, xstrerror());
739 debug(15, 1, "Hierachical logging is disabled.\n");
090089c4 740 } else if ((cache_hierarchy_log = fdopen(log_fd, "a")) == NULL) {
019dd986 741 debug(15, 0, "rotate_logs: %s: %s\n",
090089c4 742 fname, xstrerror());
019dd986 743 debug(15, 1, "Hierachical logging is disabled.\n");
090089c4 744 }
745}