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/ext/tdb/rbtdb.h
CHANGED
@@ -3,12 +3,15 @@
|
|
3
3
|
#include <ruby.h>
|
4
4
|
#include <tdb.h>
|
5
5
|
|
6
|
+
unsigned int rbtdb_siphash24(TDB_DATA *key);
|
6
7
|
unsigned int rbtdb_murmur1(TDB_DATA *key);
|
7
8
|
unsigned int rbtdb_murmur1_aligned(TDB_DATA *key);
|
8
9
|
unsigned int rbtdb_murmur2(TDB_DATA *key);
|
9
10
|
unsigned int rbtdb_murmur2a(TDB_DATA *key);
|
10
11
|
unsigned int rbtdb_murmur2_neutral(TDB_DATA *key);
|
11
12
|
unsigned int rbtdb_murmur2_aligned(TDB_DATA *key);
|
13
|
+
unsigned int rbtdb_murmur3a(TDB_DATA *key);
|
14
|
+
unsigned int rbtdb_murmur3f(TDB_DATA *key);
|
12
15
|
unsigned int rbtdb_fnv1a(TDB_DATA *key);
|
13
16
|
unsigned int rbtdb_djb2(TDB_DATA *key);
|
14
17
|
unsigned int rbtdb_djb3(TDB_DATA *key);
|
@@ -19,4 +22,5 @@ unsigned int rbtdb_jenkins_lookup3(TDB_DATA *key);
|
|
19
22
|
#endif
|
20
23
|
#define rbtdb_default 0
|
21
24
|
|
25
|
+
void rbtdb_init_tdb_hash_functions(void);
|
22
26
|
#endif /* RBTDB_H */
|
data/ext/tdb/siphash24.c
ADDED
@@ -0,0 +1,328 @@
|
|
1
|
+
#include "rbtdb.h"
|
2
|
+
/*
|
3
|
+
SipHash reference C implementation
|
4
|
+
Trivially adapted by Eric Wong for ruby-tdb
|
5
|
+
|
6
|
+
Written in 2012 by
|
7
|
+
Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
|
8
|
+
Daniel J. Bernstein <djb@cr.yp.to>
|
9
|
+
|
10
|
+
To the extent possible under law, the author(s) have dedicated all copyright
|
11
|
+
and related and neighboring rights to this software to the public domain
|
12
|
+
worldwide. This software is distributed without any warranty.
|
13
|
+
|
14
|
+
You should have received a copy of the CC0 Public Domain Dedication along with
|
15
|
+
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
16
|
+
*/
|
17
|
+
#include <stdint.h>
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <string.h>
|
20
|
+
typedef uint64_t u64;
|
21
|
+
typedef uint32_t u32;
|
22
|
+
typedef uint8_t u8;
|
23
|
+
|
24
|
+
#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
|
25
|
+
|
26
|
+
#define U32TO8_LE(p, v) \
|
27
|
+
(p)[0] = (u8)((v) ); (p)[1] = (u8)((v) >> 8); \
|
28
|
+
(p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
|
29
|
+
|
30
|
+
#define U64TO8_LE(p, v) \
|
31
|
+
U32TO8_LE((p), (u32)((v) )); \
|
32
|
+
U32TO8_LE((p) + 4, (u32)((v) >> 32));
|
33
|
+
|
34
|
+
#define U8TO64_LE(p) \
|
35
|
+
(((u64)((p)[0]) ) | \
|
36
|
+
((u64)((p)[1]) << 8) | \
|
37
|
+
((u64)((p)[2]) << 16) | \
|
38
|
+
((u64)((p)[3]) << 24) | \
|
39
|
+
((u64)((p)[4]) << 32) | \
|
40
|
+
((u64)((p)[5]) << 40) | \
|
41
|
+
((u64)((p)[6]) << 48) | \
|
42
|
+
((u64)((p)[7]) << 56))
|
43
|
+
|
44
|
+
#define SIPROUND \
|
45
|
+
do { \
|
46
|
+
v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
|
47
|
+
v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
|
48
|
+
v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
|
49
|
+
v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
|
50
|
+
} while(0)
|
51
|
+
|
52
|
+
/* SipHash-2-4 */
|
53
|
+
static int
|
54
|
+
crypto_auth(unsigned char *out, const unsigned char *in,
|
55
|
+
size_t inlen, const unsigned char *k)
|
56
|
+
{
|
57
|
+
/* "somepseudorandomlygeneratedbytes" */
|
58
|
+
u64 v0 = 0x736f6d6570736575ULL;
|
59
|
+
u64 v1 = 0x646f72616e646f6dULL;
|
60
|
+
u64 v2 = 0x6c7967656e657261ULL;
|
61
|
+
u64 v3 = 0x7465646279746573ULL;
|
62
|
+
u64 b;
|
63
|
+
u64 k0 = U8TO64_LE(k);
|
64
|
+
u64 k1 = U8TO64_LE(k + 8);
|
65
|
+
u64 m;
|
66
|
+
const u8 *end = in + inlen - (inlen % sizeof(u64));
|
67
|
+
const int left = inlen & 7;
|
68
|
+
b = ((u64) inlen) << 56;
|
69
|
+
v3 ^= k1;
|
70
|
+
v2 ^= k0;
|
71
|
+
v1 ^= k1;
|
72
|
+
v0 ^= k0;
|
73
|
+
|
74
|
+
for (; in != end; in += 8) {
|
75
|
+
m = U8TO64_LE(in);
|
76
|
+
#ifdef DEBUG
|
77
|
+
printf("(%3d) v0 %08x %08x\n", (int)inlen, (u32) (v0 >> 32),
|
78
|
+
(u32) v0);
|
79
|
+
printf("(%3d) v1 %08x %08x\n", (int)inlen, (u32) (v1 >> 32),
|
80
|
+
(u32) v1);
|
81
|
+
printf("(%3d) v2 %08x %08x\n", (int)inlen, (u32) (v2 >> 32),
|
82
|
+
(u32) v2);
|
83
|
+
printf("(%3d) v3 %08x %08x\n", (int)inlen, (u32) (v3 >> 32),
|
84
|
+
(u32) v3);
|
85
|
+
printf("(%3d) compress %08x %08x\n", (int)inlen,
|
86
|
+
(u32) (m >> 32), (u32) m);
|
87
|
+
#endif
|
88
|
+
v3 ^= m;
|
89
|
+
SIPROUND;
|
90
|
+
SIPROUND;
|
91
|
+
v0 ^= m;
|
92
|
+
}
|
93
|
+
|
94
|
+
switch (left) {
|
95
|
+
case 7:
|
96
|
+
b |= ((u64) in[6]) << 48;
|
97
|
+
|
98
|
+
case 6:
|
99
|
+
b |= ((u64) in[5]) << 40;
|
100
|
+
|
101
|
+
case 5:
|
102
|
+
b |= ((u64) in[4]) << 32;
|
103
|
+
|
104
|
+
case 4:
|
105
|
+
b |= ((u64) in[3]) << 24;
|
106
|
+
|
107
|
+
case 3:
|
108
|
+
b |= ((u64) in[2]) << 16;
|
109
|
+
|
110
|
+
case 2:
|
111
|
+
b |= ((u64) in[1]) << 8;
|
112
|
+
|
113
|
+
case 1:
|
114
|
+
b |= ((u64) in[0]);
|
115
|
+
break;
|
116
|
+
|
117
|
+
case 0:
|
118
|
+
break;
|
119
|
+
}
|
120
|
+
|
121
|
+
#ifdef DEBUG
|
122
|
+
printf("(%3d) v0 %08x %08x\n", (int)inlen, (u32) (v0 >> 32), (u32) v0);
|
123
|
+
printf("(%3d) v1 %08x %08x\n", (int)inlen, (u32) (v1 >> 32), (u32) v1);
|
124
|
+
printf("(%3d) v2 %08x %08x\n", (int)inlen, (u32) (v2 >> 32), (u32) v2);
|
125
|
+
printf("(%3d) v3 %08x %08x\n", (int)inlen, (u32) (v3 >> 32), (u32) v3);
|
126
|
+
printf("(%3d) padding %08x %08x\n", (int)inlen, (u32) (b >> 32),
|
127
|
+
(u32) b);
|
128
|
+
#endif
|
129
|
+
v3 ^= b;
|
130
|
+
SIPROUND;
|
131
|
+
SIPROUND;
|
132
|
+
v0 ^= b;
|
133
|
+
#ifdef DEBUG
|
134
|
+
printf("(%3d) v0 %08x %08x\n", (int)inlen, (u32) (v0 >> 32), (u32) v0);
|
135
|
+
printf("(%3d) v1 %08x %08x\n", (int)inlen, (u32) (v1 >> 32), (u32) v1);
|
136
|
+
printf("(%3d) v2 %08x %08x\n", (int)inlen, (u32) (v2 >> 32), (u32) v2);
|
137
|
+
printf("(%3d) v3 %08x %08x\n", (int)inlen, (u32) (v3 >> 32), (u32) v3);
|
138
|
+
#endif
|
139
|
+
v2 ^= 0xff;
|
140
|
+
SIPROUND;
|
141
|
+
SIPROUND;
|
142
|
+
SIPROUND;
|
143
|
+
SIPROUND;
|
144
|
+
b = v0 ^ v1 ^ v2 ^ v3;
|
145
|
+
U64TO8_LE(out, b);
|
146
|
+
return 0;
|
147
|
+
}
|
148
|
+
|
149
|
+
/*
|
150
|
+
SipHash-2-4 output with
|
151
|
+
k = 00 01 02 ...
|
152
|
+
and
|
153
|
+
in = (empty string)
|
154
|
+
in = 00 (1 byte)
|
155
|
+
in = 00 01 (2 bytes)
|
156
|
+
in = 00 01 02 (3 bytes)
|
157
|
+
...
|
158
|
+
in = 00 01 02 ... 3e (63 bytes)
|
159
|
+
*/
|
160
|
+
u8 vectors[64][8] = {
|
161
|
+
{0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72,}
|
162
|
+
,
|
163
|
+
{0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74,}
|
164
|
+
,
|
165
|
+
{0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d,}
|
166
|
+
,
|
167
|
+
{0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85,}
|
168
|
+
,
|
169
|
+
{0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf,}
|
170
|
+
,
|
171
|
+
{0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18,}
|
172
|
+
,
|
173
|
+
{0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb,}
|
174
|
+
,
|
175
|
+
{0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab,}
|
176
|
+
,
|
177
|
+
{0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93,}
|
178
|
+
,
|
179
|
+
{0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e,}
|
180
|
+
,
|
181
|
+
{0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a,}
|
182
|
+
,
|
183
|
+
{0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4,}
|
184
|
+
,
|
185
|
+
{0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75,}
|
186
|
+
,
|
187
|
+
{0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14,}
|
188
|
+
,
|
189
|
+
{0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7,}
|
190
|
+
,
|
191
|
+
{0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1,}
|
192
|
+
,
|
193
|
+
{0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f,}
|
194
|
+
,
|
195
|
+
{0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69,}
|
196
|
+
,
|
197
|
+
{0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b,}
|
198
|
+
,
|
199
|
+
{0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb,}
|
200
|
+
,
|
201
|
+
{0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe,}
|
202
|
+
,
|
203
|
+
{0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0,}
|
204
|
+
,
|
205
|
+
{0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93,}
|
206
|
+
,
|
207
|
+
{0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8,}
|
208
|
+
,
|
209
|
+
{0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8,}
|
210
|
+
,
|
211
|
+
{0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc,}
|
212
|
+
,
|
213
|
+
{0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17,}
|
214
|
+
,
|
215
|
+
{0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f,}
|
216
|
+
,
|
217
|
+
{0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde,}
|
218
|
+
,
|
219
|
+
{0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6,}
|
220
|
+
,
|
221
|
+
{0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad,}
|
222
|
+
,
|
223
|
+
{0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32,}
|
224
|
+
,
|
225
|
+
{0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71,}
|
226
|
+
,
|
227
|
+
{0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7,}
|
228
|
+
,
|
229
|
+
{0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12,}
|
230
|
+
,
|
231
|
+
{0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15,}
|
232
|
+
,
|
233
|
+
{0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31,}
|
234
|
+
,
|
235
|
+
{0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02,}
|
236
|
+
,
|
237
|
+
{0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca,}
|
238
|
+
,
|
239
|
+
{0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a,}
|
240
|
+
,
|
241
|
+
{0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e,}
|
242
|
+
,
|
243
|
+
{0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad,}
|
244
|
+
,
|
245
|
+
{0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18,}
|
246
|
+
,
|
247
|
+
{0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4,}
|
248
|
+
,
|
249
|
+
{0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9,}
|
250
|
+
,
|
251
|
+
{0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9,}
|
252
|
+
,
|
253
|
+
{0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb,}
|
254
|
+
,
|
255
|
+
{0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0,}
|
256
|
+
,
|
257
|
+
{0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6,}
|
258
|
+
,
|
259
|
+
{0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7,}
|
260
|
+
,
|
261
|
+
{0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee,}
|
262
|
+
,
|
263
|
+
{0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1,}
|
264
|
+
,
|
265
|
+
{0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a,}
|
266
|
+
,
|
267
|
+
{0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81,}
|
268
|
+
,
|
269
|
+
{0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f,}
|
270
|
+
,
|
271
|
+
{0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24,}
|
272
|
+
,
|
273
|
+
{0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7,}
|
274
|
+
,
|
275
|
+
{0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea,}
|
276
|
+
,
|
277
|
+
{0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60,}
|
278
|
+
,
|
279
|
+
{0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66,}
|
280
|
+
,
|
281
|
+
{0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c,}
|
282
|
+
,
|
283
|
+
{0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f,}
|
284
|
+
,
|
285
|
+
{0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5,}
|
286
|
+
,
|
287
|
+
{0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95,}
|
288
|
+
};
|
289
|
+
|
290
|
+
int rbtdb_siphash_test_vectors(void)
|
291
|
+
{
|
292
|
+
#define MAXLEN 64
|
293
|
+
u8 in[MAXLEN], out[8], k[16];
|
294
|
+
int i;
|
295
|
+
int ok = 1;
|
296
|
+
|
297
|
+
for (i = 0; i < 16; ++i)
|
298
|
+
k[i] = i;
|
299
|
+
|
300
|
+
for (i = 0; i < MAXLEN; ++i) {
|
301
|
+
in[i] = i;
|
302
|
+
crypto_auth(out, in, i, k);
|
303
|
+
|
304
|
+
if (memcmp(out, vectors[i], 8)) {
|
305
|
+
printf("test vector failed for %d bytes\n", i);
|
306
|
+
ok = 0;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
return ok;
|
311
|
+
}
|
312
|
+
|
313
|
+
unsigned int rbtdb_siphash24(TDB_DATA *data)
|
314
|
+
{
|
315
|
+
/* n.b.: tdb is for persistent storage, so the key must be constant */
|
316
|
+
static uint8_t key[] = "trivial database";
|
317
|
+
/* static const uint8_t check[(sizeof(key) >= 16)]; */
|
318
|
+
union {
|
319
|
+
uint32_t x32[2];
|
320
|
+
uint64_t x64;
|
321
|
+
} out;
|
322
|
+
unsigned char *in = data->dptr;
|
323
|
+
size_t len = data->dsize;
|
324
|
+
|
325
|
+
crypto_auth((unsigned char *)&out, in, len, key);
|
326
|
+
|
327
|
+
return (unsigned int)(out.x32[0] ^ out.x32[1]);
|
328
|
+
}
|
data/ext/tdb/tdb.c
CHANGED
@@ -3,17 +3,12 @@
|
|
3
3
|
#include <sys/stat.h>
|
4
4
|
#include <fcntl.h>
|
5
5
|
#include <errno.h>
|
6
|
-
#ifdef HAVE_RUBY_ST_H
|
7
|
-
# include <ruby/st.h>
|
8
|
-
#else
|
9
|
-
# include <st.h>
|
10
|
-
#endif
|
11
6
|
#include <pthread.h>
|
12
7
|
|
13
8
|
/* this protects the global list of tdb objects maintained by libtdb */
|
14
9
|
static pthread_mutex_t big_lock = PTHREAD_MUTEX_INITIALIZER;
|
15
10
|
static VALUE cTDB, cERR;
|
16
|
-
static
|
11
|
+
static VALUE exc_hash;
|
17
12
|
static VALUE hashes;
|
18
13
|
|
19
14
|
/* must be a macro to prevent GC from killing converted 'val's */
|
@@ -26,13 +21,14 @@ static VALUE hashes;
|
|
26
21
|
static void init_exc(enum TDB_ERROR ecode, const char *name)
|
27
22
|
{
|
28
23
|
VALUE exc = rb_define_class_under(cERR, name, cERR);
|
29
|
-
|
24
|
+
rb_hash_aset(exc_hash, INT2NUM(ecode), exc);
|
30
25
|
}
|
31
26
|
|
32
27
|
static void init_errors(void)
|
33
28
|
{
|
34
29
|
cERR = rb_define_class_under(cTDB, "ERR", rb_eStandardError);
|
35
|
-
exc_hash =
|
30
|
+
exc_hash = rb_hash_new();
|
31
|
+
rb_global_variable(&exc_hash);
|
36
32
|
|
37
33
|
init_exc(TDB_ERR_CORRUPT, "CORRUPT");
|
38
34
|
init_exc(TDB_ERR_IO, "IO");
|
@@ -53,7 +49,7 @@ static void my_raise(struct tdb_context *tdb)
|
|
53
49
|
{
|
54
50
|
enum TDB_ERROR ecode = tdb_error(tdb);
|
55
51
|
const char *str = tdb_errorstr(tdb);
|
56
|
-
VALUE exc;
|
52
|
+
VALUE exc = Qnil;
|
57
53
|
|
58
54
|
switch (ecode) {
|
59
55
|
case TDB_SUCCESS:
|
@@ -71,9 +67,10 @@ static void my_raise(struct tdb_context *tdb)
|
|
71
67
|
#ifdef HAVE_CONST_TDB_ERR_NESTING
|
72
68
|
case TDB_ERR_NESTING:
|
73
69
|
#endif /* HAVE_CONST_TDB_ERR_NESTING */
|
74
|
-
|
75
|
-
rb_bug("no-existent exception: %s\n", str);
|
70
|
+
exc = rb_hash_aref(exc_hash, INT2NUM(ecode));
|
76
71
|
}
|
72
|
+
if (NIL_P(exc))
|
73
|
+
rb_bug("no-existent exception: %s\n", str);
|
77
74
|
rb_raise(exc, str);
|
78
75
|
}
|
79
76
|
|
@@ -81,12 +78,15 @@ static void init_hashes(void)
|
|
81
78
|
{
|
82
79
|
#define HF(x) \
|
83
80
|
rb_hash_aset(hashes,ID2SYM(rb_intern(#x)),ULONG2NUM((unsigned long)rbtdb_##x))
|
81
|
+
HF(siphash24);
|
84
82
|
HF(murmur1);
|
85
83
|
HF(murmur1_aligned);
|
86
84
|
HF(murmur2);
|
87
85
|
HF(murmur2a);
|
88
86
|
HF(murmur2_neutral);
|
89
87
|
HF(murmur2_aligned);
|
88
|
+
HF(murmur3a);
|
89
|
+
HF(murmur3f);
|
90
90
|
HF(fnv1a);
|
91
91
|
HF(djb2);
|
92
92
|
HF(djb3);
|
@@ -94,26 +94,39 @@ rb_hash_aset(hashes,ID2SYM(rb_intern(#x)),ULONG2NUM((unsigned long)rbtdb_##x))
|
|
94
94
|
HF(default);
|
95
95
|
}
|
96
96
|
|
97
|
-
|
98
|
-
|
97
|
+
/* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
|
98
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) && \
|
99
|
+
defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
100
|
+
/*
|
101
|
+
* Ruby 1.9 - 2.1 (we use deprecated rb_thread_blocking_region in 2.0+
|
102
|
+
* because we can detect (but not use) rb_thread_blocking_region in 1.9.3
|
103
|
+
*/
|
104
|
+
typedef VALUE (*my_blocking_fn_t)(void*);
|
105
|
+
# define WITHOUT_GVL(fn,a,ubf,b) \
|
106
|
+
rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
|
107
|
+
#elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) /* Ruby 2.2+ */
|
108
|
+
#include <ruby/thread.h>
|
109
|
+
# define WITHOUT_GVL(fn,a,ubf,b) \
|
110
|
+
rb_thread_call_without_gvl((fn),(a),(ubf),(b))
|
111
|
+
#else /* Ruby 1.8 */
|
99
112
|
# include <rubysig.h>
|
100
|
-
|
101
|
-
|
113
|
+
# define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
114
|
+
typedef void rb_unblock_function_t(void *);
|
115
|
+
typedef void * rb_blocking_function_t(void *);
|
116
|
+
static void * WITHOUT_GVL(rb_blocking_function_t *func, void *data1,
|
117
|
+
rb_unblock_function_t *ubf, void *data2)
|
102
118
|
{
|
103
|
-
|
119
|
+
void *rv;
|
104
120
|
|
105
121
|
TRAP_BEG;
|
106
|
-
rv =
|
122
|
+
rv = func(data1);
|
107
123
|
TRAP_END;
|
108
124
|
|
109
125
|
return rv;
|
110
126
|
}
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
return rb_thread_blocking_region(fn, data, RUBY_UBF_IO, 0);
|
115
|
-
}
|
116
|
-
#endif /* HAVE_RUBY_THREAD_BLOCKING_REGION */
|
127
|
+
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
128
|
+
|
129
|
+
#define my_tbr(fn,data) WITHOUT_GVL((void *)(fn),(data),RUBY_UBF_IO,0)
|
117
130
|
|
118
131
|
static void gcfree(void *ptr)
|
119
132
|
{
|
@@ -154,7 +167,7 @@ struct open_args {
|
|
154
167
|
tdb_hash_func hash_fn;
|
155
168
|
};
|
156
169
|
|
157
|
-
static
|
170
|
+
static void * nogvl_open(void *ptr)
|
158
171
|
{
|
159
172
|
struct open_args *o = ptr;
|
160
173
|
struct tdb_context *tdb;
|
@@ -164,7 +177,7 @@ static VALUE nogvl_open(void *ptr)
|
|
164
177
|
o->open_flags, o->mode, o->log_ctx, o->hash_fn);
|
165
178
|
pthread_mutex_unlock(&big_lock);
|
166
179
|
|
167
|
-
return (
|
180
|
+
return (void *)tdb;
|
168
181
|
}
|
169
182
|
|
170
183
|
static void set_args(VALUE self, struct open_args *o, VALUE opts)
|
@@ -260,7 +273,7 @@ static VALUE init(int argc, VALUE *argv, VALUE self)
|
|
260
273
|
if (NIL_P(path))
|
261
274
|
o.tdb_flags |= TDB_INTERNAL;
|
262
275
|
else
|
263
|
-
o.name =
|
276
|
+
o.name = StringValueCStr(path);
|
264
277
|
|
265
278
|
tdb = (struct tdb_context *)my_tbr(nogvl_open, &o);
|
266
279
|
if (!tdb) {
|
@@ -280,16 +293,16 @@ static VALUE init(int argc, VALUE *argv, VALUE self)
|
|
280
293
|
}
|
281
294
|
|
282
295
|
/* tdb_close can do a lot, including cancel transactions an munmap */
|
283
|
-
static
|
296
|
+
static void * nogvl_close(void *ptr)
|
284
297
|
{
|
285
298
|
struct tdb_context *tdb = ptr;
|
286
|
-
|
299
|
+
long rv;
|
287
300
|
|
288
301
|
pthread_mutex_lock(&big_lock);
|
289
|
-
rv =
|
302
|
+
rv = tdb_close(tdb);
|
290
303
|
pthread_mutex_unlock(&big_lock);
|
291
304
|
|
292
|
-
return rv;
|
305
|
+
return (void *)rv;
|
293
306
|
}
|
294
307
|
|
295
308
|
static VALUE tdbclose(VALUE self)
|
@@ -298,7 +311,7 @@ static VALUE tdbclose(VALUE self)
|
|
298
311
|
|
299
312
|
DATA_PTR(self) = NULL;
|
300
313
|
|
301
|
-
if ((
|
314
|
+
if ((long)my_tbr(nogvl_close, tdb) == -1)
|
302
315
|
rb_sys_fail("tdb_close");
|
303
316
|
|
304
317
|
return Qnil;
|
@@ -365,14 +378,14 @@ static int fetch_parse(TDB_DATA key, TDB_DATA val, void *data)
|
|
365
378
|
return 0;
|
366
379
|
}
|
367
380
|
|
368
|
-
static
|
381
|
+
static void * nogvl_parse_record(void *ptr)
|
369
382
|
{
|
370
383
|
struct fetch_parse_args *f = ptr;
|
371
384
|
|
372
385
|
if (tdb_parse_record(f->tdb, f->as.key, fetch_parse, ptr) == -1)
|
373
|
-
return Qnil;
|
386
|
+
return (void *)Qnil;
|
374
387
|
|
375
|
-
return f->value == f->as.value ? f->value : Qnil;
|
388
|
+
return (void *)(f->value == f->as.value ? f->value : Qnil);
|
376
389
|
}
|
377
390
|
|
378
391
|
static VALUE fetch(int argc, VALUE *argv, VALUE self)
|
@@ -391,7 +404,7 @@ static VALUE fetch(int argc, VALUE *argv, VALUE self)
|
|
391
404
|
f.tdb = db(self, 1);
|
392
405
|
TO_TDB_DATA(f.as.key, key);
|
393
406
|
|
394
|
-
return my_tbr(nogvl_parse_record, &f);
|
407
|
+
return (VALUE)my_tbr(nogvl_parse_record, &f);
|
395
408
|
}
|
396
409
|
|
397
410
|
struct store_args {
|
@@ -401,11 +414,12 @@ struct store_args {
|
|
401
414
|
int flag;
|
402
415
|
};
|
403
416
|
|
404
|
-
static
|
417
|
+
static void * nogvl_store(void *ptr)
|
405
418
|
{
|
406
419
|
struct store_args *s = ptr;
|
420
|
+
long rc = tdb_store(s->tdb, s->key, s->val, s->flag);
|
407
421
|
|
408
|
-
return (
|
422
|
+
return (void *)rc;
|
409
423
|
}
|
410
424
|
|
411
425
|
static VALUE rbtdb_store(VALUE self, VALUE key, VALUE val, int flag, int soft)
|
@@ -417,7 +431,7 @@ static VALUE rbtdb_store(VALUE self, VALUE key, VALUE val, int flag, int soft)
|
|
417
431
|
TO_TDB_DATA(s.val, val);
|
418
432
|
s.flag = flag;
|
419
433
|
|
420
|
-
if ((
|
434
|
+
if ((long)my_tbr(nogvl_store, &s) == -1) {
|
421
435
|
if (soft) {
|
422
436
|
int ecode = tdb_error(s.tdb);
|
423
437
|
|
@@ -462,11 +476,11 @@ struct exists_args {
|
|
462
476
|
TDB_DATA key;
|
463
477
|
};
|
464
478
|
|
465
|
-
static
|
479
|
+
static void * nogvl_exists(void *ptr)
|
466
480
|
{
|
467
481
|
struct exists_args *e = ptr;
|
468
482
|
|
469
|
-
return tdb_exists(e->tdb, e->key) == 0 ? Qfalse : Qtrue;
|
483
|
+
return (void *)(tdb_exists(e->tdb, e->key) == 0 ? Qfalse : Qtrue);
|
470
484
|
}
|
471
485
|
|
472
486
|
static VALUE has_key(VALUE self, VALUE key)
|
@@ -476,7 +490,7 @@ static VALUE has_key(VALUE self, VALUE key)
|
|
476
490
|
e.tdb = db(self, 1);
|
477
491
|
TO_TDB_DATA(e.key, key);
|
478
492
|
|
479
|
-
return my_tbr(nogvl_exists, &e);
|
493
|
+
return (VALUE)my_tbr(nogvl_exists, &e);
|
480
494
|
}
|
481
495
|
|
482
496
|
struct traverse_args {
|
@@ -518,13 +532,13 @@ traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, void *data)
|
|
518
532
|
return t->state;
|
519
533
|
}
|
520
534
|
|
521
|
-
static
|
535
|
+
static void * nogvl_traverse(void *ptr)
|
522
536
|
{
|
523
537
|
struct traverse_args *t = ptr;
|
524
538
|
|
525
539
|
(void)tdb_traverse(t->tdb, traverse_fn, t);
|
526
540
|
|
527
|
-
return Qfalse;
|
541
|
+
return (void *)Qfalse;
|
528
542
|
}
|
529
543
|
|
530
544
|
static VALUE each(VALUE self)
|
@@ -545,11 +559,11 @@ struct delete_args {
|
|
545
559
|
TDB_DATA key;
|
546
560
|
};
|
547
561
|
|
548
|
-
static
|
562
|
+
static void * nogvl_delete(void *ptr)
|
549
563
|
{
|
550
564
|
struct delete_args *d = ptr;
|
551
565
|
|
552
|
-
return tdb_delete(d->tdb, d->key) == 0 ? Qtrue : Qfalse;
|
566
|
+
return (void *)(tdb_delete(d->tdb, d->key) == 0 ? Qtrue : Qfalse);
|
553
567
|
}
|
554
568
|
|
555
569
|
static VALUE nuke(VALUE self, VALUE key)
|
@@ -559,7 +573,7 @@ static VALUE nuke(VALUE self, VALUE key)
|
|
559
573
|
d.tdb = db(self, 1);
|
560
574
|
TO_TDB_DATA(d.key, key);
|
561
575
|
|
562
|
-
return my_tbr(nogvl_delete, &d);
|
576
|
+
return (VALUE)my_tbr(nogvl_delete, &d);
|
563
577
|
}
|
564
578
|
|
565
579
|
static VALUE aref(VALUE self, VALUE key)
|
@@ -580,7 +594,7 @@ static VALUE delete(int argc, VALUE *argv, VALUE self)
|
|
580
594
|
static VALUE lockall(VALUE self)
|
581
595
|
{
|
582
596
|
struct tdb_context *tdb = db(self, 1);
|
583
|
-
if (
|
597
|
+
if (my_tbr(tdb_lockall, tdb))
|
584
598
|
my_raise(tdb);
|
585
599
|
|
586
600
|
return Qtrue;
|
@@ -591,7 +605,7 @@ static VALUE trylockall(VALUE self)
|
|
591
605
|
struct tdb_context *tdb = db(self, 1);
|
592
606
|
void *fn = tdb_lockall_nonblock;
|
593
607
|
|
594
|
-
if (
|
608
|
+
if (my_tbr(fn, tdb)) {
|
595
609
|
if (tdb_error(tdb) == TDB_ERR_LOCK)
|
596
610
|
return Qfalse;
|
597
611
|
my_raise(tdb);
|
@@ -602,7 +616,7 @@ static VALUE trylockall(VALUE self)
|
|
602
616
|
static VALUE unlockall(VALUE self)
|
603
617
|
{
|
604
618
|
struct tdb_context *tdb = db(self, 1);
|
605
|
-
if (
|
619
|
+
if (my_tbr(tdb_unlockall, tdb))
|
606
620
|
my_raise(tdb);
|
607
621
|
return Qtrue;
|
608
622
|
}
|
@@ -610,7 +624,7 @@ static VALUE unlockall(VALUE self)
|
|
610
624
|
static VALUE lockall_read(VALUE self)
|
611
625
|
{
|
612
626
|
struct tdb_context *tdb = db(self, 1);
|
613
|
-
if (
|
627
|
+
if (my_tbr(tdb_lockall_read, tdb))
|
614
628
|
my_raise(tdb);
|
615
629
|
return Qtrue;
|
616
630
|
}
|
@@ -619,7 +633,7 @@ static VALUE trylockall_read(VALUE self)
|
|
619
633
|
{
|
620
634
|
struct tdb_context *tdb = db(self, 1);
|
621
635
|
void *fn = tdb_lockall_read_nonblock;
|
622
|
-
if (
|
636
|
+
if (my_tbr(fn, tdb)) {
|
623
637
|
if (tdb_error(tdb) == TDB_ERR_LOCK)
|
624
638
|
return Qfalse;
|
625
639
|
my_raise(tdb);
|
@@ -630,7 +644,7 @@ static VALUE trylockall_read(VALUE self)
|
|
630
644
|
static VALUE unlockall_read(VALUE self)
|
631
645
|
{
|
632
646
|
struct tdb_context *tdb = db(self, 1);
|
633
|
-
if (
|
647
|
+
if (my_tbr(tdb_unlockall_read, tdb))
|
634
648
|
my_raise(tdb);
|
635
649
|
return Qtrue;
|
636
650
|
}
|
@@ -638,7 +652,7 @@ static VALUE unlockall_read(VALUE self)
|
|
638
652
|
static VALUE lockall_mark(VALUE self)
|
639
653
|
{
|
640
654
|
struct tdb_context *tdb = db(self, 1);
|
641
|
-
if (
|
655
|
+
if (my_tbr(tdb_lockall_mark, tdb))
|
642
656
|
my_raise(tdb);
|
643
657
|
return Qtrue;
|
644
658
|
}
|
@@ -646,7 +660,8 @@ static VALUE lockall_mark(VALUE self)
|
|
646
660
|
static VALUE lockall_unmark(VALUE self)
|
647
661
|
{
|
648
662
|
struct tdb_context *tdb = db(self, 1);
|
649
|
-
|
663
|
+
|
664
|
+
if (my_tbr(tdb_lockall_unmark, tdb))
|
650
665
|
my_raise(tdb);
|
651
666
|
return Qtrue;
|
652
667
|
}
|
@@ -657,7 +672,7 @@ static VALUE lockall_unmark(VALUE self)
|
|
657
672
|
static VALUE clear(VALUE self)
|
658
673
|
{
|
659
674
|
struct tdb_context *tdb = db(self, 1);
|
660
|
-
if (
|
675
|
+
if (my_tbr(tdb_wipe_all, tdb))
|
661
676
|
my_raise(tdb);
|
662
677
|
return self;
|
663
678
|
}
|
@@ -667,7 +682,7 @@ static VALUE clear(VALUE self)
|
|
667
682
|
static VALUE repack(VALUE self)
|
668
683
|
{
|
669
684
|
struct tdb_context *tdb = db(self, 1);
|
670
|
-
if (
|
685
|
+
if (my_tbr(tdb_repack, tdb))
|
671
686
|
my_raise(tdb);
|
672
687
|
return self;
|
673
688
|
}
|