This is a forward port of the sourcehash and userhash peering
algorithms.
These are effectively just copies of carp.cc with the request key
changed accordingly.
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
# jhqo27vfnrb0080u
# target_branch: file:///data/bzr/squid3/trunk/
# testament_sha1: c3b574b953b0e22d77a8a35b435b908e1b1ac646
# timestamp: 2008-07-11 22:44:44 +0200
# base_revision_id: [EMAIL PROTECTED]
# 0lhqbyg4izx30e4b
#
# Begin patch
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2008-07-04 12:09:33 +0000
+++ src/Makefile.am 2008-07-11 20:43:43 +0000
@@ -593,6 +593,8 @@
PeerDigest.h \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
PeerSelectState.h \
PingData.h \
protos.h \
@@ -890,6 +892,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
protos.h \
redirect.cc \
referer.cc \
@@ -1435,6 +1439,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
redirect.cc \
referer.cc \
refresh.cc \
@@ -1606,6 +1612,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
redirect.cc \
referer.cc \
refresh.cc \
@@ -1762,6 +1770,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
redirect.cc \
referer.cc \
refresh.cc \
@@ -1907,6 +1917,8 @@
Parsing.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
pconn.cc \
redirect.cc \
referer.cc \
@@ -2068,6 +2080,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
redirect.cc \
referer.cc \
refresh.cc \
@@ -2430,6 +2444,8 @@
pconn.cc \
peer_digest.cc \
peer_select.cc \
+ peer_sourcehash.cc \
+ peer_userhash.cc \
redirect.cc \
referer.cc \
refresh.cc \
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2008-07-11 19:32:10 +0000
+++ src/cache_cf.cc 2008-07-11 20:20:31 +0000
@@ -1740,6 +1740,18 @@
p->options.carp = 1;
+ } else if (!strcasecmp(token, "userhash")) {
+ if (p->type != PEER_PARENT)
+ fatalf("parse_peer: non-parent userhash peer %s/%d\n", p->host, p->http_port);
+
+ p->options.userhash = 1;
+
+ } else if (!strcasecmp(token, "sourcehash")) {
+ if (p->type != PEER_PARENT)
+ fatalf("parse_peer: non-parent sourcehash peer %s/%d\n", p->host, p->http_port);
+
+ p->options.sourcehash = 1;
+
#if DELAY_POOLS
} else if (!strcasecmp(token, "no-delay")) {
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2008-06-30 16:27:12 +0000
+++ src/cf.data.pre 2008-07-11 20:20:31 +0000
@@ -1571,6 +1571,8 @@
round-robin
weighted-round-robin
carp
+ userhash
+ sourcehash
multicast-responder
closest-only
no-digest
@@ -1645,6 +1647,12 @@
distributed among the parents based on the CARP load
balancing hash function based on their weight.
+ use 'userhash' to load-balance amongst a set of parents
+ based on the client proxy_auth or ident username.
+
+ use 'sourcehash' to load-balance amongst a set of parents
+ based on the client source ip.
+
'multicast-responder' indicates the named peer
is a member of a multicast group. ICP queries will
not be sent directly to the peer, but ICP replies
=== modified file 'src/enums.h'
--- src/enums.h 2008-07-11 19:32:10 +0000
+++ src/enums.h 2008-07-11 20:43:43 +0000
@@ -175,6 +175,8 @@
#endif
CARP,
ANY_OLD_PARENT,
+ USERHASH_PARENT,
+ SOURCEHASH_PARENT,
HIER_MAX
} hier_code;
=== modified file 'src/main.cc'
--- src/main.cc 2008-07-11 20:14:45 +0000
+++ src/main.cc 2008-07-11 20:20:31 +0000
@@ -628,6 +628,8 @@
peerSelectInit();
carpInit();
+ peerUserHashInit();
+ peerSourceHashInit();
}
void
@@ -969,6 +971,8 @@
asnRegisterWithCacheManager(manager);
authenticateRegisterWithCacheManager(&Config.authConfiguration, manager);
carpRegisterWithCacheManager(manager);
+ peerUserHashRegisterWithCacheManager(manager);
+ peerSourceHashRegisterWithCacheManager(manager);
cbdataRegisterWithCacheManager(manager);
/* These use separate calls so that the comm loops can eventually
* coexist.
=== modified file 'src/neighbors.cc'
--- src/neighbors.cc 2008-06-12 12:49:29 +0000
+++ src/neighbors.cc 2008-07-11 20:20:31 +0000
@@ -1538,6 +1538,15 @@
if (p->options.roundrobin)
storeAppendPrintf(sentry, " round-robin");
+ if (p->options.carp)
+ storeAppendPrintf(sentry, " carp");
+
+ if (p->options.userhash)
+ storeAppendPrintf(sentry, " userhash");
+
+ if (p->options.userhash)
+ storeAppendPrintf(sentry, " sourcehash");
+
if (p->options.weighted_roundrobin)
storeAppendPrintf(sentry, " weighted-round-robin");
=== modified file 'src/peer_select.cc'
--- src/peer_select.cc 2008-07-11 19:32:10 +0000
+++ src/peer_select.cc 2008-07-11 20:43:43 +0000
@@ -65,6 +65,8 @@
#endif
"CARP",
"ANY_PARENT",
+ "USERHASH",
+ "SOURCEHASH",
"INVALID CODE"
};
@@ -503,6 +505,10 @@
if ((p = getDefaultParent(request))) {
code = DEFAULT_PARENT;
+ } else if ((p = peerUserHashSelectParent(request))) {
+ code = USERHASH_PARENT;
+ } else if ((p = peerSourceHashSelectParent(request))) {
+ code = SOURCEHASH_PARENT;
} else if ((p = carpSelectParent(request))) {
code = CARP;
} else if ((p = getRoundRobinParent(request))) {
=== added file 'src/peer_sourcehash.cc'
--- src/peer_sourcehash.cc 1970-01-01 00:00:00 +0000
+++ src/peer_sourcehash.cc 2008-07-11 20:43:43 +0000
@@ -0,0 +1,229 @@
+
+/*
+ * $Id: carp.cc,v 1.27 2008/01/14 12:13:49 hno Exp $
+ *
+ * DEBUG: section 39 Peer source hash based selection
+ * AUTHOR: Henrik Nordstrom
+ * BASED ON: carp.cc
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "CacheManager.h"
+#include "Store.h"
+#include "HttpRequest.h"
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+static int n_sourcehash_peers = 0;
+static peer **sourcehash_peers = NULL;
+static OBJH peerSourceHashCachemgr;
+
+static int
+peerSortWeight(const void *a, const void *b)
+{
+ const peer *const *p1 = (const peer *const *)a;
+ const peer *const *p2 = (const peer *const *)b;
+ return (*p1)->weight - (*p2)->weight;
+}
+
+void
+peerSourceHashInit(void)
+{
+ int W = 0;
+ int K;
+ int k;
+ double P_last, X_last, Xn;
+ peer *p;
+ peer **P;
+ char *t;
+ /* Clean up */
+
+ for (k = 0; k < n_sourcehash_peers; k++) {
+ cbdataReferenceDone(sourcehash_peers[k]);
+ }
+
+ safe_free(sourcehash_peers);
+ n_sourcehash_peers = 0;
+ /* find out which peers we have */
+
+ for (p = Config.peers; p; p = p->next) {
+ if (!p->options.sourcehash)
+ continue;
+
+ assert(p->type == PEER_PARENT);
+
+ if (p->weight == 0)
+ continue;
+
+ n_sourcehash_peers++;
+
+ W += p->weight;
+ }
+
+ if (n_sourcehash_peers == 0)
+ return;
+
+ sourcehash_peers = (peer **)xcalloc(n_sourcehash_peers, sizeof(*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) {
+ if (!p->options.sourcehash)
+ continue;
+
+ if (p->weight == 0)
+ continue;
+
+ /* calculate this peers hash */
+ p->sourcehash.hash = 0;
+
+ for (t = p->name; *t != 0; t++)
+ p->sourcehash.hash += ROTATE_LEFT(p->sourcehash.hash, 19) + (unsigned int) *t;
+
+ p->sourcehash.hash += p->sourcehash.hash * 0x62531965;
+
+ p->sourcehash.hash = ROTATE_LEFT(p->sourcehash.hash, 21);
+
+ /* and load factor */
+ p->sourcehash.load_factor = ((double) p->weight) / (double) W;
+
+ 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);
+
+ /* 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_sourcehash_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 = 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);
+ Xn *= p->sourcehash.load_multiplier;
+ X_last = p->sourcehash.load_multiplier;
+ P_last = p->sourcehash.load_factor;
+ }
+}
+
+void
+peerSourceHashRegisterWithCacheManager(CacheManager & manager)
+{
+ manager.registerAction("sourcehash", "peer sourcehash information", peerSourceHashCachemgr, 0, 1);
+}
+
+peer *
+peerSourceHashSelectParent(HttpRequest * request)
+{
+ int k;
+ const char *c;
+ peer *p = NULL;
+ peer *tp;
+ unsigned int user_hash = 0;
+ unsigned int combined_hash;
+ double score;
+ double high_score = 0;
+ const char *key = NULL;
+ char ntoabuf[MAX_IPSTRLEN];
+
+ if (n_sourcehash_peers == 0)
+ return NULL;
+
+ key = request->client_addr.NtoA(ntoabuf, sizeof(ntoabuf));
+
+ /* calculate hash key */
+ debugs(39, 2, "peerSourceHashSelectParent: Calculating hash for " << key);
+
+ for (c = key; *c != 0; c++)
+ user_hash += ROTATE_LEFT(user_hash, 19) + *c;
+
+ /* select peer */
+ for (k = 0; k < n_sourcehash_peers; k++) {
+ tp = sourcehash_peers[k];
+ combined_hash = (user_hash ^ tp->sourcehash.hash);
+ combined_hash += combined_hash * 0x62531965;
+ combined_hash = ROTATE_LEFT(combined_hash, 21);
+ score = combined_hash * tp->sourcehash.load_multiplier;
+ debugs(39, 3, "peerSourceHashSelectParent: " << tp->name << " combined_hash " << combined_hash <<
+ " score " << std::setprecision(0) << score);
+
+ if ((score > high_score) && peerHTTPOkay(tp, request)) {
+ p = tp;
+ high_score = score;
+ }
+ }
+
+ if (p)
+ debugs(39, 2, "peerSourceHashSelectParent: selected " << p->name);
+
+ return p;
+}
+
+static void
+peerSourceHashCachemgr(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->name, p->sourcehash.hash,
+ p->sourcehash.load_multiplier,
+ p->sourcehash.load_factor,
+ sumfetches ? (double) p->stats.fetches / sumfetches : -1.0);
+ }
+}
=== added file 'src/peer_userhash.cc'
--- src/peer_userhash.cc 1970-01-01 00:00:00 +0000
+++ src/peer_userhash.cc 2008-07-11 20:43:43 +0000
@@ -0,0 +1,233 @@
+
+/*
+ * $Id: carp.cc,v 1.27 2008/01/14 12:13:49 hno Exp $
+ *
+ * DEBUG: section 39 Peer user hash based selection
+ * AUTHOR: Henrik Nordstrom
+ * BASED ON: carp.cc
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "CacheManager.h"
+#include "Store.h"
+#include "HttpRequest.h"
+#include "AuthUserRequest.h"
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+static int n_userhash_peers = 0;
+static peer **userhash_peers = NULL;
+static OBJH peerUserHashCachemgr;
+
+static int
+peerSortWeight(const void *a, const void *b)
+{
+ const peer *const *p1 = (const peer *const *)a;
+ const peer *const *p2 = (const peer *const *)b;
+ return (*p1)->weight - (*p2)->weight;
+}
+
+void
+peerUserHashInit(void)
+{
+ int W = 0;
+ int K;
+ int k;
+ double P_last, X_last, Xn;
+ peer *p;
+ peer **P;
+ char *t;
+ /* Clean up */
+
+ for (k = 0; k < n_userhash_peers; k++) {
+ cbdataReferenceDone(userhash_peers[k]);
+ }
+
+ safe_free(userhash_peers);
+ n_userhash_peers = 0;
+ /* find out which peers we have */
+
+ for (p = Config.peers; p; p = p->next) {
+ if (!p->options.userhash)
+ continue;
+
+ assert(p->type == PEER_PARENT);
+
+ if (p->weight == 0)
+ continue;
+
+ n_userhash_peers++;
+
+ W += p->weight;
+ }
+
+ if (n_userhash_peers == 0)
+ return;
+
+ userhash_peers = (peer **)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->name; *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++ = cbdataReference(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;
+ }
+}
+
+void
+peerUserHashRegisterWithCacheManager(CacheManager & manager)
+{
+ manager.registerAction("userhash", "peer userhash information", peerUserHashCachemgr, 0, 1);
+}
+
+peer *
+peerUserHashSelectParent(HttpRequest * request)
+{
+ int k;
+ const char *c;
+ peer *p = NULL;
+ peer *tp;
+ unsigned int user_hash = 0;
+ unsigned int combined_hash;
+ double score;
+ double high_score = 0;
+ const char *key = NULL;
+
+ if (n_userhash_peers == 0)
+ return NULL;
+
+ if (request->auth_user_request)
+ key = request->auth_user_request->username();
+
+ if (!key)
+ return NULL;
+
+ /* calculate hash key */
+ debugs(39, 2, "peerUserHashSelectParent: Calculating hash for " << key);
+
+ for (c = key; *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];
+ combined_hash = (user_hash ^ tp->userhash.hash);
+ combined_hash += combined_hash * 0x62531965;
+ combined_hash = ROTATE_LEFT(combined_hash, 21);
+ score = combined_hash * tp->userhash.load_multiplier;
+ debugs(39, 3, "peerUserHashSelectParent: " << tp->name << " combined_hash " << combined_hash <<
+ " score " << std::setprecision(0) << score);
+
+ if ((score > high_score) && peerHTTPOkay(tp, request)) {
+ p = tp;
+ high_score = score;
+ }
+ }
+
+ if (p)
+ debugs(39, 2, "peerUserHashSelectParent: selected " << p->name);
+
+ return p;
+}
+
+static void
+peerUserHashCachemgr(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->name, p->userhash.hash,
+ p->userhash.load_multiplier,
+ p->userhash.load_factor,
+ sumfetches ? (double) p->stats.fetches / sumfetches : -1.0);
+ }
+}
=== modified file 'src/protos.h'
--- src/protos.h 2008-07-11 19:32:10 +0000
+++ src/protos.h 2008-07-11 20:26:11 +0000
@@ -729,9 +729,16 @@
SQUIDCEXTERN int internalHostnameIs(const char *);
SQUIDCEXTERN void carpInit(void);
-extern void carpRegisterWithCacheManager(CacheManager & manager);
+SQUIDCEXTERN void carpRegisterWithCacheManager(CacheManager & manager);
SQUIDCEXTERN peer *carpSelectParent(HttpRequest *);
+SQUIDCEXTERN void peerUserHashInit(void);
+SQUIDCEXTERN void peerUserHashRegisterWithCacheManager(CacheManager & manager);
+SQUIDCEXTERN peer * peerUserHashSelectParent(HttpRequest * request);
+
+SQUIDCEXTERN void peerSourceHashInit(void);
+SQUIDCEXTERN void peerSourceHashRegisterWithCacheManager(CacheManager & manager);
+SQUIDCEXTERN peer * peerSourceHashSelectParent(HttpRequest * request);
#if USE_LEAKFINDER
SQUIDCEXTERN void leakInit(void);
=== modified file 'src/structs.h'
--- src/structs.h 2008-07-11 19:32:10 +0000
+++ src/structs.h 2008-07-11 20:20:31 +0000
@@ -930,6 +930,8 @@
#endif
unsigned int allow_miss:1;
unsigned int carp:1;
+ unsigned int userhash:1;
+ unsigned int sourcehash:1;
unsigned int originserver:1;
} options;
@@ -972,6 +974,20 @@
double load_factor; /* normalized weight value */
} carp;
+ struct
+ {
+ unsigned int hash;
+ double load_multiplier;
+ double load_factor; /* normalized weight value */
+ } userhash;
+
+ struct
+ {
+ unsigned int hash;
+ double load_multiplier;
+ double load_factor; /* normalized weight value */
+ } sourcehash;
+
char *login; /* Proxy authorization */
time_t connect_timeout;
int max_conn;
# Begin bundle
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
YcMfMafna0086P/i7kinChIM9s5xYA==