couchbase 1.3.2-x86-mingw32 → 1.3.3-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 64c92cbfdb47cf90b52c5a3ddf6817b0b2f47824
4
+ data.tar.gz: 52b91ab4cad3bd75ca351b24f34a7cf3b68b7344
5
+ SHA512:
6
+ metadata.gz: 1cc2d6eaf5fff25fa40b9d0ac9e389bd2cbc3561c6e98355d138c746db7004614d01e3e47ef5c1f2990657cfb68571bba12a19182c091c8c70f045320232fb66
7
+ data.tar.gz: db81527b9c87d8522e5b4e0c9712fbef06b53628d388757e0f5c60d12e9403afd71b10b4c8311073fbf178f79397b6c86775da28e02c6fb1f961e26dbaf3bfb6
data/.travis.yml CHANGED
@@ -19,4 +19,4 @@ rvm:
19
19
 
20
20
  notifications:
21
21
  email:
22
- - sdk_dev@couchbase.com
22
+ - sergey@couchbase.com
@@ -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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[ii], params->cmd.touch.ttl);
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, RARRAY_PTR(argv)[ii], params->cmd.touch.ttl);
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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[ii], params->cmd.remove.cas);
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, RARRAY_PTR(argv)[ii], params->cmd.remove.cas);
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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(argv)[0], RARRAY_PTR(argv)[1],
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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[ii]);
486
- cb_params_get_init_item(params, ii, RARRAY_PTR(keys)[ii], params->cmd.get.ttl);
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, RARRAY_PTR(argv)[ii]);
509
- cb_params_get_init_item(params, ii, RARRAY_PTR(argv)[ii], params->cmd.get.ttl);
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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[ii], params->cmd.arith.delta);
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, RARRAY_PTR(argv)[ii], params->cmd.arith.delta);
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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[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, RARRAY_PTR(argv)[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 = RARRAY_PTR(argv)[0];
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, RARRAY_PTR(keys)[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, RARRAY_PTR(argv)[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 = RARRAY_PTR(argv)[0];
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(RARRAY_PTR(argv)[argc-1]) == T_HASH) {
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(RARRAY_PTR(argv)[1]);
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(RARRAY_PTR(argv)[1]) == T_FIXNUM) {
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(RARRAY_PTR(argv)[1]);
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;
@@ -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
- st_foreach(bucket->object_space, cb_bucket_mark_object_i, (st_data_t)bucket);
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
- #ifndef _WIN32
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
- lcb_destroy(bucket->handle);
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_WINIOCP;
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->username) ? RSTRING_PTR(bucket->password) : NULL;
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
- lcb_destroy(bucket->handle);
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
- lcb_destroy(bucket->handle);
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 cb_symbol in the shared object
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
- lcb_get_replica_cmd_t cmd;
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.0.7\nSee http://www.couchbase.com/communities/c/ for more details")
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")
@@ -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
- flags = ULONG2NUM(resp->v.v0.flags);
40
- cas = ULL2NUM(resp->v.v0.cas);
41
- raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
42
- val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts);
43
- if (rb_obj_is_kind_of(val, rb_eStandardError)) {
44
- VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
45
- VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
46
- rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str);
47
- ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
48
- rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
49
- rb_ivar_set(ctx->exception, cb_id_iv_key, key);
50
- rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
51
- val = Qnil;
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 *keys_ptr, ret;
298
+ VALUE keys, ret;
295
299
  ret = rb_ary_new();
296
- keys_ptr = RARRAY_PTR(params.cmd.get.keys_ary);
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, keys_ptr[ii]));
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
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
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
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
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()) {
@@ -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(RARRAY_PTR(ret)[1]);
379
- return RARRAY_PTR(ret)[0];
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
- thread_storage[:bucket] ||= connect(connection_options)
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
- thread_storage[:bucket] = connection
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
 
@@ -17,5 +17,5 @@
17
17
 
18
18
  # Couchbase ruby client
19
19
  module Couchbase
20
- VERSION = "1.3.2"
20
+ VERSION = "1.3.3"
21
21
  end
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 = [ENV['HOST'] || "i386-mingw32"]
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.0.7"
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" do
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=1.8.7:1.9.2 RBENV_VERSION=1.9.2-p320 rbenv exec bundle exec rake cross native gem")
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::Auth do
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,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
5
- prerelease:
4
+ version: 1.3.3
6
5
  platform: x86-mingw32
7
6
  authors:
8
7
  - Couchbase
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-07-10 00:00:00.000000000 Z
11
+ date: 2013-09-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: yaji
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: multi_json
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: connection_pool
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rake
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: minitest
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
@@ -94,7 +83,6 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: rake-compiler
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ! '>='
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ! '>='
108
95
  - !ruby/object:Gem::Version
@@ -110,7 +97,6 @@ dependencies:
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: mini_portile
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ! '>='
116
102
  - !ruby/object:Gem::Version
@@ -118,7 +104,6 @@ dependencies:
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ! '>='
124
109
  - !ruby/object:Gem::Version
@@ -126,7 +111,6 @@ dependencies:
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: yajl-ruby
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
115
  - - ~>
132
116
  - !ruby/object:Gem::Version
@@ -134,7 +118,6 @@ dependencies:
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
122
  - - ~>
140
123
  - !ruby/object:Gem::Version
@@ -142,7 +125,6 @@ dependencies:
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: active_support
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
129
  - - ! '>='
148
130
  - !ruby/object:Gem::Version
@@ -150,7 +132,6 @@ dependencies:
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
136
  - - ! '>='
156
137
  - !ruby/object:Gem::Version
@@ -158,7 +139,6 @@ dependencies:
158
139
  - !ruby/object:Gem::Dependency
159
140
  name: eventmachine
160
141
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
142
  requirements:
163
143
  - - ! '>='
164
144
  - !ruby/object:Gem::Version
@@ -166,7 +146,6 @@ dependencies:
166
146
  type: :development
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
149
  requirements:
171
150
  - - ! '>='
172
151
  - !ruby/object:Gem::Version
@@ -269,36 +248,30 @@ files:
269
248
  - test/test_version.rb
270
249
  - lib/couchbase/1.8/couchbase_ext.so
271
250
  - lib/couchbase/1.9/couchbase_ext.so
251
+ - lib/couchbase/2.0/couchbase_ext.so
272
252
  - lib/couchbase_ext.rb
273
253
  homepage: http://couchbase.org
274
254
  licenses:
275
255
  - ASL-2
256
+ metadata: {}
276
257
  post_install_message:
277
258
  rdoc_options: []
278
259
  require_paths:
279
260
  - lib
280
261
  required_ruby_version: !ruby/object:Gem::Requirement
281
- none: false
282
262
  requirements:
283
263
  - - ! '>='
284
264
  - !ruby/object:Gem::Version
285
265
  version: '0'
286
- segments:
287
- - 0
288
- hash: 786073145375983008
289
266
  required_rubygems_version: !ruby/object:Gem::Requirement
290
- none: false
291
267
  requirements:
292
268
  - - ! '>='
293
269
  - !ruby/object:Gem::Version
294
270
  version: '0'
295
- segments:
296
- - 0
297
- hash: 786073145375983008
298
271
  requirements: []
299
272
  rubyforge_project:
300
- rubygems_version: 1.8.23
273
+ rubygems_version: 2.0.7
301
274
  signing_key:
302
- specification_version: 3
275
+ specification_version: 4
303
276
  summary: Couchbase ruby driver
304
277
  test_files: []