lmdb 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +8 -0
- data/Gemfile +1 -1
- data/README.md +4 -0
- data/ext/lmdb_ext/extconf.rb +2 -0
- data/ext/lmdb_ext/lmdb_ext.c +533 -585
- data/ext/lmdb_ext/lmdb_ext.h +124 -0
- data/ext/lmdb_ext/prototypes.sh +4 -0
- data/lib/lmdb.rb +22 -7
- data/lmdb.gemspec +13 -13
- data/spec/helper.rb +28 -0
- data/spec/lmdb_spec.rb +260 -35
- metadata +7 -13
- data/lib/lmdb/database.rb +0 -66
- data/lib/lmdb/environment.rb +0 -135
- data/spec/lmdb/database_spec.rb +0 -23
- data/spec/lmdb/environment_spec.rb +0 -22
- data/spec/lmdb/lmdb_ext_spec.rb +0 -253
- data/spec/spec_helper.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e261f77741383fa6cfe1b174ed0856a76d18d92e
|
4
|
+
data.tar.gz: b44bb1ca05ec5dfec80b13ee9bdac03a3b745e83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2980d425391ff3ddb32210c7c05970927836648355ed9e31c18fad1e48f32b234ec4c8b9a6509c2b19afaf7e54f4391835fc136c0c61b716733760c103f1d22d
|
7
|
+
data.tar.gz: 3abc9db5742fac65951e9bc62f0f8c0ed8ebcc7b6625ca336f5fdeda925c3f7b72bc8bff51a3558101de8bee833862725d14a4e34dd5f70316301888e522753e
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
gemspec
|
data/README.md
CHANGED
data/ext/lmdb_ext/extconf.rb
CHANGED
data/ext/lmdb_ext/lmdb_ext.c
CHANGED
@@ -1,725 +1,673 @@
|
|
1
|
-
#include "
|
2
|
-
#include "lmdb.h"
|
3
|
-
|
4
|
-
/*-----------------------------------------------------------------------------
|
5
|
-
* Macros
|
6
|
-
*----------------------------------------------------------------------------*/
|
7
|
-
|
8
|
-
#define ENV_FLAGS ( \
|
9
|
-
MDB_FIXEDMAP | \
|
10
|
-
MDB_NOSUBDIR | \
|
11
|
-
MDB_NOSYNC | \
|
12
|
-
MDB_RDONLY | \
|
13
|
-
MDB_NOMETASYNC | \
|
14
|
-
MDB_WRITEMAP | \
|
15
|
-
MDB_MAPASYNC)
|
16
|
-
|
17
|
-
#define ENVIRONMENT(var, var_env) \
|
18
|
-
Environment* var_env; \
|
19
|
-
Data_Get_Struct(var, Environment, var_env); \
|
20
|
-
do { if (!var_env->env) rb_raise(cError, "Environment is closed"); } while(0)
|
21
|
-
|
22
|
-
#define TRANSACTION(var, var_txn, var_env) \
|
23
|
-
Transaction* var_txn; \
|
24
|
-
Data_Get_Struct(var, Transaction, var_txn); \
|
25
|
-
{ \
|
26
|
-
Transaction* parent = var_txn; \
|
27
|
-
for (;;) { \
|
28
|
-
if (!parent->txn) \
|
29
|
-
rb_raise(cError, "Transaction is terminated"); \
|
30
|
-
if (NIL_P(parent->parent)) \
|
31
|
-
break; \
|
32
|
-
Data_Get_Struct(parent->parent, Transaction, parent); \
|
33
|
-
} \
|
34
|
-
} \
|
35
|
-
ENVIRONMENT(transaction->environment, var_env)
|
36
|
-
|
37
|
-
#define DATABASE(var, var_db, var_env) \
|
38
|
-
Database* var_db; \
|
39
|
-
Data_Get_Struct(var, Database, var_db); \
|
40
|
-
if (!var_db->open) rb_raise(cError, "Database is closed"); \
|
41
|
-
ENVIRONMENT(database->environment, var_env)
|
42
|
-
|
43
|
-
#define DATABASE_TRANSACTION(dbvar, txvar, var_db, var_txn, var_env) \
|
44
|
-
DATABASE(dbvar, var_db, tmp_env); \
|
45
|
-
TRANSACTION(txvar, var_txn, var_env); \
|
46
|
-
do { if (var_env != tmp_env) rb_raise(cError, "Different environments"); } while(0) \
|
47
|
-
|
48
|
-
#define CURSOR(var, var_cur, var_db, var_txn, var_env) \
|
49
|
-
Cursor* var_cur; \
|
50
|
-
Data_Get_Struct(var, Cursor, var_cur); \
|
51
|
-
if (!cursor->cur) rb_raise(cError, "Cursor is closed"); \
|
52
|
-
DATABASE_TRANSACTION(var_cur->database, var_cur->transaction, var_db, var_txn, var_env)
|
53
|
-
|
54
|
-
/*-----------------------------------------------------------------------------
|
55
|
-
* Static
|
56
|
-
*----------------------------------------------------------------------------*/
|
57
|
-
|
58
|
-
/* Classes */
|
59
|
-
static VALUE cEnvironment, cStat, cInfo, cDatabase, cTransaction, cCursor, cError;
|
60
|
-
|
61
|
-
/* Error Classes */
|
62
|
-
#define ERROR(name) static VALUE cError_##name;
|
63
|
-
#include "errors.h"
|
64
|
-
#undef ERROR
|
65
|
-
|
66
|
-
/*-----------------------------------------------------------------------------
|
67
|
-
* Structs
|
68
|
-
*----------------------------------------------------------------------------*/
|
69
|
-
|
70
|
-
typedef struct {
|
71
|
-
MDB_env* env;
|
72
|
-
} Environment;
|
73
|
-
|
74
|
-
typedef struct {
|
75
|
-
VALUE environment;
|
76
|
-
MDB_dbi dbi;
|
77
|
-
int open;
|
78
|
-
} Database;
|
79
|
-
|
80
|
-
typedef struct {
|
81
|
-
VALUE environment;
|
82
|
-
VALUE parent;
|
83
|
-
MDB_txn* txn;
|
84
|
-
} Transaction;
|
85
|
-
|
86
|
-
typedef struct {
|
87
|
-
VALUE transaction;
|
88
|
-
VALUE database;
|
89
|
-
MDB_cursor* cur;
|
90
|
-
} Cursor;
|
91
|
-
|
92
|
-
/*-----------------------------------------------------------------------------
|
93
|
-
* Prototypes
|
94
|
-
*----------------------------------------------------------------------------*/
|
95
|
-
|
96
|
-
static void transaction_mark(Transaction* transaction);
|
97
|
-
static void transaction_free(Transaction *transaction);
|
98
|
-
|
99
|
-
/*-----------------------------------------------------------------------------
|
100
|
-
* Helpers
|
101
|
-
*----------------------------------------------------------------------------*/
|
102
|
-
|
103
|
-
#define F_STAT(name) \
|
104
|
-
static VALUE stat_##name(VALUE self) { \
|
105
|
-
MDB_stat* stat; \
|
106
|
-
Data_Get_Struct(self, MDB_stat, stat); \
|
107
|
-
return INT2NUM(stat->ms_##name); \
|
108
|
-
}
|
109
|
-
F_STAT(psize)
|
110
|
-
F_STAT(depth)
|
111
|
-
F_STAT(branch_pages)
|
112
|
-
F_STAT(leaf_pages)
|
113
|
-
F_STAT(overflow_pages)
|
114
|
-
F_STAT(entries)
|
115
|
-
#undef F_STAT
|
116
|
-
|
117
|
-
#define F_INFO(name) \
|
118
|
-
static VALUE info_##name(VALUE self) { \
|
119
|
-
MDB_envinfo* info; \
|
120
|
-
Data_Get_Struct(self, MDB_envinfo, info); \
|
121
|
-
return INT2NUM((size_t)info->me_##name); \
|
122
|
-
}
|
123
|
-
F_INFO(mapaddr)
|
124
|
-
F_INFO(mapsize)
|
125
|
-
F_INFO(last_pgno)
|
126
|
-
F_INFO(last_txnid)
|
127
|
-
F_INFO(maxreaders)
|
128
|
-
F_INFO(numreaders)
|
129
|
-
#undef F_INFO
|
1
|
+
#include "lmdb_ext.h"
|
130
2
|
|
131
3
|
static void check(int code) {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
err = mdb_strerror(code);
|
136
|
-
sep = strchr(err, ':');
|
137
|
-
if (sep) err = sep + 2;
|
4
|
+
if (!code)
|
5
|
+
return;
|
138
6
|
|
139
|
-
|
140
|
-
|
141
|
-
|
7
|
+
const char* err = mdb_strerror(code);
|
8
|
+
const char* sep = strchr(err, ':');
|
9
|
+
if (sep)
|
10
|
+
err = sep + 2;
|
142
11
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
/*-----------------------------------------------------------------------------
|
148
|
-
* Environment functions
|
149
|
-
*----------------------------------------------------------------------------*/
|
12
|
+
#define ERROR(name) if (code == MDB_##name) rb_raise(cError_##name, "%s", err);
|
13
|
+
#include "errors.h"
|
14
|
+
#undef ERROR
|
150
15
|
|
151
|
-
|
152
|
-
if (environment->env)
|
153
|
-
mdb_env_close(environment->env);
|
154
|
-
free(environment);
|
16
|
+
rb_raise(cError, "%s", err); /* fallback */
|
155
17
|
}
|
156
18
|
|
157
|
-
static
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
19
|
+
static void transaction_deref(Transaction* transaction) {
|
20
|
+
if (--transaction->refcount == 0) {
|
21
|
+
Environment* env = (Environment*)DATA_PTR(transaction->env);
|
22
|
+
environment_deref(env);
|
23
|
+
if (!NIL_P(transaction->parent)) {
|
24
|
+
Transaction* parent = (Transaction*)DATA_PTR(transaction->parent);
|
25
|
+
transaction_deref(parent);
|
26
|
+
}
|
27
|
+
if (transaction->txn)
|
28
|
+
mdb_txn_abort(transaction->txn);
|
29
|
+
free(transaction);
|
30
|
+
}
|
162
31
|
}
|
163
32
|
|
164
|
-
static
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
ENVIRONMENT(self, environment);
|
169
|
-
vstat = Data_Make_Struct(cStat, MDB_stat, 0, -1, stat);
|
170
|
-
check(mdb_env_stat(environment->env, stat));
|
171
|
-
return vstat;
|
33
|
+
static void transaction_mark(Transaction* transaction) {
|
34
|
+
rb_gc_mark(transaction->parent);
|
35
|
+
rb_gc_mark(transaction->env);
|
172
36
|
}
|
173
37
|
|
174
|
-
static VALUE
|
175
|
-
|
176
|
-
|
38
|
+
static VALUE transaction_commit(VALUE self) {
|
39
|
+
TRANSACTION(self, transaction);
|
40
|
+
ENVIRONMENT(transaction->env, environment);
|
41
|
+
if (!transaction->txn)
|
42
|
+
rb_raise(cError, "Transaction is terminated");
|
177
43
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
44
|
+
// Check nesting
|
45
|
+
VALUE p = environment->txn;
|
46
|
+
while (!NIL_P(p) && p != self) {
|
47
|
+
TRANSACTION(p, txn);
|
48
|
+
p = txn->parent;
|
49
|
+
}
|
50
|
+
if (p != self)
|
51
|
+
rb_raise(cError, "Transaction is not active");
|
183
52
|
|
184
|
-
|
185
|
-
ENVIRONMENT(self, environment);
|
186
|
-
check(mdb_env_copy(environment->env, StringValueCStr(path)));
|
187
|
-
return Qnil;
|
188
|
-
}
|
53
|
+
mdb_txn_commit(transaction->txn);
|
189
54
|
|
190
|
-
|
191
|
-
|
192
|
-
|
55
|
+
p = environment->txn;
|
56
|
+
while (p != self) {
|
57
|
+
TRANSACTION(p, txn);
|
58
|
+
txn->txn = 0;
|
59
|
+
p = txn->parent;
|
60
|
+
}
|
61
|
+
transaction->txn = 0;
|
193
62
|
|
194
|
-
|
195
|
-
|
196
|
-
check(mdb_env_sync(environment->env, n == 1 && RTEST(force) ? 0 : 1));
|
197
|
-
return Qnil;
|
63
|
+
environment->txn = transaction->parent;
|
64
|
+
return Qnil;
|
198
65
|
}
|
199
66
|
|
200
|
-
static VALUE
|
201
|
-
|
202
|
-
|
203
|
-
Environment* environment;
|
204
|
-
|
205
|
-
int n = rb_scan_args(argc, argv, "11", &path, &options);
|
206
|
-
|
207
|
-
int flags = 0, maxreaders = -1, maxdbs = 10;
|
208
|
-
size_t mapsize = 0;
|
209
|
-
mode_t mode = 0755;
|
210
|
-
if (n == 2) {
|
211
|
-
VALUE value = rb_hash_aref(options, ID2SYM(rb_intern("flags")));
|
212
|
-
if (!NIL_P(value))
|
213
|
-
flags = NUM2INT(value);
|
214
|
-
|
215
|
-
value = rb_hash_aref(options, ID2SYM(rb_intern("mode")));
|
216
|
-
if (!NIL_P(value))
|
217
|
-
mode = NUM2INT(value);
|
218
|
-
|
219
|
-
value = rb_hash_aref(options, ID2SYM(rb_intern("maxreaders")));
|
220
|
-
if (!NIL_P(value))
|
221
|
-
maxreaders = NUM2INT(value);
|
222
|
-
|
223
|
-
value = rb_hash_aref(options, ID2SYM(rb_intern("maxdbs")));
|
224
|
-
if (!NIL_P(value))
|
225
|
-
maxdbs = NUM2INT(value);
|
67
|
+
static VALUE transaction_abort(VALUE self) {
|
68
|
+
TRANSACTION(self, transaction);
|
69
|
+
ENVIRONMENT(transaction->env, environment);
|
226
70
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
71
|
+
// Check nesting
|
72
|
+
VALUE p = environment->txn;
|
73
|
+
while (!NIL_P(p) && p != self) {
|
74
|
+
TRANSACTION(p, txn);
|
75
|
+
p = txn->parent;
|
76
|
+
}
|
77
|
+
if (p != self)
|
78
|
+
rb_raise(cError, "Transaction is not active");
|
233
79
|
|
234
|
-
|
235
|
-
|
80
|
+
if (!transaction->txn)
|
81
|
+
rb_raise(cError, "Transaction is terminated");
|
82
|
+
mdb_txn_abort(transaction->txn);
|
236
83
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
84
|
+
p = environment->txn;
|
85
|
+
while (p != self) {
|
86
|
+
TRANSACTION(p, txn);
|
87
|
+
txn->txn = 0;
|
88
|
+
p = txn->parent;
|
89
|
+
} while (p != self);
|
90
|
+
transaction->txn = 0;
|
241
91
|
|
242
|
-
|
243
|
-
|
244
|
-
if (rb_block_given_p())
|
245
|
-
return rb_ensure(rb_yield, venv, environment_close, venv);
|
246
|
-
return venv;
|
92
|
+
environment->txn = transaction->parent;
|
93
|
+
return Qnil;
|
247
94
|
}
|
248
95
|
|
249
|
-
static VALUE
|
250
|
-
|
251
|
-
|
252
|
-
check(mdb_env_get_flags(environment->env, &flags));
|
253
|
-
return INT2NUM(flags & ENV_FLAGS);
|
96
|
+
static VALUE call_with_transaction_helper(VALUE arg) {
|
97
|
+
HelperArgs* a = (HelperArgs*)arg;
|
98
|
+
return rb_funcall_passing_block(a->self, rb_intern(a->name), a->argc, a->argv);
|
254
99
|
}
|
255
100
|
|
256
|
-
static VALUE
|
257
|
-
|
258
|
-
|
259
|
-
check(mdb_env_get_path(environment->env, &path));
|
260
|
-
return rb_str_new2(path);
|
101
|
+
static VALUE call_with_transaction(VALUE venv, VALUE self, const char* name, int argc, const VALUE* argv, int flags) {
|
102
|
+
HelperArgs arg = { self, name, argc, argv };
|
103
|
+
return with_transaction(venv, call_with_transaction_helper, (VALUE)&arg, flags);
|
261
104
|
}
|
262
105
|
|
263
|
-
static VALUE
|
264
|
-
|
265
|
-
ENVIRONMENT(self, environment);
|
266
|
-
check(mdb_env_get_flags(environment->env, &oldflags));
|
267
|
-
check(mdb_env_set_flags(environment->env, oldflags & ENV_FLAGS, 0));
|
268
|
-
check(mdb_env_set_flags(environment->env, flags, 1));
|
269
|
-
return environment_flags(self);
|
270
|
-
}
|
106
|
+
static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flags) {
|
107
|
+
ENVIRONMENT(venv, environment);
|
271
108
|
|
272
|
-
|
273
|
-
|
274
|
-
MDB_txn* txn;
|
275
|
-
unsigned int flags;
|
276
|
-
Transaction* transaction;
|
277
|
-
|
278
|
-
ENVIRONMENT(self, environment);
|
279
|
-
flags = (rb_scan_args(argc, argv, "01", &readonly) == 1 && !NIL_P(readonly)) ? MDB_RDONLY : 0;
|
280
|
-
check(mdb_txn_begin(environment->env, 0, flags, &txn));
|
109
|
+
MDB_txn* txn;
|
110
|
+
check(mdb_txn_begin(environment->env, environment_txn(venv), flags, &txn));
|
281
111
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
112
|
+
Transaction* transaction;
|
113
|
+
VALUE vtxn = Data_Make_Struct(cTransaction, Transaction, transaction_mark, transaction_deref, transaction);
|
114
|
+
transaction->refcount = 1;
|
115
|
+
transaction->parent = environment->txn;
|
116
|
+
transaction->env = venv;
|
117
|
+
transaction->txn = txn;
|
118
|
+
environment->txn = vtxn;
|
286
119
|
|
287
|
-
if (rb_block_given_p()) {
|
288
120
|
int exception;
|
289
|
-
VALUE result = rb_protect(
|
121
|
+
VALUE result = rb_protect(fn, NIL_P(arg) ? vtxn : arg, &exception);
|
122
|
+
|
290
123
|
if (exception) {
|
291
|
-
|
292
|
-
|
293
|
-
|
124
|
+
if (vtxn == environment->txn)
|
125
|
+
transaction_abort(vtxn);
|
126
|
+
rb_jump_tag(exception);
|
294
127
|
}
|
295
|
-
|
296
|
-
|
128
|
+
if (vtxn == environment->txn)
|
129
|
+
transaction_commit(vtxn);
|
297
130
|
return result;
|
298
|
-
}
|
299
|
-
return vtxn;
|
300
131
|
}
|
301
132
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
static VALUE transaction_environment(VALUE self) {
|
307
|
-
TRANSACTION(self, transaction, environment);
|
308
|
-
return transaction->environment;
|
133
|
+
static void environment_check(Environment* environment) {
|
134
|
+
if (!environment->env)
|
135
|
+
rb_raise(cError, "Environment is closed");
|
309
136
|
}
|
310
137
|
|
311
|
-
static
|
312
|
-
|
313
|
-
|
138
|
+
static void environment_deref(Environment *environment) {
|
139
|
+
if (--environment->refcount == 0) {
|
140
|
+
if (environment->env)
|
141
|
+
mdb_env_close(environment->env);
|
142
|
+
free(environment);
|
143
|
+
}
|
314
144
|
}
|
315
145
|
|
316
|
-
static
|
317
|
-
|
318
|
-
|
146
|
+
static VALUE environment_close(VALUE self) {
|
147
|
+
ENVIRONMENT(self, environment);
|
148
|
+
mdb_env_close(environment->env);
|
149
|
+
environment->env = 0;
|
150
|
+
return Qnil;
|
319
151
|
}
|
320
152
|
|
321
|
-
static
|
322
|
-
|
323
|
-
mdb_txn_abort(transaction->txn);
|
324
|
-
free(transaction);
|
325
|
-
}
|
153
|
+
static VALUE stat2hash(const MDB_stat* stat) {
|
154
|
+
VALUE result = rb_hash_new();
|
326
155
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
156
|
+
#define STAT_SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), INT2NUM(stat->ms_##name))
|
157
|
+
STAT_SET(psize);
|
158
|
+
STAT_SET(depth);
|
159
|
+
STAT_SET(branch_pages);
|
160
|
+
STAT_SET(leaf_pages);
|
161
|
+
STAT_SET(overflow_pages);
|
162
|
+
STAT_SET(entries);
|
163
|
+
#undef STAT_SET
|
333
164
|
|
334
|
-
|
335
|
-
TRANSACTION(self, transaction, environment);
|
336
|
-
mdb_txn_commit(transaction->txn);
|
337
|
-
transaction->txn = 0;
|
338
|
-
return Qnil;
|
165
|
+
return result;
|
339
166
|
}
|
340
167
|
|
341
|
-
VALUE
|
342
|
-
|
343
|
-
|
344
|
-
|
168
|
+
static VALUE environment_stat(VALUE self) {
|
169
|
+
ENVIRONMENT(self, environment);
|
170
|
+
MDB_stat stat;
|
171
|
+
check(mdb_env_stat(environment->env, &stat));
|
172
|
+
return stat2hash(&stat);
|
345
173
|
}
|
346
174
|
|
347
|
-
VALUE
|
348
|
-
|
349
|
-
mdb_txn_reset(transaction->txn);
|
350
|
-
return Qnil;
|
351
|
-
}
|
175
|
+
static VALUE environment_info(VALUE self) {
|
176
|
+
MDB_envinfo info;
|
352
177
|
|
353
|
-
|
354
|
-
|
355
|
-
Transaction* child;
|
356
|
-
VALUE vtxn;
|
178
|
+
ENVIRONMENT(self, environment);
|
179
|
+
check(mdb_env_info(environment->env, &info));
|
357
180
|
|
358
|
-
|
359
|
-
check(mdb_txn_begin(environment->env, transaction->txn, 0, &txn));
|
181
|
+
VALUE result = rb_hash_new();
|
360
182
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
183
|
+
#define INFO_SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), INT2NUM((size_t)info.me_##name));
|
184
|
+
INFO_SET(mapaddr);
|
185
|
+
INFO_SET(mapsize);
|
186
|
+
INFO_SET(last_pgno);
|
187
|
+
INFO_SET(last_txnid);
|
188
|
+
INFO_SET(maxreaders);
|
189
|
+
INFO_SET(numreaders);
|
190
|
+
#undef INFO_SET
|
365
191
|
|
366
|
-
if (rb_block_given_p()) {
|
367
|
-
int exception;
|
368
|
-
VALUE result = rb_protect(rb_yield, vtxn, &exception);
|
369
|
-
if (exception) {
|
370
|
-
mdb_txn_abort(child->txn);
|
371
|
-
child->txn = 0;
|
372
|
-
rb_jump_tag(exception);
|
373
|
-
}
|
374
|
-
mdb_txn_commit(child->txn);
|
375
|
-
child->txn = 0;
|
376
192
|
return result;
|
377
|
-
}
|
378
|
-
return vtxn;
|
379
193
|
}
|
380
194
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
static VALUE database_environment(VALUE self) {
|
386
|
-
DATABASE(self, database, environment);
|
387
|
-
return database->environment;
|
195
|
+
static VALUE environment_copy(VALUE self, VALUE path) {
|
196
|
+
ENVIRONMENT(self, environment);
|
197
|
+
check(mdb_env_copy(environment->env, StringValueCStr(path)));
|
198
|
+
return Qnil;
|
388
199
|
}
|
389
200
|
|
390
|
-
static
|
391
|
-
|
392
|
-
ENVIRONMENT(database->environment, environment);
|
393
|
-
mdb_dbi_close(environment->env, database->dbi);
|
394
|
-
}
|
395
|
-
free(database);
|
396
|
-
}
|
201
|
+
static VALUE environment_sync(int argc, VALUE *argv, VALUE self) {
|
202
|
+
ENVIRONMENT(self, environment);
|
397
203
|
|
398
|
-
|
399
|
-
|
204
|
+
VALUE force;
|
205
|
+
rb_scan_args(argc, argv, "01", &force);
|
206
|
+
|
207
|
+
check(mdb_env_sync(environment->env, RTEST(force)));
|
208
|
+
return Qnil;
|
400
209
|
}
|
401
210
|
|
402
|
-
static VALUE
|
403
|
-
|
211
|
+
static VALUE environment_open(int argc, VALUE *argv, VALUE klass) {
|
212
|
+
VALUE path, options;
|
213
|
+
rb_scan_args(argc, argv, "11", &path, &options);
|
214
|
+
|
215
|
+
int flags = 0, maxreaders = -1, maxdbs = 10;
|
216
|
+
size_t mapsize = 0;
|
217
|
+
mode_t mode = 0755;
|
218
|
+
if (!NIL_P(options)) {
|
219
|
+
VALUE value = rb_hash_aref(options, ID2SYM(rb_intern("flags")));
|
220
|
+
if (!NIL_P(value))
|
221
|
+
flags = NUM2INT(value);
|
222
|
+
|
223
|
+
value = rb_hash_aref(options, ID2SYM(rb_intern("mode")));
|
224
|
+
if (!NIL_P(value))
|
225
|
+
mode = NUM2INT(value);
|
226
|
+
|
227
|
+
value = rb_hash_aref(options, ID2SYM(rb_intern("maxreaders")));
|
228
|
+
if (!NIL_P(value))
|
229
|
+
maxreaders = NUM2INT(value);
|
230
|
+
|
231
|
+
value = rb_hash_aref(options, ID2SYM(rb_intern("maxdbs")));
|
232
|
+
if (!NIL_P(value))
|
233
|
+
maxdbs = NUM2INT(value);
|
234
|
+
|
235
|
+
value = rb_hash_aref(options, ID2SYM(rb_intern("mapsize")));
|
236
|
+
if (!NIL_P(value))
|
237
|
+
mapsize = NUM2SIZET(value);
|
238
|
+
}
|
404
239
|
|
405
|
-
|
406
|
-
|
240
|
+
MDB_env* env;
|
241
|
+
check(mdb_env_create(&env));
|
407
242
|
|
408
|
-
|
409
|
-
|
410
|
-
|
243
|
+
Environment* environment;
|
244
|
+
VALUE venv = Data_Make_Struct(cEnvironment, Environment, 0, environment_deref, environment);
|
245
|
+
environment->env = env;
|
246
|
+
environment->refcount = 1;
|
247
|
+
environment->txn = Qnil;
|
411
248
|
|
412
|
-
|
413
|
-
|
249
|
+
if (maxreaders > 0)
|
250
|
+
check(mdb_env_set_maxreaders(environment->env, maxreaders));
|
251
|
+
if (mapsize > 0)
|
252
|
+
check(mdb_env_set_mapsize(environment->env, mapsize));
|
414
253
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
database->open = 1;
|
254
|
+
check(mdb_env_set_maxdbs(environment->env, maxdbs <= 0 ? 1 : maxdbs));
|
255
|
+
check(mdb_env_open(environment->env, StringValueCStr(path), flags, mode));
|
256
|
+
if (rb_block_given_p())
|
257
|
+
return rb_ensure(rb_yield, venv, environment_close, venv);
|
420
258
|
|
421
|
-
|
259
|
+
return venv;
|
422
260
|
}
|
423
261
|
|
424
|
-
static VALUE
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
262
|
+
static VALUE environment_flags(VALUE self) {
|
263
|
+
unsigned int flags;
|
264
|
+
ENVIRONMENT(self, environment);
|
265
|
+
check(mdb_env_get_flags(environment->env, &flags));
|
266
|
+
return INT2NUM(flags & ENV_FLAGS);
|
429
267
|
}
|
430
268
|
|
431
|
-
static VALUE
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
return vstat;
|
269
|
+
static VALUE environment_path(VALUE self) {
|
270
|
+
const char* path;
|
271
|
+
ENVIRONMENT(self, environment);
|
272
|
+
check(mdb_env_get_path(environment->env, &path));
|
273
|
+
return rb_str_new2(path);
|
437
274
|
}
|
438
275
|
|
439
|
-
static VALUE
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
276
|
+
static VALUE environment_set_flags(VALUE self, VALUE vflags) {
|
277
|
+
unsigned int flags = NUM2INT(vflags), oldflags;
|
278
|
+
ENVIRONMENT(self, environment);
|
279
|
+
check(mdb_env_get_flags(environment->env, &oldflags));
|
280
|
+
check(mdb_env_set_flags(environment->env, oldflags & ENV_FLAGS, 0));
|
281
|
+
check(mdb_env_set_flags(environment->env, flags, 1));
|
282
|
+
return environment_flags(self);
|
444
283
|
}
|
445
284
|
|
446
|
-
static
|
447
|
-
|
448
|
-
|
449
|
-
|
285
|
+
static MDB_txn* environment_txn(VALUE self) {
|
286
|
+
ENVIRONMENT(self, environment);
|
287
|
+
if (NIL_P(environment->txn))
|
288
|
+
return 0;
|
289
|
+
TRANSACTION(environment->txn, transaction);
|
290
|
+
if (!transaction->txn)
|
291
|
+
rb_raise(cError, "Transaction is terminated");
|
292
|
+
return transaction->txn;
|
450
293
|
}
|
451
294
|
|
452
|
-
static
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
key.mv_data = RSTRING_PTR(vkey);
|
458
|
-
check(mdb_get(transaction->txn, database->dbi, &key, &value));
|
459
|
-
return rb_str_new(value.mv_data, value.mv_size);
|
295
|
+
static MDB_txn* environment_need_txn(VALUE self) {
|
296
|
+
MDB_txn* txn = environment_txn(self);
|
297
|
+
if (!txn)
|
298
|
+
rb_raise(cError, "No active transaction");
|
299
|
+
return txn;
|
460
300
|
}
|
461
301
|
|
462
|
-
static VALUE
|
463
|
-
|
464
|
-
int n = rb_scan_args(argc, argv, "31", &vtxn, &vkey, &vval, &vflags);
|
302
|
+
static VALUE environment_transaction(int argc, VALUE *argv, VALUE self) {
|
303
|
+
rb_need_block();
|
465
304
|
|
466
|
-
|
305
|
+
VALUE readonly;
|
306
|
+
rb_scan_args(argc, argv, "01", &readonly);
|
307
|
+
unsigned int flags = RTEST(readonly) ? MDB_RDONLY : 0;
|
467
308
|
|
468
|
-
|
469
|
-
|
309
|
+
return with_transaction(self, rb_yield, Qnil, flags);
|
310
|
+
}
|
470
311
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
312
|
+
static void database_deref(Database* database) {
|
313
|
+
if (--database->refcount == 0) {
|
314
|
+
Environment* env = (Environment*)DATA_PTR(database->env);
|
315
|
+
environment_deref(env);
|
316
|
+
free(database);
|
317
|
+
}
|
318
|
+
}
|
476
319
|
|
477
|
-
|
478
|
-
|
320
|
+
static void database_mark(Database* database) {
|
321
|
+
rb_gc_mark(database->env);
|
479
322
|
}
|
480
323
|
|
481
|
-
static VALUE
|
482
|
-
|
483
|
-
|
324
|
+
static VALUE environment_database(int argc, VALUE *argv, VALUE self) {
|
325
|
+
ENVIRONMENT(self, environment);
|
326
|
+
if (NIL_P(environment->txn))
|
327
|
+
return call_with_transaction(self, self, "database", argc, argv, 0);
|
484
328
|
|
485
|
-
|
329
|
+
VALUE vname, vflags;
|
330
|
+
rb_scan_args(argc, argv, "02", &vname, &vflags);
|
486
331
|
|
487
|
-
|
332
|
+
MDB_dbi dbi;
|
333
|
+
check(mdb_dbi_open(environment_need_txn(self), NIL_P(vname) ? 0 : StringValueCStr(vname), NIL_P(vflags) ? 0 : NUM2INT(vflags), &dbi));
|
488
334
|
|
489
|
-
|
490
|
-
|
491
|
-
|
335
|
+
Database* database;
|
336
|
+
VALUE vdb = Data_Make_Struct(cDatabase, Database, database_mark, database_deref, database);
|
337
|
+
database->dbi = dbi;
|
338
|
+
database->env = self;
|
339
|
+
database->refcount = 1;
|
340
|
+
++environment->refcount;
|
492
341
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
check(mdb_del(transaction->txn, database->dbi, &key, 0));
|
501
|
-
}
|
342
|
+
return vdb;
|
343
|
+
}
|
344
|
+
|
345
|
+
static VALUE database_stat(VALUE self) {
|
346
|
+
DATABASE(self, database);
|
347
|
+
if (!environment_txn(database->env))
|
348
|
+
return call_with_transaction(database->env, self, "stat", 0, 0, MDB_RDONLY);
|
502
349
|
|
503
|
-
|
350
|
+
MDB_stat stat;
|
351
|
+
check(mdb_stat(environment_need_txn(database->env), database->dbi, &stat));
|
352
|
+
return stat2hash(&stat);
|
504
353
|
}
|
505
354
|
|
506
|
-
|
507
|
-
|
508
|
-
|
355
|
+
static VALUE database_drop(VALUE self) {
|
356
|
+
DATABASE(self, database);
|
357
|
+
if (!environment_txn(database->env))
|
358
|
+
return call_with_transaction(database->env, self, "drop", 0, 0, 0);
|
359
|
+
check(mdb_drop(environment_need_txn(database->env), database->dbi, 1));
|
360
|
+
return Qnil;
|
361
|
+
}
|
509
362
|
|
510
|
-
static
|
511
|
-
|
512
|
-
|
513
|
-
|
363
|
+
static VALUE database_clear(VALUE self) {
|
364
|
+
DATABASE(self, database);
|
365
|
+
if (!environment_txn(database->env))
|
366
|
+
return call_with_transaction(database->env, self, "clear", 0, 0, 0);
|
367
|
+
check(mdb_drop(environment_need_txn(database->env), database->dbi, 0));
|
368
|
+
return Qnil;
|
514
369
|
}
|
515
370
|
|
516
|
-
static
|
517
|
-
|
518
|
-
|
371
|
+
static VALUE database_get(VALUE self, VALUE vkey) {
|
372
|
+
DATABASE(self, database);
|
373
|
+
if (!environment_txn(database->env))
|
374
|
+
return call_with_transaction(database->env, self, "get", 1, &vkey, MDB_RDONLY);
|
375
|
+
|
376
|
+
vkey = StringValue(vkey);
|
377
|
+
MDB_val key, value;
|
378
|
+
key.mv_size = RSTRING_LEN(vkey);
|
379
|
+
key.mv_data = RSTRING_PTR(vkey);
|
380
|
+
|
381
|
+
int ret = mdb_get(environment_need_txn(database->env), database->dbi, &key, &value);
|
382
|
+
if (ret == MDB_NOTFOUND)
|
383
|
+
return Qnil;
|
384
|
+
check(ret);
|
385
|
+
return rb_str_new(value.mv_data, value.mv_size);
|
386
|
+
}
|
387
|
+
|
388
|
+
static VALUE database_put(int argc, VALUE *argv, VALUE self) {
|
389
|
+
DATABASE(self, database);
|
390
|
+
if (!environment_txn(database->env))
|
391
|
+
return call_with_transaction(database->env, self, "put", argc, argv, 0);
|
392
|
+
|
393
|
+
VALUE vkey, vflags, vval;
|
394
|
+
rb_scan_args(argc, argv, "21", &vkey, &vval, &vflags);
|
395
|
+
|
396
|
+
vkey = StringValue(vkey);
|
397
|
+
vval = StringValue(vval);
|
398
|
+
|
399
|
+
MDB_val key, value;
|
400
|
+
key.mv_size = RSTRING_LEN(vkey);
|
401
|
+
key.mv_data = RSTRING_PTR(vkey);
|
402
|
+
value.mv_size = RSTRING_LEN(vval);
|
403
|
+
value.mv_data = RSTRING_PTR(vval);
|
404
|
+
|
405
|
+
check(mdb_put(environment_need_txn(database->env), database->dbi, &key, &value, NIL_P(vflags) ? 0 : NUM2INT(vflags)));
|
406
|
+
return Qnil;
|
519
407
|
}
|
520
408
|
|
521
|
-
static VALUE
|
522
|
-
|
409
|
+
static VALUE database_delete(int argc, VALUE *argv, VALUE self) {
|
410
|
+
DATABASE(self, database);
|
411
|
+
if (!environment_txn(database->env))
|
412
|
+
return call_with_transaction(database->env, self, "delete", argc, argv, 0);
|
413
|
+
|
414
|
+
VALUE vkey, vval;
|
415
|
+
rb_scan_args(argc, argv, "11", &vkey, &vval);
|
416
|
+
|
417
|
+
vkey = StringValue(vkey);
|
418
|
+
|
419
|
+
MDB_val key;
|
420
|
+
key.mv_size = RSTRING_LEN(vkey);
|
421
|
+
key.mv_data = RSTRING_PTR(vkey);
|
422
|
+
|
423
|
+
if (NIL_P(vval)) {
|
424
|
+
check(mdb_del(environment_need_txn(database->env), database->dbi, &key, 0));
|
425
|
+
} else {
|
426
|
+
VALUE vval = StringValue(vval);
|
427
|
+
MDB_val value;
|
428
|
+
value.mv_size = RSTRING_LEN(vval);
|
429
|
+
value.mv_data = RSTRING_PTR(vval);
|
430
|
+
check(mdb_del(environment_need_txn(database->env), database->dbi, &key, &value));
|
431
|
+
}
|
523
432
|
|
524
|
-
|
525
|
-
|
433
|
+
return Qnil;
|
434
|
+
}
|
526
435
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
cursor->database = self;
|
531
|
-
cursor->transaction = vtxn;
|
436
|
+
static void cursor_free(Cursor* cursor) {
|
437
|
+
if (cursor->cur)
|
438
|
+
mdb_cursor_close(cursor->cur);
|
532
439
|
|
533
|
-
|
440
|
+
database_deref((Database*)DATA_PTR(cursor->db));
|
441
|
+
free(cursor);
|
534
442
|
}
|
535
443
|
|
536
|
-
static
|
537
|
-
|
538
|
-
|
444
|
+
static void cursor_check(Cursor* cursor) {
|
445
|
+
if (!cursor->cur)
|
446
|
+
rb_raise(cError, "Cursor is closed");
|
539
447
|
}
|
540
448
|
|
541
|
-
static
|
542
|
-
|
543
|
-
return cursor->database;
|
449
|
+
static void cursor_mark(Cursor* cursor) {
|
450
|
+
rb_gc_mark(cursor->db);
|
544
451
|
}
|
545
452
|
|
546
453
|
static VALUE cursor_close(VALUE self) {
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
454
|
+
CURSOR(self, cursor);
|
455
|
+
mdb_cursor_close(cursor->cur);
|
456
|
+
cursor->cur = 0;
|
457
|
+
return Qnil;
|
458
|
+
}
|
459
|
+
|
460
|
+
static VALUE database_cursor(VALUE self) {
|
461
|
+
DATABASE(self, database);
|
462
|
+
if (!environment_txn(database->env))
|
463
|
+
return call_with_transaction(database->env, self, "cursor", 0, 0, 0);
|
464
|
+
|
465
|
+
MDB_cursor* cur;
|
466
|
+
check(mdb_cursor_open(environment_need_txn(database->env), database->dbi, &cur));
|
467
|
+
|
468
|
+
Cursor* cursor;
|
469
|
+
VALUE vcur = Data_Make_Struct(cCursor, Cursor, cursor_mark, cursor_free, cursor);
|
470
|
+
cursor->cur = cur;
|
471
|
+
cursor->db = self;
|
472
|
+
++database->refcount;
|
473
|
+
|
474
|
+
if (rb_block_given_p()) {
|
475
|
+
int exception;
|
476
|
+
VALUE result = rb_protect(rb_yield, vcur, &exception);
|
477
|
+
if (exception) {
|
478
|
+
cursor_close(vcur);
|
479
|
+
rb_jump_tag(exception);
|
480
|
+
}
|
481
|
+
cursor_close(vcur);
|
482
|
+
return result;
|
483
|
+
}
|
484
|
+
|
485
|
+
return vcur;
|
551
486
|
}
|
552
487
|
|
553
488
|
static VALUE cursor_first(VALUE self) {
|
554
|
-
|
555
|
-
|
489
|
+
CURSOR(self, cursor);
|
490
|
+
MDB_val key, value;
|
556
491
|
|
557
|
-
|
558
|
-
|
492
|
+
check(mdb_cursor_get(cursor->cur, &key, &value, MDB_FIRST));
|
493
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
494
|
+
}
|
495
|
+
|
496
|
+
static VALUE cursor_prev(VALUE self) {
|
497
|
+
CURSOR(self, cursor);
|
498
|
+
MDB_val key, value;
|
499
|
+
|
500
|
+
int ret = mdb_cursor_get(cursor->cur, &key, &value, MDB_PREV);
|
501
|
+
if (ret == MDB_NOTFOUND)
|
502
|
+
return Qnil;
|
503
|
+
check(ret);
|
504
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
559
505
|
}
|
560
506
|
|
561
507
|
static VALUE cursor_next(VALUE self) {
|
562
|
-
|
563
|
-
|
508
|
+
CURSOR(self, cursor);
|
509
|
+
MDB_val key, value;
|
564
510
|
|
565
|
-
|
566
|
-
|
511
|
+
int ret = mdb_cursor_get(cursor->cur, &key, &value, MDB_NEXT);
|
512
|
+
if (ret == MDB_NOTFOUND)
|
513
|
+
return Qnil;
|
514
|
+
check(ret);
|
515
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
567
516
|
}
|
568
517
|
|
569
|
-
static VALUE cursor_set(VALUE self, VALUE
|
570
|
-
|
571
|
-
|
518
|
+
static VALUE cursor_set(VALUE self, VALUE vkey) {
|
519
|
+
CURSOR(self, cursor);
|
520
|
+
MDB_val key, value;
|
572
521
|
|
573
|
-
|
574
|
-
|
522
|
+
key.mv_size = RSTRING_LEN(vkey);
|
523
|
+
key.mv_data = StringValuePtr(vkey);
|
575
524
|
|
576
|
-
|
577
|
-
|
525
|
+
check(mdb_cursor_get(cursor->cur, &key, &value, MDB_SET_KEY));
|
526
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
578
527
|
}
|
579
528
|
|
580
|
-
static VALUE cursor_set_range(VALUE self, VALUE
|
581
|
-
|
582
|
-
|
529
|
+
static VALUE cursor_set_range(VALUE self, VALUE vkey) {
|
530
|
+
CURSOR(self, cursor);
|
531
|
+
MDB_val key, value;
|
583
532
|
|
584
|
-
|
585
|
-
|
533
|
+
key.mv_size = RSTRING_LEN(vkey);
|
534
|
+
key.mv_data = StringValuePtr(vkey);
|
586
535
|
|
587
|
-
|
588
|
-
|
536
|
+
check(mdb_cursor_get(cursor->cur, &key, &value, MDB_SET_RANGE));
|
537
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
589
538
|
}
|
590
539
|
|
591
540
|
static VALUE cursor_get(VALUE self) {
|
592
|
-
|
593
|
-
|
594
|
-
|
541
|
+
CURSOR(self, cursor);
|
542
|
+
|
543
|
+
MDB_val key, value;
|
544
|
+
int ret = mdb_cursor_get(cursor->cur, &key, &value, MDB_GET_CURRENT);
|
545
|
+
if (ret == MDB_NOTFOUND)
|
546
|
+
return Qnil;
|
547
|
+
check(ret);
|
548
|
+
return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
|
595
549
|
}
|
596
550
|
|
597
|
-
static VALUE cursor_put(VALUE self) {
|
598
|
-
|
599
|
-
|
600
|
-
|
551
|
+
static VALUE cursor_put(int argc, VALUE* argv, VALUE self) {
|
552
|
+
CURSOR(self, cursor);
|
553
|
+
|
554
|
+
VALUE vkey, vflags, vval;
|
555
|
+
rb_scan_args(argc, argv, "21", &vkey, &vval, &vflags);
|
556
|
+
|
557
|
+
vkey = StringValue(vkey);
|
558
|
+
vval = StringValue(vval);
|
559
|
+
|
560
|
+
MDB_val key, value;
|
561
|
+
key.mv_size = RSTRING_LEN(vkey);
|
562
|
+
key.mv_data = RSTRING_PTR(vkey);
|
563
|
+
value.mv_size = RSTRING_LEN(vval);
|
564
|
+
value.mv_data = RSTRING_PTR(vval);
|
565
|
+
|
566
|
+
check(mdb_cursor_put(cursor->cur, &key, &value, NIL_P(vflags) ? 0 : NUM2INT(vflags)));
|
567
|
+
return Qnil;
|
601
568
|
}
|
602
569
|
|
603
570
|
static VALUE cursor_delete(int argc, VALUE *argv, VALUE self) {
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
571
|
+
CURSOR(self, cursor);
|
572
|
+
VALUE vflags;
|
573
|
+
rb_scan_args(argc, argv, "01", &vflags);
|
574
|
+
check(mdb_cursor_del(cursor->cur, NIL_P(vflags) ? 0 : NUM2INT(vflags)));
|
575
|
+
return Qnil;
|
609
576
|
}
|
610
577
|
|
611
578
|
static VALUE cursor_count(VALUE self) {
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
579
|
+
CURSOR(self, cursor);
|
580
|
+
size_t count;
|
581
|
+
check(mdb_cursor_count(cursor->cur, &count));
|
582
|
+
return SIZET2NUM(count);
|
616
583
|
}
|
617
584
|
|
618
|
-
|
619
585
|
void Init_lmdb_ext() {
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
586
|
+
VALUE mLMDB;
|
587
|
+
|
588
|
+
mLMDB = rb_define_module("LMDB");
|
589
|
+
rb_define_const(mLMDB, "VERSION", rb_str_new2(MDB_VERSION_STRING));
|
590
|
+
rb_define_singleton_method(mLMDB, "open", environment_open, -1);
|
591
|
+
|
592
|
+
#define NUM_CONST(name) rb_define_const(mLMDB, #name, INT2NUM(MDB_##name))
|
593
|
+
|
594
|
+
// Versions
|
595
|
+
NUM_CONST(VERSION_MAJOR);
|
596
|
+
NUM_CONST(VERSION_MINOR);
|
597
|
+
NUM_CONST(VERSION_PATCH);
|
598
|
+
|
599
|
+
// Environment flags
|
600
|
+
NUM_CONST(FIXEDMAP);
|
601
|
+
NUM_CONST(NOSUBDIR);
|
602
|
+
NUM_CONST(NOSYNC);
|
603
|
+
NUM_CONST(RDONLY);
|
604
|
+
NUM_CONST(NOMETASYNC);
|
605
|
+
NUM_CONST(WRITEMAP);
|
606
|
+
NUM_CONST(MAPASYNC);
|
607
|
+
NUM_CONST(NOTLS);
|
608
|
+
|
609
|
+
// Database flags
|
610
|
+
NUM_CONST(REVERSEKEY);
|
611
|
+
NUM_CONST(DUPSORT);
|
612
|
+
NUM_CONST(INTEGERKEY);
|
613
|
+
NUM_CONST(DUPFIXED);
|
614
|
+
NUM_CONST(INTEGERDUP);
|
615
|
+
NUM_CONST(REVERSEDUP);
|
616
|
+
NUM_CONST(CREATE);
|
617
|
+
|
618
|
+
// Write flags
|
619
|
+
NUM_CONST(NOOVERWRITE);
|
620
|
+
NUM_CONST(NODUPDATA);
|
621
|
+
NUM_CONST(CURRENT);
|
622
|
+
NUM_CONST(RESERVE);
|
623
|
+
NUM_CONST(APPEND);
|
624
|
+
NUM_CONST(APPENDDUP);
|
625
|
+
NUM_CONST(MULTIPLE);
|
626
|
+
|
627
|
+
cError = rb_define_class_under(mLMDB, "Error", rb_eRuntimeError);
|
661
628
|
#define ERROR(name) cError_##name = rb_define_class_under(cError, #name, cError);
|
662
629
|
#include "errors.h"
|
663
630
|
#undef ERROR
|
664
631
|
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
rb_define_method(cTransaction, "abort", transaction_abort, 0);
|
707
|
-
rb_define_method(cTransaction, "commit", transaction_commit, 0);
|
708
|
-
rb_define_method(cTransaction, "reset", transaction_reset, 0);
|
709
|
-
rb_define_method(cTransaction, "renew", transaction_renew, 0);
|
710
|
-
rb_define_method(cTransaction, "transaction", transaction_transaction, 0);
|
711
|
-
rb_define_method(cTransaction, "environment", transaction_environment, 0);
|
712
|
-
rb_define_method(cTransaction, "parent", transaction_parent, 0);
|
713
|
-
|
714
|
-
cCursor = rb_define_class_under(mExt, "Cursor", rb_cObject);
|
715
|
-
rb_define_method(cCursor, "close", cursor_close, 0);
|
716
|
-
rb_define_method(cCursor, "get", cursor_get, 0);
|
717
|
-
rb_define_method(cCursor, "first", cursor_first, 0);
|
718
|
-
rb_define_method(cCursor, "next", cursor_next, 0);
|
719
|
-
rb_define_method(cCursor, "set", cursor_set, 1);
|
720
|
-
rb_define_method(cCursor, "set_range", cursor_set_range, 1);
|
721
|
-
rb_define_method(cCursor, "put", cursor_put, 0);
|
722
|
-
rb_define_method(cCursor, "delete", cursor_delete, 0);
|
723
|
-
rb_define_method(cCursor, "database", cursor_database, 0);
|
724
|
-
rb_define_method(cCursor, "transaction", cursor_transaction, 0);
|
632
|
+
cEnvironment = rb_define_class_under(mLMDB, "Environment", rb_cObject);
|
633
|
+
rb_undef_method(rb_singleton_class(cEnvironment), "new");
|
634
|
+
rb_define_singleton_method(cEnvironment, "open", environment_open, -1);
|
635
|
+
rb_define_method(cEnvironment, "database", environment_database, -1);
|
636
|
+
rb_define_method(cEnvironment, "close", environment_close, 0);
|
637
|
+
rb_define_method(cEnvironment, "stat", environment_stat, 0);
|
638
|
+
rb_define_method(cEnvironment, "info", environment_info, 0);
|
639
|
+
rb_define_method(cEnvironment, "copy", environment_copy, 1);
|
640
|
+
rb_define_method(cEnvironment, "sync", environment_sync, -1);
|
641
|
+
rb_define_method(cEnvironment, "flags=", environment_set_flags, 1);
|
642
|
+
rb_define_method(cEnvironment, "flags", environment_flags, 0);
|
643
|
+
rb_define_method(cEnvironment, "path", environment_path, 0);
|
644
|
+
rb_define_method(cEnvironment, "transaction", environment_transaction, -1);
|
645
|
+
|
646
|
+
cDatabase = rb_define_class_under(mLMDB, "Database", rb_cObject);
|
647
|
+
rb_undef_method(rb_singleton_class(cDatabase), "new");
|
648
|
+
rb_define_method(cDatabase, "stat", database_stat, 0);
|
649
|
+
rb_define_method(cDatabase, "drop", database_drop, 0);
|
650
|
+
rb_define_method(cDatabase, "clear", database_clear, 0);
|
651
|
+
rb_define_method(cDatabase, "get", database_get, 1);
|
652
|
+
rb_define_method(cDatabase, "put", database_put, -1);
|
653
|
+
rb_define_method(cDatabase, "delete", database_delete, -1);
|
654
|
+
rb_define_method(cDatabase, "cursor", database_cursor, 0);
|
655
|
+
|
656
|
+
cTransaction = rb_define_class_under(mLMDB, "Transaction", rb_cObject);
|
657
|
+
rb_undef_method(rb_singleton_class(cCursor), "new");
|
658
|
+
rb_define_method(cTransaction, "commit", transaction_commit, 0);
|
659
|
+
rb_define_method(cTransaction, "abort", transaction_abort, 0);
|
660
|
+
|
661
|
+
cCursor = rb_define_class_under(mLMDB, "Cursor", rb_cObject);
|
662
|
+
rb_undef_method(rb_singleton_class(cCursor), "new");
|
663
|
+
rb_define_method(cCursor, "close", cursor_close, 0);
|
664
|
+
rb_define_method(cCursor, "get", cursor_get, 0);
|
665
|
+
rb_define_method(cCursor, "first", cursor_first, 0);
|
666
|
+
rb_define_method(cCursor, "next", cursor_next, 0);
|
667
|
+
rb_define_method(cCursor, "prev", cursor_prev, 0);
|
668
|
+
rb_define_method(cCursor, "set", cursor_set, 1);
|
669
|
+
rb_define_method(cCursor, "set_range", cursor_set_range, 1);
|
670
|
+
rb_define_method(cCursor, "put", cursor_put, 0);
|
671
|
+
rb_define_method(cCursor, "count", cursor_count, 0);
|
672
|
+
rb_define_method(cCursor, "delete", cursor_delete, 0);
|
725
673
|
}
|