=== modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2011-07-14 08:59:10 +0000 +++ src/cache_cf.cc 2011-07-30 18:08:42 +0000 @@ -2244,6 +2244,33 @@ fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port); p->options.carp = 1; + } else if (!strncasecmp(token, "carp-key=", strlen("carp-key="))) { + if (p->options.carp != 1) + fatalf("parse_peer: carp-key specified on non-carp peer %s/%d\n", p->host, p->http_port); + p->options.carp_key.set=1; + char *tmp=xstrdup(token+strlen("carp-key=")); + char *key,*nextkey; + for (key = nextkey = tmp; key; key=nextkey) { + nextkey=strchr(key,','); + if (nextkey) + *nextkey++='\0'; + if (!strcasecmp(key,"scheme")) { + p->options.carp_key.scheme=1; + } else if (!strcasecmp(key,"login")) { + p->options.carp_key.login=1; + } else if (!strcasecmp(key,"host")) { + p->options.carp_key.host=1; + } else if (!strcasecmp(key,"port")) { + p->options.carp_key.port=1; + } else if (!strcasecmp(key,"path")) { + p->options.carp_key.path=1; + } else if (!strcasecmp(key,"params")) { + p->options.carp_key.params=1; + } else { + fatalf("invalid carp key '%s'",key); + } + } + safe_free(tmp); } else if (!strcasecmp(token, "userhash")) { #if USE_AUTH if (p->type != PEER_PARENT) === modified file 'src/carp.cc' --- src/carp.cc 2010-10-28 18:52:59 +0000 +++ src/carp.cc 2011-07-30 19:15:00 +0000 @@ -35,8 +35,10 @@ */ #include "squid.h" +#include "HttpRequest.h" #include "mgr/Registration.h" #include "Store.h" +#include "URLScheme.h" #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) @@ -164,35 +166,74 @@ carpSelectParent(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_carp_peers == 0) return NULL; - key = urlCanonical(request); - /* calculate hash key */ - debugs(39, 2, "carpSelectParent: Calculating hash for " << key); - - for (c = key; *c != 0; c++) - user_hash += ROTATE_LEFT(user_hash, 19) + *c; + debugs(39, 2, "carpSelectParent: Calculating hash for " << urlCanonical(request)); /* select peer */ for (k = 0; k < n_carp_peers; k++) { + String key; tp = carp_peers[k]; + if (tp->options.carp_key.set) { + //this code follows urlCanonical's pattern. + // all cornercases default to urlCanonical + if (request->protocol == AnyP::PROTO_URN) { + key=urlCanonical(request); + } else if (request->method.id()==METHOD_CONNECT) { + key=urlCanonical(request); + } else { + if (tp->options.carp_key.scheme) { + // temporary, until bug 1961 URL handling is fixed. + const URLScheme sch = request->protocol; + key.append(sch.const_str()); + key.append("://"); + } + if (tp->options.carp_key.login) { + key.append(request->login); + key.append('@'); + } + if (tp->options.carp_key.host) { + key.append(request->GetHost()); + } + if (tp->options.carp_key.port) { + static char portbuf[7]; + snprintf(portbuf,7,":%d", request->port); + key.append(portbuf); + } + if (tp->options.carp_key.path) { + String::size_type pos; + if ((pos=request->urlpath.find('?'))!=String::npos) + key.append(request->urlpath.substr(0,pos)); + else + key.append(request->urlpath); + } + if (tp->options.carp_key.params) { + String::size_type pos; + if ((pos=request->urlpath.find('?'))!=String::npos) + key.append(request->urlpath.substr(pos,request->urlpath.size())); + } + + } + } else { + key=urlCanonical(request); + } + for (const char *c = key.rawBuf(), *e=key.rawBuf()+key.size(); c < e; c++) + user_hash += ROTATE_LEFT(user_hash, 19) + *c; combined_hash = (user_hash ^ tp->carp.hash); combined_hash += combined_hash * 0x62531965; combined_hash = ROTATE_LEFT(combined_hash, 21); score = combined_hash * tp->carp.load_multiplier; - debugs(39, 3, "carpSelectParent: " << tp->name << " combined_hash " << combined_hash << - " score " << std::setprecision(0) << score); + debugs(39, 3, "carpSelectParent: key=" << key << " name=" << tp->name << " combined_hash=" << combined_hash << + " score=" << std::setprecision(0) << score); if ((score > high_score) && peerHTTPOkay(tp, request)) { p = tp; === modified file 'src/cf.data.pre' --- src/cf.data.pre 2011-07-22 13:36:58 +0000 +++ src/cf.data.pre 2011-07-30 19:21:17 +0000 @@ -2178,6 +2178,14 @@ than the Squid default location. + ==== CARP OPTIONS ==== + + carp-key=key-specification + use a different key than the full URL to hash against the peer. + the key-specification is a comma-separated list of the keywords + scheme, login, host, port, path, params + Order is not important. + ==== ACCELERATOR / REVERSE-PROXY OPTIONS ==== originserver Causes this parent to be contacted as an origin server. === modified file 'src/structs.h' --- src/structs.h 2011-06-23 08:33:13 +0000 +++ src/structs.h 2011-07-30 18:08:45 +0000 @@ -855,6 +855,15 @@ #endif unsigned int allow_miss:1; unsigned int carp:1; + struct { + unsigned int set:1; //If false, whole url is to be used. Overrides others + unsigned int scheme:1; + unsigned int login:1; + unsigned int host:1; + unsigned int port:1; + unsigned int path:1; + unsigned int params:1; + } carp_key; #if USE_AUTH unsigned int userhash:1; #endif