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

Sign up to get free protection for your applications and to get access to all the features.
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: []