--------------------- PatchSet 2245 Date: 2001/05/08 10:00:00 Author: hno Branch: rproxy-peergroup Tag: (none) Log: Use peer groups to divide the hash calculation for the peers Members: src/peer_userhash.c:1.1.2.7->1.1.2.7.2.1 Index: squid/src/peer_userhash.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/peer_userhash.c,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.7.2.1 diff -u -r1.1.2.7 -r1.1.2.7.2.1 --- squid/src/peer_userhash.c 8 May 2001 09:45:38 -0000 1.1.2.7 +++ squid/src/peer_userhash.c 8 May 2001 10:00:00 -0000 1.1.2.7.2.1 @@ -1,6 +1,6 @@ /* - * $Id: peer_userhash.c,v 1.1.2.7 2001/05/08 09:45:38 hno Exp $ + * $Id: peer_userhash.c,v 1.1.2.7.2.1 2001/05/08 10:00:00 hno Exp $ * * DEBUG: section 44 Peer user hash based selection * AUTHOR: Henrik Nordstrom @@ -38,32 +38,79 @@ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (((sizeof(unsigned long)*8)-(n))))) -static int n_userhash_peers = 0; -static peer **userhash_peers = NULL; +struct userhash_group { + struct userhash_group *next; + char *name; + int n_peers; + peer **peers; +}; -static int -peerSortWeight(const void *a, const void *b) +static struct userhash_group *peer_groups; + +static void +freeUserhashGroups(void) { - const peer *p1 = a, *p2 = b; - return p1->weight - p2->weight; + int k; + while (peer_groups) { + struct userhash_group *g = peer_groups; + peer_groups = g->next; + for (k = 0; k < g->n_peers; k++) { + cbdataUnlock(g->peers[k]); + } + safe_free(g->name); + safe_free(g->peers); + safe_free(g); + } +} + +struct userhash_group * +findUserhashGroup(char *name) +{ + struct userhash_group *g; + for (g = peer_groups; g; g = g->next) { + if (strcmp(g->name, name) == 0) + return g; + } + return NULL; +} +void +addUserhashPeer(peer *p) +{ + char *group = p->group ? p->group : "-"; + struct userhash_group *g; + int n; + + g = findUserhashGroup(group); + if (!g) { + g = xcalloc(1, sizeof(*g)); + g->name = xstrdup(group); + g->next = peer_groups; + peer_groups = g; + } + g->n_peers++; + g->peers = xrealloc(g->peers, sizeof(*g->peers)*g->n_peers); + for (n = g->n_peers - 1; n > 0; n--) { + if (g->peers[n-1]->weight >= p->weight) + break; + } + if (n < g->n_peers - 1) { + memmove(&g->peers[n+1], &g->peers[n], sizeof(*g->peers)*(g->n_peers - n - 1)); + } + g->peers[n] = p; + cbdataLock(p); } void peerUserHashInit(void) { - int W = 0; int K; int k; double P_last, X_last, Xn; peer *p; - peer **P; char *t; + struct userhash_group *g; /* Clean up */ - for (k = 0; k < n_userhash_peers; k++) { - cbdataUnlock(userhash_peers[k]); - } - safe_free(userhash_peers); - n_userhash_peers = 0; + freeUserhashGroups(); /* find out which peers we have */ for (p = Config.peers; p; p = p->next) { if (!p->options.userhash) @@ -71,55 +118,52 @@ assert(p->type == PEER_PARENT); if (p->weight == 0) continue; - n_userhash_peers++; - W += p->weight; + addUserhashPeer(p); } - if (n_userhash_peers == 0) + if (!peer_groups) return; - userhash_peers = xcalloc(n_userhash_peers, sizeof(*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) { - if (!p->options.userhash) - continue; - if (p->weight == 0) - continue; - /* calculate this peers hash */ - p->userhash.hash = 0; - for (t = p->host; *t != 0; t++) - p->userhash.hash += ROTATE_LEFT(p->userhash.hash, 19) + (unsigned int) *t; - p->userhash.hash += p->userhash.hash * 0x62531965; - p->userhash.hash = ROTATE_LEFT(p->userhash.hash, 21); - /* and load factor */ - p->userhash.load_factor = ((double) p->weight) / (double) W; - if (floor(p->userhash.load_factor * 1000.0) == 0.0) - p->userhash.load_factor = 0.0; - /* add it to our list of peers */ - *P++ = p; - cbdataLock(p); - } - /* Sort our list on weight */ - qsort(userhash_peers, n_userhash_peers, sizeof(*userhash_peers), peerSortWeight); - /* Calculate the load factor multipliers X_k - * - * X_1 = pow ((K*p_1), (1/K)) - * X_k = ([K-k+1] * [P_k - P_{k-1}])/(X_1 * X_2 * ... * X_{k-1}) - * X_k += pow ((X_{k-1}, {K-k+1}) - * X_k = pow (X_k, {1/(K-k+1)}) - * simplified to have X_1 part of the loop - */ - K = n_userhash_peers; - P_last = 0.0; /* Empty P_0 */ - Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */ - X_last = 0.0; /* Empty X_0, nullifies the first pow statement */ - for (k = 1; k <= K; k++) { - double Kk1 = (double) (K - k + 1); - 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); - Xn *= p->userhash.load_multiplier; - X_last = p->userhash.load_multiplier; - P_last = p->userhash.load_factor; + /* Calculate hashes and load factors */ + for (g = peer_groups; g; g = g->next) { + int W = 0; + /* Sum the weight of all peers */ + for (k = 0; k < g->n_peers; k++) { + W += g->peers[k]->weight; + } + for (k = 0; k < g->n_peers; k++) { + p = g->peers[k]; + /* calculate this peers hash */ + p->userhash.hash = 0; + for (t = p->host; *t != 0; t++) + p->userhash.hash += ROTATE_LEFT(p->userhash.hash, 19) + (unsigned int) *t; + p->userhash.hash += p->userhash.hash * 0x62531965; + p->userhash.hash = ROTATE_LEFT(p->userhash.hash, 21); + /* and load factor */ + p->userhash.load_factor = ((double) p->weight) / (double) W; + if (floor(p->userhash.load_factor * 1000.0) == 0.0) + p->userhash.load_factor = 0.0; + } + /* Calculate the load factor multipliers X_k + * + * X_1 = pow ((K*p_1), (1/K)) + * X_k = ([K-k+1] * [P_k - P_{k-1}])/(X_1 * X_2 * ... * X_{k-1}) + * X_k += pow ((X_{k-1}, {K-k+1}) + * X_k = pow (X_k, {1/(K-k+1)}) + * simplified to have X_1 part of the loop + */ + K = g->n_peers; + P_last = 0.0; /* Empty P_0 */ + Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */ + X_last = 0.0; /* Empty X_0, nullifies the first pow statement */ + for (k = 1; k <= K; k++) { + double Kk1 = (double) (K - k + 1); + p = g->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); + Xn *= p->userhash.load_multiplier; + X_last = p->userhash.load_multiplier; + P_last = p->userhash.load_factor; + } } } @@ -130,10 +174,13 @@ const char *c; peer *p = NULL; peer *tp; + struct userhash_group *g = findUserhashGroup(request->peer_group ? request->peer_group->name : "-"); unsigned long user_hash = 0; unsigned long combined_hash; unsigned long high_score = 0; const char *user = NULL; + if (!g) + return NULL; /* no peers to select between */ /* Find the username */ if (request->auth_user_request) { user = authenticateUserRequestUsername(request->auth_user_request); @@ -144,16 +191,16 @@ debug(39, 2) ("carpSelectParent: userhash Calculating hash for %s\n", user); for (c = user; *c != 0; c++) user_hash += ROTATE_LEFT(user_hash, 19) + *c; - /* select peer */ - for (k = 0; k < n_userhash_peers; k++) { - tp = userhash_peers[k]; + /* select the peer with highest score */ + for (k = 0; k < g->n_peers; k++) { + tp = g->peers[k]; combined_hash = (user_hash ^ tp->userhash.hash); combined_hash += combined_hash * 0x62531965; combined_hash = ROTATE_LEFT(combined_hash, 21); combined_hash = combined_hash * tp->userhash.load_multiplier; debug(39, 3) ("carpSelectParent: %s combined_hash %d\n", tp->host, combined_hash); - if ((combined_hash > high_score) && peerHTTPOkay(tp, request)) { + if ((combined_hash > high_score) && peerHTTPOkay(tp, reqest)) { p = tp; high_score = combined_hash; }