#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/// CARP cache_peers ordered by their CARP weight
-static SelectedCachePeers TheCarpPeers;
+static auto &
+CarpPeers()
+{
+ static const auto carpPeers = new SelectedCachePeers();
+ return *carpPeers;
+}
static OBJH carpCachemgr;
char *t;
/* Clean up */
- TheCarpPeers.clear();
+ CarpPeers().clear();
/* initialize cache manager before we have a chance to leave the execution path */
carpRegisterWithCacheManager();
P_last = p->carp.load_factor;
}
- TheCarpPeers.assign(rawCarpPeers.begin(), rawCarpPeers.end());
+ CarpPeers().assign(rawCarpPeers.begin(), rawCarpPeers.end());
}
CachePeer *
double score;
double high_score = 0;
- if (TheCarpPeers.empty())
+ if (CarpPeers().empty())
return nullptr;
/* calculate hash key */
debugs(39, 2, "carpSelectParent: Calculating hash for " << request->effectiveRequestUri());
/* select CachePeer */
- for (const auto &tp: TheCarpPeers) {
+ for (const auto &tp: CarpPeers()) {
if (!tp)
continue; // peer gone
"Factor",
"Actual");
- for (const auto &p: TheCarpPeers) {
+ for (const auto &p: CarpPeers()) {
if (!p)
continue;
sumfetches += p->stats.fetches;
}
- for (const auto &p: TheCarpPeers) {
+ for (const auto &p: CarpPeers()) {
if (!p)
continue;
storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-static int n_sourcehash_peers = 0;
-static CachePeer **sourcehash_peers = nullptr;
+/// sourcehash peers ordered by their sourcehash weight
+static auto &
+SourceHashPeers()
+{
+ static const auto hashPeers = new SelectedCachePeers();
+ return *hashPeers;
+}
+
static OBJH peerSourceHashCachemgr;
static void peerSourceHashRegisterWithCacheManager(void);
peerSourceHashInit(void)
{
int W = 0;
- int K;
- int k;
double P_last, X_last, Xn;
char *t;
/* Clean up */
- for (k = 0; k < n_sourcehash_peers; ++k) {
- cbdataReferenceDone(sourcehash_peers[k]);
- }
-
- safe_free(sourcehash_peers);
- n_sourcehash_peers = 0;
+ SourceHashPeers().clear();
/* find out which peers we have */
+ RawCachePeers rawSourceHashPeers;
for (const auto &p: CurrentCachePeers()) {
+ const auto peer = p.get();
+
if (!p->options.sourcehash)
continue;
if (p->weight == 0)
continue;
- ++n_sourcehash_peers;
+ rawSourceHashPeers.push_back(peer);
W += p->weight;
}
peerSourceHashRegisterWithCacheManager();
- if (n_sourcehash_peers == 0)
+ if (rawSourceHashPeers.empty())
return;
- 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 (const auto &peer: CurrentCachePeers()) {
- const auto p = peer.get();
-
- if (!p->options.sourcehash)
- continue;
-
- if (p->weight == 0)
- continue;
-
+ /* calculate hashes and load factors */
+ for (const auto &p: rawSourceHashPeers) {
/* calculate this peers hash */
p->sourcehash.hash = 0;
if (floor(p->sourcehash.load_factor * 1000.0) == 0.0)
p->sourcehash.load_factor = 0.0;
-
- /* add it to our list of peers */
- *P++ = cbdataReference(p);
}
/* Sort our list on weight */
- qsort(sourcehash_peers, n_sourcehash_peers, sizeof(*sourcehash_peers), peerSortWeight);
+ qsort(rawSourceHashPeers.data(), rawSourceHashPeers.size(), sizeof(decltype(rawSourceHashPeers)::value_type), peerSortWeight);
/* Calculate the load factor multipliers X_k
*
* X_k = pow (X_k, {1/(K-k+1)})
* simplified to have X_1 part of the loop
*/
- K = n_sourcehash_peers;
+ const auto K = rawSourceHashPeers.size();
P_last = 0.0; /* Empty P_0 */
X_last = 0.0; /* Empty X_0, nullifies the first pow statement */
- for (k = 1; k <= K; ++k) {
+ for (size_t k = 1; k <= K; ++k) {
double Kk1 = (double) (K - k + 1);
- const auto p = sourcehash_peers[k - 1];
+ const auto p = rawSourceHashPeers[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);
X_last = p->sourcehash.load_multiplier;
P_last = p->sourcehash.load_factor;
}
+
+ SourceHashPeers().assign(rawSourceHashPeers.begin(), rawSourceHashPeers.end());
}
static void
CachePeer *
peerSourceHashSelectParent(PeerSelector *ps)
{
- int k;
const char *c;
CachePeer *p = nullptr;
- CachePeer *tp;
unsigned int user_hash = 0;
unsigned int combined_hash;
double score;
const char *key = nullptr;
char ntoabuf[MAX_IPSTRLEN];
- if (n_sourcehash_peers == 0)
+ if (SourceHashPeers().empty())
return nullptr;
assert(ps);
user_hash += ROTATE_LEFT(user_hash, 19) + *c;
/* select CachePeer */
- for (k = 0; k < n_sourcehash_peers; ++k) {
- tp = sourcehash_peers[k];
+ for (const auto &tp: SourceHashPeers()) {
+ if (!tp)
+ continue; // peer gone
+
combined_hash = (user_hash ^ tp->sourcehash.hash);
combined_hash += combined_hash * 0x62531965;
combined_hash = ROTATE_LEFT(combined_hash, 21);
debugs(39, 3, *tp << " combined_hash " << combined_hash <<
" score " << std::setprecision(0) << score);
- if ((score > high_score) && peerHTTPOkay(tp, ps)) {
- p = tp;
+ if ((score > high_score) && peerHTTPOkay(tp.get(), ps)) {
+ p = tp.get();
high_score = score;
}
}
"Factor",
"Actual");
- for (const auto &p: CurrentCachePeers())
+ for (const auto &p: SourceHashPeers()) {
+ if (!p)
+ continue;
sumfetches += p->stats.fetches;
+ }
- for (const auto &p: CurrentCachePeers()) {
+ for (const auto &p: SourceHashPeers()) {
+ if (!p)
+ continue;
storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
p->name, p->sourcehash.hash,
p->sourcehash.load_multiplier,