tdb 0.5.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.wrongdoc.yml +4 -2
- data/COPYING +497 -160
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -151
- data/HACKING +1 -1
- data/Hash_Functions +17 -6
- data/LICENSE +2 -3
- data/README +4 -4
- data/Rakefile +0 -36
- data/TODO +0 -2
- data/ext/tdb/extconf.rb +1 -0
- data/ext/tdb/hash_functions.c +6 -0
- data/ext/tdb/murmur3.c +230 -0
- data/ext/tdb/rbtdb.h +4 -0
- data/ext/tdb/siphash24.c +328 -0
- data/ext/tdb/tdb.c +71 -56
- data/pkg.mk +175 -0
- data/tdb.gemspec +2 -6
- data/test/test_tdb.rb +24 -2
- data/test/test_tdb_hash_functions.rb +30 -0
- data/test/test_tdb_mt.rb +1 -0
- metadata +47 -58
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,155 +1,6 @@
|
|
1
|
-
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
1
|
all::
|
3
|
-
|
4
|
-
RAKE = rake
|
5
|
-
RSYNC = rsync
|
6
|
-
|
7
|
-
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
8
|
-
@./GIT-VERSION-GEN
|
9
|
-
-include GIT-VERSION-FILE
|
10
|
-
-include local.mk
|
11
|
-
ifeq ($(DLEXT),) # "so" for Linux
|
12
|
-
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
|
13
|
-
endif
|
14
|
-
ifeq ($(RUBY_VERSION),)
|
15
|
-
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
16
|
-
endif
|
17
|
-
|
18
|
-
install:
|
19
|
-
$(prep_setup_rb)
|
20
|
-
$(RM) -r .install-tmp
|
21
|
-
mkdir .install-tmp
|
22
|
-
$(RUBY) setup.rb all
|
23
|
-
$(RM) $^
|
24
|
-
$(RM) -r .install-tmp
|
25
|
-
$(prep_setup_rb)
|
26
|
-
|
27
|
-
setup_rb_files := .config InstalledFiles
|
28
|
-
prep_setup_rb := @-$(RM) $(setup_rb_files);$(MAKE) -C $(ext) clean
|
29
|
-
|
30
|
-
extdir := ext/tdb
|
31
|
-
clean:
|
32
|
-
-$(MAKE) -C $(extdir) clean
|
33
|
-
$(RM) $(setup_rb_files) $(extdir)/Makefile
|
34
|
-
|
35
|
-
pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
|
36
|
-
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
37
|
-
wrongdoc prepare
|
38
|
-
|
39
|
-
.manifest: ChangeLog
|
40
|
-
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
41
|
-
LC_ALL=C sort > $@+
|
42
|
-
cmp $@+ $@ || mv $@+ $@
|
43
|
-
$(RM) $@+
|
44
|
-
|
45
|
-
doc: .document .wrongdoc.yml
|
46
|
-
find lib ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
47
|
-
$(RM) -r doc
|
48
|
-
wrongdoc all
|
49
|
-
install -m644 COPYING doc/COPYING
|
50
|
-
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
51
|
-
|
52
|
-
ifneq ($(VERSION),)
|
2
|
+
RSYNC_DEST := bogomips.org:/srv/bogomips/ruby-tdb
|
53
3
|
rfproject := qrp
|
54
4
|
rfpackage := tdb
|
55
|
-
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
56
|
-
pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
|
57
|
-
release_notes := release_notes-$(VERSION)
|
58
|
-
release_changes := release_changes-$(VERSION)
|
59
|
-
|
60
|
-
release-notes: $(release_notes)
|
61
|
-
release-changes: $(release_changes)
|
62
|
-
$(release_changes):
|
63
|
-
wrongdoc release_changes > $@+
|
64
|
-
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
65
|
-
$(release_notes):
|
66
|
-
wrongdoc release_notes > $@+
|
67
|
-
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
68
|
-
|
69
|
-
# ensures we're actually on the tagged $(VERSION), only used for release
|
70
|
-
verify:
|
71
|
-
test x"$(shell umask)" = x0022
|
72
|
-
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
73
|
-
git diff-index --quiet HEAD^0
|
74
|
-
test `git rev-parse --verify HEAD^0` = \
|
75
|
-
`git rev-parse --verify refs/tags/v$(VERSION)^{}`
|
76
|
-
|
77
|
-
fix-perms:
|
78
|
-
-git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
79
|
-
-git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
80
|
-
|
81
|
-
gem: $(pkggem)
|
82
|
-
|
83
|
-
install-gem: $(pkggem)
|
84
|
-
gem install $(CURDIR)/$<
|
85
|
-
|
86
|
-
$(pkggem): .manifest fix-perms
|
87
|
-
gem build $(rfpackage).gemspec
|
88
|
-
mkdir -p pkg
|
89
|
-
mv $(@F) $@
|
90
|
-
|
91
|
-
$(pkgtgz): distdir = $(basename $@)
|
92
|
-
$(pkgtgz): HEAD = v$(VERSION)
|
93
|
-
$(pkgtgz): .manifest fix-perms
|
94
|
-
@test -n "$(distdir)"
|
95
|
-
$(RM) -r $(distdir)
|
96
|
-
mkdir -p $(distdir)
|
97
|
-
tar cf - `cat .manifest` | (cd $(distdir) && tar xf -)
|
98
|
-
cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
|
99
|
-
mv $@+ $@
|
100
|
-
|
101
|
-
package: $(pkgtgz) $(pkggem)
|
102
|
-
|
103
|
-
test-release: verify package $(release_notes) $(release_changes)
|
104
|
-
release: verify package $(release_notes) $(release_changes)
|
105
|
-
# make tgz release on RubyForge
|
106
|
-
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
107
|
-
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
108
|
-
# push gem to RubyGems.org
|
109
|
-
gem push $(pkggem)
|
110
|
-
# in case of gem downloads from RubyForge releases page
|
111
|
-
-rubyforge add_file \
|
112
|
-
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
113
|
-
$(RAKE) raa_update VERSION=$(VERSION)
|
114
|
-
$(RAKE) publish_news VERSION=$(VERSION)
|
115
|
-
else
|
116
|
-
gem install-gem: GIT-VERSION-FILE
|
117
|
-
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
118
|
-
endif
|
119
|
-
|
120
|
-
ext := $(extdir)/tdb_ext.$(DLEXT)
|
121
|
-
$(extdir)/Makefile: $(extdir)/extconf.rb
|
122
|
-
cd $(@D) && $(RUBY) extconf.rb
|
123
|
-
|
124
|
-
c_files := $(wildcard $(extdir)/*.[ch] $(extdir)/*/*.h)
|
125
|
-
$(ext): $(c_files) $(extdir)/Makefile
|
126
|
-
$(MAKE) -C $(@D)
|
127
|
-
|
128
|
-
all:: test
|
129
|
-
|
130
|
-
build: $(ext)
|
131
|
-
test_units := $(wildcard test/test_*.rb)
|
132
|
-
test: test-unit
|
133
|
-
test-unit: $(test_units)
|
134
|
-
$(test_units): build
|
135
|
-
$(RUBY) -I lib:$(extdir) $@
|
136
|
-
|
137
|
-
# this requires GNU coreutils variants
|
138
|
-
publish_doc:
|
139
|
-
-git set-file-times
|
140
|
-
$(MAKE) doc
|
141
|
-
find doc/images -type f | \
|
142
|
-
TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
|
143
|
-
$(MAKE) doc_gz
|
144
|
-
chmod 644 $$(find doc -type f)
|
145
|
-
$(RSYNC) -av doc/ bogomips.org:/srv/bogomips/ruby-tdb/
|
146
|
-
git ls-files | xargs touch
|
147
|
-
|
148
|
-
# Create gzip variants of the same timestamp as the original so nginx
|
149
|
-
# "gzip_static on" can serve the gzipped versions directly.
|
150
|
-
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
151
|
-
doc_gz:
|
152
|
-
for i in $(docs); do \
|
153
|
-
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
154
5
|
|
155
|
-
|
6
|
+
include pkg.mk
|
data/HACKING
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
=== Code Compatibility
|
4
4
|
|
5
|
-
We target Ruby 1.9.
|
5
|
+
We target C Ruby 1.9.3+ and (time permitting) Rubinius and their respective C
|
6
6
|
APIs.
|
7
7
|
|
8
8
|
All of our C code should be compatible with all reasonably modern Unices
|
data/Hash_Functions
CHANGED
@@ -19,15 +19,27 @@ corruption, so don't do it.
|
|
19
19
|
{lookup3 hash}[http://www.burtleburtle.net/bob/c/lookup3.c].
|
20
20
|
<code>:hash => :jenkins_lookup3</code>
|
21
21
|
|
22
|
+
== SipHash
|
23
|
+
|
24
|
+
https://en.wikipedia.org/wiki/Sip_Hash
|
25
|
+
https://131002.net/siphash/
|
26
|
+
|
27
|
+
Currently (as of Ruby 2.1) the favored hash in Ruby for hash-flooding
|
28
|
+
protection.
|
29
|
+
|
30
|
+
* :siphash24 - the reference implementation
|
31
|
+
|
22
32
|
== Murmur family
|
23
33
|
|
24
34
|
The {Murmur}[https://sites.google.com/site/murmurhash/] family of hashes
|
25
|
-
are supported by Ruby TDB.
|
26
|
-
|
27
|
-
|
28
|
-
designed with x86 and x86_64 in mind (they may crash or not work on
|
35
|
+
are supported by Ruby TDB. Most of these are not endian-neutral so
|
36
|
+
databases are no compatible between machines of different endianness and
|
37
|
+
were designed with x86 and x86_64 in mind (they may crash or not work on
|
29
38
|
other architectures).
|
30
39
|
|
40
|
+
* :murmur3a - The latest 32-bit version optimized for x86
|
41
|
+
https://code.google.com/p/smhasher/wiki/MurmurHash3
|
42
|
+
|
31
43
|
* :murmur2 - the simple and fast implementation
|
32
44
|
|
33
45
|
* :murmur2a - words of the author:
|
@@ -61,7 +73,6 @@ other architectures).
|
|
61
73
|
|
62
74
|
== Bernstein hashes
|
63
75
|
|
64
|
-
* :djb3 -
|
65
|
-
See http://www.cse.yorku.ca/~oz/hash.html
|
76
|
+
* :djb3 - See http://www.cse.yorku.ca/~oz/hash.html
|
66
77
|
|
67
78
|
* :djb2 - See http://www.cse.yorku.ca/~oz/hash.html
|
data/LICENSE
CHANGED
@@ -4,7 +4,7 @@ revision control for names and email addresses of all of them.
|
|
4
4
|
This library is free software; you can redistribute it and/or modify it
|
5
5
|
under the terms of the GNU Lesser General Public License as published by
|
6
6
|
the Free Software Foundation; either version
|
7
|
-
{
|
7
|
+
{2.1}[https://www.gnu.org/licenses/lgpl-2.1.txt] of the License, or (at
|
8
8
|
your option) any later version.
|
9
9
|
|
10
10
|
Ruby tdb is distributed in the hope that it will be useful, but WITHOUT
|
@@ -13,5 +13,4 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
13
13
|
License for more details.
|
14
14
|
|
15
15
|
You should have received a copy of the GNU Lesser General Public License
|
16
|
-
along with Ruby tdb; if not,
|
17
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
16
|
+
along with Ruby tdb; if not, see [https://www.gnu.org/licenses/].
|
data/README
CHANGED
@@ -8,8 +8,8 @@ write to the same databases used by Samba!
|
|
8
8
|
== Features
|
9
9
|
|
10
10
|
* Concurrent reader and writer processes may safely operate on the
|
11
|
-
same file. This is great for MRI
|
12
|
-
|
11
|
+
same file. This is great for MRI where multi-core performance
|
12
|
+
is easiest to achieve with processes and not threads.
|
13
13
|
|
14
14
|
* Fork-safe, you may fork and share the same TDB object in your parent
|
15
15
|
and child processes.
|
@@ -70,13 +70,13 @@ Or if you have a non-standard prefix that linkers normally do not search:
|
|
70
70
|
You can get the latest source via git from the following locations
|
71
71
|
(these versions may not be stable):
|
72
72
|
|
73
|
-
git://
|
73
|
+
git://bogomips.org/ruby-tdb.git
|
74
74
|
git://repo.or.cz/ruby-tdb.git (mirror)
|
75
75
|
|
76
76
|
You may browse the code from the web and download the latest snapshot
|
77
77
|
tarballs here:
|
78
78
|
|
79
|
-
* http://
|
79
|
+
* http://bogomips.org/ruby-tdb.git (cgit)
|
80
80
|
* http://repo.or.cz/w/ruby-tdb.git (gitweb)
|
81
81
|
|
82
82
|
See the HACKING guide on how to contribute and build prerelease gems
|
data/Rakefile
CHANGED
@@ -1,37 +1 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
desc "post to RAA"
|
3
|
-
task :raa_update do
|
4
|
-
require 'net/http'
|
5
|
-
require 'net/netrc'
|
6
|
-
rc = Net::Netrc.locate('tdb-raa') or abort "~/.netrc not found"
|
7
|
-
password = rc.password
|
8
|
-
|
9
|
-
s = Gem::Specification.load('tdb.gemspec')
|
10
|
-
desc = [ s.description.strip ]
|
11
|
-
desc << ""
|
12
|
-
desc << "* #{s.email}"
|
13
|
-
desc << "* #{git_url}"
|
14
|
-
desc << "* #{cgit_url}"
|
15
|
-
desc = desc.join("\n")
|
16
|
-
uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
|
17
|
-
form = {
|
18
|
-
:name => s.name,
|
19
|
-
:short_description => s.summary,
|
20
|
-
:version => s.version.to_s,
|
21
|
-
:status => 'experimental',
|
22
|
-
:owner => s.authors.first,
|
23
|
-
:email => s.email,
|
24
|
-
:category_major => 'Library',
|
25
|
-
:category_minor => 'Database',
|
26
|
-
:url => s.homepage,
|
27
|
-
:download => 'http://bogomips.org/ruby-tdb/files/',
|
28
|
-
:license => "LGPL",
|
29
|
-
:description_style => 'Plain',
|
30
|
-
:description => desc,
|
31
|
-
:pass => password,
|
32
|
-
:submit => 'Update',
|
33
|
-
}
|
34
|
-
res = Net::HTTP.post_form(uri, form)
|
35
|
-
p res
|
36
|
-
puts res.body
|
37
|
-
end
|
data/TODO
CHANGED
data/ext/tdb/extconf.rb
CHANGED
data/ext/tdb/hash_functions.c
CHANGED
@@ -10,12 +10,15 @@ static VALUE fn(VALUE self,VALUE str) \
|
|
10
10
|
return UINT2NUM(rbtdb_##fn(&data)); \
|
11
11
|
}
|
12
12
|
|
13
|
+
HASH_FN(siphash24)
|
13
14
|
HASH_FN(murmur1)
|
14
15
|
HASH_FN(murmur1_aligned)
|
15
16
|
HASH_FN(murmur2)
|
16
17
|
HASH_FN(murmur2a)
|
17
18
|
HASH_FN(murmur2_neutral)
|
18
19
|
HASH_FN(murmur2_aligned)
|
20
|
+
HASH_FN(murmur3a)
|
21
|
+
HASH_FN(murmur3f)
|
19
22
|
HASH_FN(fnv1a)
|
20
23
|
HASH_FN(djb2)
|
21
24
|
HASH_FN(djb3)
|
@@ -27,12 +30,15 @@ void rbtdb_init_tdb_hash_functions(void)
|
|
27
30
|
VALUE cTDB = rb_const_get(rb_cObject, rb_intern("TDB"));
|
28
31
|
VALUE mHashFunctions = rb_define_module_under(cTDB, "HashFunctions");
|
29
32
|
|
33
|
+
HASH_M(siphash24);
|
30
34
|
HASH_M(murmur1);
|
31
35
|
HASH_M(murmur1_aligned);
|
32
36
|
HASH_M(murmur2);
|
33
37
|
HASH_M(murmur2a);
|
34
38
|
HASH_M(murmur2_neutral);
|
35
39
|
HASH_M(murmur2_aligned);
|
40
|
+
HASH_M(murmur3a);
|
41
|
+
HASH_M(murmur3f);
|
36
42
|
HASH_M(fnv1a);
|
37
43
|
HASH_M(djb2);
|
38
44
|
HASH_M(djb3);
|
data/ext/tdb/murmur3.c
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
#include "rbtdb.h"
|
2
|
+
/*
|
3
|
+
* https://sites.google.com/site/murmurhash/
|
4
|
+
*
|
5
|
+
* MurmurHash3 was written by Austin Appleby, and is placed in the public
|
6
|
+
* domain. The author hereby disclaims copyright to this source code.
|
7
|
+
*
|
8
|
+
* Eric Wong trivially ported this to C for Ruby tdb (32-bit versions only)
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <stdint.h>
|
12
|
+
|
13
|
+
static inline uint32_t rotl32(uint32_t x, int8_t r)
|
14
|
+
{
|
15
|
+
return (x << r) | (x >> (32 - r));
|
16
|
+
}
|
17
|
+
|
18
|
+
#define ROTL32(x,y) rotl32(x,y)
|
19
|
+
|
20
|
+
#define BIG_CONSTANT(x) (x##LLU)
|
21
|
+
|
22
|
+
/* ----------------------------------------------------------------------------
|
23
|
+
* Block read - if your platform needs to do endian-swapping or can only
|
24
|
+
* handle aligned reads, do the conversion here
|
25
|
+
*/
|
26
|
+
|
27
|
+
static inline uint32_t getblock(const uint32_t * p, int i)
|
28
|
+
{
|
29
|
+
return p[i];
|
30
|
+
}
|
31
|
+
|
32
|
+
/* ----------------------------------------------------------------------------
|
33
|
+
* Finalization mix - force all bits of a hash block to avalanche
|
34
|
+
*/
|
35
|
+
|
36
|
+
static inline uint32_t fmix(uint32_t h)
|
37
|
+
{
|
38
|
+
h ^= h >> 16;
|
39
|
+
h *= 0x85ebca6b;
|
40
|
+
h ^= h >> 13;
|
41
|
+
h *= 0xc2b2ae35;
|
42
|
+
h ^= h >> 16;
|
43
|
+
|
44
|
+
return h;
|
45
|
+
}
|
46
|
+
|
47
|
+
unsigned int rbtdb_murmur3a(TDB_DATA * key)
|
48
|
+
{
|
49
|
+
const uint8_t *data = key->dptr;
|
50
|
+
int len = (int)key->dsize;
|
51
|
+
const int nblocks = len / 4;
|
52
|
+
static const uint32_t seed;
|
53
|
+
uint32_t h1 = seed;
|
54
|
+
int i;
|
55
|
+
|
56
|
+
static const uint32_t c1 = 0xcc9e2d51;
|
57
|
+
static const uint32_t c2 = 0x1b873593;
|
58
|
+
|
59
|
+
/* body */
|
60
|
+
const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
|
61
|
+
|
62
|
+
for (i = -nblocks; i; i++) {
|
63
|
+
uint32_t k1 = getblock(blocks, i);
|
64
|
+
|
65
|
+
k1 *= c1;
|
66
|
+
k1 = ROTL32(k1, 15);
|
67
|
+
k1 *= c2;
|
68
|
+
|
69
|
+
h1 ^= k1;
|
70
|
+
h1 = ROTL32(h1, 13);
|
71
|
+
h1 = h1 * 5 + 0xe6546b64;
|
72
|
+
}
|
73
|
+
|
74
|
+
/* tail */
|
75
|
+
{
|
76
|
+
const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
|
77
|
+
uint32_t k1 = 0;
|
78
|
+
|
79
|
+
switch (len & 3) {
|
80
|
+
case 3:
|
81
|
+
k1 ^= tail[2] << 16;
|
82
|
+
case 2:
|
83
|
+
k1 ^= tail[1] << 8;
|
84
|
+
case 1:
|
85
|
+
k1 ^= tail[0];
|
86
|
+
k1 *= c1;
|
87
|
+
k1 = ROTL32(k1, 15);
|
88
|
+
k1 *= c2;
|
89
|
+
h1 ^= k1;
|
90
|
+
};
|
91
|
+
}
|
92
|
+
|
93
|
+
/* finalization */
|
94
|
+
|
95
|
+
h1 ^= len;
|
96
|
+
|
97
|
+
return fmix(h1);
|
98
|
+
}
|
99
|
+
|
100
|
+
static inline uint64_t rotl64(uint64_t x, int8_t r)
|
101
|
+
{
|
102
|
+
return (x << r) | (x >> (64 - r));
|
103
|
+
}
|
104
|
+
|
105
|
+
#define ROTL64(x,y) rotl64(x,y)
|
106
|
+
|
107
|
+
static inline uint64_t getblock64(const uint64_t * p, int i)
|
108
|
+
{
|
109
|
+
return p[i];
|
110
|
+
}
|
111
|
+
|
112
|
+
static inline uint64_t fmix64(uint64_t k)
|
113
|
+
{
|
114
|
+
k ^= k >> 33;
|
115
|
+
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
|
116
|
+
k ^= k >> 33;
|
117
|
+
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
|
118
|
+
k ^= k >> 33;
|
119
|
+
|
120
|
+
return k;
|
121
|
+
}
|
122
|
+
|
123
|
+
/* this was a 128-bit hash for x86_64, but we only want 32-bits */
|
124
|
+
unsigned int rbtdb_murmur3f(TDB_DATA * key)
|
125
|
+
{
|
126
|
+
const uint8_t *data = key->dptr;
|
127
|
+
int len = (int)key->dsize;
|
128
|
+
const int nblocks = len / 16;
|
129
|
+
static const uint32_t seed;
|
130
|
+
uint64_t h1 = seed;
|
131
|
+
uint64_t h2 = seed;
|
132
|
+
uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
|
133
|
+
uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
|
134
|
+
int i;
|
135
|
+
|
136
|
+
/* body */
|
137
|
+
const uint64_t *blocks = (const uint64_t *)(data);
|
138
|
+
|
139
|
+
for (i = 0; i < nblocks; i++) {
|
140
|
+
uint64_t k1 = getblock64(blocks, i * 2 + 0);
|
141
|
+
uint64_t k2 = getblock64(blocks, i * 2 + 1);
|
142
|
+
|
143
|
+
k1 *= c1;
|
144
|
+
k1 = ROTL64(k1, 31);
|
145
|
+
k1 *= c2;
|
146
|
+
h1 ^= k1;
|
147
|
+
|
148
|
+
h1 = ROTL64(h1, 27);
|
149
|
+
h1 += h2;
|
150
|
+
h1 = h1 * 5 + 0x52dce729;
|
151
|
+
|
152
|
+
k2 *= c2;
|
153
|
+
k2 = ROTL64(k2, 33);
|
154
|
+
k2 *= c1;
|
155
|
+
h2 ^= k2;
|
156
|
+
|
157
|
+
h2 = ROTL64(h2, 31);
|
158
|
+
h2 += h1;
|
159
|
+
h2 = h2 * 5 + 0x38495ab5;
|
160
|
+
}
|
161
|
+
|
162
|
+
/* tail */
|
163
|
+
{
|
164
|
+
const uint8_t *tail = (const uint8_t *)(data + nblocks * 16);
|
165
|
+
|
166
|
+
uint64_t k1 = 0;
|
167
|
+
uint64_t k2 = 0;
|
168
|
+
#define CAST64(x) ((uint64_t)(x))
|
169
|
+
|
170
|
+
switch (len & 15) {
|
171
|
+
case 15:
|
172
|
+
k2 ^= CAST64(tail[14]) << 48;
|
173
|
+
case 14:
|
174
|
+
k2 ^= CAST64(tail[13]) << 40;
|
175
|
+
case 13:
|
176
|
+
k2 ^= CAST64(tail[12]) << 32;
|
177
|
+
case 12:
|
178
|
+
k2 ^= CAST64(tail[11]) << 24;
|
179
|
+
case 11:
|
180
|
+
k2 ^= CAST64(tail[10]) << 16;
|
181
|
+
case 10:
|
182
|
+
k2 ^= CAST64(tail[9]) << 8;
|
183
|
+
case 9:
|
184
|
+
k2 ^= CAST64(tail[8]) << 0;
|
185
|
+
k2 *= c2;
|
186
|
+
k2 = ROTL64(k2, 33);
|
187
|
+
k2 *= c1;
|
188
|
+
h2 ^= k2;
|
189
|
+
|
190
|
+
case 8:
|
191
|
+
k1 ^= CAST64(tail[7]) << 56;
|
192
|
+
case 7:
|
193
|
+
k1 ^= CAST64(tail[6]) << 48;
|
194
|
+
case 6:
|
195
|
+
k1 ^= CAST64(tail[5]) << 40;
|
196
|
+
case 5:
|
197
|
+
k1 ^= CAST64(tail[4]) << 32;
|
198
|
+
case 4:
|
199
|
+
k1 ^= CAST64(tail[3]) << 24;
|
200
|
+
case 3:
|
201
|
+
k1 ^= CAST64(tail[2]) << 16;
|
202
|
+
case 2:
|
203
|
+
k1 ^= CAST64(tail[1]) << 8;
|
204
|
+
case 1:
|
205
|
+
k1 ^= CAST64(tail[0]) << 0;
|
206
|
+
k1 *= c1;
|
207
|
+
k1 = ROTL64(k1, 31);
|
208
|
+
k1 *= c2;
|
209
|
+
h1 ^= k1;
|
210
|
+
};
|
211
|
+
}
|
212
|
+
|
213
|
+
/* finalization */
|
214
|
+
|
215
|
+
h1 ^= len;
|
216
|
+
h2 ^= len;
|
217
|
+
|
218
|
+
h1 += h2;
|
219
|
+
h2 += h1;
|
220
|
+
|
221
|
+
h1 = fmix64(h1);
|
222
|
+
h2 = fmix64(h2);
|
223
|
+
|
224
|
+
h1 += h2;
|
225
|
+
|
226
|
+
/* not needed for 32-bit hash */
|
227
|
+
/* h2 += h1; */
|
228
|
+
|
229
|
+
return (unsigned int)h1; /* truncate to 32-bits */
|
230
|
+
}
|