From: wessels <> Date: Tue, 5 Dec 2000 17:10:57 +0000 (+0000) Subject: A number of CARP bug fixes. X-Git-Tag: SQUID_3_0_PRE1~1742 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8ee9b49;p=thirdparty%2Fsquid.git A number of CARP bug fixes. peer->carp.hash was an unsigned long, but the spec requires 32-bit math on integers. Since longs are known to sometimes be 64-bits, its safer to use unsigned int. peer->carp.load_factor was a float, but its better to use double to be consistent with other floating point functions and variables. In parse_peer() I'm concerned that *token could be signed, so its now casted to unsigned int. In parse_peer() there is a bug in calculating the proxy hostname hash. On the final ROTATE_LEFT, it should be "=" rather than "+=". In carpInit() pay special attention to int/double conversion bugs and passing ints to functions that expect doubles. In carpInit() there is a bug with the value of "k". In the loop, k needs to be incremented *before* its used. The internet-draft begins with k=1, so the first time through the loop k should equal 2. Added "carp" to cache manager for info and debugging. I think there are still two bugs: (1) the draft says the multipliers must be calculated in order of smallest to largest factor. We don't do that yet. (2) the 'score' calculation needs to be converted to double when we multiply by the multiplier. Otherwise there will be overflows since the multiplier can be greater than 1. --- diff --git a/src/cache_cf.cc b/src/cache_cf.cc index a59446588e..7a77bff1c5 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.359 2000/12/05 08:55:47 wessels Exp $ + * $Id: cache_cf.cc,v 1.360 2000/12/05 10:10:57 wessels Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -1106,14 +1106,14 @@ parse_peer(peer ** head) p->tcp_up = PEER_TCP_MAGIC_COUNT; p->test_fd = -1; #if USE_CARP -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> ((sizeof(u_long)*8)-(n)))) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) if (p->carp.load_factor) { /* calculate this peers hash for use in CARP */ p->carp.hash = 0; for (token = p->host; *token != 0; token++) - p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + *token; + p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + (unsigned int) *token; p->carp.hash += p->carp.hash * 0x62531965; - p->carp.hash += ROTATE_LEFT(p->carp.hash, 21); + p->carp.hash = ROTATE_LEFT(p->carp.hash, 21); } #endif /* This must preceed peerDigestCreate */ diff --git a/src/carp.cc b/src/carp.cc index 1771229eef..c0c0de61d4 100644 --- a/src/carp.cc +++ b/src/carp.cc @@ -1,6 +1,6 @@ /* - * $Id: carp.cc,v 1.13 2000/10/20 23:50:59 hno Exp $ + * $Id: carp.cc,v 1.14 2000/12/05 10:10:57 wessels Exp $ * * DEBUG: section 39 Cache Array Routing Protocol * AUTHOR: Eric Stern @@ -37,15 +37,18 @@ #if USE_CARP +static OBJH carpCachemgr; + void carpInit(void) { /* calculate load factors */ int K = 0; - float a = 0.0; - float Xn; - float P_last; - float X_last; + double a = 0.0; + double dJ; + double Xn; + double P_last; + double X_last; int k; peer *p; for (p = Config.peers; p; p = p->next) { @@ -54,7 +57,7 @@ carpInit(void) } if (a == 0.0) { for (p = Config.peers; p; p = p->next) - p->carp.load_multiplier = 1; + p->carp.load_multiplier = 1.0; return; } /* @@ -66,21 +69,23 @@ carpInit(void) k = 1; P_last = 0; p = Config.peers; - p->carp.load_multiplier = pow(K * p->carp.load_factor, 1 / K); + p->carp.load_multiplier = pow(p->carp.load_factor * K, 1.0 / K); Xn = p->carp.load_multiplier; P_last = p->carp.load_factor; X_last = p->carp.load_multiplier; if (!p->next) return; for (p = p->next; p; p = p->next) { - p->carp.load_multiplier = ((K - k + 1) * (p->carp.load_factor - P_last)) / Xn; - p->carp.load_multiplier += pow(X_last, K - k + 1); - p->carp.load_multiplier = pow(p->carp.load_multiplier, 1 / (K - k + 1)); + k++; + dJ = (double) (K - k + 1); + p->carp.load_multiplier = (dJ * (p->carp.load_factor - P_last)) / Xn; + p->carp.load_multiplier += pow(X_last, dJ); + p->carp.load_multiplier = pow(p->carp.load_multiplier, 1 / dJ); Xn *= p->carp.load_multiplier; X_last = p->carp.load_multiplier; - k++; P_last = p->carp.load_factor; } + cachemgrRegister("carp", "CARP information", carpCachemgr, 0, 1); } peer * @@ -120,4 +125,28 @@ carpSelectParent(request_t * request) debug(39, 3) ("carpSelectParent: selected CARP %s\n", p->host); return p; } + +static void +carpCachemgr(StoreEntry * sentry) +{ + peer *p; + int sumfetches = 0; + storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n", + "Hostname", + "Hash", + "Multiplier", + "Factor", + "Actual"); + for (p = Config.peers; p; p = p->next) + sumfetches += p->stats.fetches; + for (p = Config.peers; p; p = p->next) { + storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n", + p->host, p->carp.hash, + p->carp.load_multiplier, + p->carp.load_factor, + sumfetches ? (double) p->stats.fetches / sumfetches : -1.0); + } + +} + #endif diff --git a/src/structs.h b/src/structs.h index 48285050d0..05b8fe4165 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.363 2000/12/05 09:16:00 wessels Exp $ + * $Id: structs.h,v 1.364 2000/12/05 10:10:59 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1103,8 +1103,8 @@ struct _peer { int test_fd; #if USE_CARP struct { - unsigned long hash; - unsigned long load_multiplier; + unsigned int hash; + double load_multiplier; float load_factor; } carp; #endif