21
18
* it under the terms of the GNU General Public License as published by
22
19
* the Free Software Foundation; either version 2 of the License, or
23
20
* (at your option) any later version.
25
22
* This program is distributed in the hope that it will be useful,
26
23
* but WITHOUT ANY WARRANTY; without even the implied warranty of
27
24
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
25
* GNU General Public License for more details.
30
27
* You should have received a copy of the GNU General Public License
31
28
* along with this program; if not, write to the Free Software
32
29
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
43
41
#include "MemObject.h"
44
42
#include "PeerDigest.h"
45
43
#include "PeerSelectState.h"
44
#include "SquidMath.h"
46
45
#include "SquidTime.h"
47
#include "icmp/net_db.h"
48
#include "ip/IpAddress.h"
49
50
/* count mcast group peers every 15 minutes */
50
51
#define MCAST_COUNT_RATE 900
52
static int peerAllowedToUse(const peer *, HttpRequest *);
53
int peerAllowedToUse(const peer *, HttpRequest *);
53
54
static int peerWouldBePinged(const peer *, HttpRequest *);
54
55
static void neighborRemove(peer *);
55
56
static void neighborAlive(peer *, const MemObject *, const icp_common_t *);
66
67
static void peerCountMcastPeersSchedule(peer * p, time_t when);
67
68
static IRCB peerCountHandleIcpReply;
69
static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode);
70
static void neighborIgnoreNonPeer(const IpAddress &, icp_opcode);
70
71
static OBJH neighborDumpPeers;
71
72
static OBJH neighborDumpNonPeers;
72
73
static void dump_peers(StoreEntry * sentry, peer * peers);
98
whichPeer(const struct sockaddr_in * from)
98
whichPeer(const IpAddress &from)
101
u_short port = ntohs(from->sin_port);
103
struct IN_ADDR ip = from->sin_addr;
105
debugs(15, 3, "whichPeer: from " << inet_ntoa(ip) << " port " << port);
103
debugs(15, 3, "whichPeer: from " << from);
107
for (p = Config.peers; p; p = p->next)
105
for (p = Config.peers; p; p = p->next) {
109
106
for (j = 0; j < p->n_addresses; j++) {
110
if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) {
107
if (from == p->addresses[j] && from.GetPort() == p->icp.port) {
123
120
const struct _domain_type *d = NULL;
125
122
for (d = p->typelist; d; d = d->next) {
126
if (0 == matchDomainName(request->host, d->domain))
123
if (0 == matchDomainName(request->GetHost(), d->domain))
127
124
if (d->type != PEER_NONE)
127
#if PEER_MULTICAST_SIBLINGS
128
if (p->type == PEER_MULTICAST)
129
if (p->options.mcast_siblings)
146
148
assert(request != NULL);
148
150
if (neighborType(p, request) == PEER_SIBLING) {
151
#if PEER_MULTICAST_SIBLINGS
152
if (p->type == PEER_MULTICAST && p->options.mcast_siblings &&
153
(request->flags.nocache || request->flags.refresh || request->flags.loopdetect || request->flags.need_validation))
154
debugs(15, 2, "peerAllowedToUse(" << p->name << ", " << request->GetHost() << ") : multicast-siblings optimization match");
149
156
if (request->flags.nocache)
179
186
if (p->access == NULL)
182
ACLChecklist checklist;
189
ACLFilledChecklist checklist(p->access, request, NULL);
184
190
checklist.src_addr = request->client_addr;
186
191
checklist.my_addr = request->my_addr;
188
checklist.my_port = request->my_port;
190
checklist.request = HTTPMSGLOCK(request);
192
checklist.accessList = cbdataReference(p->access);
194
/* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
196
193
#if 0 && USE_IDENT
198
195
* this is currently broken because 'request->user_ident' has been
422
419
* Called whenever the round-robin counters need to be reset to a sane state.
423
420
* So far those times are:
424
\item On startup and reconfigure - to set the counters to sane initial settings.
425
\item When a peer has revived from dead, to prevent the revived peer being
421
* - On startup and reconfigure - to set the counters to sane initial settings.
422
* - When a peer has revived from dead, to prevent the revived peer being
426
423
* flooded with requests which it has 'missed' during the down period.
478
475
* XXX DW thinks this function is equivalent to/redundant with
479
476
* getFirstUpParent(). peerHTTPOkay() only returns true if the
480
* peer is UP anyway, so this function would not return a
477
* peer is UP anyway, so this function would not return a
539
536
first_ping = Config.peers;
540
neighborsRegisterWithCacheManager()
542
CacheManager *manager = CacheManager::GetInstance();
543
manager->registerAction("server_list",
544
"Peer Cache Statistics",
545
neighborDumpPeers, 0, 1);
547
if (theInIcpConnection >= 0) {
548
manager->registerAction("non_peers",
549
"List of Unknown sites sending ICP messages",
550
neighborDumpNonPeers, 0, 1);
543
555
neighbors_init(void)
546
struct sockaddr_in name;
548
socklen_t len = sizeof(struct sockaddr_in);
558
struct addrinfo *AI = NULL;
550
559
struct servent *sep = NULL;
551
560
const char *me = getMyHostname();
561
peer *thisPeer = NULL;
554
563
int fd = theInIcpConnection;
565
neighborsRegisterWithCacheManager();
567
/* setup addrinfo for use */
568
nul.InitAddrInfo(AI);
558
memset(&name, '\0', sizeof(struct sockaddr_in));
560
if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
561
debugs(15, 1, "getsockname(" << fd << "," << &name << "," << &len << ") failed.");
572
if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen) < 0)
573
debugs(15, 1, "getsockname(" << fd << "," << AI->ai_addr << "," << &AI->ai_addrlen << ") failed.");
563
575
for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
576
http_port_list *s = NULL;
565
577
next = thisPeer->next;
567
579
if (0 != strcmp(thisPeer->host, me))
570
582
for (s = Config.Sockaddr.http; s; s = s->next) {
571
if (thisPeer->http_port != ntohs(s->s.sin_port))
583
if (thisPeer->http_port != s->s.GetPort())
574
586
debugs(15, 1, "WARNING: Peer looks like this host");
593
604
echo_hdr.reqnum = 0;
594
605
echo_hdr.flags = 0;
595
606
echo_hdr.pad = 0;
596
echo_hdr.shostid = name.sin_addr.s_addr;
608
nul.GetInAddr( *((struct in_addr*)&echo_hdr.shostid) );
597
609
sep = getservbyname("echo", "udp");
598
610
echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
601
613
first_ping = Config.peers;
605
neighborsRegisterWithCacheManager(CacheManager & manager)
607
manager.registerAction("server_list",
608
"Peer Cache Statistics",
609
neighborDumpPeers, 0, 1);
611
if (theInIcpConnection >= 0) {
612
manager.registerAction("non_peers",
613
"List of Unknown sites sending ICP messages",
614
neighborDumpNonPeers, 0, 1);
617
/* XXX FIXME: unregister if we were registered. Something like:
619
* CacheManagerAction * action = manager.findAction("non_peers");
620
* if (action != NULL)
621
* manager.unregisterAction(action);
614
nul.FreeAddrInfo(AI);
675
666
debugs(15, 3, "neighborsUdpPing: reqnum = " << reqnum);
679
if (p->options.htcp) {
669
if (p->options.htcp && !p->options.htcp_only_clr) {
680
670
if (Config.Port.htcp <= 0) {
681
671
debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer.");
699
689
debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping");
700
690
echo_hdr.reqnum = reqnum;
701
691
query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0);
702
icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0);
692
icpUdpSend(theOutIcpConnection,p->in_addr,query,LOG_ICP_QUERY,0);
710
700
query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0);
712
icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0);
702
icpUdpSend(theOutIcpConnection, p->in_addr, query, LOG_ICP_QUERY, 0);
755
745
if ((first_ping = first_ping->next) == NULL)
756
746
first_ping = Config.peers;
758
#if ALLOW_SOURCE_PING
759
/* only do source_ping if we have neighbors */
761
const ipcache_addrs *ia = NULL;
763
struct sockaddr_in to_addr;
764
char *host = request->host;
766
if (!Config.onoff.source_ping) {
767
debugs(15, 6, "neighborsUdpPing: Source Ping is disabled.");
768
} else if ((ia = ipcache_gethostbyname(host, 0))) {
769
debugs(15, 6, "neighborsUdpPing: Source Ping: to " << host << " for '" << url << "'");
770
echo_hdr.reqnum = reqnum;
772
if (icmp_sock != -1) {
773
icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url);
775
to_addr.sin_family = AF_INET;
776
to_addr.sin_addr = ia->in_addrs[ia->cur];
777
to_addr.sin_port = htons(echo_port);
778
query = _icp_common_t::createMessage(ICP_SECHO, 0, url, reqnum, 0);
779
icpUdpSend(theOutIcpConnection,
786
debugs(15, 6, "neighborsUdpPing: Source Ping: unknown host: " << host);
792
749
* How many replies to expect?
940
897
request->hier.cd_lookup = lookup;
942
debugs(15, 4, "peerNoteDigestLookup: peer " <<
943
(p ? p->host : "<none>") << ", lookup: " <<
944
lookup_t_str[lookup] );
899
debugs(15, 4, "peerNoteDigestLookup: peer " <<
900
(p ? p->host : "<none>") << ", lookup: " <<
901
lookup_t_str[lookup] );
979
936
if (p->options.weighted_roundrobin)
980
937
rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
982
p->stats.rtt = intAverage(p->stats.rtt, rtt,
983
p->stats.pings_acked, rtt_av_factor);
939
p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor);
1009
965
static peer *non_peers = NULL;
1013
neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode)
968
neighborIgnoreNonPeer(const IpAddress &from, icp_opcode opcode)
1017
for (np = non_peers; np; np = np->next)
1019
if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr)
972
for (np = non_peers; np; np = np->next) {
973
if (np->in_addr != from)
1022
if (np->in_addr.sin_port != from->sin_port)
976
if (np->in_addr.GetPort() != from.GetPort())
1030
983
np = (peer *)xcalloc(1, sizeof(peer));
1031
np->in_addr.sin_addr = from->sin_addr;
1032
np->in_addr.sin_port = from->sin_port;
1033
np->icp.port = ntohl(from->sin_port);
985
np->icp.port = from.GetPort();
1034
986
np->type = PEER_NONE;
1035
np->host = xstrdup(inet_ntoa(from->sin_addr));
987
np->host = new char[MAX_IPSTRLEN];
988
from.NtoA(np->host,MAX_IPSTRLEN);
1036
989
np->next = non_peers;
1067
1020
/* I should attach these records to the entry. We take the first
1068
1021
* hit we get our wait until everyone misses. The timeout handler
1069
1022
* call needs to nip this shopping list or call one of the misses.
1071
1024
* If a hit process is already started, then sobeit
1075
neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr_in *from)
1028
neighborsUdpAck(const cache_key * key, icp_common_t * header, const IpAddress &from)
1077
1030
peer *p = NULL;
1078
1031
StoreEntry *entry;
1098
1051
neighborUpdateRtt(p, mem);
1100
1053
/* Does the entry exist? */
1054
if (NULL == entry) {
1103
1055
debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found");
1104
1056
neighborCountIgnored(p);
1108
1060
/* check if someone is already fetching it */
1109
if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED))
1061
if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
1111
1062
debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1112
1063
neighborCountIgnored(p);
1118
1068
debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key));
1119
1069
neighborCountIgnored(p);
1123
if (entry->ping_status != PING_WAITING)
1073
if (entry->ping_status != PING_WAITING) {
1125
1074
debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key));
1126
1075
neighborCountIgnored(p);
1130
if (entry->lock_count == 0)
1079
if (entry->lock_count == 0) {
1132
1080
debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1133
1081
neighborCountIgnored(p);
1137
1085
debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " ");
1141
1088
ntype = neighborType(p, mem->request);
1144
if (ignoreMulticastReply(p, mem))
1091
if (ignoreMulticastReply(p, mem)) {
1146
1092
neighborCountIgnored(p);
1147
} else if (opcode == ICP_MISS)
1093
} else if (opcode == ICP_MISS) {
1149
1094
if (p == NULL) {
1150
1095
neighborIgnoreNonPeer(from, opcode);
1152
1097
mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1154
} else if (opcode == ICP_HIT)
1099
} else if (opcode == ICP_HIT) {
1156
1100
if (p == NULL) {
1157
1101
neighborIgnoreNonPeer(from, opcode);
1159
1103
header->opcode = ICP_HIT;
1160
1104
mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1162
} else if (opcode == ICP_DECHO)
1106
} else if (opcode == ICP_DECHO) {
1164
1107
if (p == NULL) {
1165
1108
neighborIgnoreNonPeer(from, opcode);
1166
1109
} else if (ntype == PEER_SIBLING) {
1170
1113
mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1172
} else if (opcode == ICP_SECHO)
1115
} else if (opcode == ICP_SECHO) {
1175
1117
debugs(15, 1, "Ignoring SECHO from neighbor " << p->host);
1176
1118
neighborCountIgnored(p);
1177
#if ALLOW_SOURCE_PING
1179
} else if (Config.onoff.source_ping) {
1180
mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data);
1184
debugs(15, 1, "Unsolicited SECHO from " << inet_ntoa(from->sin_addr));
1120
debugs(15, 1, "Unsolicited SECHO from " << from);
1186
} else if (opcode == ICP_DENIED)
1122
} else if (opcode == ICP_DENIED) {
1188
1123
if (p == NULL) {
1189
1124
neighborIgnoreNonPeer(from, opcode);
1190
1125
} else if (p->stats.pings_acked > 100) {
1197
1132
neighborCountIgnored(p);
1200
} else if (opcode == ICP_MISS_NOFETCH)
1135
} else if (opcode == ICP_MISS_NOFETCH) {
1202
1136
mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1205
1138
debugs(15, 0, "neighborsUdpAck: Unexpected ICP reply: " << opcode_d);
1241
1174
neighborUp(const peer * p)
1243
1176
if (!p->tcp_up) {
1244
if (!peerProbeConnect((peer *) p))
1177
if (!peerProbeConnect((peer *) p)) {
1178
debugs(15, 8, "neighborUp: DOWN (probed): " << p->host << " (" << p->in_addr << ")");
1249
1184
* The peer can not be UP if we don't have any IP addresses
1252
if (0 == p->n_addresses)
1187
if (0 == p->n_addresses) {
1188
debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")");
1255
if (p->options.no_query)
1192
if (p->options.no_query) {
1193
debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")");
1258
1197
if (p->stats.probe_start != 0 &&
1259
squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer)
1198
squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer) {
1199
debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")");
1203
debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")");
1301
peerDNSConfigure(const ipcache_addrs * ia, void *data)
1243
peerDNSConfigure(const ipcache_addrs *ia, const DnsLookupDetails &, void *data)
1303
1245
peer *p = (peer *)data;
1305
struct sockaddr_in *ap;
1308
1249
if (p->n_addresses == 0) {
1327
p->tcp_up = PEER_TCP_MAGIC_COUNT;
1268
p->tcp_up = p->connect_fail_limit;
1329
1270
for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) {
1330
1271
p->addresses[j] = ia->in_addrs[j];
1331
debugs(15, 2, "--> IP address #" << j << ": " << inet_ntoa(p->addresses[j]));
1272
debugs(15, 2, "--> IP address #" << j << ": " << p->addresses[j]);
1332
1273
p->n_addresses++;
1337
memset(ap, '\0', sizeof(struct sockaddr_in));
1338
ap->sin_family = AF_INET;
1339
ap->sin_addr = p->addresses[0];
1340
ap->sin_port = htons(p->icp.port);
1276
p->in_addr.SetEmpty();
1277
p->in_addr = p->addresses[0];
1278
p->in_addr.SetPort(p->icp.port);
1342
1280
if (p->type == PEER_MULTICAST)
1343
1281
peerCountMcastPeersSchedule(p, 10);
1345
1284
if (p->type != PEER_MULTICAST)
1346
1285
if (!p->options.no_netdb_exchange)
1347
1286
eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
1400
1341
if (!p->tcp_up) {
1401
1342
debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeded");
1402
p->tcp_up = PEER_TCP_MAGIC_COUNT; // NP: so peerAlive(p) works properly.
1343
p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly.
1404
if (!p->n_addresses)
1405
ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
1408
p->tcp_up = PEER_TCP_MAGIC_COUNT;
1345
if (!p->n_addresses)
1346
ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
1348
p->tcp_up = p->connect_fail_limit;
1351
/// called by Comm when test_fd is closed while connect is in progress
1353
peerProbeClosed(int fd, void *data)
1355
peer *p = (peer*)data;
1357
// it is a failure because we failed to connect
1358
peerConnectFailedSilent(p);
1412
1362
peerProbeConnectTimeout(int fd, void *data)
1414
1364
peer * p = (peer *)data;
1365
comm_remove_close_handler(fd, &peerProbeClosed, p);
1415
1366
comm_close(fd);
1416
1367
p->test_fd = -1;
1417
1368
peerConnectFailedSilent(p);
1421
* peerProbeConnect will be called on dead peers by neighborUp
1372
* peerProbeConnect will be called on dead peers by neighborUp
1424
1375
peerProbeConnect(peer * p)
1434
1385
if (squid_curtime - p->stats.last_connect_probe == 0)
1435
1386
return ret;/* don't probe to often */
1437
fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL),
1438
0, COMM_NONBLOCKING, p->host);
1388
IpAddress temp(getOutgoingAddr(NULL,p));
1390
fd = comm_open(SOCK_STREAM, IPPROTO_TCP, temp, COMM_NONBLOCKING, p->host);
1395
comm_add_close_handler(fd, &peerProbeClosed, p);
1443
1396
commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p);
1445
1398
p->test_fd = fd;
1459
peerProbeConnectDone(int fd, comm_err_t status, int xerrno, void *data)
1412
peerProbeConnectDone(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data)
1461
1414
peer *p = (peer*)data;
1497
1451
LOCAL_ARRAY(char, url, MAX_URL);
1498
1452
assert(p->type == PEER_MULTICAST);
1499
1453
p->mcast.flags.count_event_pending = 0;
1500
snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr));
1454
snprintf(url, MAX_URL, "http://");
1455
p->in_addr.ToURL(url+7, MAX_URL -8 );
1501
1457
fake = storeCreateEntry(url, url, request_flags(), METHOD_GET);
1502
1458
HttpRequest *req = HttpRequest::CreateFromUrl(url);
1503
1459
psstate = new ps_state;
1516
1472
reqnum = icpSetCacheKey((const cache_key *)fake->key);
1517
1473
query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0);
1518
1474
icpUdpSend(theOutIcpConnection,
1538
1494
if (cbdataReferenceValid(psstate->callback_data)) {
1539
1495
peer *p = (peer *)psstate->callback_data;
1540
1496
p->mcast.flags.counting = 0;
1541
p->mcast.avg_n_members = doubleAverage(p->mcast.avg_n_members,
1542
(double) psstate->ping.n_recv,
1543
++p->mcast.n_times_counted,
1497
p->mcast.avg_n_members = Math::doubleAverage(p->mcast.avg_n_members, (double) psstate->ping.n_recv, ++p->mcast.n_times_counted, 10);
1545
1498
debugs(15, 1, "Group " << p->host << ": " << psstate->ping.n_recv <<
1546
1499
" replies, "<< std::setw(4)<< std::setprecision(2) <<
1547
1500
p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt);
1576
1529
if (p->options.weighted_roundrobin)
1577
1530
rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
1579
p->stats.rtt = intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1532
p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1612
1565
if (p->options.roundrobin)
1613
1566
storeAppendPrintf(sentry, " round-robin");
1616
1568
if (p->options.carp)
1617
1569
storeAppendPrintf(sentry, " carp");
1620
1571
if (p->options.userhash)
1621
1572
storeAppendPrintf(sentry, " userhash");
1629
1580
if (p->options.mcast_responder)
1630
1581
storeAppendPrintf(sentry, " multicast-responder");
1583
#if PEER_MULTICAST_SIBLINGS
1584
if (p->options.mcast_siblings)
1585
storeAppendPrintf(sentry, " multicast-siblings");
1632
1588
if (p->weight != 1)
1633
1589
storeAppendPrintf(sentry, " weight=%d", p->weight);
1636
1592
storeAppendPrintf(sentry, " closest-only");
1640
1595
if (p->options.htcp)
1641
1596
storeAppendPrintf(sentry, " htcp");
1597
if (p->options.htcp_oldsquid)
1598
storeAppendPrintf(sentry, " htcp-oldsquid");
1599
if (p->options.htcp_no_clr)
1600
storeAppendPrintf(sentry, " htcp-no-clr");
1601
if (p->options.htcp_no_purge_clr)
1602
storeAppendPrintf(sentry, " htcp-no-purge-clr");
1603
if (p->options.htcp_only_clr)
1604
storeAppendPrintf(sentry, " htcp-only-clr");
1645
1607
if (p->options.no_netdb_exchange)
1661
1623
if (p->connect_timeout > 0)
1662
1624
storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout);
1626
if (p->connect_fail_limit != PEER_TCP_MAGIC_COUNT)
1627
storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit);
1664
1629
#if USE_CACHE_DIGESTS
1666
1631
if (p->digest_url)
1671
1636
if (p->options.allow_miss)
1672
1637
storeAppendPrintf(sentry, " allow-miss");
1639
if (p->options.no_tproxy)
1640
storeAppendPrintf(sentry, " no-tproxy");
1674
1642
if (p->max_conn > 0)
1675
1643
storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
1681
1649
storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
1651
if (p->connection_auth == 0)
1652
storeAppendPrintf(sentry, " connection-auth=off");
1653
else if (p->connection_auth == 1)
1654
storeAppendPrintf(sentry, " connection-auth=on");
1655
else if (p->connection_auth == 2)
1656
storeAppendPrintf(sentry, " connection-auth=auto");
1683
1658
storeAppendPrintf(sentry, "\n");
1710
1685
for (i = 0; i < e->n_addresses; i++) {
1711
1686
storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
1712
inet_ntoa(e->addresses[i]));
1687
e->addresses[i].NtoA(ntoabuf,MAX_IPSTRLEN) );
1715
1690
storeAppendPrintf(sentry, "Status : %s\n",
1733
1708
storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
1734
1709
e->stats.pings_acked,
1735
percent(e->stats.pings_acked, e->stats.pings_sent));
1710
Math::intPercent(e->stats.pings_acked, e->stats.pings_sent));
1738
storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n",
1739
e->stats.ignored_replies,
1740
percent(e->stats.ignored_replies, e->stats.pings_acked));
1713
storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked));
1742
1715
if (!e->options.no_query) {
1743
1716
storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
1746
1719
if (e->options.htcp) {
1747
1720
storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
1748
1721
e->htcp.counts[0],
1749
percent(e->htcp.counts[0], e->stats.pings_acked));
1722
Math::intPercent(e->htcp.counts[0], e->stats.pings_acked));
1750
1723
storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
1751
1724
e->htcp.counts[1],
1752
percent(e->htcp.counts[1], e->stats.pings_acked));
1725
Math::intPercent(e->htcp.counts[1], e->stats.pings_acked));
1760
1733
storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n",
1761
1734
icp_opcode_str[op],
1762
1735
e->icp.counts[op],
1763
percent(e->icp.counts[op], e->stats.pings_acked));
1736
Math::intPercent(e->icp.counts[op], e->stats.pings_acked));
1787
1760
storeAppendPrintf(sentry, "\n");
1790
storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
1791
percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1763
storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1798
neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr_in *from)
1769
neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const IpAddress &from)
1800
1771
StoreEntry *e = Store::Root().get(key);
1801
1772
MemObject *mem = NULL;
1803
1774
peer_t ntype = PEER_NONE;
1804
debugs(15, 6, "neighborsHtcpReply: " <<
1805
(htcp->hit ? "HIT" : "MISS") << " " <<
1806
storeKeyText(key) );
1775
debugs(15, 6, "neighborsHtcpReply: " <<
1776
(htcp->hit ? "HIT" : "MISS") << " " <<
1777
storeKeyText(key) );
1809
1780
mem = e->mem_obj;
1812
1783
neighborAliveHtcp(p, mem, htcp);
1814
1785
/* Does the entry exist? */
1817
1787
debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found");
1818
1788
neighborCountIgnored(p);
1822
1792
/* check if someone is already fetching it */
1823
if (EBIT_TEST(e->flags, ENTRY_DISPATCHED))
1793
if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
1825
1794
debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1826
1795
neighborCountIgnored(p);
1832
1800
debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key));
1833
1801
neighborCountIgnored(p);
1837
if (e->ping_status != PING_WAITING)
1805
if (e->ping_status != PING_WAITING) {
1839
1806
debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING");
1840
1807
neighborCountIgnored(p);
1844
if (e->lock_count == 0)
1811
if (e->lock_count == 0) {
1846
1812
debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1847
1813
neighborCountIgnored(p);
1853
1818
ntype = neighborType(p, mem->request);
1854
1819
neighborUpdateRtt(p, mem);
1857
if (ignoreMulticastReply(p, mem))
1822
if (ignoreMulticastReply(p, mem)) {
1859
1823
neighborCountIgnored(p);
1864
1828
mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data);
1832
* Send HTCP CLR messages to all peers configured to receive them.
1835
neighborsHtcpClear(StoreEntry * e, const char *uri, HttpRequest * req, const HttpRequestMethod &method, htcp_clr_reason reason)
1840
for (p = Config.peers; p; p = p->next) {
1841
if (!p->options.htcp) {
1844
if (p->options.htcp_no_clr) {
1847
if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
1850
debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.ToURL(buf, 128));
1851
htcpClear(e, uri, req, method, p, reason);