tdb 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.5.0.GIT
4
+ DEF_VER=v0.6.0
5
5
 
6
6
  LF='
7
7
  '
@@ -1,155 +1,6 @@
1
- # use GNU Make to run tests in parallel, and without depending on RubyGems
2
1
  all::
3
- RUBY = ruby
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
- .PHONY: .FORCE-GIT-VERSION-FILE doc test $(test_units)
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.2 and eventually Rubinius 1.1+ and their respective C
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
@@ -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. MurmurHash3 will be supported as soon as it
26
- becomes finalized. Most of these are not endian-neutral so databases
27
- are no compatible between machines of different endianness and were
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 - The hash currently favored by Bernstein.
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
- {3}[http://www.gnu.org/licenses/lgpl-3.0.txt] of the License, or (at
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, write to the Free Software
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 1.8 and 1.9 where multi-core
12
- performance is easiest to achieve with processes and not threads.
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://git.bogomips.org/ruby-tdb.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://git.bogomips.org/cgit/ruby-tdb.git (cgit)
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
@@ -1,5 +1,3 @@
1
- * port the final Murmur3 hash implementation
2
-
3
1
  * support more TDB-specific features
4
2
 
5
3
  * make it reasonably API-compatible with other DBM bindings
@@ -2,6 +2,7 @@ require 'mkmf'
2
2
 
3
3
  have_func('rb_thread_blocking_region')
4
4
  have_func('rb_thread_call_with_gvl')
5
+ have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
5
6
 
6
7
  dir_config('tdb')
7
8
  have_header('tdb.h') or abort 'tdb.h missing'
@@ -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);
@@ -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
+ }