couchbase 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +1 -1
- data/RELEASE_NOTES.markdown +50 -0
- data/ext/couchbase_ext/arguments.c +27 -27
- data/ext/couchbase_ext/bucket.c +22 -16
- data/ext/couchbase_ext/couchbase_ext.c +132 -2
- data/ext/couchbase_ext/couchbase_ext.h +17 -0
- data/ext/couchbase_ext/extconf.rb +4 -3
- data/ext/couchbase_ext/get.c +23 -16
- data/ext/couchbase_ext/multithread_plugin.c +8 -2
- data/ext/couchbase_ext/utils.c +32 -2
- data/lib/couchbase.rb +39 -5
- data/lib/couchbase/version.rb +1 -1
- data/tasks/compile.rake +16 -11
- data/test/test_bucket.rb +14 -1
- metadata +62 -114
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
metadata.gz: 6e17257cd0c7c6e0d867ac56962ad7561b8a658bc3bb06b07d82a1c2e6047b0b032b4c1fc6b1e19d4c75762b37be3fca941f5691f74ada008feba7dffaa57ed8
|
4
|
+
data.tar.gz: c3283d9b48c266c38f53045841e6b191573f570fa05b6cb9fa13ac9046e24eaab599f38b7f5444bb2555f35a113b763e6813078d860201b90b32a93c9b49513f
|
5
|
+
SHA1:
|
6
|
+
metadata.gz: 3f5b7a5d5b5960a30be144f90b68a6a697cfd601
|
7
|
+
data.tar.gz: 58c37ac51144332757baecff17a3b1677d9ee6c8
|
data/.travis.yml
CHANGED
data/RELEASE_NOTES.markdown
CHANGED
@@ -3,6 +3,56 @@
|
|
3
3
|
This document is a list of user visible feature changes and important
|
4
4
|
bugfixes. Do not forget to update this doc in every important patch.
|
5
5
|
|
6
|
+
## 1.3.3 (2013-09-12)
|
7
|
+
|
8
|
+
* [major] RCBC-134 Allow application to use several connections with
|
9
|
+
thread-local singleton.
|
10
|
+
|
11
|
+
* [major] RCBC-135 Fixed invalid memory access which was detected by
|
12
|
+
using 'GC.stress = true' in tests.
|
13
|
+
|
14
|
+
* [major] RCBC-141 Initialize event indexes correctly. The plugin
|
15
|
+
didn't trace event callbacks, which might lead to invalid memory
|
16
|
+
access during rebalance, where libcouchbase creates/removes a lot of
|
17
|
+
events because of a fast-changing topology.
|
18
|
+
|
19
|
+
* [major] RCBC-137 Add selection options for new IO engines: select
|
20
|
+
and iocp.
|
21
|
+
|
22
|
+
* [major] When setting the username field, check for password
|
23
|
+
presence. Fixes segmentation fault in this code:
|
24
|
+
|
25
|
+
Couchbase.connect(:username => "default", :bucket => "default")
|
26
|
+
|
27
|
+
* [minor] Allow to determine the version of libcouchbase:
|
28
|
+
|
29
|
+
Couchbase.libcouchbase_version
|
30
|
+
|
31
|
+
* [major] RCBC-136 Build shared object for ruby 2.0 on windows. Also
|
32
|
+
fixes build script when using latest rake and rake-compiler.
|
33
|
+
|
34
|
+
* [minor] Fix deprecation warning on ruby 2.x. On newer versions it
|
35
|
+
should use `rb_thread_call_without_gvl()`.
|
36
|
+
|
37
|
+
ext/couchbase_ext/multithread_plugin.c: In function ‘loop_run_poll’:
|
38
|
+
ext/couchbase_ext/multithread_plugin.c:772:5: warning: ‘rb_thread_blocking_region’ is deprecated (declared at .../2.0.0-p247-dbg/include/ruby-2.0.0/ruby/intern.h:839) [-Wdeprecated-declarations]
|
39
|
+
rb_thread_blocking_region(loop_blocking_poll, args, RUBY_UBF_PROCESS, NULL);
|
40
|
+
|
41
|
+
* [major] Do not try to compile with plugins for Windows platform.
|
42
|
+
|
43
|
+
* [major] Force handle to be NULL on `lcb_create()` failure.
|
44
|
+
`lcb_create()` can leave garbage in the pointer even if the call
|
45
|
+
itself failed. This behaviour could lead to illegal memory access
|
46
|
+
on GC.
|
47
|
+
|
48
|
+
* [minor] Remove usage of `RARRAY_PTR` in favor of `rb_ary_entry`.
|
49
|
+
This improves performance significantly on Rubinius and also
|
50
|
+
improves compatibility with future CRuby 2.1 which introduces
|
51
|
+
generational garbage collection. This results in these arrays not
|
52
|
+
having to be rescanned in Rubinius and not marked as shady in
|
53
|
+
RBGCENC in CRuby 2.1.
|
54
|
+
For more discussion, also see: https://bugs.ruby-lang.org/issues/8399
|
55
|
+
|
6
56
|
## 1.3.2 (2013-07-10)
|
7
57
|
|
8
58
|
* [major] RCBC-133 Allow application to select the strategy of reading
|
@@ -130,14 +130,14 @@ cb_params_touch_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
130
130
|
rb_raise(rb_eArgError, "must be at least one key");
|
131
131
|
}
|
132
132
|
if (argc == 1) {
|
133
|
-
VALUE keys =
|
133
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
134
134
|
switch(TYPE(keys)) {
|
135
135
|
case T_ARRAY:
|
136
136
|
/* array of keys as a first argument */
|
137
137
|
params->cmd.touch.array = 1;
|
138
138
|
cb_params_touch_alloc(params, RARRAY_LEN(keys));
|
139
139
|
for (ii = 0; ii < params->cmd.touch.num; ++ii) {
|
140
|
-
cb_params_touch_init_item(params, ii,
|
140
|
+
cb_params_touch_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.touch.ttl);
|
141
141
|
}
|
142
142
|
break;
|
143
143
|
case T_HASH:
|
@@ -155,7 +155,7 @@ cb_params_touch_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
155
155
|
/* just list of arguments */
|
156
156
|
cb_params_touch_alloc(params, argc);
|
157
157
|
for (ii = 0; ii < params->cmd.touch.num; ++ii) {
|
158
|
-
cb_params_touch_init_item(params, ii,
|
158
|
+
cb_params_touch_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.touch.ttl);
|
159
159
|
}
|
160
160
|
}
|
161
161
|
}
|
@@ -215,14 +215,14 @@ cb_params_remove_parse_arguments(struct cb_params_st *params, int argc, VALUE ar
|
|
215
215
|
rb_raise(rb_eArgError, "must be at least one key");
|
216
216
|
}
|
217
217
|
if (argc == 1) {
|
218
|
-
VALUE keys =
|
218
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
219
219
|
switch(TYPE(keys)) {
|
220
220
|
case T_ARRAY:
|
221
221
|
/* array of keys as a first argument */
|
222
222
|
params->cmd.remove.array = 1;
|
223
223
|
cb_params_remove_alloc(params, RARRAY_LEN(keys));
|
224
224
|
for (ii = 0; ii < params->cmd.remove.num; ++ii) {
|
225
|
-
cb_params_remove_init_item(params, ii,
|
225
|
+
cb_params_remove_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.remove.cas);
|
226
226
|
}
|
227
227
|
break;
|
228
228
|
case T_HASH:
|
@@ -240,7 +240,7 @@ cb_params_remove_parse_arguments(struct cb_params_st *params, int argc, VALUE ar
|
|
240
240
|
/* just list of arguments */
|
241
241
|
cb_params_remove_alloc(params, argc);
|
242
242
|
for (ii = 0; ii < params->cmd.remove.num; ++ii) {
|
243
|
-
cb_params_remove_init_item(params, ii,
|
243
|
+
cb_params_remove_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.remove.cas);
|
244
244
|
}
|
245
245
|
}
|
246
246
|
}
|
@@ -344,7 +344,7 @@ cb_params_store_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
344
344
|
}
|
345
345
|
switch (argc) {
|
346
346
|
case 1:
|
347
|
-
keys =
|
347
|
+
keys = rb_ary_entry(argv, 0);
|
348
348
|
switch(TYPE(keys)) {
|
349
349
|
case T_HASH:
|
350
350
|
/* key-value pairs */
|
@@ -360,7 +360,7 @@ cb_params_store_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
360
360
|
case 2:
|
361
361
|
/* just key and value */
|
362
362
|
cb_params_store_alloc(params, 1);
|
363
|
-
cb_params_store_init_item(params, 0,
|
363
|
+
cb_params_store_init_item(params, 0, rb_ary_entry(argv, 0), rb_ary_entry(argv, 1),
|
364
364
|
params->cmd.store.flags, params->cmd.store.cas, params->cmd.store.ttl);
|
365
365
|
break;
|
366
366
|
default:
|
@@ -475,15 +475,15 @@ cb_params_get_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
|
|
475
475
|
rb_raise(rb_eArgError, "must be at least one key");
|
476
476
|
}
|
477
477
|
if (argc == 1) {
|
478
|
-
VALUE keys =
|
478
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
479
479
|
switch(TYPE(keys)) {
|
480
480
|
case T_ARRAY:
|
481
481
|
/* array of keys as a first argument */
|
482
482
|
params->cmd.get.array = 1;
|
483
483
|
cb_params_get_alloc(params, RARRAY_LEN(keys));
|
484
484
|
for (ii = 0; ii < params->cmd.get.num; ++ii) {
|
485
|
-
rb_ary_push(params->cmd.get.keys_ary,
|
486
|
-
cb_params_get_init_item(params, ii,
|
485
|
+
rb_ary_push(params->cmd.get.keys_ary, rb_ary_entry(keys, ii));
|
486
|
+
cb_params_get_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.get.ttl);
|
487
487
|
}
|
488
488
|
break;
|
489
489
|
case T_HASH:
|
@@ -505,8 +505,8 @@ cb_params_get_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
|
|
505
505
|
/* just list of arguments */
|
506
506
|
cb_params_get_alloc(params, argc);
|
507
507
|
for (ii = 0; ii < params->cmd.get.num; ++ii) {
|
508
|
-
rb_ary_push(params->cmd.get.keys_ary,
|
509
|
-
cb_params_get_init_item(params, ii,
|
508
|
+
rb_ary_push(params->cmd.get.keys_ary, rb_ary_entry(argv, ii));
|
509
|
+
cb_params_get_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.get.ttl);
|
510
510
|
}
|
511
511
|
}
|
512
512
|
}
|
@@ -589,14 +589,14 @@ cb_params_arith_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
589
589
|
rb_raise(rb_eArgError, "must be at least one key");
|
590
590
|
}
|
591
591
|
if (argc == 1) {
|
592
|
-
VALUE keys =
|
592
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
593
593
|
switch(TYPE(keys)) {
|
594
594
|
case T_ARRAY:
|
595
595
|
/* array of keys as a first argument */
|
596
596
|
params->cmd.arith.array = 1;
|
597
597
|
cb_params_arith_alloc(params, RARRAY_LEN(keys));
|
598
598
|
for (ii = 0; ii < params->cmd.arith.num; ++ii) {
|
599
|
-
cb_params_arith_init_item(params, ii,
|
599
|
+
cb_params_arith_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.arith.delta);
|
600
600
|
}
|
601
601
|
break;
|
602
602
|
case T_HASH:
|
@@ -613,7 +613,7 @@ cb_params_arith_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
613
613
|
/* just list of arguments */
|
614
614
|
cb_params_arith_alloc(params, argc);
|
615
615
|
for (ii = 0; ii < params->cmd.arith.num; ++ii) {
|
616
|
-
cb_params_arith_init_item(params, ii,
|
616
|
+
cb_params_arith_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.arith.delta);
|
617
617
|
}
|
618
618
|
}
|
619
619
|
}
|
@@ -643,14 +643,14 @@ cb_params_stats_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
643
643
|
lcb_size_t ii;
|
644
644
|
|
645
645
|
if (argc == 1) {
|
646
|
-
VALUE keys =
|
646
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
647
647
|
switch(TYPE(keys)) {
|
648
648
|
case T_ARRAY:
|
649
649
|
/* array of keys as a first argument */
|
650
650
|
params->cmd.stats.array = 1;
|
651
651
|
cb_params_stats_alloc(params, RARRAY_LEN(keys));
|
652
652
|
for (ii = 0; ii < params->cmd.stats.num; ++ii) {
|
653
|
-
cb_params_stats_init_item(params, ii,
|
653
|
+
cb_params_stats_init_item(params, ii, rb_ary_entry(keys, ii));
|
654
654
|
}
|
655
655
|
break;
|
656
656
|
default:
|
@@ -665,7 +665,7 @@ cb_params_stats_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
|
|
665
665
|
/* just list of arguments */
|
666
666
|
cb_params_stats_alloc(params, argc);
|
667
667
|
for (ii = 0; ii < params->cmd.stats.num; ++ii) {
|
668
|
-
cb_params_stats_init_item(params, ii,
|
668
|
+
cb_params_stats_init_item(params, ii, rb_ary_entry(argv, ii));
|
669
669
|
}
|
670
670
|
}
|
671
671
|
}
|
@@ -698,14 +698,14 @@ cb_params_observe_parse_arguments(struct cb_params_st *params, int argc, VALUE a
|
|
698
698
|
rb_raise(rb_eArgError, "must be at least one key");
|
699
699
|
}
|
700
700
|
if (argc == 1) {
|
701
|
-
VALUE keys =
|
701
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
702
702
|
switch(TYPE(keys)) {
|
703
703
|
case T_ARRAY:
|
704
704
|
/* array of keys as a first argument */
|
705
705
|
params->cmd.observe.array = 1;
|
706
706
|
cb_params_observe_alloc(params, RARRAY_LEN(keys));
|
707
707
|
for (ii = 0; ii < params->cmd.observe.num; ++ii) {
|
708
|
-
cb_params_observe_init_item(params, ii,
|
708
|
+
cb_params_observe_init_item(params, ii, rb_ary_entry(keys, ii));
|
709
709
|
}
|
710
710
|
break;
|
711
711
|
default:
|
@@ -717,7 +717,7 @@ cb_params_observe_parse_arguments(struct cb_params_st *params, int argc, VALUE a
|
|
717
717
|
/* just list of arguments */
|
718
718
|
cb_params_observe_alloc(params, argc);
|
719
719
|
for (ii = 0; ii < params->cmd.observe.num; ++ii) {
|
720
|
-
cb_params_observe_init_item(params, ii,
|
720
|
+
cb_params_observe_init_item(params, ii, rb_ary_entry(argv, ii));
|
721
721
|
}
|
722
722
|
}
|
723
723
|
}
|
@@ -771,7 +771,7 @@ cb_params_unlock_parse_options(struct cb_params_st *params, VALUE options)
|
|
771
771
|
cb_params_unlock_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
|
772
772
|
{
|
773
773
|
if (argc == 1) {
|
774
|
-
VALUE keys =
|
774
|
+
VALUE keys = rb_ary_entry(argv, 0);
|
775
775
|
switch(TYPE(keys)) {
|
776
776
|
case T_HASH:
|
777
777
|
/* key-cas pairs */
|
@@ -847,7 +847,7 @@ do_params_build(VALUE ptr)
|
|
847
847
|
VALUE argv = params->args;
|
848
848
|
|
849
849
|
/* extract options */
|
850
|
-
if (argc > 1 && TYPE(
|
850
|
+
if (argc > 1 && TYPE(rb_ary_entry(argv, argc-1)) == T_HASH) {
|
851
851
|
opts = rb_ary_pop(argv);
|
852
852
|
--argc;
|
853
853
|
} else {
|
@@ -865,7 +865,7 @@ do_params_build(VALUE ptr)
|
|
865
865
|
case cb_cmd_remove:
|
866
866
|
params->cmd.remove.quiet = params->bucket->quiet;
|
867
867
|
if (argc == 2) {
|
868
|
-
int type = TYPE(
|
868
|
+
int type = TYPE(rb_ary_entry(argv, 1));
|
869
869
|
if (type == T_FIXNUM || type == T_BIGNUM) {
|
870
870
|
/* allow form delete("foo", 0xdeadbeef) */
|
871
871
|
--argc;
|
@@ -906,7 +906,7 @@ do_params_build(VALUE ptr)
|
|
906
906
|
params->cmd.arith.initial = params->bucket->default_arith_init;
|
907
907
|
params->cmd.arith.delta = 1;
|
908
908
|
params->cmd.arith.ttl = params->bucket->default_ttl;
|
909
|
-
if (argc == 2 && TYPE(
|
909
|
+
if (argc == 2 && TYPE(rb_ary_entry(argv, 1)) == T_FIXNUM) {
|
910
910
|
/* allow form incr("foo", 1) */
|
911
911
|
--argc;
|
912
912
|
params->cmd.arith.delta = NUM2ULL(rb_ary_pop(argv)) & INT64_MAX;
|
@@ -926,7 +926,7 @@ do_params_build(VALUE ptr)
|
|
926
926
|
case cb_cmd_unlock:
|
927
927
|
params->cmd.unlock.quiet = params->bucket->quiet;
|
928
928
|
if (argc == 2) {
|
929
|
-
int type = TYPE(
|
929
|
+
int type = TYPE(rb_ary_entry(argv, 1));
|
930
930
|
if (type == T_FIXNUM || type == T_BIGNUM) {
|
931
931
|
/* allow form unlock("foo", 0xdeadbeef) */
|
932
932
|
--argc;
|
data/ext/couchbase_ext/bucket.c
CHANGED
@@ -97,7 +97,9 @@ cb_bucket_mark(void *ptr)
|
|
97
97
|
rb_gc_mark(bucket->on_error_proc);
|
98
98
|
rb_gc_mark(bucket->on_connect_proc);
|
99
99
|
rb_gc_mark(bucket->key_prefix_val);
|
100
|
-
|
100
|
+
if (bucket->object_space) {
|
101
|
+
st_foreach(bucket->object_space, cb_bucket_mark_object_i, (st_data_t)bucket);
|
102
|
+
}
|
101
103
|
}
|
102
104
|
}
|
103
105
|
|
@@ -260,7 +262,12 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
|
|
260
262
|
if (arg != Qnil) {
|
261
263
|
if (arg == cb_sym_default) {
|
262
264
|
bucket->engine = cb_sym_default;
|
263
|
-
|
265
|
+
} else if (arg == cb_sym_select) {
|
266
|
+
bucket->engine = cb_sym_select;
|
267
|
+
#ifdef _WIN32
|
268
|
+
} else if (arg == cb_sym_iocp) {
|
269
|
+
bucket->engine = cb_sym_iocp;
|
270
|
+
#else
|
264
271
|
} else if (arg == cb_sym_libev) {
|
265
272
|
bucket->engine = cb_sym_libev;
|
266
273
|
} else if (arg == cb_sym_libevent) {
|
@@ -317,11 +324,7 @@ do_connect(struct cb_bucket_st *bucket)
|
|
317
324
|
struct lcb_create_st create_opts;
|
318
325
|
|
319
326
|
if (bucket->handle) {
|
320
|
-
|
321
|
-
lcb_destroy_io_ops(bucket->io);
|
322
|
-
bucket->handle = NULL;
|
323
|
-
bucket->io = NULL;
|
324
|
-
bucket->connected = 0;
|
327
|
+
cb_bucket_disconnect(bucket->self);
|
325
328
|
}
|
326
329
|
|
327
330
|
{
|
@@ -331,6 +334,12 @@ do_connect(struct cb_bucket_st *bucket)
|
|
331
334
|
|
332
335
|
if (bucket->engine == cb_sym_libevent) {
|
333
336
|
ciops.v.v0.type = LCB_IO_OPS_LIBEVENT;
|
337
|
+
} else if (bucket->engine == cb_sym_select) {
|
338
|
+
ciops.v.v0.type = LCB_IO_OPS_SELECT;
|
339
|
+
#ifdef _WIN32
|
340
|
+
} else if (bucket->engine == cb_sym_iocp) {
|
341
|
+
ciops.v.v0.type = LCB_IO_OPS_IOCP;
|
342
|
+
#endif
|
334
343
|
} else if (bucket->engine == cb_sym_libev) {
|
335
344
|
ciops.v.v0.type = LCB_IO_OPS_LIBEV;
|
336
345
|
} else if (bucket->engine == cb_sym_eventmachine) {
|
@@ -359,11 +368,12 @@ do_connect(struct cb_bucket_st *bucket)
|
|
359
368
|
create_opts.v.v1.type = bucket->type;
|
360
369
|
create_opts.v.v1.host = RTEST(bucket->node_list) ? RSTRING_PTR(bucket-> node_list) : RSTRING_PTR(bucket->authority);
|
361
370
|
create_opts.v.v1.user = RTEST(bucket->username) ? RSTRING_PTR(bucket->username) : NULL;
|
362
|
-
create_opts.v.v1.passwd = RTEST(bucket->
|
371
|
+
create_opts.v.v1.passwd = RTEST(bucket->password) ? RSTRING_PTR(bucket->password) : NULL;
|
363
372
|
create_opts.v.v1.bucket = RSTRING_PTR(bucket->bucket);
|
364
373
|
create_opts.v.v1.io = bucket->io;
|
365
374
|
err = lcb_create(&bucket->handle, &create_opts);
|
366
375
|
if (err != LCB_SUCCESS) {
|
376
|
+
bucket->handle = NULL;
|
367
377
|
rb_exc_raise(cb_check_error(err, "failed to create libcouchbase instance", Qnil));
|
368
378
|
}
|
369
379
|
lcb_set_cookie(bucket->handle, bucket);
|
@@ -388,10 +398,7 @@ do_connect(struct cb_bucket_st *bucket)
|
|
388
398
|
}
|
389
399
|
err = lcb_connect(bucket->handle);
|
390
400
|
if (err != LCB_SUCCESS) {
|
391
|
-
|
392
|
-
lcb_destroy_io_ops(bucket->io);
|
393
|
-
bucket->handle = NULL;
|
394
|
-
bucket->io = NULL;
|
401
|
+
cb_bucket_disconnect(bucket->self);
|
395
402
|
rb_exc_raise(cb_check_error(err, "failed to connect libcouchbase instance to server", Qnil));
|
396
403
|
}
|
397
404
|
bucket->exception = Qnil;
|
@@ -402,10 +409,7 @@ do_connect(struct cb_bucket_st *bucket)
|
|
402
409
|
if (!bucket->async) {
|
403
410
|
lcb_wait(bucket->handle);
|
404
411
|
if (bucket->exception != Qnil) {
|
405
|
-
|
406
|
-
lcb_destroy_io_ops(bucket->io);
|
407
|
-
bucket->handle = NULL;
|
408
|
-
bucket->io = NULL;
|
412
|
+
cb_bucket_disconnect(bucket->self);
|
409
413
|
rb_exc_raise(bucket->exception);
|
410
414
|
}
|
411
415
|
}
|
@@ -484,6 +488,8 @@ cb_bucket_alloc(VALUE klass)
|
|
484
488
|
* @option options [Symbol] :engine (:default) the IO engine to use
|
485
489
|
* Currently following engines are supported:
|
486
490
|
* :default :: Built-in engine (multi-thread friendly)
|
491
|
+
* :select :: select(2) IO plugin from libcouchbase
|
492
|
+
* :iocp :: "I/O Completion Ports" plugin from libcouchbase (windows only)
|
487
493
|
* :libevent :: libevent IO plugin from libcouchbase (optional)
|
488
494
|
* :libev :: libev IO plugin from libcouchbase (optional)
|
489
495
|
* :eventmachine :: EventMachine plugin (builtin, but requires EM gem and ruby 1.9+)
|
@@ -73,6 +73,7 @@ ID cb_sym_hostname;
|
|
73
73
|
ID cb_sym_http_request;
|
74
74
|
ID cb_sym_increment;
|
75
75
|
ID cb_sym_initial;
|
76
|
+
ID cb_sym_iocp;
|
76
77
|
ID cb_sym_key_prefix;
|
77
78
|
ID cb_sym_libev;
|
78
79
|
ID cb_sym_libevent;
|
@@ -97,6 +98,7 @@ ID cb_sym_put;
|
|
97
98
|
ID cb_sym_quiet;
|
98
99
|
ID cb_sym_replace;
|
99
100
|
ID cb_sym_replica;
|
101
|
+
ID cb_sym_select;
|
100
102
|
ID cb_sym_send_threshold;
|
101
103
|
ID cb_sym_set;
|
102
104
|
ID cb_sym_stats;
|
@@ -183,6 +185,16 @@ VALUE cb_eBucketNotFoundError; /* LCB_BUCKET_ENOENT = 0x19 */
|
|
183
185
|
VALUE cb_eClientNoMemoryError; /* LCB_CLIENT_ENOMEM = 0x1a */
|
184
186
|
VALUE cb_eClientTmpFailError; /* LCB_CLIENT_ETMPFAIL = 0x1b */
|
185
187
|
VALUE cb_eBadHandleError; /* LCB_EBADHANDLE = 0x1c */
|
188
|
+
VALUE cb_eServerBug; /* LCB_SERVER_BUG = 0x1d */
|
189
|
+
VALUE cb_ePluginVersionMismatch; /* LCB_PLUGIN_VERSION_MISMATCH = 0x1e */
|
190
|
+
VALUE cb_eInvalidHostFormat; /* LCB_INVALID_HOST_FORMAT = 0x1f */
|
191
|
+
VALUE cb_eInvalidChar; /* LCB_INVALID_CHAR = 0x20 */
|
192
|
+
VALUE cb_eDurabilityTooMany; /* LCB_DURABILITY_ETOOMANY = 0x21 */
|
193
|
+
VALUE cb_eDuplicateCommands; /* LCB_DUPLICATE_COMMANDS = 0x22 */
|
194
|
+
VALUE cb_eNoMatchingServer; /* LCB_NO_MATCHING_SERVER = 0x23 */
|
195
|
+
VALUE cb_eBadEnvironment; /* LCB_BAD_ENVIRONMENT = 0x24 */
|
196
|
+
VALUE cb_eBusy; /* LCB_BUSY = 0x25 */
|
197
|
+
VALUE cb_eInvalidUsername; /* LCB_INVALID_USERNAME = 0x26 */
|
186
198
|
|
187
199
|
/* Default Strings */
|
188
200
|
VALUE cb_vStrDefault;
|
@@ -198,6 +210,14 @@ cb_intern_string(VALUE ar, const char *str)
|
|
198
210
|
return tmp;
|
199
211
|
}
|
200
212
|
|
213
|
+
static VALUE
|
214
|
+
cb_libcouchbase_version(VALUE self)
|
215
|
+
{
|
216
|
+
const char *ver = lcb_get_version(NULL);
|
217
|
+
(void)self;
|
218
|
+
return STR_NEW_CSTR(ver);
|
219
|
+
}
|
220
|
+
|
201
221
|
/* Ruby Extension initializer */
|
202
222
|
void
|
203
223
|
Init_couchbase_ext(void)
|
@@ -209,6 +229,15 @@ Init_couchbase_ext(void)
|
|
209
229
|
|
210
230
|
cb_mURI = rb_const_get(rb_cObject, rb_intern("URI"));
|
211
231
|
cb_mCouchbase = rb_define_module("Couchbase");
|
232
|
+
/* Document-method: libcouchbase_version
|
233
|
+
*
|
234
|
+
* @since 1.3.3
|
235
|
+
*
|
236
|
+
* Version of the libcouchbase library currently loaded
|
237
|
+
* @return [String]
|
238
|
+
*/
|
239
|
+
rb_define_singleton_method(cb_mCouchbase, "libcouchbase_version", cb_libcouchbase_version, 0);
|
240
|
+
|
212
241
|
cb_mTranscoder = rb_const_get(cb_mCouchbase, rb_intern("Transcoder"));
|
213
242
|
cb_mDocument = rb_const_get(cb_mTranscoder, rb_intern("Document"));
|
214
243
|
cb_mMarshal = rb_const_get(cb_mTranscoder, rb_intern("Marshal"));
|
@@ -436,12 +465,108 @@ Init_couchbase_ext(void)
|
|
436
465
|
/* Document-class: Couchbase::Error::DlsymFailed
|
437
466
|
* dlsym() failed
|
438
467
|
*
|
439
|
-
* Failed to locate the requested
|
468
|
+
* Failed to locate the requested symbol in the shared object
|
440
469
|
*
|
441
470
|
* @since 1.2.0
|
442
471
|
*/
|
443
472
|
cb_eDlsymFailedError = rb_define_class_under(cb_mError, "DlsymFailed", cb_eBaseError);
|
444
473
|
|
474
|
+
/* Document-class: Couchbase::Error::ServerBug
|
475
|
+
* Server Bug
|
476
|
+
*
|
477
|
+
* Unexpected usage of the server protocol, like unexpected
|
478
|
+
* response. If you've received this error code, please record your
|
479
|
+
* steps and file the issue at:
|
480
|
+
*
|
481
|
+
* http://www.couchbase.com/issues/browse/MB
|
482
|
+
*
|
483
|
+
* @since 1.3.3
|
484
|
+
*/
|
485
|
+
cb_eServerBug = rb_define_class_under(cb_mError, "ServerBug", cb_eBaseError);
|
486
|
+
|
487
|
+
/* Document-class: Couchbase::Error::PluginVersionMismatch
|
488
|
+
* Plugin Version Mismatch
|
489
|
+
*
|
490
|
+
* Libcouchbase cannot load the plugin because of version mismatch
|
491
|
+
*
|
492
|
+
* @since 1.3.3
|
493
|
+
*/
|
494
|
+
cb_ePluginVersionMismatch = rb_define_class_under(cb_mError, "PluginVersionMismatch", cb_eBaseError);
|
495
|
+
|
496
|
+
/* Document-class: Couchbase::Error::InvalidHostFormat
|
497
|
+
* Invalid Host Format
|
498
|
+
*
|
499
|
+
* The bootstrap hosts list use an invalid/unsupported format
|
500
|
+
*
|
501
|
+
* @since 1.3.3
|
502
|
+
*/
|
503
|
+
cb_eInvalidHostFormat = rb_define_class_under(cb_mError, "InvalidHostFormat", cb_eBaseError);
|
504
|
+
|
505
|
+
/* Document-class: Couchbase::Error::InvalidChar
|
506
|
+
* Invalid Character
|
507
|
+
*
|
508
|
+
* Invalid character used in the path component of an URL
|
509
|
+
*
|
510
|
+
* @since 1.3.3
|
511
|
+
*/
|
512
|
+
cb_eInvalidChar = rb_define_class_under(cb_mError, "InvalidChar", cb_eBaseError);
|
513
|
+
|
514
|
+
/* Document-class: Couchbase::Error::DurabilityTooMany
|
515
|
+
* Too Many Nodes
|
516
|
+
*
|
517
|
+
* Too many nodes were requested for the observe criteria
|
518
|
+
*
|
519
|
+
* @since 1.3.3
|
520
|
+
*/
|
521
|
+
cb_eDurabilityTooMany = rb_define_class_under(cb_mError, "DurabilityTooMany", cb_eBaseError);
|
522
|
+
|
523
|
+
/* Document-class: Couchbase::Error::DuplicateCommands
|
524
|
+
* Duplicate Commands
|
525
|
+
*
|
526
|
+
* The same key was passed multiple times in a command list
|
527
|
+
*
|
528
|
+
* @since 1.3.3
|
529
|
+
*/
|
530
|
+
cb_eDuplicateCommands = rb_define_class_under(cb_mError, "DuplicateCommands", cb_eBaseError);
|
531
|
+
|
532
|
+
/* Document-class: Couchbase::Error::NoMatchingServer
|
533
|
+
* No Matching Server
|
534
|
+
*
|
535
|
+
* The config says that there is no server yet at that
|
536
|
+
* position (-1 in the cluster topology map)
|
537
|
+
*
|
538
|
+
* @since 1.3.3
|
539
|
+
*/
|
540
|
+
cb_eNoMatchingServer = rb_define_class_under(cb_mError, "NoMatchingServer", cb_eBaseError);
|
541
|
+
|
542
|
+
/* Document-class: Couchbase::Error::BadEnvironment
|
543
|
+
* Busy
|
544
|
+
*
|
545
|
+
* An operation has not yet completed
|
546
|
+
*
|
547
|
+
* @since 1.3.3
|
548
|
+
*/
|
549
|
+
cb_eBadEnvironment = rb_define_class_under(cb_mError, "BadEnvironment", cb_eBaseError);
|
550
|
+
|
551
|
+
/* Document-class: Couchbase::Error::Busy
|
552
|
+
* Invalid Character
|
553
|
+
*
|
554
|
+
* Invalid character used in the path component of an URL
|
555
|
+
*
|
556
|
+
* @since 1.3.3
|
557
|
+
*/
|
558
|
+
cb_eBusy = rb_define_class_under(cb_mError, "Busy", cb_eBaseError);
|
559
|
+
|
560
|
+
/* Document-class: Couchbase::Error::InvalidUsername
|
561
|
+
* Invalid Username
|
562
|
+
*
|
563
|
+
* Administrator account must not be used to access the data
|
564
|
+
* in the bucket
|
565
|
+
*
|
566
|
+
* @since 1.3.3
|
567
|
+
*/
|
568
|
+
cb_eInvalidUsername = rb_define_class_under(cb_mError, "InvalidUsername", cb_eBaseError);
|
569
|
+
|
445
570
|
/* Document-class: Couchbase::Error::HTTP
|
446
571
|
* HTTP error with status code
|
447
572
|
*
|
@@ -484,7 +609,10 @@ Init_couchbase_ext(void)
|
|
484
609
|
* 0x1a :: LCB_CLIENT_ENOMEM (Out of memory on the client)
|
485
610
|
* 0x1b :: LCB_CLIENT_ETMPFAIL (Temporary failure on the client)
|
486
611
|
* 0x1c :: LCB_EBADHANDLE (Invalid handle type)
|
487
|
-
*
|
612
|
+
* 0x1d :: LCB_SERVER_BUG (Server bug)
|
613
|
+
* 0x1e :: LCB_PLUGIN_VERSION_MISMATCH (Plugin version mismatch)
|
614
|
+
* 0x1f :: LCB_INVALID_HOST_FORMAT (Invalid host format)
|
615
|
+
* 0x20 :: LCB_INVALID_CHAR (Invalid character)
|
488
616
|
*
|
489
617
|
* @since 1.0.0
|
490
618
|
*
|
@@ -1189,6 +1317,7 @@ Init_couchbase_ext(void)
|
|
1189
1317
|
cb_sym_http_request = ID2SYM(rb_intern("http_request"));
|
1190
1318
|
cb_sym_increment = ID2SYM(rb_intern("increment"));
|
1191
1319
|
cb_sym_initial = ID2SYM(rb_intern("initial"));
|
1320
|
+
cb_sym_iocp = ID2SYM(rb_intern("iocp"));
|
1192
1321
|
cb_sym_key_prefix = ID2SYM(rb_intern("key_prefix"));
|
1193
1322
|
cb_sym_libev = ID2SYM(rb_intern("libev"));
|
1194
1323
|
cb_sym_libevent = ID2SYM(rb_intern("libevent"));
|
@@ -1213,6 +1342,7 @@ Init_couchbase_ext(void)
|
|
1213
1342
|
cb_sym_quiet = ID2SYM(rb_intern("quiet"));
|
1214
1343
|
cb_sym_replace = ID2SYM(rb_intern("replace"));
|
1215
1344
|
cb_sym_replica = ID2SYM(rb_intern("replica"));
|
1345
|
+
cb_sym_select = ID2SYM(rb_intern("select"));
|
1216
1346
|
cb_sym_send_threshold = ID2SYM(rb_intern("send_threshold"));
|
1217
1347
|
cb_sym_set = ID2SYM(rb_intern("set"));
|
1218
1348
|
cb_sym_stats = ID2SYM(rb_intern("stats"));
|
@@ -22,6 +22,10 @@
|
|
22
22
|
#include <st.h>
|
23
23
|
#endif
|
24
24
|
|
25
|
+
#ifdef HAVE_RUBY_THREAD_H
|
26
|
+
#include <ruby/thread.h>
|
27
|
+
#endif
|
28
|
+
|
25
29
|
#include "couchbase_config.h"
|
26
30
|
#ifdef HAVE_RB_FIBER_YIELD
|
27
31
|
#define BUILD_EVENTMACHINE_PLUGIN
|
@@ -217,6 +221,7 @@ extern ID cb_sym_hostname;
|
|
217
221
|
extern ID cb_sym_http_request;
|
218
222
|
extern ID cb_sym_increment;
|
219
223
|
extern ID cb_sym_initial;
|
224
|
+
extern ID cb_sym_iocp;
|
220
225
|
extern ID cb_sym_key_prefix;
|
221
226
|
extern ID cb_sym_libev;
|
222
227
|
extern ID cb_sym_libevent;
|
@@ -241,6 +246,7 @@ extern ID cb_sym_put;
|
|
241
246
|
extern ID cb_sym_quiet;
|
242
247
|
extern ID cb_sym_replace;
|
243
248
|
extern ID cb_sym_replica;
|
249
|
+
extern ID cb_sym_select;
|
244
250
|
extern ID cb_sym_send_threshold;
|
245
251
|
extern ID cb_sym_set;
|
246
252
|
extern ID cb_sym_stats;
|
@@ -326,6 +332,17 @@ extern VALUE cb_eBucketNotFoundError; /* LCB_BUCKET_ENOENT = 0x19 */
|
|
326
332
|
extern VALUE cb_eClientNoMemoryError; /* LCB_CLIENT_ENOMEM = 0x1a */
|
327
333
|
extern VALUE cb_eClientTmpFailError; /* LCB_CLIENT_ETMPFAIL = 0x1b */
|
328
334
|
extern VALUE cb_eBadHandleError; /* LCB_EBADHANDLE = 0x1c */
|
335
|
+
extern VALUE cb_eServerBug; /* LCB_SERVER_BUG = 0x1d */
|
336
|
+
extern VALUE cb_ePluginVersionMismatch; /* LCB_PLUGIN_VERSION_MISMATCH = 0x1e */
|
337
|
+
extern VALUE cb_eInvalidHostFormat; /* LCB_INVALID_HOST_FORMAT = 0x1f */
|
338
|
+
extern VALUE cb_eInvalidChar; /* LCB_INVALID_CHAR = 0x20 */
|
339
|
+
extern VALUE cb_eDurabilityTooMany; /* LCB_DURABILITY_ETOOMANY = 0x21 */
|
340
|
+
extern VALUE cb_eDuplicateCommands; /* LCB_DUPLICATE_COMMANDS = 0x22 */
|
341
|
+
extern VALUE cb_eNoMatchingServer; /* LCB_NO_MATCHING_SERVER = 0x23 */
|
342
|
+
extern VALUE cb_eBadEnvironment; /* LCB_BAD_ENVIRONMENT = 0x24 */
|
343
|
+
extern VALUE cb_eBusy; /* LCB_BUSY = 0x25 */
|
344
|
+
extern VALUE cb_eInvalidUsername; /* LCB_INVALID_USERNAME = 0x26 */
|
345
|
+
|
329
346
|
|
330
347
|
/* Default Strings */
|
331
348
|
extern VALUE cb_vStrDefault;
|
@@ -128,14 +128,14 @@ end
|
|
128
128
|
|
129
129
|
unless try_compile(<<-SRC)
|
130
130
|
#include <libcouchbase/couchbase.h>
|
131
|
+
#include <stdio.h>
|
131
132
|
|
132
133
|
int main() {
|
133
|
-
|
134
|
-
cmd.v.v1.strategy = 42;
|
134
|
+
printf("User not found: %d\\n", LCB_INVALID_USERNAME);
|
135
135
|
return 0;
|
136
136
|
}
|
137
137
|
SRC
|
138
|
-
die("You must install libcouchbase >= 2.
|
138
|
+
die("You must install libcouchbase >= 2.1.3\nSee http://www.couchbase.com/communities/c/ for more details")
|
139
139
|
end
|
140
140
|
|
141
141
|
have_library("couchbase", "lcb_verify_compiler_setup", "libcouchbase/couchbase.h") # just to add -lcouchbase properly
|
@@ -151,6 +151,7 @@ have_func("gethrtime")
|
|
151
151
|
have_func("rb_hash_lookup2")
|
152
152
|
have_func("rb_thread_fd_select")
|
153
153
|
have_func("rb_thread_blocking_region")
|
154
|
+
have_func("rb_thread_call_without_gvl")
|
154
155
|
have_func("poll", "poll.h")
|
155
156
|
have_func("ppoll", "poll.h")
|
156
157
|
have_func("rb_fiber_yield")
|
data/ext/couchbase_ext/get.c
CHANGED
@@ -36,19 +36,23 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
|
|
36
36
|
}
|
37
37
|
}
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
39
|
+
if (error == LCB_SUCCESS) {
|
40
|
+
flags = ULONG2NUM(resp->v.v0.flags);
|
41
|
+
cas = ULL2NUM(resp->v.v0.cas);
|
42
|
+
raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
|
43
|
+
val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts);
|
44
|
+
if (rb_obj_is_kind_of(val, rb_eStandardError)) {
|
45
|
+
VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
|
46
|
+
VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
|
47
|
+
rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str);
|
48
|
+
ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
|
49
|
+
rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
|
50
|
+
rb_ivar_set(ctx->exception, cb_id_iv_key, key);
|
51
|
+
rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
|
52
|
+
val = Qnil;
|
53
|
+
}
|
54
|
+
} else {
|
55
|
+
val = flags = cas = Qnil;
|
52
56
|
}
|
53
57
|
if (bucket->async) { /* asynchronous */
|
54
58
|
if (ctx->proc != Qnil) {
|
@@ -291,11 +295,14 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
|
|
291
295
|
return rv; /* return as a hash {key => [value, flags, cas], ...} */
|
292
296
|
}
|
293
297
|
if (params.cmd.get.num > 1 || params.cmd.get.array) {
|
294
|
-
VALUE
|
298
|
+
VALUE keys, ret;
|
295
299
|
ret = rb_ary_new();
|
296
|
-
|
300
|
+
/* make sure ret is guarded so not invisible in a register
|
301
|
+
* when stack scanning */
|
302
|
+
RB_GC_GUARD(ret);
|
303
|
+
keys = params.cmd.get.keys_ary;
|
297
304
|
for (ii = 0; ii < params.cmd.get.num; ++ii) {
|
298
|
-
rb_ary_push(ret, rb_hash_aref(rv,
|
305
|
+
rb_ary_push(ret, rb_hash_aref(rv, rb_ary_entry(keys, ii)));
|
299
306
|
}
|
300
307
|
return ret; /* return as an array [value1, value2, ...] */
|
301
308
|
} else {
|
@@ -433,6 +433,7 @@ callbacks_push(rb_mt_callbacks *callbacks, rb_mt_event *event)
|
|
433
433
|
callbacks->capa = new_capa;
|
434
434
|
callbacks->events = new_events;
|
435
435
|
}
|
436
|
+
event->loop_index = callbacks->count;
|
436
437
|
callbacks->events[callbacks->count] = event;
|
437
438
|
callbacks->count++;
|
438
439
|
}
|
@@ -457,6 +458,8 @@ callbacks_run(rb_mt_callbacks *callbacks)
|
|
457
458
|
for(i = 0; i < callbacks->count; i++) {
|
458
459
|
rb_mt_event *cb = callbacks->events[i];
|
459
460
|
if (cb) {
|
461
|
+
cb->loop_index = -1;
|
462
|
+
callbacks->events[i] = NULL;
|
460
463
|
cb->handler(cb->socket, cb->actual_flags, cb->cb_data);
|
461
464
|
}
|
462
465
|
}
|
@@ -725,7 +728,7 @@ lp_arg_alloc(lp_arg **args)
|
|
725
728
|
return Data_Make_Struct(rb_cObject, lp_arg, 0, lp_arg_free, *args);
|
726
729
|
}
|
727
730
|
|
728
|
-
#
|
731
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
729
732
|
static VALUE
|
730
733
|
loop_blocking_poll(void *argp)
|
731
734
|
{
|
@@ -768,7 +771,10 @@ retry:
|
|
768
771
|
args->ts = HRTIME_INFINITY;
|
769
772
|
}
|
770
773
|
|
771
|
-
|
774
|
+
|
775
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
776
|
+
rb_thread_call_without_gvl((void *(*)(void*))loop_blocking_poll, args, RUBY_UBF_IO, 0);
|
777
|
+
#elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
772
778
|
rb_thread_blocking_region(loop_blocking_poll, args, RUBY_UBF_PROCESS, NULL);
|
773
779
|
#else
|
774
780
|
if (rb_thread_alone()) {
|
data/ext/couchbase_ext/utils.c
CHANGED
@@ -235,6 +235,36 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key,
|
|
235
235
|
case LCB_EBADHANDLE:
|
236
236
|
klass = cb_eBadHandleError;
|
237
237
|
break;
|
238
|
+
case LCB_SERVER_BUG:
|
239
|
+
klass = cb_eServerBug;
|
240
|
+
break;
|
241
|
+
case LCB_PLUGIN_VERSION_MISMATCH:
|
242
|
+
klass = cb_ePluginVersionMismatch;
|
243
|
+
break;
|
244
|
+
case LCB_INVALID_HOST_FORMAT:
|
245
|
+
klass = cb_eInvalidHostFormat;
|
246
|
+
break;
|
247
|
+
case LCB_INVALID_CHAR:
|
248
|
+
klass = cb_eInvalidChar;
|
249
|
+
break;
|
250
|
+
case LCB_DURABILITY_ETOOMANY:
|
251
|
+
klass = cb_eDurabilityTooMany;
|
252
|
+
break;
|
253
|
+
case LCB_DUPLICATE_COMMANDS:
|
254
|
+
klass = cb_eDuplicateCommands;
|
255
|
+
break;
|
256
|
+
case LCB_NO_MATCHING_SERVER:
|
257
|
+
klass = cb_eBadEnvironment;
|
258
|
+
break;
|
259
|
+
case LCB_BAD_ENVIRONMENT:
|
260
|
+
klass = cb_eBadEnvironment;
|
261
|
+
break;
|
262
|
+
case LCB_BUSY:
|
263
|
+
klass = cb_eBusyError;
|
264
|
+
break;
|
265
|
+
case LCB_INVALID_USERNAME:
|
266
|
+
klass = cb_eInvalidUsername;
|
267
|
+
break;
|
238
268
|
case LCB_ERROR:
|
239
269
|
/* fall through */
|
240
270
|
default:
|
@@ -375,8 +405,8 @@ do_encode(VALUE *args)
|
|
375
405
|
if (RARRAY_LEN(ret) != 2) {
|
376
406
|
rb_raise(rb_eArgError, "#dump method of transcoder should return two items");
|
377
407
|
}
|
378
|
-
*flags = NUM2ULONG(
|
379
|
-
return
|
408
|
+
*flags = NUM2ULONG(rb_ary_entry(ret, 1));
|
409
|
+
return rb_ary_entry(ret, 0);
|
380
410
|
}
|
381
411
|
|
382
412
|
static VALUE
|
data/lib/couchbase.rb
CHANGED
@@ -77,7 +77,7 @@ module Couchbase
|
|
77
77
|
|
78
78
|
# @private the thread local storage
|
79
79
|
def thread_storage
|
80
|
-
Thread.current[:couchbase] ||= { :pid => Process.pid }
|
80
|
+
Thread.current[:couchbase] ||= { :pid => Process.pid, :bucket => {} }
|
81
81
|
end
|
82
82
|
|
83
83
|
# @private resets thread local storage if process ids don't match
|
@@ -100,10 +100,42 @@ module Couchbase
|
|
100
100
|
# @example
|
101
101
|
# Couchbase.bucket.set("foo", "bar")
|
102
102
|
#
|
103
|
+
# @example Set connection options using Hash
|
104
|
+
# Couchbase.connection_options = {:node_list => ["example.com:8091"]}
|
105
|
+
# Couchbase.bucket("slot1").set("foo", "bar")
|
106
|
+
# Couchbase.bucket("slot1").bucket #=> "default"
|
107
|
+
# Couchbase.connection_options[:bucket] = "test"
|
108
|
+
# Couchbase.bucket("slot2").bucket #=> "test"
|
109
|
+
#
|
110
|
+
# @example Set connection options using URI
|
111
|
+
# Couchbase.connection_options = "http://example.com:8091/pools"
|
112
|
+
# Couchbase.bucket("slot1").set("foo", "bar")
|
113
|
+
# Couchbase.bucket("slot1").bucket #=> "default"
|
114
|
+
# Couchbase.connection_options = "http://example.com:8091/pools/buckets/test"
|
115
|
+
# Couchbase.bucket("slot2").bucket #=> "test"
|
116
|
+
#
|
117
|
+
# @example Use named slots to keep a connection
|
118
|
+
# Couchbase.connection_options = {
|
119
|
+
# :node_list => ["example.com", "example.org"],
|
120
|
+
# :bucket => "users"
|
121
|
+
# }
|
122
|
+
# Couchbase.bucket("users").set("john", {"balance" => 0})
|
123
|
+
# Couchbase.connection_options[:bucket] = "orders"
|
124
|
+
# Couchbase.bucket("other").set("john:1", {"products" => [42, 66]})
|
125
|
+
#
|
103
126
|
# @return [Bucket]
|
104
|
-
def bucket
|
127
|
+
def bucket(name = nil)
|
105
128
|
verify_connection!
|
106
|
-
|
129
|
+
name ||= case @connection_options
|
130
|
+
when Hash
|
131
|
+
@connection_options[:bucket]
|
132
|
+
when String
|
133
|
+
path = URI.parse(@connection_options).path
|
134
|
+
path[%r(^(/pools/([A-Za-z0-9_.-]+)(/buckets/([A-Za-z0-9_.-]+))?)?), 3] || "default"
|
135
|
+
else
|
136
|
+
"default"
|
137
|
+
end
|
138
|
+
thread_storage[:bucket][name] ||= connect(connection_options)
|
107
139
|
end
|
108
140
|
|
109
141
|
# Set a connection instance for current thread
|
@@ -111,10 +143,12 @@ module Couchbase
|
|
111
143
|
# @since 1.1.0
|
112
144
|
#
|
113
145
|
# @return [Bucket]
|
114
|
-
def bucket=(connection)
|
146
|
+
def bucket=(connection, name = nil)
|
115
147
|
verify_connection!
|
116
|
-
|
148
|
+
name ||= @connection_options && @connection_options[:bucket] || "default"
|
149
|
+
thread_storage[:bucket][name] = connection
|
117
150
|
end
|
151
|
+
alias set_bucket bucket=
|
118
152
|
|
119
153
|
end
|
120
154
|
|
data/lib/couchbase/version.rb
CHANGED
data/tasks/compile.rake
CHANGED
@@ -22,6 +22,14 @@ def gemspec
|
|
22
22
|
@clean_gemspec ||= eval(File.read(File.expand_path('../../couchbase.gemspec', __FILE__)))
|
23
23
|
end
|
24
24
|
|
25
|
+
version_router = lambda do |t|
|
26
|
+
File.open(t.name, 'wb') do |f|
|
27
|
+
f.write <<-RUBY
|
28
|
+
require "couchbase/\#{RUBY_VERSION.sub(/\\.\\d+$/, '')}/couchbase_ext"
|
29
|
+
RUBY
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
25
33
|
# Setup compile tasks. Configuration can be passed via ENV.
|
26
34
|
# Example:
|
27
35
|
# rake compile with_libcouchbase_include=/opt/couchbase/include
|
@@ -33,13 +41,14 @@ end
|
|
33
41
|
#
|
34
42
|
Rake::ExtensionTask.new("couchbase_ext", gemspec) do |ext|
|
35
43
|
ext.cross_compile = true
|
36
|
-
ext.cross_platform =
|
44
|
+
ext.cross_platform = ENV['HOST'] || "i386-mingw32"
|
37
45
|
if ENV['RUBY_CC_VERSION']
|
38
46
|
ext.lib_dir = "lib/couchbase"
|
39
47
|
end
|
40
48
|
ext.cross_compiling do |spec|
|
41
49
|
spec.files.delete("lib/couchbase/couchbase_ext.so")
|
42
50
|
spec.files.push("lib/couchbase_ext.rb", Dir["lib/couchbase/1.{8,9}/couchbase_ext.so"])
|
51
|
+
file "#{ext.tmp_dir}/#{ext.cross_platform}/stage/lib/couchbase_ext.rb", &version_router
|
43
52
|
end
|
44
53
|
|
45
54
|
CLEAN.include "#{ext.lib_dir}/*.#{RbConfig::CONFIG['DLEXT']}"
|
@@ -84,12 +93,14 @@ namespace :ports do
|
|
84
93
|
directory "ports"
|
85
94
|
|
86
95
|
task :libcouchbase => ["ports"] do
|
87
|
-
recipe = MiniPortile.new "libcouchbase", "2.
|
96
|
+
recipe = MiniPortile.new "libcouchbase", "2.1.3"
|
88
97
|
recipe.files << "http://packages.couchbase.com/clients/c/libcouchbase-#{recipe.version}.tar.gz"
|
98
|
+
|
89
99
|
recipe.configure_options.push("--disable-debug",
|
90
100
|
"--disable-dependency-tracking",
|
91
101
|
"--disable-couchbasemock",
|
92
102
|
"--disable-cxx",
|
103
|
+
"--disable-plugins",
|
93
104
|
"--disable-examples",
|
94
105
|
"--disable-tools")
|
95
106
|
recipe.cook
|
@@ -97,19 +108,13 @@ namespace :ports do
|
|
97
108
|
end
|
98
109
|
end
|
99
110
|
|
100
|
-
file "lib/couchbase_ext.rb"
|
101
|
-
File.open("lib/couchbase_ext.rb", 'wb') do |f|
|
102
|
-
f.write <<-RUBY
|
103
|
-
require "couchbase/\#{RUBY_VERSION.sub(/\\.\\d+$/, '')}/couchbase_ext"
|
104
|
-
RUBY
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
111
|
+
file "lib/couchbase_ext.rb", &version_router
|
108
112
|
task :cross => ["lib/couchbase_ext.rb", "ports:libcouchbase"]
|
109
113
|
|
110
114
|
desc "Package gem for windows"
|
111
115
|
task "package:windows" => :package do
|
112
116
|
sh("env RUBY_CC_VERSION=1.8.7 RBENV_VERSION=1.8.7-p370 rbenv exec bundle exec rake cross compile")
|
113
117
|
sh("env RUBY_CC_VERSION=1.9.2 RBENV_VERSION=1.9.2-p320 rbenv exec bundle exec rake cross compile")
|
114
|
-
sh("env RUBY_CC_VERSION=
|
118
|
+
sh("env RUBY_CC_VERSION=2.0.0 RBENV_VERSION=2.0.0-p247 rbenv exec bundle exec rake cross compile")
|
119
|
+
sh("env RUBY_CC_VERSION=1.8.7:1.9.2:2.0.0 RBENV_VERSION=1.9.2-p320 rbenv exec bundle exec rake cross native gem")
|
115
120
|
end
|
data/test/test_bucket.rb
CHANGED
@@ -119,6 +119,12 @@ class TestBucket < MiniTest::Test
|
|
119
119
|
def test_it_raises_error_with_wrong_credentials
|
120
120
|
with_mock do |mock|
|
121
121
|
assert_raises Couchbase::Error::Auth do
|
122
|
+
Couchbase.new(:hostname => mock.host,
|
123
|
+
:port => mock.port,
|
124
|
+
:bucket => 'default',
|
125
|
+
:password => 'wrong_password')
|
126
|
+
end
|
127
|
+
assert_raises Couchbase::Error::InvalidUsername do
|
122
128
|
Couchbase.new(:hostname => mock.host,
|
123
129
|
:port => mock.port,
|
124
130
|
:bucket => 'default',
|
@@ -130,7 +136,7 @@ class TestBucket < MiniTest::Test
|
|
130
136
|
|
131
137
|
def test_it_unable_to_connect_to_protected_buckets_with_wrong_credentials
|
132
138
|
with_mock(:buckets_spec => 'protected:secret') do |mock|
|
133
|
-
assert_raises Couchbase::Error::
|
139
|
+
assert_raises Couchbase::Error::InvalidUsername do
|
134
140
|
Couchbase.new(:hostname => mock.host,
|
135
141
|
:port => mock.port,
|
136
142
|
:bucket => 'protected',
|
@@ -234,4 +240,11 @@ class TestBucket < MiniTest::Test
|
|
234
240
|
end
|
235
241
|
end
|
236
242
|
|
243
|
+
def test_it_doesnt_try_to_destroy_handle_in_case_of_lcb_create_failure
|
244
|
+
assert_raises(Couchbase::Error::InvalidHostFormat) do
|
245
|
+
Couchbase.connect(:hostname => "foobar:baz")
|
246
|
+
end
|
247
|
+
GC.start # make sure it won't touch handle in finalizer
|
248
|
+
end
|
249
|
+
|
237
250
|
end
|
metadata
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couchbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 3
|
9
|
-
- 2
|
10
|
-
version: 1.3.2
|
4
|
+
version: 1.3.3
|
11
5
|
platform: ruby
|
12
6
|
authors:
|
13
7
|
- Couchbase
|
@@ -15,160 +9,103 @@ autorequire:
|
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
11
|
|
18
|
-
date: 2013-
|
19
|
-
default_executable:
|
12
|
+
date: 2013-09-13 00:00:00 Z
|
20
13
|
dependencies:
|
21
14
|
- !ruby/object:Gem::Dependency
|
15
|
+
prerelease: false
|
22
16
|
type: :runtime
|
17
|
+
name: yaji
|
23
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
19
|
requirements:
|
26
20
|
- - ~>
|
27
21
|
- !ruby/object:Gem::Version
|
28
|
-
hash: 23
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 3
|
32
|
-
- 2
|
33
22
|
version: 0.3.2
|
34
|
-
name: yaji
|
35
23
|
version_requirements: *id001
|
36
|
-
prerelease: false
|
37
24
|
- !ruby/object:Gem::Dependency
|
25
|
+
prerelease: false
|
38
26
|
type: :runtime
|
27
|
+
name: multi_json
|
39
28
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
-
none: false
|
41
29
|
requirements:
|
42
30
|
- - ~>
|
43
31
|
- !ruby/object:Gem::Version
|
44
|
-
hash: 15
|
45
|
-
segments:
|
46
|
-
- 1
|
47
|
-
- 0
|
48
32
|
version: "1.0"
|
49
|
-
name: multi_json
|
50
33
|
version_requirements: *id002
|
51
|
-
prerelease: false
|
52
34
|
- !ruby/object:Gem::Dependency
|
35
|
+
prerelease: false
|
53
36
|
type: :runtime
|
37
|
+
name: connection_pool
|
54
38
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
39
|
requirements:
|
57
40
|
- - ~>
|
58
41
|
- !ruby/object:Gem::Version
|
59
|
-
hash: 23
|
60
|
-
segments:
|
61
|
-
- 1
|
62
|
-
- 0
|
63
|
-
- 0
|
64
42
|
version: 1.0.0
|
65
|
-
name: connection_pool
|
66
43
|
version_requirements: *id003
|
67
|
-
prerelease: false
|
68
44
|
- !ruby/object:Gem::Dependency
|
45
|
+
prerelease: false
|
69
46
|
type: :development
|
47
|
+
name: rake
|
70
48
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
49
|
requirements:
|
73
|
-
-
|
50
|
+
- &id007
|
51
|
+
- ">="
|
74
52
|
- !ruby/object:Gem::Version
|
75
|
-
hash: 3
|
76
|
-
segments:
|
77
|
-
- 0
|
78
53
|
version: "0"
|
79
|
-
name: rake
|
80
54
|
version_requirements: *id004
|
81
|
-
prerelease: false
|
82
55
|
- !ruby/object:Gem::Dependency
|
56
|
+
prerelease: false
|
83
57
|
type: :development
|
58
|
+
name: minitest
|
84
59
|
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
-
none: false
|
86
60
|
requirements:
|
87
61
|
- - ~>
|
88
62
|
- !ruby/object:Gem::Version
|
89
|
-
hash: 63
|
90
|
-
segments:
|
91
|
-
- 5
|
92
|
-
- 0
|
93
|
-
- 4
|
94
63
|
version: 5.0.4
|
95
|
-
name: minitest
|
96
64
|
version_requirements: *id005
|
97
|
-
prerelease: false
|
98
65
|
- !ruby/object:Gem::Dependency
|
66
|
+
prerelease: false
|
99
67
|
type: :development
|
68
|
+
name: rake-compiler
|
100
69
|
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
-
none: false
|
102
70
|
requirements:
|
103
71
|
- - ">="
|
104
72
|
- !ruby/object:Gem::Version
|
105
|
-
hash: 9
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
- 7
|
109
|
-
- 5
|
110
73
|
version: 0.7.5
|
111
|
-
name: rake-compiler
|
112
74
|
version_requirements: *id006
|
113
|
-
prerelease: false
|
114
75
|
- !ruby/object:Gem::Dependency
|
115
|
-
type: :development
|
116
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
117
|
-
none: false
|
118
|
-
requirements:
|
119
|
-
- - ">="
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
hash: 3
|
122
|
-
segments:
|
123
|
-
- 0
|
124
|
-
version: "0"
|
125
|
-
name: mini_portile
|
126
|
-
version_requirements: *id007
|
127
76
|
prerelease: false
|
128
|
-
- !ruby/object:Gem::Dependency
|
129
77
|
type: :development
|
78
|
+
name: mini_portile
|
130
79
|
requirement: &id008 !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
80
|
requirements:
|
133
|
-
-
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
hash: 19
|
136
|
-
segments:
|
137
|
-
- 1
|
138
|
-
- 1
|
139
|
-
- 0
|
140
|
-
version: 1.1.0
|
141
|
-
name: yajl-ruby
|
81
|
+
- *id007
|
142
82
|
version_requirements: *id008
|
143
|
-
prerelease: false
|
144
83
|
- !ruby/object:Gem::Dependency
|
84
|
+
prerelease: false
|
145
85
|
type: :development
|
86
|
+
name: yajl-ruby
|
146
87
|
requirement: &id009 !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
88
|
requirements:
|
149
|
-
- -
|
89
|
+
- - ~>
|
150
90
|
- !ruby/object:Gem::Version
|
151
|
-
|
152
|
-
segments:
|
153
|
-
- 0
|
154
|
-
version: "0"
|
155
|
-
name: active_support
|
91
|
+
version: 1.1.0
|
156
92
|
version_requirements: *id009
|
157
|
-
prerelease: false
|
158
93
|
- !ruby/object:Gem::Dependency
|
94
|
+
prerelease: false
|
159
95
|
type: :development
|
96
|
+
name: active_support
|
160
97
|
requirement: &id010 !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
98
|
requirements:
|
163
|
-
-
|
164
|
-
- !ruby/object:Gem::Version
|
165
|
-
hash: 3
|
166
|
-
segments:
|
167
|
-
- 0
|
168
|
-
version: "0"
|
169
|
-
name: eventmachine
|
99
|
+
- *id007
|
170
100
|
version_requirements: *id010
|
101
|
+
- !ruby/object:Gem::Dependency
|
171
102
|
prerelease: false
|
103
|
+
type: :development
|
104
|
+
name: eventmachine
|
105
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- *id007
|
108
|
+
version_requirements: *id011
|
172
109
|
description: The official client library for use with Couchbase Server.
|
173
110
|
email: support@couchbase.com
|
174
111
|
executables: []
|
@@ -268,39 +205,50 @@ files:
|
|
268
205
|
- test/test_unlock.rb
|
269
206
|
- test/test_utils.rb
|
270
207
|
- test/test_version.rb
|
271
|
-
has_rdoc: true
|
272
208
|
homepage: http://couchbase.org
|
273
209
|
licenses:
|
274
210
|
- ASL-2
|
211
|
+
metadata: {}
|
212
|
+
|
275
213
|
post_install_message:
|
276
214
|
rdoc_options: []
|
277
215
|
|
278
216
|
require_paths:
|
279
217
|
- lib
|
280
218
|
required_ruby_version: !ruby/object:Gem::Requirement
|
281
|
-
none: false
|
282
219
|
requirements:
|
283
|
-
-
|
284
|
-
- !ruby/object:Gem::Version
|
285
|
-
hash: 3
|
286
|
-
segments:
|
287
|
-
- 0
|
288
|
-
version: "0"
|
220
|
+
- *id007
|
289
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
290
|
-
none: false
|
291
222
|
requirements:
|
292
|
-
-
|
293
|
-
- !ruby/object:Gem::Version
|
294
|
-
hash: 3
|
295
|
-
segments:
|
296
|
-
- 0
|
297
|
-
version: "0"
|
223
|
+
- *id007
|
298
224
|
requirements: []
|
299
225
|
|
300
226
|
rubyforge_project:
|
301
|
-
rubygems_version: 1.
|
227
|
+
rubygems_version: 2.1.3
|
302
228
|
signing_key:
|
303
|
-
specification_version:
|
229
|
+
specification_version: 4
|
304
230
|
summary: Couchbase ruby driver
|
305
|
-
test_files:
|
306
|
-
|
231
|
+
test_files:
|
232
|
+
- test/profile/.gitignore
|
233
|
+
- test/profile/Gemfile
|
234
|
+
- test/profile/benchmark.rb
|
235
|
+
- test/setup.rb
|
236
|
+
- test/test_arithmetic.rb
|
237
|
+
- test/test_async.rb
|
238
|
+
- test/test_bucket.rb
|
239
|
+
- test/test_cas.rb
|
240
|
+
- test/test_couchbase.rb
|
241
|
+
- test/test_couchbase_connection_pool.rb
|
242
|
+
- test/test_couchbase_rails_cache_store.rb
|
243
|
+
- test/test_delete.rb
|
244
|
+
- test/test_errors.rb
|
245
|
+
- test/test_eventmachine.rb
|
246
|
+
- test/test_format.rb
|
247
|
+
- test/test_get.rb
|
248
|
+
- test/test_stats.rb
|
249
|
+
- test/test_store.rb
|
250
|
+
- test/test_timer.rb
|
251
|
+
- test/test_touch.rb
|
252
|
+
- test/test_unlock.rb
|
253
|
+
- test/test_utils.rb
|
254
|
+
- test/test_version.rb
|