]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: backend: add support for the wt6 hash
authorWilly Tarreau <w@1wt.eu>
Thu, 14 Nov 2013 13:30:35 +0000 (14:30 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 14 Nov 2013 15:37:50 +0000 (16:37 +0100)
This function was designed for haproxy while testing other functions
in the past. Initially it was not planned to be used given the not
very interesting numbers it showed on real URL data : it is not as
smooth as the other ones. But later tests showed that the other ones
are extremely sensible to the server count and the type of input data,
especially DJB2 which must not be used on numeric input. So in fact
this function is still a generally average performer and it can make
sense to merge it in the end, as it can provide an alternative to
sdbm+avalanche or djb2+avalanche for consistent hashing or when hashing
on numeric data such as a source IP address or a visitor identifier in
a URL parameter.

doc/configuration.txt
include/common/hash.h
include/types/backend.h
src/backend.c
src/cfgparse.c
src/hash.c

index c430ec3b8283f813bf13fdcec7bb9dc9aa244927..0b4844b184b27fee2dc080068dea5f742b61f237 100644 (file)
@@ -2548,6 +2548,14 @@ hash-type <method> <function> <modifier>
               poorly with numeric-only input or when the total server weight is
               a multiple of 33, unless the avalanche modifier is also used.
 
+       wt6    this function was designed for haproxy while testing other
+              functions in the past. It is not as smooth as the other ones, but
+              is much less sensible to the input data set or to the number of
+              servers. It can make sense as an alternative to sdbm+avalanche or
+              djb2+avalanche for consistent hashing or when hashing on numeric
+              data such as a source IP address or a visitor identifier in a URL
+              parameter.
+
     <modifier> indicates an optional method applied after hashing the key :
 
        avalanche   This directive indicates that the result from the hash
index f6875c9ac40007d5952aca112a67e18d53993a9c..379bf898c1df0fcaf3c33367420f6cadcfd93a27 100644 (file)
@@ -23,6 +23,7 @@
 #define _COMMON_HASH_H_
 
 unsigned long hash_djb2(const char *key, int len);
+unsigned long hash_wt6(const char *key, int len);
 unsigned long hash_sdbm(const char *key, int len);
 
 #endif /* _COMMON_HASH_H_ */
index 57d17bdf23f87905352d0c4b768393d5b771c737..6325be2bf4445421aff9c4f6a90261db161ff167 100644 (file)
 /* BE_LB_HFCN_* is the hash function, to be used with BE_LB_HASH_FUNC */
 #define BE_LB_HFCN_SDBM   0x000000 /* sdbm hash */
 #define BE_LB_HFCN_DJB2   0x400000 /* djb2 hash */
+#define BE_LB_HFCN_WT6    0x800000 /* wt6 hash */
 #define BE_LB_HASH_FUNC   0xC00000 /* get/clear hash function */
 
 
index e044430e0f99c758819a7ec661e9c69db3d2c105..7689cea6748bf4de9a497bc53a02d76df93cbb1b 100644 (file)
@@ -61,6 +61,9 @@ static unsigned long gen_hash(const struct proxy* px, const char* key, unsigned
        case BE_LB_HFCN_DJB2:
                hash = hash_djb2(key, len);
                break;
+       case BE_LB_HFCN_WT6:
+               hash = hash_wt6(key, len);
+               break;
        case BE_LB_HFCN_SDBM:
                /* this is the default hash function */
        default:
index bb79a34a16372d42cc3dec68ac9ffbf1aec7cd81..28507dd0649063f65fc30265649bc77cab208a7c 100644 (file)
@@ -4128,9 +4128,11 @@ stats_error_parsing:
                        }
                        else if (!strcmp(args[2], "djb2")) {
                                curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
+                       } else if (!strcmp(args[2], "wt6")) {
+                               curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
                        }
                        else {
-                               Alert("parsing [%s:%d] : '%s' only supports 'sdbm' and 'djb2' hash functions.\n", file, linenum, args[0]);
+                               Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
                                err_code |= ERR_ALERT | ERR_FATAL;
                                goto out;
                        }
index 8da3003b9b5dd42fb1895b86e12eb76ed08c3ce7..034685efd538373ac8ea8bc89f5d2ae5c28e63b5 100644 (file)
 #include <common/hash.h>
 
 
+unsigned long hash_wt6(const char *key, int len)
+{
+       unsigned h0 = 0xa53c965aUL;
+       unsigned h1 = 0x5ca6953aUL;
+       unsigned step0 = 6;
+       unsigned step1 = 18;
+
+       for (; len > 0; len--) {
+               unsigned int t;
+
+               t = ((unsigned int)*key);
+               key++;
+
+               h0 = ~(h0 ^ t);
+               h1 = ~(h1 + t);
+
+               t  = (h1 << step0) | (h1 >> (32-step0));
+               h1 = (h0 << step1) | (h0 >> (32-step1));
+               h0 = t;
+
+               t = ((h0 >> 16) ^ h1) & 0xffff;
+               step0 = t & 0x1F;
+               step1 = t >> 11;
+       }
+       return h0 ^ h1;
+}
+
 unsigned long hash_djb2(const char *key, int len)
 {
        unsigned long hash = 5381;