kyotocabinet 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/extconf.rb +30 -0
  2. data/kyotocabinet.cc +1266 -0
  3. metadata +67 -0
@@ -0,0 +1,30 @@
1
+ require "mkmf"
2
+
3
+ File::unlink("Makefile") if (File::exist?("Makefile"))
4
+ dir_config('kyotocabinet')
5
+
6
+ home = ENV["HOME"]
7
+ ENV["PATH"] = ENV["PATH"] + ":/usr/local/bin:$home/bin:."
8
+ kccflags = `kcutilcodec conf -i 2>/dev/null`.chomp
9
+ kcldflags = `kcutilcodec conf -l 2>/dev/null`.chomp
10
+ kcldflags = kcldflags.gsub(/-l[\S]+/, "").strip
11
+ kclibs = `kcutilcodec conf -l 2>/dev/null`.chomp
12
+ kclibs = kclibs.gsub(/-L[\S]+/, "").strip
13
+
14
+ kccflags = "-I/usr/local/include" if(kccflags.length < 1)
15
+ kcldflags = "-L/usr/local/lib" if(kcldflags.length < 1)
16
+ kclibs = "-lkyotocabinet -lz -lstdc++ -lrt -lpthread -lm -lc" if(kclibs.length < 1)
17
+
18
+ Config::CONFIG["CPP"] = "g++ -E"
19
+ $CFLAGS = "-I. #{kccflags} -Wall #{$CFLAGS} -O2"
20
+ $LDFLAGS = "#{$LDFLAGS} -L. #{kcldflags}"
21
+ $libs = "#{$libs} #{kclibs}"
22
+
23
+ printf("setting variables ...\n")
24
+ printf(" \$CFLAGS = %s\n", $CFLAGS)
25
+ printf(" \$LDFLAGS = %s\n", $LDFLAGS)
26
+ printf(" \$libs = %s\n", $libs)
27
+
28
+ if have_header('kccommon.h')
29
+ create_makefile('kyotocabinet')
30
+ end
@@ -0,0 +1,1266 @@
1
+ /*************************************************************************************************
2
+ * Ruby binding
3
+ * Copyright (C) 2009-2010 Mikio Hirabayashi
4
+ * This file is part of Kyoto Cabinet.
5
+ * This program is free software: you can redistribute it and/or modify it under the terms of
6
+ * the GNU General Public License as published by the Free Software Foundation, either version
7
+ * 3 of the License, or any later version.
8
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
+ * See the GNU General Public License for more details.
11
+ * You should have received a copy of the GNU General Public License along with this program.
12
+ * If not, see <http://www.gnu.org/licenses/>.
13
+ *************************************************************************************************/
14
+
15
+
16
+ #include <kcpolydb.h>
17
+
18
+ namespace kc = kyotocabinet;
19
+
20
+ extern "C" {
21
+
22
+ #include <ruby.h>
23
+
24
+
25
+ typedef std::map<std::string, std::string> StringMap;
26
+ typedef VALUE (*METHOD)(...);
27
+
28
+
29
+ const int32_t VISMAGICNOP = INT32_MAX / 4 + 0;
30
+ const int32_t VISMAGICREMOVE = INT32_MAX / 4 + 1;
31
+
32
+
33
+ VALUE mod_kc;
34
+ VALUE cls_th;
35
+ VALUE cls_mtx;
36
+ VALUE cls_ex_arg;
37
+ VALUE cls_err;
38
+ VALUE cls_vis;
39
+ VALUE cls_vis_magic;
40
+ VALUE cls_fproc;
41
+ VALUE cls_cur;
42
+ VALUE cls_db;
43
+ ID id_th_pass;
44
+ ID id_mtx_lock;
45
+ ID id_mtx_unlock;
46
+ ID id_err_to_s;
47
+ ID id_vis_magic;
48
+ ID id_vis_nop;
49
+ ID id_vis_remove;
50
+ ID id_vis_visit_full;
51
+ ID id_vis_visit_empty;
52
+ ID id_fproc_process;
53
+ ID id_cur_db;
54
+ ID id_db_error;
55
+ ID id_db_open;
56
+ ID id_db_close;
57
+ ID id_db_mutex;
58
+
59
+
60
+ void Init_kyotocabinet();
61
+ static volatile VALUE StringValueEx(VALUE vobj);
62
+ static VALUE maptovhash(const StringMap* map);
63
+ static void init_env();
64
+ static void th_pass();
65
+ static void init_err();
66
+ static VALUE err_new(VALUE cls);
67
+ static void err_del(void* ptr);
68
+ static VALUE err_initialize(int argc, VALUE* argv, VALUE vself);
69
+ static VALUE err_set(VALUE vself, VALUE vcode, VALUE vmsg);
70
+ static VALUE err_code(VALUE vself);
71
+ static VALUE err_name(VALUE vself);
72
+ static VALUE err_message(VALUE vself);
73
+ static VALUE err_to_s(VALUE vself);
74
+ static void init_vis();
75
+ static VALUE vis_magic_initialize(VALUE vself, VALUE vnum);
76
+ static VALUE vis_visit_full(VALUE vself, VALUE vkey, VALUE vvalue);
77
+ static VALUE vis_visit_empty(VALUE vself, VALUE vkey);
78
+ static void init_fproc();
79
+ static VALUE fproc_process(VALUE vself, VALUE vpath);
80
+ static void init_cur();
81
+ static VALUE cur_new(VALUE cls);
82
+ static void cur_del(void* ptr);
83
+ static VALUE cur_initialize(VALUE vself, VALUE vdb);
84
+ static VALUE cur_disable(VALUE vself);
85
+ static VALUE cur_accept(int argc, VALUE* argv, VALUE vself);
86
+ static VALUE cur_get_key(VALUE vself);
87
+ static VALUE cur_get_value(VALUE vself);
88
+ static VALUE cur_get(VALUE vself);
89
+ static VALUE cur_remove(VALUE vself);
90
+ static VALUE cur_jump(int argc, VALUE* argv, VALUE vself);
91
+ static VALUE cur_step(VALUE vself);
92
+ static VALUE cur_db(VALUE vself);
93
+ static VALUE cur_error(VALUE vself);
94
+ static VALUE cur_to_s(VALUE vself);
95
+ static void init_db();
96
+ static VALUE db_new(VALUE cls);
97
+ static void db_del(void* ptr);
98
+ static void db_lock(VALUE vdb);
99
+ static void db_unlock(VALUE vdb);
100
+ static VALUE db_initialize(VALUE vself);
101
+ static VALUE db_error(VALUE vself);
102
+ static VALUE db_open(int argc, VALUE* argv, VALUE vself);
103
+ static VALUE db_close(VALUE vself);
104
+ static VALUE db_accept(int argc, VALUE* argv, VALUE vself);
105
+ static VALUE db_iterate(int argc, VALUE* argv, VALUE vself);
106
+ static VALUE db_set(VALUE vself, VALUE vkey, VALUE vvalue);
107
+ static VALUE db_add(VALUE vself, VALUE vkey, VALUE vvalue);
108
+ static VALUE db_append(VALUE vself, VALUE vkey, VALUE vvalue);
109
+ static VALUE db_increment(int argc, VALUE* argv, VALUE vself);
110
+ static VALUE db_cas(VALUE vself, VALUE vkey, VALUE voval, VALUE vnval);
111
+ static VALUE db_remove(VALUE vself, VALUE vkey);
112
+ static VALUE db_get(VALUE vself, VALUE vkey);
113
+ static VALUE db_clear(VALUE vself);
114
+ static VALUE db_synchronize(int argc, VALUE* argv, VALUE vself);
115
+ static VALUE db_begin_transaction(int argc, VALUE* argv, VALUE vself);
116
+ static VALUE db_end_transaction(int argc, VALUE* argv, VALUE vself);
117
+ static VALUE db_count(VALUE vself);
118
+ static VALUE db_size(VALUE vself);
119
+ static VALUE db_path(VALUE vself);
120
+ static VALUE db_status(VALUE vself);
121
+ static VALUE db_cursor(VALUE vself);
122
+ static VALUE db_to_s(VALUE vself);
123
+ static VALUE db_each(VALUE vself);
124
+ static VALUE db_each_key(VALUE vself);
125
+ static VALUE db_each_value(VALUE vself);
126
+ static VALUE db_process(int argc, VALUE* argv, VALUE vself);
127
+ static VALUE db_process_body(VALUE args);
128
+ static VALUE db_process_ensure(VALUE args);
129
+
130
+
131
+ class CursorBurrow {
132
+ private:
133
+ typedef std::vector<kc::PolyDB::Cursor*> CursorList;
134
+ public:
135
+ CursorBurrow() : dcurs_() {}
136
+ ~CursorBurrow() {
137
+ sweap();
138
+ }
139
+ void sweap() {
140
+ if (dcurs_.size() > 0) {
141
+ CursorList::iterator dit = dcurs_.begin();
142
+ CursorList::iterator ditend = dcurs_.end();
143
+ while (dit != ditend) {
144
+ kc::PolyDB::Cursor* cur = *dit;
145
+ delete cur;
146
+ dit++;
147
+ }
148
+ dcurs_.clear();
149
+ }
150
+ }
151
+ void deposit(kc::PolyDB::Cursor* cur) {
152
+ dcurs_.push_back(cur);
153
+ }
154
+ private:
155
+ CursorList dcurs_;
156
+ } g_curbur;
157
+
158
+
159
+ struct SoftCursor {
160
+ kc::PolyDB::Cursor* cur_;
161
+ SoftCursor() : cur_(NULL) {}
162
+ ~SoftCursor() {
163
+ if (cur_) g_curbur.deposit(cur_);
164
+ }
165
+ };
166
+
167
+
168
+ class SoftVisitor : public kc::PolyDB::Visitor {
169
+ public:
170
+ SoftVisitor(VALUE vvisitor) : vvisitor_(vvisitor) {}
171
+ private:
172
+ const char* visit_full(const char* kbuf, size_t ksiz,
173
+ const char* vbuf, size_t vsiz, size_t* sp) {
174
+ VALUE vkey = rb_str_new(kbuf, ksiz);
175
+ VALUE vvalue = rb_str_new(vbuf, vsiz);
176
+ VALUE args = rb_ary_new3(3, vvisitor_, vkey, vvalue);
177
+ int result = 0;
178
+ VALUE vrv = rb_protect(visit_full_impl, args, &result);
179
+ const char* rv;
180
+ if (result) {
181
+ rv = NOP;
182
+ } else if (rb_obj_is_kind_of(vrv, cls_vis_magic)) {
183
+ VALUE vmagic = rb_ivar_get(vrv, id_vis_magic);
184
+ int32_t num = NUM2INT(vmagic);
185
+ if (num == VISMAGICREMOVE) {
186
+ rv = kc::PolyDB::Visitor::REMOVE;
187
+ } else {
188
+ rv = kc::PolyDB::Visitor::NOP;
189
+ }
190
+ } else if (vrv == Qnil || vrv == Qfalse) {
191
+ rv = NOP;
192
+ } else {
193
+ vrv = StringValueEx(vrv);
194
+ rv = RSTRING_PTR(vrv);
195
+ *sp = RSTRING_LEN(vrv);
196
+ }
197
+ return rv;
198
+ }
199
+ const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp) {
200
+ VALUE vkey = rb_str_new(kbuf, ksiz);
201
+ VALUE args = rb_ary_new3(2, vvisitor_, vkey);
202
+ int result = 0;
203
+ VALUE vrv = rb_protect(visit_empty_impl, args, &result);
204
+ const char* rv;
205
+ if (result) {
206
+ rv = NOP;
207
+ } else if (rb_obj_is_instance_of(vrv, cls_vis_magic)) {
208
+ VALUE vmagic = rb_ivar_get(vrv, id_vis_magic);
209
+ int32_t num = NUM2INT(vmagic);
210
+ if (num == VISMAGICREMOVE) {
211
+ rv = kc::PolyDB::Visitor::REMOVE;
212
+ } else {
213
+ rv = kc::PolyDB::Visitor::NOP;
214
+ }
215
+ } else if (vrv == Qnil || vrv == Qfalse) {
216
+ rv = NOP;
217
+ } else {
218
+ vrv = StringValueEx(vrv);
219
+ rv = RSTRING_PTR(vrv);
220
+ *sp = RSTRING_LEN(vrv);
221
+ }
222
+ return rv;
223
+ }
224
+ static VALUE visit_full_impl(VALUE args) {
225
+ VALUE vvisitor = rb_ary_shift(args);
226
+ VALUE vkey = rb_ary_shift(args);
227
+ VALUE vvalue = rb_ary_shift(args);
228
+ return rb_funcall(vvisitor, id_vis_visit_full, 2, vkey, vvalue);
229
+ }
230
+ static VALUE visit_empty_impl(VALUE args) {
231
+ VALUE vvisitor = rb_ary_shift(args);
232
+ VALUE vkey = rb_ary_shift(args);
233
+ return rb_funcall(vvisitor, id_vis_visit_empty, 1, vkey);
234
+ }
235
+ VALUE vvisitor_;
236
+ };
237
+
238
+
239
+ class SoftEachVisitor : public kc::PolyDB::Visitor {
240
+ private:
241
+ const char* visit_full(const char* kbuf, size_t ksiz,
242
+ const char* vbuf, size_t vsiz, size_t* sp) {
243
+ VALUE vkey = rb_str_new(kbuf, ksiz);
244
+ VALUE vvalue = rb_str_new(vbuf, vsiz);
245
+ VALUE args = rb_ary_new3(2, vkey, vvalue);
246
+ int result = 0;
247
+ rb_protect(visit_full_impl, args, &result);
248
+ return NOP;
249
+ }
250
+ static VALUE visit_full_impl(VALUE args) {
251
+ return rb_yield(args);
252
+ }
253
+ };
254
+
255
+
256
+ class SoftEachKeyVisitor : public kc::PolyDB::Visitor {
257
+ private:
258
+ const char* visit_full(const char* kbuf, size_t ksiz,
259
+ const char* vbuf, size_t vsiz, size_t* sp) {
260
+ VALUE vkey = rb_str_new(kbuf, ksiz);
261
+ VALUE args = rb_ary_new3(1, vkey);
262
+ int result = 0;
263
+ rb_protect(visit_full_impl, args, &result);
264
+ return NOP;
265
+ }
266
+ static VALUE visit_full_impl(VALUE args) {
267
+ return rb_yield(args);
268
+ }
269
+ };
270
+
271
+
272
+ class SoftEachValueVisitor : public kc::PolyDB::Visitor {
273
+ private:
274
+ const char* visit_full(const char* kbuf, size_t ksiz,
275
+ const char* vbuf, size_t vsiz, size_t* sp) {
276
+ VALUE vvalue = rb_str_new(vbuf, vsiz);
277
+ VALUE args = rb_ary_new3(1, vvalue);
278
+ int result = 0;
279
+ rb_protect(visit_full_impl, args, &result);
280
+ return NOP;
281
+ }
282
+ static VALUE visit_full_impl(VALUE args) {
283
+ return rb_yield(args);
284
+ }
285
+ };
286
+
287
+
288
+ class SoftFileProcessor : public kc::PolyDB::FileProcessor {
289
+ public:
290
+ SoftFileProcessor(VALUE vproc) : vproc_(vproc) {}
291
+ private:
292
+ bool process(const std::string& path) {
293
+ VALUE vpath = rb_str_new2(path.c_str());
294
+ VALUE args = rb_ary_new3(2, vproc_, vpath);
295
+ int result = 0;
296
+ VALUE vrv = rb_protect(process_impl, args, &result);
297
+ return !result && vrv != Qnil && vrv != Qfalse;
298
+ }
299
+ static VALUE process_impl(VALUE args) {
300
+ VALUE vproc = rb_ary_shift(args);
301
+ VALUE vpath = rb_ary_shift(args);
302
+ return rb_funcall(vproc, id_fproc_process, 1, vpath);
303
+ }
304
+ VALUE vproc_;
305
+ };
306
+
307
+
308
+ void Init_kyotocabinet() {
309
+ mod_kc = rb_define_module("KyotoCabinet");
310
+ rb_define_const(mod_kc, "VERSION", rb_str_new2(kc::VERSION));
311
+ init_env();
312
+ init_err();
313
+ init_vis();
314
+ init_fproc();
315
+ init_cur();
316
+ init_db();
317
+ }
318
+
319
+
320
+ static volatile VALUE StringValueEx(VALUE vobj) {
321
+ char kbuf[kc::NUMBUFSIZ];
322
+ switch (TYPE(vobj)) {
323
+ case T_FIXNUM: {
324
+ size_t ksiz = std::sprintf(kbuf, "%d", (int)FIX2INT(vobj));
325
+ return rb_str_new(kbuf, ksiz);
326
+ }
327
+ case T_BIGNUM: {
328
+ size_t ksiz = std::sprintf(kbuf, "%lld", (long long)NUM2LL(vobj));
329
+ return rb_str_new(kbuf, ksiz);
330
+ }
331
+ case T_TRUE: {
332
+ size_t ksiz = std::sprintf(kbuf, "true");
333
+ return rb_str_new(kbuf, ksiz);
334
+ }
335
+ case T_FALSE: {
336
+ size_t ksiz = std::sprintf(kbuf, "false");
337
+ return rb_str_new(kbuf, ksiz);
338
+ }
339
+ case T_NIL: {
340
+ size_t ksiz = std::sprintf(kbuf, "nil");
341
+ return rb_str_new(kbuf, ksiz);
342
+ }
343
+ case T_SYMBOL: {
344
+ return rb_str_new2(rb_id2name(SYM2ID(vobj)));
345
+ }
346
+ }
347
+ return StringValue(vobj);
348
+ }
349
+
350
+
351
+ static VALUE maptovhash(const StringMap* map) {
352
+ VALUE vhash = rb_hash_new();
353
+ StringMap::const_iterator it = map->begin();
354
+ StringMap::const_iterator itend = map->end();
355
+ while (it != itend) {
356
+ VALUE vkey = rb_str_new(it->first.c_str(), it->first.size());
357
+ VALUE vvalue = rb_str_new(it->second.c_str(), it->second.size());
358
+ rb_hash_aset(vhash, vkey, vvalue);
359
+ it++;
360
+ }
361
+ return vhash;
362
+ }
363
+
364
+
365
+ static void init_env() {
366
+ rb_require("thread");
367
+ cls_th = rb_path2class("Thread");
368
+ id_th_pass = rb_intern("pass");
369
+ cls_mtx = rb_path2class("Mutex");
370
+ id_mtx_lock = rb_intern("lock");
371
+ id_mtx_unlock = rb_intern("unlock");
372
+ cls_ex_arg = rb_path2class("ArgumentError");
373
+ }
374
+
375
+
376
+ static void th_pass() {
377
+ rb_funcall(cls_th, id_th_pass, 0);
378
+ }
379
+
380
+
381
+ static void init_err() {
382
+ cls_err = rb_define_class_under(mod_kc, "Error", rb_cObject);
383
+ rb_define_alloc_func(cls_err, err_new);
384
+ rb_define_const(cls_err, "SUCCESS", INT2FIX(kc::PolyDB::Error::SUCCESS));
385
+ rb_define_const(cls_err, "NOIMPL", INT2FIX(kc::PolyDB::Error::NOIMPL));
386
+ rb_define_const(cls_err, "INVALID", INT2FIX(kc::PolyDB::Error::INVALID));
387
+ rb_define_const(cls_err, "NOFILE", INT2FIX(kc::PolyDB::Error::NOFILE));
388
+ rb_define_const(cls_err, "NOPERM", INT2FIX(kc::PolyDB::Error::NOPERM));
389
+ rb_define_const(cls_err, "BROKEN", INT2FIX(kc::PolyDB::Error::BROKEN));
390
+ rb_define_const(cls_err, "DUPREC", INT2FIX(kc::PolyDB::Error::DUPREC));
391
+ rb_define_const(cls_err, "NOREC", INT2FIX(kc::PolyDB::Error::NOREC));
392
+ rb_define_const(cls_err, "LOGIC", INT2FIX(kc::PolyDB::Error::LOGIC));
393
+ rb_define_const(cls_err, "SYSTEM", INT2FIX(kc::PolyDB::Error::SYSTEM));
394
+ rb_define_const(cls_err, "MISC", INT2FIX(kc::PolyDB::Error::MISC));
395
+ rb_define_private_method(cls_err, "initialize", (METHOD)err_initialize, -1);
396
+ rb_define_method(cls_err, "set", (METHOD)err_set, 2);
397
+ rb_define_method(cls_err, "code", (METHOD)err_code, 0);
398
+ rb_define_method(cls_err, "name", (METHOD)err_name, 0);
399
+ rb_define_method(cls_err, "message", (METHOD)err_message, 0);
400
+ rb_define_method(cls_err, "to_i", (METHOD)err_code, 0);
401
+ rb_define_method(cls_err, "to_s", (METHOD)err_to_s, 0);
402
+ id_err_to_s = rb_intern("to_s");
403
+ }
404
+
405
+
406
+ static VALUE err_new(VALUE cls) {
407
+ kc::PolyDB::Error* err = new kc::PolyDB::Error();
408
+ return Data_Wrap_Struct(cls_err, 0, err_del, err);
409
+ }
410
+
411
+
412
+ static void err_del(void* ptr) {
413
+ delete (kc::PolyDB::Error*)ptr;
414
+ }
415
+
416
+
417
+ static VALUE err_initialize(int argc, VALUE* argv, VALUE vself) {
418
+ kc::PolyDB::Error* err;
419
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
420
+ VALUE vcode, vmsg;
421
+ rb_scan_args(argc, argv, "02", &vcode, &vmsg);
422
+ int32_t code = vcode == Qnil ? kc::PolyDB::Error::SUCCESS : NUM2INT(vcode);
423
+ const char* msg;
424
+ if (vmsg == Qnil) {
425
+ msg = "error";
426
+ } else {
427
+ vmsg = StringValueEx(vmsg);
428
+ msg = RSTRING_PTR(vmsg);
429
+ }
430
+ err->set((kc::PolyDB::Error::Code)code, msg);
431
+ return Qnil;
432
+ }
433
+
434
+
435
+ static VALUE err_set(VALUE vself, VALUE vcode, VALUE vmsg) {
436
+ kc::PolyDB::Error* err;
437
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
438
+ int32_t code = NUM2INT(vcode);
439
+ vmsg = StringValueEx(vmsg);
440
+ const char* msg = RSTRING_PTR(vmsg);
441
+ err->set((kc::PolyDB::Error::Code)code, msg);
442
+ return Qnil;
443
+ }
444
+
445
+
446
+ static VALUE err_code(VALUE vself) {
447
+ kc::PolyDB::Error* err;
448
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
449
+ return INT2FIX(err->code());
450
+ }
451
+
452
+
453
+ static VALUE err_name(VALUE vself) {
454
+ kc::PolyDB::Error* err;
455
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
456
+ return rb_str_new2(err->name());
457
+ }
458
+
459
+
460
+ static VALUE err_message(VALUE vself) {
461
+ kc::PolyDB::Error* err;
462
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
463
+ return rb_str_new2(err->message());
464
+ }
465
+
466
+
467
+ static VALUE err_to_s(VALUE vself) {
468
+ kc::PolyDB::Error* err;
469
+ Data_Get_Struct(vself, kc::PolyDB::Error, err);
470
+ std::string str;
471
+ kc::strprintf(&str, "%s: %s", err->name(), err->message());
472
+ return rb_str_new2(str.c_str());
473
+ }
474
+
475
+
476
+ static void init_vis() {
477
+ cls_vis = rb_define_class_under(mod_kc, "Visitor", rb_cObject);
478
+ cls_vis_magic = rb_define_class_under(mod_kc, "VisitorMagic", rb_cObject);
479
+ rb_define_private_method(cls_vis_magic, "initialize", (METHOD)vis_magic_initialize, 1);
480
+ id_vis_magic = rb_intern("@magic_");
481
+ VALUE vnopnum = INT2FIX(VISMAGICNOP);
482
+ VALUE vnop = rb_class_new_instance(1, &vnopnum, cls_vis_magic);
483
+ rb_define_const(cls_vis, "NOP", vnop);
484
+ VALUE vremovenum = INT2FIX(VISMAGICREMOVE);
485
+ VALUE vremove = rb_class_new_instance(1, &vremovenum, cls_vis_magic);
486
+ rb_define_const(cls_vis, "REMOVE", vremove);
487
+ rb_define_method(cls_vis, "visit_full", (METHOD)vis_visit_full, 2);
488
+ rb_define_method(cls_vis, "visit_empty", (METHOD)vis_visit_empty, 1);
489
+ id_vis_nop = rb_intern("NOP");
490
+ id_vis_remove = rb_intern("REMOVE");
491
+ id_vis_visit_full = rb_intern("visit_full");
492
+ id_vis_visit_empty = rb_intern("visit_empty");
493
+ }
494
+
495
+
496
+ static VALUE vis_magic_initialize(VALUE vself, VALUE vnum) {
497
+ rb_ivar_set(vself, id_vis_magic, vnum);
498
+ return Qnil;
499
+ }
500
+
501
+
502
+ static VALUE vis_visit_full(VALUE vself, VALUE vkey, VALUE vvalue) {
503
+ return rb_const_get(cls_vis, id_vis_nop);
504
+ }
505
+
506
+
507
+ static VALUE vis_visit_empty(VALUE vself, VALUE vkey) {
508
+ return rb_const_get(cls_vis, id_vis_nop);
509
+ }
510
+
511
+
512
+ static void init_fproc() {
513
+ cls_fproc = rb_define_class_under(mod_kc, "FileProcessor", rb_cObject);
514
+ rb_define_method(cls_fproc, "process", (METHOD)fproc_process, 1);
515
+ id_fproc_process = rb_intern("process");
516
+ }
517
+
518
+
519
+ static VALUE fproc_process(VALUE vself, VALUE vpath) {
520
+ return Qtrue;
521
+ }
522
+
523
+
524
+ static void init_cur() {
525
+ cls_cur = rb_define_class_under(mod_kc, "Cursor", rb_cObject);
526
+ rb_define_alloc_func(cls_cur, cur_new);
527
+ rb_define_private_method(cls_cur, "initialize", (METHOD)cur_initialize, 1);
528
+ rb_define_method(cls_cur, "disable", (METHOD)cur_disable, 0);
529
+ rb_define_method(cls_cur, "accept", (METHOD)cur_accept, -1);
530
+ rb_define_method(cls_cur, "get_key", (METHOD)cur_get_key, 0);
531
+ rb_define_method(cls_cur, "get_value", (METHOD)cur_get_value, 0);
532
+ rb_define_method(cls_cur, "get", (METHOD)cur_get, 0);
533
+ rb_define_method(cls_cur, "remove", (METHOD)cur_remove, 0);
534
+ rb_define_method(cls_cur, "jump", (METHOD)cur_jump, -1);
535
+ rb_define_method(cls_cur, "step", (METHOD)cur_step, 0);
536
+ rb_define_method(cls_cur, "db", (METHOD)cur_db, 0);
537
+ rb_define_method(cls_cur, "error", (METHOD)cur_error, 0);
538
+ rb_define_method(cls_cur, "to_s", (METHOD)cur_to_s, 0);
539
+ id_cur_db = rb_intern("@db_");
540
+ }
541
+
542
+
543
+ static VALUE cur_new(VALUE cls) {
544
+ SoftCursor* cur = new SoftCursor;
545
+ return Data_Wrap_Struct(cls_cur, 0, cur_del, cur);
546
+ }
547
+
548
+
549
+ static void cur_del(void* ptr) {
550
+ delete (SoftCursor*)ptr;
551
+ }
552
+
553
+
554
+ static VALUE cur_initialize(VALUE vself, VALUE vdb) {
555
+ SoftCursor* cur;
556
+ Data_Get_Struct(vself, SoftCursor, cur);
557
+ kc::PolyDB* db;
558
+ Data_Get_Struct(vdb, kc::PolyDB, db);
559
+ db_lock(vdb);
560
+ g_curbur.sweap();
561
+ cur->cur_ = db->cursor();
562
+ db_unlock(vdb);
563
+ rb_ivar_set(vself, id_cur_db, vdb);
564
+ return Qnil;
565
+ }
566
+
567
+
568
+ static VALUE cur_disable(VALUE vself) {
569
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
570
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
571
+ SoftCursor* cur;
572
+ Data_Get_Struct(vself, SoftCursor, cur);
573
+ db_lock(vdb);
574
+ delete cur->cur_;
575
+ cur->cur_ = NULL;
576
+ db_unlock(vdb);
577
+ rb_ivar_set(vself, id_cur_db, Qnil);
578
+ return Qnil;
579
+ }
580
+
581
+
582
+ static VALUE cur_accept(int argc, VALUE* argv, VALUE vself) {
583
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
584
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
585
+ SoftCursor* cur;
586
+ Data_Get_Struct(vself, SoftCursor, cur);
587
+ VALUE vvisitor, vwritable, vstep;
588
+ rb_scan_args(argc, argv, "12", &vvisitor, &vwritable, &vstep);
589
+ SoftVisitor visitor(vvisitor);
590
+ bool writable = vwritable != Qfalse;
591
+ bool step = vstep != Qnil && vstep != Qfalse;
592
+ db_lock(vdb);
593
+ bool rv = cur->cur_->accept(&visitor, writable, step);
594
+ db_unlock(vdb);
595
+ return rv ? Qtrue : Qfalse;
596
+ }
597
+
598
+
599
+ static VALUE cur_get_key(VALUE vself) {
600
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
601
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
602
+ SoftCursor* cur;
603
+ Data_Get_Struct(vself, SoftCursor, cur);
604
+ db_lock(vdb);
605
+ size_t ksiz;
606
+ char* kbuf = cur->cur_->get_key(&ksiz);
607
+ db_unlock(vdb);
608
+ VALUE vrv;
609
+ if (kbuf) {
610
+ vrv = rb_str_new(kbuf, ksiz);
611
+ delete[] kbuf;
612
+ } else {
613
+ vrv = Qnil;
614
+ }
615
+ return vrv;
616
+ }
617
+
618
+
619
+ static VALUE cur_get_value(VALUE vself) {
620
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
621
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
622
+ SoftCursor* cur;
623
+ Data_Get_Struct(vself, SoftCursor, cur);
624
+ db_lock(vdb);
625
+ size_t vsiz;
626
+ char* vbuf = cur->cur_->get_value(&vsiz);
627
+ db_unlock(vdb);
628
+ VALUE vrv;
629
+ if (vbuf) {
630
+ vrv = rb_str_new(vbuf, vsiz);
631
+ delete[] vbuf;
632
+ } else {
633
+ vrv = Qnil;
634
+ }
635
+ return vrv;
636
+ }
637
+
638
+
639
+ static VALUE cur_get(VALUE vself) {
640
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
641
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
642
+ SoftCursor* cur;
643
+ Data_Get_Struct(vself, SoftCursor, cur);
644
+ db_lock(vdb);
645
+ size_t ksiz, vsiz;
646
+ const char* vbuf;
647
+ char* kbuf = cur->cur_->get(&ksiz, &vbuf, &vsiz);
648
+ db_unlock(vdb);
649
+ VALUE vrv;
650
+ if (kbuf) {
651
+ VALUE vkey = rb_str_new(kbuf, ksiz);
652
+ VALUE vvalue = rb_str_new(vbuf, vsiz);
653
+ vrv = rb_ary_new3(2, vkey, vvalue);
654
+ delete[] kbuf;
655
+ } else {
656
+ vrv = Qnil;
657
+ }
658
+ return vrv;
659
+ }
660
+
661
+
662
+ static VALUE cur_remove(VALUE vself) {
663
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
664
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
665
+ SoftCursor* cur;
666
+ Data_Get_Struct(vself, SoftCursor, cur);
667
+ db_lock(vdb);
668
+ bool rv = cur->cur_->remove();
669
+ db_unlock(vdb);
670
+ return rv ? Qtrue : Qfalse;
671
+ }
672
+
673
+
674
+ static VALUE cur_jump(int argc, VALUE* argv, VALUE vself) {
675
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
676
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
677
+ SoftCursor* cur;
678
+ Data_Get_Struct(vself, SoftCursor, cur);
679
+ VALUE vkey;
680
+ rb_scan_args(argc, argv, "01", &vkey);
681
+ VALUE vrv;
682
+ if (vkey == Qnil) {
683
+ db_lock(vdb);
684
+ bool rv = cur->cur_->jump();
685
+ db_unlock(vdb);
686
+ vrv = rv ? Qtrue : Qfalse;
687
+ } else {
688
+ vkey = StringValueEx(vkey);
689
+ const char* kbuf = RSTRING_PTR(vkey);
690
+ size_t ksiz = RSTRING_LEN(vkey);
691
+ db_lock(vdb);
692
+ bool rv = cur->cur_->jump(kbuf, ksiz);
693
+ db_unlock(vdb);
694
+ vrv = rv ? Qtrue : Qfalse;
695
+ }
696
+ return vrv;
697
+ }
698
+
699
+
700
+ static VALUE cur_step(VALUE vself) {
701
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
702
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
703
+ SoftCursor* cur;
704
+ Data_Get_Struct(vself, SoftCursor, cur);
705
+ db_lock(vdb);
706
+ bool rv = cur->cur_->step();
707
+ db_unlock(vdb);
708
+ return rv ? Qtrue : Qfalse;
709
+ }
710
+
711
+
712
+ static VALUE cur_db(VALUE vself) {
713
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
714
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
715
+ return vdb;
716
+ }
717
+
718
+
719
+ static VALUE cur_error(VALUE vself) {
720
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
721
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
722
+ SoftCursor* cur;
723
+ Data_Get_Struct(vself, SoftCursor, cur);
724
+ db_lock(vdb);
725
+ kc::PolyDB::Error err = cur->cur_->error();
726
+ db_unlock(vdb);
727
+ VALUE args[2];
728
+ args[0] = INT2FIX(err.code());
729
+ args[1] = rb_str_new2(err.message());
730
+ return rb_class_new_instance(2, args, cls_err);
731
+ }
732
+
733
+
734
+ static VALUE cur_to_s(VALUE vself) {
735
+ VALUE vdb = rb_ivar_get(vself, id_cur_db);
736
+ if (vdb == Qnil) rb_raise(cls_ex_arg, "disabled cursor");
737
+ SoftCursor* cur;
738
+ Data_Get_Struct(vself, SoftCursor, cur);
739
+ db_lock(vdb);
740
+ kc::PolyDB* db = cur->cur_->db();
741
+ std::string path = db->path();
742
+ std::string str;
743
+ kc::strprintf(&str, "#<KyotoCabinet::Cursor:%p: %s", cur, path.c_str());
744
+ size_t ksiz;
745
+ char* kbuf = cur->cur_->get_key(&ksiz);
746
+ if (kbuf) {
747
+ kc::strprintf(&str, ":");
748
+ str.append(kbuf, ksiz);
749
+ delete[] kbuf;
750
+ }
751
+ kc::strprintf(&str, ">");
752
+ db_unlock(vdb);
753
+ return rb_str_new2(str.c_str());
754
+ }
755
+
756
+
757
+ static void init_db() {
758
+ cls_db = rb_define_class_under(mod_kc, "DB", rb_cObject);
759
+ rb_define_alloc_func(cls_db, db_new);
760
+ rb_define_const(cls_db, "OREADER", INT2FIX(kc::PolyDB::OREADER));
761
+ rb_define_const(cls_db, "OWRITER", INT2FIX(kc::PolyDB::OWRITER));
762
+ rb_define_const(cls_db, "OCREATE", INT2FIX(kc::PolyDB::OCREATE));
763
+ rb_define_const(cls_db, "OTRUNCATE", INT2FIX(kc::PolyDB::OTRUNCATE));
764
+ rb_define_const(cls_db, "OAUTOTRAN", INT2FIX(kc::PolyDB::OAUTOTRAN));
765
+ rb_define_const(cls_db, "OAUTOSYNC", INT2FIX(kc::PolyDB::OAUTOSYNC));
766
+ rb_define_const(cls_db, "ONOLOCK", INT2FIX(kc::PolyDB::ONOLOCK));
767
+ rb_define_const(cls_db, "OTRYLOCK", INT2FIX(kc::PolyDB::OTRYLOCK));
768
+ rb_define_const(cls_db, "ONOREPAIR", INT2FIX(kc::PolyDB::ONOREPAIR));
769
+ rb_define_private_method(cls_db, "initialize", (METHOD)db_initialize, 0);
770
+ rb_define_method(cls_db, "error", (METHOD)db_error, 0);
771
+ rb_define_method(cls_db, "open", (METHOD)db_open, -1);
772
+ rb_define_method(cls_db, "close", (METHOD)db_close, 0);
773
+ rb_define_method(cls_db, "accept", (METHOD)db_accept, -1);
774
+ rb_define_method(cls_db, "iterate", (METHOD)db_iterate, -1);
775
+ rb_define_method(cls_db, "set", (METHOD)db_set, 2);
776
+ rb_define_method(cls_db, "add", (METHOD)db_add, 2);
777
+ rb_define_method(cls_db, "append", (METHOD)db_append, 2);
778
+ rb_define_method(cls_db, "increment", (METHOD)db_increment, -1);
779
+ rb_define_method(cls_db, "cas", (METHOD)db_cas, 3);
780
+ rb_define_method(cls_db, "remove", (METHOD)db_remove, 1);
781
+ rb_define_method(cls_db, "get", (METHOD)db_get, 1);
782
+ rb_define_method(cls_db, "clear", (METHOD)db_clear, 0);
783
+ rb_define_method(cls_db, "synchronize", (METHOD)db_synchronize, -1);
784
+ rb_define_method(cls_db, "begin_transaction", (METHOD)db_begin_transaction, -1);
785
+ rb_define_method(cls_db, "end_transaction", (METHOD)db_end_transaction, -1);
786
+ rb_define_method(cls_db, "count", (METHOD)db_count, 0);
787
+ rb_define_method(cls_db, "size", (METHOD)db_size, 0);
788
+ rb_define_method(cls_db, "path", (METHOD)db_path, 0);
789
+ rb_define_method(cls_db, "status", (METHOD)db_status, 0);
790
+ rb_define_method(cls_db, "cursor", (METHOD)db_cursor, 0);
791
+ rb_define_method(cls_db, "to_s", (METHOD)db_to_s, 0);
792
+ rb_define_method(cls_db, "[]", (METHOD)db_get, 1);
793
+ rb_define_method(cls_db, "[]=", (METHOD)db_set, 2);
794
+ rb_define_method(cls_db, "store", (METHOD)db_set, 2);
795
+ rb_define_method(cls_db, "delete", (METHOD)db_set, 1);
796
+ rb_define_method(cls_db, "fetch", (METHOD)db_set, 1);
797
+ rb_define_method(cls_db, "length", (METHOD)db_count, 0);
798
+ rb_define_method(cls_db, "each", (METHOD)db_each, 0);
799
+ rb_define_method(cls_db, "each_pair", (METHOD)db_each, 0);
800
+ rb_define_method(cls_db, "each_key", (METHOD)db_each_key, 0);
801
+ rb_define_method(cls_db, "each_value", (METHOD)db_each_value, 0);
802
+ id_db_error = rb_intern("error");
803
+ id_db_open = rb_intern("open");
804
+ id_db_close = rb_intern("close");
805
+ id_db_mutex = rb_intern("@mutex_");
806
+ rb_define_singleton_method(cls_db, "process", (METHOD)db_process, -1);
807
+ }
808
+
809
+
810
+ static VALUE db_new(VALUE cls) {
811
+ kc::PolyDB* db = new kc::PolyDB();
812
+ return Data_Wrap_Struct(cls_db, 0, db_del, db);
813
+ }
814
+
815
+
816
+ static void db_del(void* ptr) {
817
+ g_curbur.sweap();
818
+ delete (kc::PolyDB*)ptr;
819
+ }
820
+
821
+
822
+ static void db_lock(VALUE vdb) {
823
+ VALUE vmutex = rb_ivar_get(vdb, id_db_mutex);
824
+ rb_funcall(vmutex, id_mtx_lock, 0);
825
+ }
826
+
827
+
828
+ static void db_unlock(VALUE vdb) {
829
+ VALUE vmutex = rb_ivar_get(vdb, id_db_mutex);
830
+ rb_funcall(vmutex, id_mtx_unlock, 0);
831
+ }
832
+
833
+
834
+ static VALUE db_initialize(VALUE vself) {
835
+ VALUE vmutex = rb_class_new_instance(0, NULL, cls_mtx);
836
+ rb_ivar_set(vself, id_db_mutex, vmutex);
837
+ return Qnil;
838
+ }
839
+
840
+
841
+ static VALUE db_error(VALUE vself) {
842
+ kc::PolyDB* db;
843
+ Data_Get_Struct(vself, kc::PolyDB, db);
844
+ db_lock(vself);
845
+ kc::PolyDB::Error err = db->error();
846
+ db_unlock(vself);
847
+ VALUE args[2];
848
+ args[0] = INT2FIX(err.code());
849
+ args[1] = rb_str_new2(err.message());
850
+ return rb_class_new_instance(2, args, cls_err);
851
+ }
852
+
853
+
854
+ static VALUE db_open(int argc, VALUE* argv, VALUE vself) {
855
+ kc::PolyDB* db;
856
+ Data_Get_Struct(vself, kc::PolyDB, db);
857
+ VALUE vpath, vmode;
858
+ rb_scan_args(argc, argv, "02", &vpath, &vmode);
859
+ if (vpath == Qnil) vpath = rb_str_new2("*");
860
+ vpath = StringValueEx(vpath);
861
+ const char* path = RSTRING_PTR(vpath);
862
+ uint32_t mode = vmode == Qnil ? kc::PolyDB::OREADER : NUM2INT(vmode);
863
+ db_lock(vself);
864
+ bool rv = db->open(path, mode);
865
+ db_unlock(vself);
866
+ return rv ? Qtrue : Qfalse;
867
+ }
868
+
869
+
870
+ static VALUE db_close(VALUE vself) {
871
+ kc::PolyDB* db;
872
+ Data_Get_Struct(vself, kc::PolyDB, db);
873
+ db_lock(vself);
874
+ bool rv = db->close();
875
+ db_unlock(vself);
876
+ return rv ? Qtrue : Qfalse;
877
+ }
878
+
879
+
880
+ static VALUE db_accept(int argc, VALUE* argv, VALUE vself) {
881
+ kc::PolyDB* db;
882
+ Data_Get_Struct(vself, kc::PolyDB, db);
883
+ VALUE vkey, vvisitor, vwritable;
884
+ rb_scan_args(argc, argv, "21", &vkey, &vvisitor, &vwritable);
885
+ vkey = StringValueEx(vkey);
886
+ const char* kbuf = RSTRING_PTR(vkey);
887
+ size_t ksiz = RSTRING_LEN(vkey);
888
+ SoftVisitor visitor(vvisitor);
889
+ bool writable = vwritable != Qfalse;
890
+ db_lock(vself);
891
+ bool rv = db->accept(kbuf, ksiz, &visitor, writable);
892
+ db_unlock(vself);
893
+ return rv ? Qtrue : Qfalse;
894
+ }
895
+
896
+
897
+ static VALUE db_iterate(int argc, VALUE* argv, VALUE vself) {
898
+ kc::PolyDB* db;
899
+ Data_Get_Struct(vself, kc::PolyDB, db);
900
+ VALUE vvisitor, vwritable;
901
+ rb_scan_args(argc, argv, "11", &vvisitor, &vwritable);
902
+ SoftVisitor visitor(vvisitor);
903
+ bool writable = vwritable != Qfalse;
904
+ db_lock(vself);
905
+ bool rv = db->iterate(&visitor, writable);
906
+ db_unlock(vself);
907
+ return rv ? Qtrue : Qfalse;
908
+ }
909
+
910
+
911
+ static VALUE db_set(VALUE vself, VALUE vkey, VALUE vvalue) {
912
+ kc::PolyDB* db;
913
+ Data_Get_Struct(vself, kc::PolyDB, db);
914
+ vkey = StringValueEx(vkey);
915
+ const char* kbuf = RSTRING_PTR(vkey);
916
+ size_t ksiz = RSTRING_LEN(vkey);
917
+ vvalue = StringValueEx(vvalue);
918
+ const char* vbuf = RSTRING_PTR(vvalue);
919
+ size_t vsiz = RSTRING_LEN(vvalue);
920
+ db_lock(vself);
921
+ bool rv = db->set(kbuf, ksiz, vbuf, vsiz);
922
+ db_unlock(vself);
923
+ return rv ? Qtrue : Qfalse;
924
+ }
925
+
926
+
927
+ static VALUE db_add(VALUE vself, VALUE vkey, VALUE vvalue) {
928
+ kc::PolyDB* db;
929
+ Data_Get_Struct(vself, kc::PolyDB, db);
930
+ vkey = StringValueEx(vkey);
931
+ const char* kbuf = RSTRING_PTR(vkey);
932
+ size_t ksiz = RSTRING_LEN(vkey);
933
+ vvalue = StringValueEx(vvalue);
934
+ const char* vbuf = RSTRING_PTR(vvalue);
935
+ size_t vsiz = RSTRING_LEN(vvalue);
936
+ db_lock(vself);
937
+ bool rv = db->add(kbuf, ksiz, vbuf, vsiz);
938
+ db_unlock(vself);
939
+ return rv ? Qtrue : Qfalse;
940
+ }
941
+
942
+
943
+ static VALUE db_append(VALUE vself, VALUE vkey, VALUE vvalue) {
944
+ kc::PolyDB* db;
945
+ Data_Get_Struct(vself, kc::PolyDB, db);
946
+ vkey = StringValueEx(vkey);
947
+ const char* kbuf = RSTRING_PTR(vkey);
948
+ size_t ksiz = RSTRING_LEN(vkey);
949
+ vvalue = StringValueEx(vvalue);
950
+ const char* vbuf = RSTRING_PTR(vvalue);
951
+ size_t vsiz = RSTRING_LEN(vvalue);
952
+ db_lock(vself);
953
+ bool rv = db->append(kbuf, ksiz, vbuf, vsiz);
954
+ db_unlock(vself);
955
+ return rv ? Qtrue : Qfalse;
956
+ }
957
+
958
+
959
+ static VALUE db_increment(int argc, VALUE* argv, VALUE vself) {
960
+ kc::PolyDB* db;
961
+ Data_Get_Struct(vself, kc::PolyDB, db);
962
+ VALUE vkey, vnum;
963
+ rb_scan_args(argc, argv, "11", &vkey, &vnum);
964
+ vkey = StringValueEx(vkey);
965
+ const char* kbuf = RSTRING_PTR(vkey);
966
+ size_t ksiz = RSTRING_LEN(vkey);
967
+ bool dmode = false;
968
+ int64_t inum = 0;
969
+ double dnum = NAN;
970
+ switch (TYPE(vnum)) {
971
+ case T_FIXNUM: {
972
+ inum = FIX2INT(vnum);
973
+ break;
974
+ }
975
+ case T_BIGNUM: {
976
+ inum = NUM2LL(vnum);
977
+ break;
978
+ }
979
+ case T_FLOAT: {
980
+ dnum = NUM2DBL(vnum);
981
+ dmode = true;
982
+ break;
983
+ }
984
+ case T_TRUE: {
985
+ inum = 1;
986
+ break;
987
+ }
988
+ case T_STRING: {
989
+ const char* str = RSTRING_PTR(vnum);
990
+ if (std::strchr(str, '.')) {
991
+ dnum = kc::atof(str);
992
+ dmode = true;
993
+ } else {
994
+ inum = kc::atoi(str);
995
+ }
996
+ break;
997
+ }
998
+ }
999
+ VALUE vrv;
1000
+ if (dmode) {
1001
+ db_lock(vself);
1002
+ double num = db->increment(kbuf, ksiz, dnum);
1003
+ db_unlock(vself);
1004
+ vrv = num == num ? rb_float_new(num) : Qnil;
1005
+ } else {
1006
+ db_lock(vself);
1007
+ int64_t num = db->increment(kbuf, ksiz, inum);
1008
+ db_unlock(vself);
1009
+ vrv = num == INT64_MIN ? Qnil : LL2NUM(num);
1010
+ }
1011
+ return vrv;
1012
+ }
1013
+
1014
+
1015
+ static VALUE db_cas(VALUE vself, VALUE vkey, VALUE voval, VALUE vnval) {
1016
+ kc::PolyDB* db;
1017
+ Data_Get_Struct(vself, kc::PolyDB, db);
1018
+ vkey = StringValueEx(vkey);
1019
+ const char* kbuf = RSTRING_PTR(vkey);
1020
+ size_t ksiz = RSTRING_LEN(vkey);
1021
+ const char* ovbuf = NULL;
1022
+ size_t ovsiz = 0;
1023
+ if (voval != Qnil) {
1024
+ voval = StringValueEx(voval);
1025
+ ovbuf = RSTRING_PTR(voval);
1026
+ ovsiz = RSTRING_LEN(voval);
1027
+ }
1028
+ const char* nvbuf = NULL;
1029
+ size_t nvsiz = 0;
1030
+ if (vnval != Qnil) {
1031
+ vnval = StringValueEx(vnval);
1032
+ nvbuf = RSTRING_PTR(vnval);
1033
+ nvsiz = RSTRING_LEN(vnval);
1034
+ }
1035
+ db_lock(vself);
1036
+ bool rv = db->cas(kbuf, ksiz, ovbuf, ovsiz, nvbuf, nvsiz);
1037
+ db_unlock(vself);
1038
+ return rv ? Qtrue : Qfalse;
1039
+ }
1040
+
1041
+
1042
+ static VALUE db_remove(VALUE vself, VALUE vkey) {
1043
+ kc::PolyDB* db;
1044
+ Data_Get_Struct(vself, kc::PolyDB, db);
1045
+ vkey = StringValueEx(vkey);
1046
+ const char* kbuf = RSTRING_PTR(vkey);
1047
+ size_t ksiz = RSTRING_LEN(vkey);
1048
+ db_lock(vself);
1049
+ bool rv = db->remove(kbuf, ksiz);
1050
+ db_unlock(vself);
1051
+ return rv ? Qtrue : Qfalse;
1052
+ }
1053
+
1054
+
1055
+ static VALUE db_get(VALUE vself, VALUE vkey) {
1056
+ kc::PolyDB* db;
1057
+ Data_Get_Struct(vself, kc::PolyDB, db);
1058
+ vkey = StringValueEx(vkey);
1059
+ const char* kbuf = RSTRING_PTR(vkey);
1060
+ size_t ksiz = RSTRING_LEN(vkey);
1061
+ db_lock(vself);
1062
+ size_t vsiz;
1063
+ char* vbuf = db->get(kbuf, ksiz, &vsiz);
1064
+ db_unlock(vself);
1065
+ VALUE vrv;
1066
+ if (vbuf) {
1067
+ vrv = rb_str_new(vbuf, vsiz);
1068
+ delete[] vbuf;
1069
+ } else {
1070
+ vrv = Qnil;
1071
+ }
1072
+ return vrv;
1073
+ }
1074
+
1075
+
1076
+ static VALUE db_clear(VALUE vself) {
1077
+ kc::PolyDB* db;
1078
+ Data_Get_Struct(vself, kc::PolyDB, db);
1079
+ db_lock(vself);
1080
+ bool rv = db->clear();
1081
+ db_unlock(vself);
1082
+ return rv ? Qtrue : Qfalse;
1083
+ }
1084
+
1085
+
1086
+ static VALUE db_synchronize(int argc, VALUE* argv, VALUE vself) {
1087
+ kc::PolyDB* db;
1088
+ Data_Get_Struct(vself, kc::PolyDB, db);
1089
+ VALUE vhard, vproc;
1090
+ rb_scan_args(argc, argv, "02", &vhard, &vproc);
1091
+ bool hard = vhard != Qnil && vhard != Qfalse;
1092
+ VALUE vrv;
1093
+ if (rb_respond_to(vproc, id_fproc_process)) {
1094
+ SoftFileProcessor proc(vproc);
1095
+ db_lock(vself);
1096
+ bool rv = db->synchronize(hard, &proc);
1097
+ db_unlock(vself);
1098
+ vrv = rv ? Qtrue : Qfalse;
1099
+ } else {
1100
+ db_lock(vself);
1101
+ bool rv = db->synchronize(hard, NULL);
1102
+ db_unlock(vself);
1103
+ vrv = rv ? Qtrue : Qfalse;
1104
+ }
1105
+ return vrv;
1106
+ }
1107
+
1108
+
1109
+ static VALUE db_begin_transaction(int argc, VALUE* argv, VALUE vself) {
1110
+ kc::PolyDB* db;
1111
+ Data_Get_Struct(vself, kc::PolyDB, db);
1112
+ VALUE vhard;
1113
+ rb_scan_args(argc, argv, "01", &vhard);
1114
+ bool hard = vhard != Qnil && vhard != Qfalse;
1115
+ bool err = false;
1116
+ while (true) {
1117
+ db_lock(vself);
1118
+ bool rv = db->begin_transaction_try(hard);
1119
+ db_unlock(vself);
1120
+ if (rv) break;
1121
+ if (db->error() != kc::PolyDB::Error::LOGIC) {
1122
+ err = true;
1123
+ break;
1124
+ }
1125
+ th_pass();
1126
+ }
1127
+ return err ? Qfalse : Qtrue;
1128
+ }
1129
+
1130
+
1131
+ static VALUE db_end_transaction(int argc, VALUE* argv, VALUE vself) {
1132
+ kc::PolyDB* db;
1133
+ Data_Get_Struct(vself, kc::PolyDB, db);
1134
+ VALUE vcommit;
1135
+ rb_scan_args(argc, argv, "01", &vcommit);
1136
+ bool commit = vcommit != Qfalse;
1137
+ db_lock(vself);
1138
+ bool rv = db->end_transaction(commit);
1139
+ db_unlock(vself);
1140
+ return rv ? Qtrue : Qfalse;
1141
+ }
1142
+
1143
+
1144
+ static VALUE db_count(VALUE vself) {
1145
+ kc::PolyDB* db;
1146
+ Data_Get_Struct(vself, kc::PolyDB, db);
1147
+ db_lock(vself);
1148
+ int64_t count = db->count();
1149
+ db_unlock(vself);
1150
+ return LL2NUM(count);
1151
+ }
1152
+
1153
+
1154
+ static VALUE db_size(VALUE vself) {
1155
+ kc::PolyDB* db;
1156
+ Data_Get_Struct(vself, kc::PolyDB, db);
1157
+ db_lock(vself);
1158
+ int64_t size = db->size();
1159
+ db_unlock(vself);
1160
+ return LL2NUM(size);
1161
+ }
1162
+
1163
+
1164
+ static VALUE db_path(VALUE vself) {
1165
+ kc::PolyDB* db;
1166
+ Data_Get_Struct(vself, kc::PolyDB, db);
1167
+ db_lock(vself);
1168
+ std::string path = db->path();
1169
+ db_unlock(vself);
1170
+ if (path.size() < 1) return Qnil;
1171
+ return rb_str_new2(path.c_str());
1172
+ }
1173
+
1174
+
1175
+ static VALUE db_status(VALUE vself) {
1176
+ kc::PolyDB* db;
1177
+ Data_Get_Struct(vself, kc::PolyDB, db);
1178
+ StringMap status;
1179
+ db_lock(vself);
1180
+ bool rv = db->status(&status);
1181
+ db_unlock(vself);
1182
+ return rv ? maptovhash(&status) : Qnil;
1183
+ }
1184
+
1185
+
1186
+ static VALUE db_cursor(VALUE vself) {
1187
+ return rb_class_new_instance(1, &vself, cls_cur);
1188
+ }
1189
+
1190
+
1191
+ static VALUE db_to_s(VALUE vself) {
1192
+ kc::PolyDB* db;
1193
+ Data_Get_Struct(vself, kc::PolyDB, db);
1194
+ db_lock(vself);
1195
+ std::string path = db->path();
1196
+ std::string str;
1197
+ kc::strprintf(&str, "#<KyotoCabinet::DB:%p: %s: %lld: %lld>",
1198
+ db, path.c_str(), (long long)db->count(), (long long)db->size());
1199
+ db_unlock(vself);
1200
+ return rb_str_new2(str.c_str());
1201
+ }
1202
+
1203
+
1204
+ static VALUE db_each(VALUE vself) {
1205
+ kc::PolyDB* db;
1206
+ Data_Get_Struct(vself, kc::PolyDB, db);
1207
+ SoftEachVisitor visitor;
1208
+ db_lock(vself);
1209
+ bool rv = db->iterate(&visitor, false);
1210
+ db_unlock(vself);
1211
+ return rv ? Qtrue : Qfalse;
1212
+ }
1213
+
1214
+
1215
+ static VALUE db_each_key(VALUE vself) {
1216
+ kc::PolyDB* db;
1217
+ Data_Get_Struct(vself, kc::PolyDB, db);
1218
+ SoftEachKeyVisitor visitor;
1219
+ db_lock(vself);
1220
+ bool rv = db->iterate(&visitor, false);
1221
+ db_unlock(vself);
1222
+ return rv ? Qtrue : Qfalse;
1223
+ }
1224
+
1225
+
1226
+ static VALUE db_each_value(VALUE vself) {
1227
+ kc::PolyDB* db;
1228
+ Data_Get_Struct(vself, kc::PolyDB, db);
1229
+ SoftEachValueVisitor visitor;
1230
+ db_lock(vself);
1231
+ bool rv = db->iterate(&visitor, false);
1232
+ db_unlock(vself);
1233
+ return rv ? Qtrue : Qfalse;
1234
+ }
1235
+
1236
+
1237
+ static VALUE db_process(int argc, VALUE* argv, VALUE vself) {
1238
+ VALUE vdb = rb_class_new_instance(0, NULL, cls_db);
1239
+ VALUE vpath, vmode;
1240
+ rb_scan_args(argc, argv, "02", &vpath, &vmode);
1241
+ VALUE vrv = rb_funcall(vdb, id_db_open, 2, vpath, vmode);
1242
+ if (vrv == Qnil || vrv == Qfalse) return rb_funcall(vdb, id_db_error, 0);
1243
+ VALUE bargs = rb_ary_new3(1, vdb);
1244
+ VALUE eargs = rb_ary_new3(1, vdb);
1245
+ return rb_ensure((METHOD)db_process_body, bargs, (METHOD)db_process_ensure, eargs);
1246
+ }
1247
+
1248
+
1249
+ static VALUE db_process_body(VALUE args) {
1250
+ VALUE vdb = rb_ary_shift(args);
1251
+ rb_yield(vdb);
1252
+ return Qnil;
1253
+ }
1254
+
1255
+
1256
+ static VALUE db_process_ensure(VALUE args) {
1257
+ VALUE vdb = rb_ary_shift(args);
1258
+ rb_funcall(vdb, id_db_close, 0);
1259
+ return Qnil;
1260
+ }
1261
+
1262
+
1263
+ }
1264
+
1265
+
1266
+ // END OF FILE
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kyotocabinet
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Mikio Hirabayashi
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-02 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Kyoto Cabinet is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. Each key must be unique within a database. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.
22
+ email: hirarin@gmail.com
23
+ executables: []
24
+
25
+ extensions:
26
+ - extconf.rb
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - kyotocabinet.cc
31
+ - extconf.rb
32
+ has_rdoc: true
33
+ homepage: http://1978th.net/kyotocabinet/
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - .
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 3
47
+ segments:
48
+ - 0
49
+ version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.7
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: "Kyoto Cabinet: a straightforward implementation of DBM."
66
+ test_files: []
67
+