24#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
42 return (*p1)->
weight - (*p2)->weight;
49 double P_last, X_last, Xn;
58 const auto peer = p.get();
60 if (!p->options.sourcehash)
68 rawSourceHashPeers.push_back(peer);
75 if (rawSourceHashPeers.empty())
79 for (
const auto &p: rawSourceHashPeers) {
81 p->sourcehash.hash = 0;
83 for (t = p->name; *t != 0; ++t)
84 p->sourcehash.hash +=
ROTATE_LEFT(p->sourcehash.hash, 19) + (
unsigned int) *t;
86 p->sourcehash.hash += p->sourcehash.hash * 0x62531965;
88 p->sourcehash.hash =
ROTATE_LEFT(p->sourcehash.hash, 21);
91 p->sourcehash.load_factor = ((
double) p->weight) / (
double) W;
93 if (floor(p->sourcehash.load_factor * 1000.0) == 0.0)
94 p->sourcehash.load_factor = 0.0;
98 qsort(rawSourceHashPeers.data(), rawSourceHashPeers.size(),
sizeof(
decltype(rawSourceHashPeers)::value_type),
peerSortWeight);
108 const auto K = rawSourceHashPeers.size();
116 for (
size_t k = 1; k <= K; ++k) {
117 double Kk1 = (
double) (K - k + 1);
118 const auto p = rawSourceHashPeers[k - 1];
119 p->sourcehash.load_multiplier = (Kk1 * (p->sourcehash.load_factor - P_last)) / Xn;
120 p->sourcehash.load_multiplier += pow(X_last, Kk1);
121 p->sourcehash.load_multiplier = pow(p->sourcehash.load_multiplier, 1.0 / Kk1);
122 Xn *= p->sourcehash.load_multiplier;
123 X_last = p->sourcehash.load_multiplier;
124 P_last = p->sourcehash.load_factor;
127 SourceHashPeers().assign(rawSourceHashPeers.begin(), rawSourceHashPeers.end());
142 unsigned int user_hash = 0;
143 unsigned int combined_hash;
145 double high_score = 0;
146 const char *key =
nullptr;
158 debugs(39, 2,
"peerSourceHashSelectParent: Calculating hash for " << key);
160 for (c = key; *c != 0; ++c)
168 combined_hash = (user_hash ^ tp->sourcehash.hash);
169 combined_hash += combined_hash * 0x62531965;
171 score = combined_hash * tp->sourcehash.load_multiplier;
172 debugs(39, 3, *tp <<
" combined_hash " << combined_hash <<
173 " score " << std::setprecision(0) << score);
175 if ((score > high_score) &&
peerHTTPOkay(tp.get(), ps)) {
182 debugs(39, 2,
"selected " << *p);
201 sumfetches += p->stats.fetches;
208 p->name, p->sourcehash.hash,
209 p->sourcehash.load_multiplier,
210 p->sourcehash.load_factor,
211 sumfetches ? (
double) p->stats.fetches / sumfetches : -1.0);
const CachePeers & CurrentCachePeers()
std::vector< CachePeer *, PoolingAllocator< CachePeer * > > RawCachePeers
Temporary, local storage of raw pointers to zero or more Config.peers.
std::vector< CbcPointer< CachePeer >, PoolingAllocator< CbcPointer< CachePeer > > > SelectedCachePeers
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
#define debugs(SECTION, LEVEL, CONTENT)
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
int peerHTTPOkay(const CachePeer *p, PeerSelector *ps)
static void peerSourceHashRegisterWithCacheManager(void)
static OBJH peerSourceHashCachemgr
void peerSourceHashInit(void)
static auto & SourceHashPeers()
sourcehash peers ordered by their sourcehash weight
#define ROTATE_LEFT(x, n)
CachePeer * peerSourceHashSelectParent(PeerSelector *ps)
static int peerSortWeight(const void *a, const void *b)
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)