glusterfs
174 строки · 3.8 Кб
1/*
2Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include <stdint.h>12#include <stdlib.h>13
14#ifdef __FreeBSD__15#include <sys/endian.h>16#else17#include <endian.h>18#endif19
20#define get16bits(d) le16toh(*((const uint16_t *)(d)))21
22#define DM_DELTA 0x9E3779B923#define DM_FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */24#define DM_PARTROUNDS 6 /* 6 gets complete mixing */25
26/*
27This is apparently the "fastest hash function for strings".
28Written by Paul Hsieh <http://www.azillionmonkeys.com/qed/hash.html>
29*/
30
31/* In any case make sure, you return 1 */
32
33uint32_t
34SuperFastHash(const char *data, int32_t len)35{
36uint32_t hash = len, tmp;37int32_t rem;38
39if (len <= 1 || data == NULL)40return 1;41
42rem = len & 3;43len >>= 2;44
45/* Main loop */46for (; len > 0; len--) {47hash += get16bits(data);48tmp = (get16bits(data + 2) << 11) ^ hash;49hash = (hash << 16) ^ tmp;50data += 2 * sizeof(uint16_t);51hash += hash >> 11;52}53
54/* Handle end cases */55switch (rem) {56case 3:57hash += get16bits(data);58hash ^= hash << 16;59hash ^= data[sizeof(uint16_t)] << 18;60hash += hash >> 11;61break;62case 2:63hash += get16bits(data);64hash ^= hash << 11;65hash += hash >> 17;66break;67case 1:68hash += *data;69hash ^= hash << 10;70hash += hash >> 1;71}72
73/* Force "avalanching" of final 127 bits */74hash ^= hash << 3;75hash += hash >> 5;76hash ^= hash << 4;77hash += hash >> 17;78hash ^= hash << 25;79hash += hash >> 6;80
81return hash;82}
83
84/* Davies-Meyer hashing function implementation
85*/
86static int87dm_round(int rounds, uint32_t *array, uint32_t *h0, uint32_t *h1)88{
89uint32_t sum = 0;90int n = 0;91uint32_t b0 = 0;92uint32_t b1 = 0;93
94b0 = *h0;95b1 = *h1;96
97n = rounds;98
99do {100sum += DM_DELTA;101b0 += ((b1 << 4) + array[0]) ^ (b1 + sum) ^ ((b1 >> 5) + array[1]);102b1 += ((b0 << 4) + array[2]) ^ (b0 + sum) ^ ((b0 >> 5) + array[3]);103} while (--n);104
105*h0 += b0;106*h1 += b1;107
108return 0;109}
110
111uint32_t
112__pad(int len)113{
114uint32_t pad = 0;115
116pad = (uint32_t)len | ((uint32_t)len << 8);117pad |= pad << 16;118
119return pad;120}
121
122uint32_t
123gf_dm_hashfn(const char *msg, int len)124{
125uint32_t h0 = 0x9464a485;126uint32_t h1 = 0x542e1a94;127uint32_t array[4];128uint32_t pad = 0;129int i = 0;130int j = 0;131int full_quads = 0;132int full_words = 0;133int full_bytes = 0;134uint32_t *intmsg = NULL;135uint32_t word = 0;136
137intmsg = (uint32_t *)msg;138pad = __pad(len);139
140full_bytes = len;141full_words = len / 4;142full_quads = len / 16;143
144for (i = 0; i < full_quads; i++) {145for (j = 0; j < 4; j++) {146word = le32toh(*intmsg);147array[j] = word;148intmsg++;149full_words--;150full_bytes -= 4;151}152dm_round(DM_PARTROUNDS, &array[0], &h0, &h1);153}154
155for (j = 0; j < 4; j++) {156if (full_words) {157word = le32toh(*intmsg);158array[j] = word;159intmsg++;160full_words--;161full_bytes -= 4;162} else {163array[j] = pad;164while (full_bytes) {165array[j] <<= 8;166array[j] |= msg[len - full_bytes];167full_bytes--;168}169}170}171dm_round(DM_FULLROUNDS, &array[0], &h0, &h1);172
173return h0 ^ h1;174}
175