xfree(digest_url);
#endif
- delete next;
-
xfree(login);
delete standby.pool;
/// \returns the effective connect timeout for the given peer
time_t connectTimeout() const;
+ /// n-th cache_peer directive, starting with 1
u_int index = 0;
/// cache_peer name (if explicitly configured) or hostname (otherwise).
Ip::Address addresses[10];
int n_addresses = 0;
int rr_count = 0;
- CachePeer *next = nullptr;
int testing_now = 0;
struct {
--- /dev/null
+/*
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "CachePeers.h"
+#include "SquidConfig.h"
+
+CachePeer &
+CachePeers::nextPeerToPing(const size_t pollIndex)
+{
+ Assure(size());
+
+ // Remember the number of polls to keep shifting each poll starting point,
+ // to avoid always polling the same group of peers before other peers and
+ // risk overloading that first group with requests.
+ if (!pollIndex)
+ ++peerPolls_;
+
+ // subtract 1 to set the very first pos to zero
+ const auto pos = (peerPolls_ - 1 + pollIndex) % size();
+
+ return *storage[pos];
+}
+
+void
+CachePeers::remove(CachePeer * const peer)
+{
+ const auto pos = std::find_if(storage.begin(), storage.end(), [&](const auto &storePeer) {
+ return storePeer.get() == peer;
+ });
+ Assure(pos != storage.end());
+ storage.erase(pos);
+}
+
+const CachePeers &
+CurrentCachePeers()
+{
+ if (Config.peers)
+ return *Config.peers;
+
+ static const CachePeers empty;
+ return empty;
+}
+
+void
+DeleteConfigured(CachePeer * const peer)
+{
+ Assure(Config.peers);
+ Config.peers->remove(peer);
+}
+
#include "CachePeer.h"
#include "mem/PoolingAllocator.h"
+#include <memory>
#include <vector>
+/// cache_peer configuration storage
+class CachePeers
+{
+public:
+ /// owns stored CachePeer objects
+ using Storage = std::vector< std::unique_ptr<CachePeer>, PoolingAllocator< std::unique_ptr<CachePeer> > >;
+
+ /// stores a being-configured cache_peer
+ void add(CachePeer *p) { storage.emplace_back(p); }
+
+ /// deletes a previously add()ed CachePeer object
+ void remove(CachePeer *);
+
+ /// the number of currently stored (i.e. added and not removed) cache_peers
+ auto size() const { return storage.size(); }
+
+ /* peer iterators forming a sequence for C++ range-based for loop API */
+ using const_iterator = Storage::const_iterator;
+ auto begin() const { return storage.cbegin(); }
+ auto end() const { return storage.cend(); }
+
+ /// A CachePeer to query next when scanning all peer caches in hope to fetch
+ /// a remote cache hit. \sa neighborsUdpPing()
+ /// \param iteration a 0-based index of a loop scanning all peers
+ CachePeer &nextPeerToPing(size_t iteration);
+
+private:
+ /// cache_peers in configuration/parsing order
+ Storage storage;
+
+ /// total number of completed peer scans by nextPeerToPing()-calling code
+ uint64_t peerPolls_ = 0;
+};
+
+/// All configured cache_peers that are still available/relevant.
+/// \returns an empty container if no cache_peers were configured or all
+/// configured cache_peers were removed (e.g., by DeleteConfigured()).
+const CachePeers &CurrentCachePeers();
+
+/// destroys the given peer after removing it from the set of configured peers
+void DeleteConfigured(CachePeer *);
+
/// Weak pointers to zero or more Config.peers.
/// Users must specify the selection algorithm and the order of entries.
using SelectedCachePeers = std::vector< CbcPointer<CachePeer>, PoolingAllocator< CbcPointer<CachePeer> > >;
CacheManager.h \
CachePeer.cc \
CachePeer.h \
+ CachePeers.cc \
CachePeers.h \
ClientInfo.h \
ClientRequestContext.h \
CacheDigest.h \
CachePeer.cc \
CachePeer.h \
+ CachePeers.cc \
+ CachePeers.h \
ClientInfo.h \
tests/stub_CollapsedForwarding.cc \
ConfigOption.cc \
CacheDigest.h \
CachePeer.cc \
CachePeer.h \
+ CachePeers.cc \
+ CachePeers.h \
ClientInfo.h \
tests/stub_CollapsedForwarding.cc \
ConfigOption.cc \
tests/testCacheManager.cc \
CachePeer.cc \
CachePeer.h \
+ CachePeers.cc \
+ CachePeers.h \
ClientInfo.h \
tests/stub_CollapsedForwarding.cc \
ConfigOption.cc \
#include "base/AsyncCallbacks.h"
#include "base/RunnersRegistry.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "comm/Connection.h"
#include "comm/ConnOpener.h"
#include "debug/Stream.h"
void
PeerPoolMgrsRr::syncConfig()
{
- for (CachePeer *p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
// On reconfigure, Squid deletes the old config (and old peers in it),
// so should always be dealing with a brand new configuration.
assert(!p->standby.mgr);
{
class ActionPasswordList;
} // namespace Mgr
-class CachePeer;
+
+class CachePeers;
class CustomLog;
class CpuAffinityMap;
class DebugMessages;
size_t tcpRcvBufsz;
size_t udpMaxHitObjsz;
wordlist *mcast_group_list;
- CachePeer *peers;
+ CachePeers *peers;
int npeers;
struct {
#include "base/RunnersRegistry.h"
#include "cache_cf.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "ConfigOption.h"
#include "ConfigParser.h"
#include "CpuAffinityMap.h"
#endif
}
- for (CachePeer *p = Config.peers; p != nullptr; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
// default value for ssldomain= is the peer host/IP
if (p->secure.sslDomain.isEmpty())
}
static void
-dump_peer(StoreEntry * entry, const char *name, CachePeer * p)
+dump_peer(StoreEntry * entry, const char *name, const CachePeers *peers)
{
+ if (!peers)
+ return;
+
NeighborTypeDomainList *t;
LOCAL_ARRAY(char, xname, 128);
- while (p != nullptr) {
+ for (const auto &peer: *peers) {
+ const auto p = peer.get();
storeAppendPrintf(entry, "%s %s %s %d %d name=%s",
name,
p->host,
peer_type_str(t->type),
t->domain);
}
-
- p = p->next;
}
}
}
static void
-parse_peer(CachePeer ** head)
+parse_peer(CachePeers **peers)
{
char *host_str = ConfigParser::NextToken();
if (!host_str) {
if (p->secure.encryptTransport)
p->secure.parseOptions();
- p->index = ++Config.npeers;
+ if (!*peers)
+ *peers = new CachePeers;
- while (*head != nullptr)
- head = &(*head)->next;
+ (*peers)->add(p);
- *head = p;
+ p->index = (*peers)->size();
peerClearRRStart();
}
static void
-free_peer(CachePeer ** P)
+free_peer(CachePeers ** const peers)
{
- delete *P;
- *P = nullptr;
- Config.npeers = 0;
+ delete *peers;
+ *peers = nullptr;
}
static void
/* find out which peers we have */
RawCachePeers rawCarpPeers;
- for (auto p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
+
if (!p->options.carp)
continue;
#include "acl/FilledChecklist.h"
#include "base/AsyncCallbacks.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "comm.h"
#include "comm/Connection.h"
#include "comm/Loops.h"
static void
htcpForwardClr(char *buf, int sz)
{
- CachePeer *p;
-
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!p->options.htcp) {
continue;
}
#include "squid.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "cbdata.h"
#include "event.h"
#include "fde.h"
static CachePeer *
findUsableParentAtHostname(PeerSelector *ps, const char * const hostname, const HttpRequest &request)
{
- for (auto p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
// Both fields should be lowercase, but no code ensures that invariant.
// TODO: net_db_peer should point to CachePeer instead of its hostname!
if (strcasecmp(p->host, hostname) != 0)
#include "base/PackableStream.h"
#include "CacheDigest.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "comm/Connection.h"
#include "comm/ConnOpener.h"
#include "debug/Messages.h"
bool peerAllowedToUse(const CachePeer *, PeerSelector *);
static int peerWouldBePinged(const CachePeer *, PeerSelector *);
-static void neighborRemove(CachePeer *);
static void neighborAlive(CachePeer *, const MemObject *, const icp_common_t *);
#if USE_HTCP
static void neighborAliveHtcp(CachePeer *, const MemObject *, const HtcpReplyData *);
static void neighborIgnoreNonPeer(const Ip::Address &, icp_opcode);
static OBJH neighborDumpPeers;
-static void dump_peers(StoreEntry * sentry, CachePeer * peers);
+static void dump_peers(StoreEntry *, CachePeers *);
static unsigned short echo_port;
static int NLateReplies = 0;
-static CachePeer *first_ping = nullptr;
const char *
neighborTypeStr(const CachePeer * p)
{
int j;
- CachePeer *p = nullptr;
debugs(15, 3, "whichPeer: from " << from);
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
for (j = 0; j < p->n_addresses; ++j) {
if (from == p->addresses[j] && from.port() == p->icp.port) {
- return p;
+ return p.get();
}
}
}
int
neighborsCount(PeerSelector *ps)
{
- CachePeer *p = nullptr;
int count = 0;
- for (p = Config.peers; p; p = p->next)
- if (peerWouldBePinged(p, ps))
+ for (const auto &p: CurrentCachePeers())
+ if (peerWouldBePinged(p.get(), ps))
++count;
debugs(15, 3, "neighborsCount: " << count);
CachePeer *p = nullptr;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ p = peer.get();
+
if (!neighborUp(p))
continue;
assert(ps);
HttpRequest *request = ps->request;
- CachePeer *p;
CachePeer *q = nullptr;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
if (!p->options.roundrobin)
continue;
assert(ps);
HttpRequest *request = ps->request;
- CachePeer *p;
CachePeer *q = nullptr;
int weighted_rtt;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
+
if (!p->options.weighted_roundrobin)
continue;
}
if (q && q->rr_count > 1000000)
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!p->options.weighted_roundrobin)
continue;
- if (neighborType(p, request->url) != PEER_PARENT)
+ if (neighborType(p.get(), request->url) != PEER_PARENT)
continue;
p->rr_count = 0;
void
peerClearRR()
{
- CachePeer *p = nullptr;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers())
p->rr_count = 1;
- }
}
void
assert(ps);
HttpRequest *request = ps->request;
- CachePeer *p = nullptr;
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
- for (p = Config.peers; p; p = p->next) {
if (neighborType(p, request->url) != PEER_PARENT)
continue;
return nullptr;
}
-CachePeer *
-getNextPeer(CachePeer * p)
-{
- return p->next;
-}
-
-CachePeer *
-getFirstPeer(void)
-{
- return Config.peers;
-}
-
-static void
-neighborRemove(CachePeer * target)
-{
- CachePeer *p = nullptr;
- CachePeer **P = nullptr;
- p = Config.peers;
- P = &Config.peers;
-
- while (p) {
- if (target == p)
- break;
-
- P = &p->next;
-
- p = p->next;
- }
-
- if (p) {
- *P = p->next;
- p->next = nullptr;
- delete p;
- --Config.npeers;
- }
-
- first_ping = Config.peers;
-}
-
static void
neighborsRegisterWithCacheManager()
{
{
struct servent *sep = nullptr;
const char *me = getMyHostname();
- CachePeer *thisPeer = nullptr;
- CachePeer *next = nullptr;
neighborsRegisterWithCacheManager();
if (Comm::IsConnOpen(icpIncomingConn)) {
+ RawCachePeers peersToRemove;
- for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
- next = thisPeer->next;
-
+ for (const auto &thisPeer: CurrentCachePeers()) {
if (0 != strcmp(thisPeer->host, me))
continue;
debugs(15, DBG_IMPORTANT, "WARNING: Peer looks like this host." <<
Debug::Extra << "Ignoring cache_peer " << *thisPeer);
- neighborRemove(thisPeer);
+ peersToRemove.push_back(thisPeer.get());
+ break; // avoid warning about (and removing) the same CachePeer twice
}
}
+
+ while (peersToRemove.size()) {
+ const auto p = peersToRemove.back();
+ peersToRemove.pop_back();
+ DeleteConfigured(p);
+ }
}
peerRefreshDNS((void *) 1);
sep = getservbyname("echo", "udp");
echo_port = sep ? ntohs((unsigned short) sep->s_port) : 7;
-
- first_ping = Config.peers;
}
int
{
const char *url = entry->url();
MemObject *mem = entry->mem_obj;
- CachePeer *p = nullptr;
- int i;
int reqnum = 0;
int flags;
int peers_pinged = 0;
reqnum = icpSetCacheKey((const cache_key *)entry->key);
- for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
- if (p == nullptr)
- p = Config.peers;
+ for (size_t i = 0; i < Config.peers->size(); ++i) {
+ const auto p = &Config.peers->nextPeerToPing(i);
debugs(15, 5, "candidate: " << *p);
p->stats.probe_start = squid_curtime;
}
- if ((first_ping = first_ping->next) == nullptr)
- first_ping = Config.peers;
-
/*
* How many replies to expect?
*/
int best_rtt = 0;
int choice_count = 0;
int ichoice_count = 0;
- CachePeer *p;
int p_rtt;
- int i;
if (!request->flags.hierarchical)
return nullptr;
storeKeyPublicByRequest(request);
- for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
- lookup_t lookup;
-
- if (!p)
- p = Config.peers;
+ for (size_t i = 0; i < Config.peers->size(); ++i) {
+ const auto p = &Config.peers->nextPeerToPing(i);
- if (i == 1)
- first_ping = p;
-
- lookup = peerDigestLookup(p, ps);
+ const auto lookup = peerDigestLookup(p, ps);
if (lookup == LOOKUP_NONE)
continue;
if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
debugs(15, DBG_CRITICAL, "Disabling cache_peer " << *p <<
" because over 95% of its replies are UDP_DENIED");
- neighborRemove(p);
+ DeleteConfigured(p);
p = nullptr;
} else {
neighborCountIgnored(p);
CachePeer *
findCachePeerByName(const char * const name)
{
- CachePeer *p = nullptr;
-
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!strcasecmp(name, p->name))
- break;
+ return p.get();
}
-
- return p;
+ return nullptr;
}
int
static void
peerRefreshDNS(void *data)
{
- CachePeer *p = nullptr;
-
if (eventFind(peerRefreshDNS, nullptr))
eventDelete(peerRefreshDNS, nullptr);
return;
}
- for (p = Config.peers; p; p = p->next)
- ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
+ for (const auto &p: CurrentCachePeers())
+ ipcache_nbgethostbyname(p->host, peerDNSConfigure, p.get());
/* Reconfigure the peers every hour */
eventAddIsh("peerRefreshDNS", peerRefreshDNS, nullptr, 3600.0, 1);
}
static void
-dump_peers(StoreEntry * sentry, CachePeer * peers)
+dump_peers(StoreEntry *sentry, CachePeers *peers)
{
char ntoabuf[MAX_IPSTRLEN];
int i;
if (peers == nullptr)
storeAppendPrintf(sentry, "There are no neighbors installed.\n");
- for (CachePeer *e = peers; e; e = e->next) {
+ for (const auto &peer: *peers) {
+ const auto e = peer.get();
assert(e->host != nullptr);
storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
neighborTypeStr(e),
void
neighborsHtcpClear(StoreEntry * e, HttpRequest * req, const HttpRequestMethod &method, htcp_clr_reason reason)
{
- CachePeer *p;
char buf[128];
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!p->options.htcp) {
continue;
}
continue;
}
debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.toUrl(buf, 128));
- htcpClear(e, req, method, p, reason);
+ htcpClear(e, req, method, p.get(), reason);
}
}
class StoreEntry;
class PeerSelector;
-CachePeer *getFirstPeer(void);
CachePeer *getFirstUpParent(PeerSelector *);
-CachePeer *getNextPeer(CachePeer *);
CachePeer *getSingleParent(PeerSelector *);
int neighborsCount(PeerSelector *);
int neighborsUdpPing(HttpRequest *,
#include "base/InstanceId.h"
#include "base/TypeTraits.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "carp.h"
#include "client_side.h"
#include "dns/LookupDetails.h"
void
PeerSelector::selectAllParents()
{
- CachePeer *p;
/* Add all alive parents */
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
/* XXX: neighbors.c lacks a public interface for enumerating
* parents to a request so we have to dig some here..
*/
* simply are not configured to handle the request.
*/
/* Add default parent as a last resort */
- if ((p = getDefaultParent(this))) {
+ if (const auto p = getDefaultParent(this)) {
addSelection(p, DEFAULT_PARENT);
}
}
#include "squid.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "HttpRequest.h"
#include "mgr/Registration.h"
#include "neighbors.h"
int K;
int k;
double P_last, X_last, Xn;
- CachePeer *p;
- CachePeer **P;
char *t;
/* Clean up */
n_sourcehash_peers = 0;
/* find out which peers we have */
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!p->options.sourcehash)
continue;
sourcehash_peers = (CachePeer **)xcalloc(n_sourcehash_peers, sizeof(*sourcehash_peers));
+ auto P = sourcehash_peers;
/* Build a list of the found peers and calculate hashes and load factors */
- for (P = sourcehash_peers, p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
+
if (!p->options.sourcehash)
continue;
for (k = 1; k <= K; ++k) {
double Kk1 = (double) (K - k + 1);
- p = sourcehash_peers[k - 1];
+ const auto p = sourcehash_peers[k - 1];
p->sourcehash.load_multiplier = (Kk1 * (p->sourcehash.load_factor - P_last)) / Xn;
p->sourcehash.load_multiplier += pow(X_last, Kk1);
p->sourcehash.load_multiplier = pow(p->sourcehash.load_multiplier, 1.0 / Kk1);
static void
peerSourceHashCachemgr(StoreEntry * sentry)
{
- CachePeer *p;
int sumfetches = 0;
storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n",
"Hostname",
"Factor",
"Actual");
- for (p = Config.peers; p; p = p->next)
+ for (const auto &p: CurrentCachePeers())
sumfetches += p->stats.fetches;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
p->name, p->sourcehash.hash,
p->sourcehash.load_multiplier,
#include "auth/UserRequest.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "globals.h"
#include "HttpRequest.h"
#include "mgr/Registration.h"
int K;
int k;
double P_last, X_last, Xn;
- CachePeer *p;
- CachePeer **P;
char *t;
/* Clean up */
peerUserHashRegisterWithCacheManager();
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
if (!p->options.userhash)
continue;
userhash_peers = (CachePeer **)xcalloc(n_userhash_peers, sizeof(*userhash_peers));
+ auto P = userhash_peers;
/* Build a list of the found peers and calculate hashes and load factors */
- for (P = userhash_peers, p = Config.peers; p; p = p->next) {
+ for (const auto &peer: CurrentCachePeers()) {
+ const auto p = peer.get();
+
if (!p->options.userhash)
continue;
for (k = 1; k <= K; ++k) {
double Kk1 = (double) (K - k + 1);
- p = userhash_peers[k - 1];
+ const auto p = userhash_peers[k - 1];
p->userhash.load_multiplier = (Kk1 * (p->userhash.load_factor - P_last)) / Xn;
p->userhash.load_multiplier += pow(X_last, Kk1);
p->userhash.load_multiplier = pow(p->userhash.load_multiplier, 1.0 / Kk1);
static void
peerUserHashCachemgr(StoreEntry * sentry)
{
- CachePeer *p;
int sumfetches = 0;
storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n",
"Hostname",
"Factor",
"Actual");
- for (p = Config.peers; p; p = p->next)
+ for (const auto &p: CurrentCachePeers())
sumfetches += p->stats.fetches;
- for (p = Config.peers; p; p = p->next) {
+ for (const auto &p: CurrentCachePeers()) {
storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
p->name, p->userhash.hash,
p->userhash.load_multiplier,
#include "squid.h"
#include "cache_snmp.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "globals.h"
#include "mem/Meter.h"
#include "mem/Stats.h"
Ip::Address laddr;
char *cp = nullptr;
CachePeer *p = nullptr;
- int cnt = 0;
debugs(49, 5, "snmp_meshPtblFn: peer " << Var->name[LEN_SQ_MESH + 3] << " requested!");
*ErrP = SNMP_ERR_NOERROR;
u_int index = Var->name[LEN_SQ_MESH + 3] ;
- for (p = Config.peers; p != nullptr; p = p->next, ++cnt) {
- if (p->index == index) {
- laddr = p->in_addr ;
+ for (const auto &peer: CurrentCachePeers()) {
+ if (peer->index == index) {
+ laddr = peer->in_addr ;
+ p = peer.get();
break;
}
}
#include "base/AsyncCallbacks.h"
#include "base/CbcPointer.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "client_db.h"
#include "comm.h"
#include "comm/Connection.h"
#include "snmp_core.h"
#include "SnmpRequest.h"
#include "SquidConfig.h"
+#include "SquidMath.h"
#include "tools.h"
static void snmpPortOpened(Ipc::StartListeningAnswer&);
peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
{
oid *instance = nullptr;
- CachePeer *peers = Config.peers;
+ const auto peersAvailable = CurrentCachePeers().size();
- if (peers == nullptr) {
+ if (!peersAvailable) {
debugs(49, 6, "snmp peer_Inst: No Peers.");
current = current->parent->parent->parent->leaves[1];
while ((current) && (!current->parsefunction))
int no = name[current->len] ;
int i;
// Note: This works because the Config.peers keeps its index according to its position.
- for ( i=0 ; peers && (i < no) ; peers = peers->next, ++i ) ;
+ for (i = 0; Less(i, peersAvailable) && Less(i, no); ++i);
- if (peers) {
+ if (Less(i, peersAvailable)) {
debugs(49, 6, "snmp peer_Inst: Encode peer #" << i);
instance = (oid *)xmalloc(sizeof(*name) * (current->len + 1 ));
memcpy(instance, name, (sizeof(*name) * current->len ));
#include "AccessLogEntry.h"
#include "CacheDigest.h"
#include "CachePeer.h"
+#include "CachePeers.h"
#include "client_side.h"
#include "client_side_request.h"
#include "comm/Connection.h"
{
#if USE_CACHE_DIGESTS
StatCounters *f = &statCounter;
- CachePeer *peer;
const int tot_used = f->cd.times_used + f->icp.times_used;
/* totals */
/* per-peer */
storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
- for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
+ for (const auto &peer: CurrentCachePeers()) {
if (peer->digest)
peerDigestStatsReport(peer->digest, sentry);
else