tdb 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|