couchbase 1.2.0.z.beta5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/couchbase.gemspec CHANGED
@@ -46,6 +46,5 @@ Gem::Specification.new do |s|
46
46
  s.add_development_dependency 'yard-xml'
47
47
  s.add_development_dependency 'mini_portile'
48
48
  s.add_development_dependency 'yajl-ruby', '~> 1.1.0'
49
- s.add_development_dependency RUBY_VERSION =~ /^1\.9/ ? 'debugger' : 'ruby-debug'
50
49
  s.add_development_dependency 'active_support'
51
50
  end
@@ -19,23 +19,37 @@
19
19
 
20
20
  /* TOUCH */
21
21
 
22
+ #define _alloc_data_for_s(type, _type, size, items, ptr) do {\
23
+ lcb_size_t ii; \
24
+ \
25
+ params->cmd.type.num = size; \
26
+ params->cmd.type.items = calloc(size, sizeof(_type)); \
27
+ if (params->cmd.type.items == NULL) { \
28
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments"); \
29
+ } \
30
+ params->cmd.type.ptr = calloc(size, sizeof(_type *)); \
31
+ if (params->cmd.type.ptr == NULL) { \
32
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments"); \
33
+ } \
34
+ for (ii = 0; ii < size; ++ii) { \
35
+ params->cmd.type.ptr[ii] = params->cmd.type.items + ii; \
36
+ } \
37
+ } while(0)
38
+
39
+ #define _alloc_data_for(type, _type) _alloc_data_for_s(type, _type, size, items, ptr)
40
+
41
+
42
+ #define _release_data_for_s(type, items, ptr) \
43
+ free(params->cmd.type.items); \
44
+ free(params->cmd.type.ptr);
45
+
46
+ #define _release_data_for(type) _release_data_for_s(type, items, ptr)
47
+
48
+
22
49
  static void
23
50
  cb_params_touch_alloc(struct cb_params_st *params, lcb_size_t size)
24
51
  {
25
- lcb_size_t ii;
26
-
27
- params->cmd.touch.num = size;
28
- params->cmd.touch.items = xcalloc(size, sizeof(lcb_touch_cmd_t));
29
- if (params->cmd.touch.items == NULL) {
30
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
31
- }
32
- params->cmd.touch.ptr = xcalloc(size, sizeof(lcb_touch_cmd_t *));
33
- if (params->cmd.touch.ptr == NULL) {
34
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
35
- }
36
- for (ii = 0; ii < size; ++ii) {
37
- params->cmd.touch.ptr[ii] = params->cmd.touch.items + ii;
38
- }
52
+ _alloc_data_for(touch, lcb_touch_cmd_t);
39
53
  }
40
54
 
41
55
  static void
@@ -68,8 +82,9 @@ cb_params_touch_parse_options(struct cb_params_st *params, VALUE options)
68
82
  if (tmp != Qnil) {
69
83
  params->cmd.touch.ttl = NUM2ULONG(tmp);
70
84
  }
71
- if (RTEST(rb_funcall(options, cb_id_has_key_p, 1, cb_sym_quiet))) {
72
- params->cmd.touch.quiet = RTEST(rb_hash_aref(options, cb_sym_quiet));
85
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
86
+ if (tmp != Qundef) {
87
+ params->cmd.touch.quiet = RTEST(tmp);
73
88
  }
74
89
  }
75
90
 
@@ -118,20 +133,7 @@ cb_params_touch_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
118
133
  static void
119
134
  cb_params_remove_alloc(struct cb_params_st *params, lcb_size_t size)
120
135
  {
121
- lcb_size_t ii;
122
-
123
- params->cmd.remove.num = size;
124
- params->cmd.remove.items = xcalloc(size, sizeof(lcb_remove_cmd_t));
125
- if (params->cmd.remove.items == NULL) {
126
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
127
- }
128
- params->cmd.remove.ptr = xcalloc(size, sizeof(lcb_remove_cmd_t *));
129
- if (params->cmd.remove.ptr == NULL) {
130
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
131
- }
132
- for (ii = 0; ii < size; ++ii) {
133
- params->cmd.remove.ptr[ii] = params->cmd.remove.items + ii;
134
- }
136
+ _alloc_data_for(remove, lcb_remove_cmd_t);
135
137
  }
136
138
 
137
139
  static void
@@ -160,8 +162,9 @@ cb_params_remove_parse_options(struct cb_params_st *params, VALUE options)
160
162
  if (NIL_P(options)) {
161
163
  return;
162
164
  }
163
- if (RTEST(rb_funcall(options, cb_id_has_key_p, 1, cb_sym_quiet))) {
164
- params->cmd.remove.quiet = RTEST(rb_hash_aref(options, cb_sym_quiet));
165
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
166
+ if (tmp != Qundef) {
167
+ params->cmd.remove.quiet = RTEST(tmp);
165
168
  }
166
169
  tmp = rb_hash_aref(options, cb_sym_cas);
167
170
  if (tmp != Qnil) {
@@ -213,20 +216,7 @@ cb_params_remove_parse_arguments(struct cb_params_st *params, int argc, VALUE ar
213
216
  static void
214
217
  cb_params_store_alloc(struct cb_params_st *params, lcb_size_t size)
215
218
  {
216
- lcb_size_t ii;
217
-
218
- params->cmd.store.num = size;
219
- params->cmd.store.items = xcalloc(size, sizeof(lcb_store_cmd_t));
220
- if (params->cmd.store.items == NULL) {
221
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
222
- }
223
- params->cmd.store.ptr = xcalloc(size, sizeof(lcb_store_cmd_t *));
224
- if (params->cmd.store.ptr == NULL) {
225
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
226
- }
227
- for (ii = 0; ii < size; ++ii) {
228
- params->cmd.store.ptr[ii] = params->cmd.store.items + ii;
229
- }
219
+ _alloc_data_for(store, lcb_store_cmd_t);
230
220
  }
231
221
 
232
222
  static void
@@ -345,33 +335,10 @@ cb_params_store_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
345
335
  static void
346
336
  cb_params_get_alloc(struct cb_params_st *params, lcb_size_t size)
347
337
  {
348
- lcb_size_t ii;
349
-
350
- params->cmd.get.num = size;
351
338
  if (params->cmd.get.replica) {
352
- params->cmd.get.items = xcalloc(size, sizeof(lcb_get_replica_cmd_t));
353
- if (params->cmd.get.items_gr == NULL) {
354
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
355
- }
356
- params->cmd.get.ptr = xcalloc(size, sizeof(lcb_get_replica_cmd_t *));
357
- if (params->cmd.get.ptr_gr == NULL) {
358
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
359
- }
360
- for (ii = 0; ii < size; ++ii) {
361
- params->cmd.get.ptr_gr[ii] = params->cmd.get.items_gr + ii;
362
- }
339
+ _alloc_data_for_s(get, lcb_get_replica_cmd_t, size, items_gr, ptr_gr);
363
340
  } else {
364
- params->cmd.get.items = xcalloc(size, sizeof(lcb_get_cmd_t));
365
- if (params->cmd.get.items == NULL) {
366
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
367
- }
368
- params->cmd.get.ptr = xcalloc(size, sizeof(lcb_get_cmd_t *));
369
- if (params->cmd.get.ptr == NULL) {
370
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
371
- }
372
- for (ii = 0; ii < size; ++ii) {
373
- params->cmd.get.ptr[ii] = params->cmd.get.items + ii;
374
- }
341
+ _alloc_data_for(get, lcb_get_cmd_t);
375
342
  }
376
343
  }
377
344
 
@@ -413,8 +380,9 @@ cb_params_get_parse_options(struct cb_params_st *params, VALUE options)
413
380
  params->cmd.get.replica = RTEST(rb_hash_aref(options, cb_sym_replica));
414
381
  params->cmd.get.extended = RTEST(rb_hash_aref(options, cb_sym_extended));
415
382
  params->cmd.get.assemble_hash = RTEST(rb_hash_aref(options, cb_sym_assemble_hash));
416
- if (RTEST(rb_funcall(options, cb_id_has_key_p, 1, cb_sym_quiet))) {
417
- params->cmd.get.quiet = RTEST(rb_hash_aref(options, cb_sym_quiet));
383
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
384
+ if (tmp != Qundef) {
385
+ params->cmd.get.quiet = RTEST(tmp);
418
386
  }
419
387
  tmp = rb_hash_aref(options, cb_sym_format);
420
388
  if (tmp != Qnil) {
@@ -485,20 +453,7 @@ cb_params_get_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
485
453
  static void
486
454
  cb_params_arith_alloc(struct cb_params_st *params, lcb_size_t size)
487
455
  {
488
- lcb_size_t ii;
489
-
490
- params->cmd.arith.num = size;
491
- params->cmd.arith.items = xcalloc(size, sizeof(lcb_arithmetic_cmd_t));
492
- if (params->cmd.arith.items == NULL) {
493
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
494
- }
495
- params->cmd.arith.ptr = xcalloc(size, sizeof(lcb_arithmetic_cmd_t *));
496
- if (params->cmd.arith.ptr == NULL) {
497
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
498
- }
499
- for (ii = 0; ii < size; ++ii) {
500
- params->cmd.arith.ptr[ii] = params->cmd.arith.items + ii;
501
- }
456
+ _alloc_data_for(arith, lcb_arithmetic_cmd_t);
502
457
  }
503
458
 
504
459
  static void
@@ -602,20 +557,7 @@ cb_params_arith_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
602
557
  static void
603
558
  cb_params_stats_alloc(struct cb_params_st *params, lcb_size_t size)
604
559
  {
605
- lcb_size_t ii;
606
-
607
- params->cmd.stats.num = size;
608
- params->cmd.stats.items = xcalloc(size, sizeof(lcb_server_stats_cmd_t));
609
- if (params->cmd.stats.items == NULL) {
610
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
611
- }
612
- params->cmd.stats.ptr = xcalloc(size, sizeof(lcb_server_stats_cmd_t *));
613
- if (params->cmd.stats.ptr == NULL) {
614
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
615
- }
616
- for (ii = 0; ii < size; ++ii) {
617
- params->cmd.stats.ptr[ii] = params->cmd.stats.items + ii;
618
- }
560
+ _alloc_data_for(stats, lcb_server_stats_cmd_t);
619
561
  }
620
562
 
621
563
  static void
@@ -667,20 +609,7 @@ cb_params_stats_parse_arguments(struct cb_params_st *params, int argc, VALUE arg
667
609
  static void
668
610
  cb_params_observe_alloc(struct cb_params_st *params, lcb_size_t size)
669
611
  {
670
- lcb_size_t ii;
671
-
672
- params->cmd.observe.num = size;
673
- params->cmd.observe.items = xcalloc(size, sizeof(lcb_observe_cmd_t));
674
- if (params->cmd.observe.items == NULL) {
675
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
676
- }
677
- params->cmd.observe.ptr = xcalloc(size, sizeof(lcb_observe_cmd_t *));
678
- if (params->cmd.observe.ptr == NULL) {
679
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
680
- }
681
- for (ii = 0; ii < size; ++ii) {
682
- params->cmd.observe.ptr[ii] = params->cmd.observe.items + ii;
683
- }
612
+ _alloc_data_for(observe, lcb_observe_cmd_t);
684
613
  }
685
614
 
686
615
  static void
@@ -730,20 +659,7 @@ cb_params_observe_parse_arguments(struct cb_params_st *params, int argc, VALUE a
730
659
  static void
731
660
  cb_params_unlock_alloc(struct cb_params_st *params, lcb_size_t size)
732
661
  {
733
- lcb_size_t ii;
734
-
735
- params->cmd.unlock.num = size;
736
- params->cmd.unlock.items = xcalloc(size, sizeof(lcb_unlock_cmd_t));
737
- if (params->cmd.unlock.items == NULL) {
738
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
739
- }
740
- params->cmd.unlock.ptr = xcalloc(size, sizeof(lcb_unlock_cmd_t *));
741
- if (params->cmd.unlock.ptr == NULL) {
742
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
743
- }
744
- for (ii = 0; ii < size; ++ii) {
745
- params->cmd.unlock.ptr[ii] = params->cmd.unlock.items + ii;
746
- }
662
+ _alloc_data_for(unlock, lcb_unlock_cmd_t);
747
663
  }
748
664
 
749
665
  static void
@@ -776,8 +692,9 @@ cb_params_unlock_parse_options(struct cb_params_st *params, VALUE options)
776
692
  if (tmp != Qnil) {
777
693
  params->cmd.unlock.cas = NUM2ULL(tmp);
778
694
  }
779
- if (RTEST(rb_funcall(options, cb_id_has_key_p, 1, cb_sym_quiet))) {
780
- params->cmd.unlock.quiet = RTEST(rb_hash_aref(options, cb_sym_quiet));
695
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
696
+ if (tmp != Qundef) {
697
+ params->cmd.unlock.quiet = RTEST(tmp);
781
698
  }
782
699
  }
783
700
 
@@ -808,15 +725,7 @@ cb_params_unlock_parse_arguments(struct cb_params_st *params, int argc, VALUE ar
808
725
  cb_params_version_alloc(struct cb_params_st *params)
809
726
  {
810
727
  params->cmd.version.num = 1;
811
- params->cmd.version.items = xcalloc(1, sizeof(lcb_server_version_cmd_t));
812
- if (params->cmd.version.items == NULL) {
813
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
814
- }
815
- params->cmd.version.ptr = xcalloc(1, sizeof(lcb_server_version_cmd_t *));
816
- if (params->cmd.version.ptr == NULL) {
817
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments");
818
- }
819
- params->cmd.version.ptr[0] = params->cmd.version.items;
728
+ _alloc_data_for_s(version, lcb_server_version_cmd_t, 1, items, ptr);
820
729
  }
821
730
 
822
731
 
@@ -824,15 +733,10 @@ cb_params_version_alloc(struct cb_params_st *params)
824
733
  void
825
734
  cb_params_destroy(struct cb_params_st *params)
826
735
  {
827
- #define _release_data_for(type) \
828
- xfree(params->cmd.type.items); \
829
- xfree(params->cmd.type.ptr);
830
-
831
736
  switch (params->type) {
832
737
  case cb_cmd_get:
833
738
  _release_data_for(get);
834
- xfree(params->cmd.get.items_gr);
835
- xfree(params->cmd.get.ptr_gr);
739
+ _release_data_for_s(get, items_gr, ptr_gr);
836
740
  break;
837
741
  case cb_cmd_touch:
838
742
  _release_data_for(touch);
@@ -859,7 +763,6 @@ cb_params_destroy(struct cb_params_st *params)
859
763
  _release_data_for(unlock);
860
764
  break;
861
765
  }
862
- #undef _release_data_for
863
766
  }
864
767
 
865
768
  struct build_params_st
@@ -35,18 +35,7 @@ cb_arithmetic_callback(lcb_t handle, const void *cookie, lcb_error_t error, cons
35
35
  if (exc != Qnil) {
36
36
  rb_ivar_set(exc, cb_id_iv_cas, cas);
37
37
  rb_ivar_set(exc, cb_id_iv_operation, o);
38
- if (bucket->async) {
39
- if (bucket->on_error_proc != Qnil) {
40
- cb_proc_call(bucket->on_error_proc, 3, o, key, exc);
41
- } else {
42
- if (NIL_P(bucket->exception)) {
43
- bucket->exception = exc;
44
- }
45
- }
46
- }
47
- if (NIL_P(ctx->exception)) {
48
- ctx->exception = cb_gc_protect(bucket, exc);
49
- }
38
+ ctx->exception = cb_gc_protect(bucket, exc);
50
39
  }
51
40
  val = ULL2NUM(resp->v.v0.value);
52
41
  if (bucket->async) { /* asynchronous */
@@ -57,7 +46,7 @@ cb_arithmetic_callback(lcb_t handle, const void *cookie, lcb_error_t error, cons
57
46
  rb_ivar_set(res, cb_id_iv_key, key);
58
47
  rb_ivar_set(res, cb_id_iv_value, val);
59
48
  rb_ivar_set(res, cb_id_iv_cas, cas);
60
- cb_proc_call(ctx->proc, 1, res);
49
+ cb_proc_call(bucket, ctx->proc, 1, res);
61
50
  }
62
51
  } else { /* synchronous */
63
52
  if (NIL_P(exc)) {
@@ -71,7 +60,7 @@ cb_arithmetic_callback(lcb_t handle, const void *cookie, lcb_error_t error, cons
71
60
  if (ctx->nqueries == 0) {
72
61
  cb_gc_unprotect(bucket, ctx->proc);
73
62
  if (bucket->async) {
74
- xfree(ctx);
63
+ free(ctx);
75
64
  }
76
65
  }
77
66
  (void)handle;
@@ -98,7 +87,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
98
87
  params.bucket = bucket;
99
88
  params.cmd.arith.sign = sign;
100
89
  cb_params_build(&params, RARRAY_LEN(args), args);
101
- ctx = xcalloc(1, sizeof(struct cb_context_st));
90
+ ctx = calloc(1, sizeof(struct cb_context_st));
102
91
  if (ctx == NULL) {
103
92
  rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
104
93
  }
@@ -113,7 +102,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
113
102
  cb_params_destroy(&params);
114
103
  exc = cb_check_error(err, "failed to schedule arithmetic request", Qnil);
115
104
  if (exc != Qnil) {
116
- xfree(ctx);
105
+ free(ctx);
117
106
  rb_exc_raise(exc);
118
107
  }
119
108
  bucket->nbytes += params.npayload;
@@ -126,7 +115,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
126
115
  lcb_wait(bucket->handle);
127
116
  }
128
117
  exc = ctx->exception;
129
- xfree(ctx);
118
+ free(ctx);
130
119
  if (exc != Qnil) {
131
120
  cb_gc_unprotect(bucket, exc);
132
121
  rb_exc_raise(exc);
@@ -36,15 +36,8 @@ cb_bucket_free(void *ptr)
36
36
  lcb_destroy(bucket->handle);
37
37
  lcb_destroy_io_ops(bucket->io);
38
38
  }
39
- xfree(bucket->authority);
40
- xfree(bucket->hostname);
41
- xfree(bucket->pool);
42
- xfree(bucket->bucket);
43
- xfree(bucket->username);
44
- xfree(bucket->password);
45
- xfree(bucket->key_prefix);
46
- xfree(bucket);
47
39
  }
40
+ xfree(bucket);
48
41
  }
49
42
 
50
43
  void
@@ -53,6 +46,12 @@ cb_bucket_mark(void *ptr)
53
46
  struct cb_bucket_st *bucket = ptr;
54
47
 
55
48
  if (bucket) {
49
+ rb_gc_mark(bucket->authority);
50
+ rb_gc_mark(bucket->hostname);
51
+ rb_gc_mark(bucket->pool);
52
+ rb_gc_mark(bucket->bucket);
53
+ rb_gc_mark(bucket->username);
54
+ rb_gc_mark(bucket->password);
56
55
  rb_gc_mark(bucket->exception);
57
56
  rb_gc_mark(bucket->on_error_proc);
58
57
  rb_gc_mark(bucket->key_prefix_val);
@@ -64,7 +63,7 @@ cb_bucket_mark(void *ptr)
64
63
  do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
65
64
  {
66
65
  VALUE uri, opts, arg;
67
- size_t len;
66
+ char port_s[8];
68
67
 
69
68
  if (rb_scan_args(argc, argv, "02", &uri, &opts) > 0) {
70
69
  if (TYPE(uri) == T_HASH && argc == 1) {
@@ -85,28 +84,16 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
85
84
 
86
85
  arg = rb_funcall(uri_obj, cb_id_user, 0);
87
86
  if (arg != Qnil) {
88
- xfree(bucket->username);
89
- bucket->username = strdup(RSTRING_PTR(arg));
90
- if (bucket->username == NULL) {
91
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
92
- }
87
+ bucket->username = rb_str_dup_frozen(StringValue(arg));
93
88
  }
94
89
 
95
90
  arg = rb_funcall(uri_obj, cb_id_password, 0);
96
91
  if (arg != Qnil) {
97
- xfree(bucket->password);
98
- bucket->password = strdup(RSTRING_PTR(arg));
99
- if (bucket->password == NULL) {
100
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
101
- }
92
+ bucket->password = rb_str_dup_frozen(StringValue(arg));
102
93
  }
103
94
  arg = rb_funcall(uri_obj, cb_id_host, 0);
104
95
  if (arg != Qnil) {
105
- xfree(bucket->hostname);
106
- bucket->hostname = strdup(RSTRING_PTR(arg));
107
- if (bucket->hostname == NULL) {
108
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
109
- }
96
+ bucket->hostname = rb_str_dup_frozen(StringValue(arg));
110
97
  } else {
111
98
  rb_raise(rb_eArgError, "invalid URI: missing hostname");
112
99
  }
@@ -118,11 +105,11 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
118
105
  re = rb_reg_new(path_re, sizeof(path_re) - 1, 0);
119
106
  match = rb_funcall(re, cb_id_match, 1, arg);
120
107
  arg = rb_reg_nth_match(2, match);
121
- xfree(bucket->pool);
122
- bucket->pool = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
108
+ bucket->pool = NIL_P(arg) ? cb_vStrDefault : rb_str_dup_frozen(StringValue(arg));
109
+ rb_str_freeze(bucket->pool);
123
110
  arg = rb_reg_nth_match(4, match);
124
- xfree(bucket->bucket);
125
- bucket->bucket = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
111
+ bucket->bucket = NIL_P(arg) ? cb_vStrDefault : rb_str_dup_frozen(StringValue(arg));
112
+ rb_str_freeze(bucket->bucket);
126
113
  }
127
114
  if (TYPE(opts) == T_HASH) {
128
115
  arg = rb_hash_aref(opts, cb_sym_type);
@@ -135,43 +122,37 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
135
122
  }
136
123
  arg = rb_hash_aref(opts, cb_sym_node_list);
137
124
  if (arg != Qnil) {
138
- VALUE tt;
139
- xfree(bucket->node_list);
140
125
  Check_Type(arg, T_ARRAY);
141
- tt = rb_ary_join(arg, STR_NEW_CSTR(";"));
142
- bucket->node_list = strdup(StringValueCStr(tt));
126
+ bucket->node_list = rb_ary_join(arg, STR_NEW_CSTR(";"));
127
+ rb_str_freeze(bucket->node_list);
143
128
  }
144
129
  arg = rb_hash_aref(opts, cb_sym_hostname);
145
130
  if (arg != Qnil) {
146
- xfree(bucket->hostname);
147
- bucket->hostname = strdup(StringValueCStr(arg));
131
+ bucket->hostname = rb_str_dup_frozen(StringValue(arg));
148
132
  }
149
133
  arg = rb_hash_aref(opts, cb_sym_pool);
150
134
  if (arg != Qnil) {
151
- xfree(bucket->pool);
152
- bucket->pool = strdup(StringValueCStr(arg));
135
+ bucket->pool = rb_str_dup_frozen(StringValue(arg));
153
136
  }
154
137
  arg = rb_hash_aref(opts, cb_sym_bucket);
155
138
  if (arg != Qnil) {
156
- xfree(bucket->bucket);
157
- bucket->bucket = strdup(StringValueCStr(arg));
139
+ bucket->bucket = rb_str_dup_frozen(StringValue(arg));
158
140
  }
159
141
  arg = rb_hash_aref(opts, cb_sym_username);
160
142
  if (arg != Qnil) {
161
- xfree(bucket->username);
162
- bucket->username = strdup(StringValueCStr(arg));
143
+ bucket->username = rb_str_dup_frozen(StringValue(arg));
163
144
  }
164
145
  arg = rb_hash_aref(opts, cb_sym_password);
165
146
  if (arg != Qnil) {
166
- xfree(bucket->password);
167
- bucket->password = strdup(StringValueCStr(arg));
147
+ bucket->password = rb_str_dup_frozen(StringValue(arg));
168
148
  }
169
149
  arg = rb_hash_aref(opts, cb_sym_port);
170
150
  if (arg != Qnil) {
171
151
  bucket->port = (uint16_t)NUM2UINT(arg);
172
152
  }
173
- if (RTEST(rb_funcall(opts, cb_id_has_key_p, 1, cb_sym_quiet))) {
174
- bucket->quiet = RTEST(rb_hash_aref(opts, cb_sym_quiet));
153
+ arg = rb_hash_lookup2(opts, cb_sym_quiet, Qundef);
154
+ if (arg != Qundef) {
155
+ bucket->quiet = RTEST(arg);
175
156
  }
176
157
  arg = rb_hash_aref(opts, cb_sym_timeout);
177
158
  if (arg != Qnil) {
@@ -217,9 +198,7 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
217
198
  }
218
199
  arg = rb_hash_aref(opts, cb_sym_key_prefix);
219
200
  if (arg != Qnil) {
220
- xfree(bucket->key_prefix);
221
- bucket->key_prefix = strdup(StringValueCStr(arg));
222
- bucket->key_prefix_val = STR_NEW_CSTR(bucket->key_prefix);
201
+ bucket->key_prefix_val = rb_str_dup_frozen(StringValue(arg));
223
202
  }
224
203
  arg = rb_hash_aref(opts, cb_sym_default_arithmetic_init);
225
204
  if (arg != Qnil) {
@@ -232,19 +211,16 @@ do_scan_connection_options(struct cb_bucket_st *bucket, int argc, VALUE *argv)
232
211
  opts = Qnil;
233
212
  }
234
213
  }
235
- if (bucket->password && bucket->username == NULL) {
236
- bucket->username = strdup(bucket->bucket);
214
+ if (RTEST(bucket->password) && !RTEST(bucket->username)) {
215
+ bucket->username = bucket->bucket;
237
216
  }
238
- len = strlen(bucket->hostname) + 10;
239
217
  if (bucket->default_observe_timeout < 2) {
240
218
  rb_raise(rb_eArgError, "default_observe_timeout is too low");
241
219
  }
242
- xfree(bucket->authority);
243
- bucket->authority = xcalloc(len, sizeof(char));
244
- if (bucket->authority == NULL) {
245
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
246
- }
247
- snprintf(bucket->authority, len, "%s:%u", bucket->hostname, bucket->port);
220
+ snprintf(port_s, sizeof(port_s), ":%u", bucket->port);
221
+ bucket->authority = rb_str_dup(bucket->hostname);
222
+ rb_str_cat2(bucket->authority, port_s);
223
+ rb_str_freeze(bucket->authority);
248
224
  }
249
225
 
250
226
  static void
@@ -259,7 +235,21 @@ do_connect(struct cb_bucket_st *bucket)
259
235
  bucket->handle = NULL;
260
236
  bucket->io = NULL;
261
237
  }
238
+
239
+ #ifndef _WIN32
240
+ {
241
+ struct lcb_create_io_ops_st ciops;
242
+ memset(&ciops, 0, sizeof(ciops));
243
+ ciops.version = 1;
244
+ ciops.v.v1.sofile = NULL;
245
+ ciops.v.v1.symbol = "cb_create_ruby_mt_io_opts";
246
+ ciops.v.v1.cookie = NULL;
247
+
248
+ err = lcb_create_io_ops(&bucket->io, &ciops);
249
+ }
250
+ #else
262
251
  err = lcb_create_io_ops(&bucket->io, NULL);
252
+ #endif
263
253
  if (err != LCB_SUCCESS) {
264
254
  rb_exc_raise(cb_check_error(err, "failed to create IO instance", Qnil));
265
255
  }
@@ -267,10 +257,10 @@ do_connect(struct cb_bucket_st *bucket)
267
257
  memset(&create_opts, 0, sizeof(struct lcb_create_st));
268
258
  create_opts.version = 1;
269
259
  create_opts.v.v1.type = bucket->type;
270
- create_opts.v.v1.host = bucket->node_list ? bucket-> node_list : bucket->authority;
271
- create_opts.v.v1.user = bucket->username;
272
- create_opts.v.v1.passwd = bucket->password;
273
- create_opts.v.v1.bucket = bucket->bucket;
260
+ create_opts.v.v1.host = RTEST(bucket->node_list) ? RSTRING_PTR(bucket-> node_list) : RSTRING_PTR(bucket->authority);
261
+ create_opts.v.v1.user = RTEST(bucket->username) ? RSTRING_PTR(bucket->username) : NULL;
262
+ create_opts.v.v1.passwd = RTEST(bucket->username) ? RSTRING_PTR(bucket->password) : NULL;
263
+ create_opts.v.v1.bucket = RSTRING_PTR(bucket->bucket);
274
264
  create_opts.v.v1.io = bucket->io;
275
265
  err = lcb_create(&bucket->handle, &create_opts);
276
266
  if (err != LCB_SUCCESS) {
@@ -416,10 +406,14 @@ cb_bucket_init(int argc, VALUE *argv, VALUE self)
416
406
  bucket->self = self;
417
407
  bucket->exception = Qnil;
418
408
  bucket->type = LCB_TYPE_BUCKET;
419
- bucket->hostname = strdup("localhost");
409
+ bucket->hostname = rb_str_new2("localhost");
420
410
  bucket->port = 8091;
421
- bucket->pool = strdup("default");
422
- bucket->bucket = strdup("default");
411
+ bucket->pool = cb_vStrDefault;
412
+ rb_str_freeze(bucket->pool);
413
+ bucket->bucket = cb_vStrDefault;
414
+ rb_str_freeze(bucket->bucket);
415
+ bucket->username = Qnil;
416
+ bucket->password = Qnil;
423
417
  bucket->async = 0;
424
418
  bucket->quiet = 0;
425
419
  bucket->default_ttl = 0;
@@ -429,11 +423,9 @@ cb_bucket_init(int argc, VALUE *argv, VALUE self)
429
423
  bucket->on_error_proc = Qnil;
430
424
  bucket->timeout = 0;
431
425
  bucket->environment = cb_sym_production;
432
- bucket->key_prefix = NULL;
433
426
  bucket->key_prefix_val = Qnil;
434
- bucket->node_list = NULL;
427
+ bucket->node_list = Qnil;
435
428
  bucket->object_space = rb_hash_new();
436
- bucket->node_list = NULL;
437
429
 
438
430
  do_scan_connection_options(bucket, argc, argv);
439
431
  do_connect(bucket);
@@ -469,19 +461,12 @@ cb_bucket_init_copy(VALUE copy, VALUE orig)
469
461
 
470
462
  copy_b->self = copy_b->self;
471
463
  copy_b->port = orig_b->port;
472
- copy_b->authority = strdup(orig_b->authority);
473
- copy_b->hostname = strdup(orig_b->hostname);
474
- copy_b->pool = strdup(orig_b->pool);
475
- copy_b->bucket = strdup(orig_b->bucket);
476
- if (orig_b->username) {
477
- copy_b->username = strdup(orig_b->username);
478
- }
479
- if (orig_b->password) {
480
- copy_b->password = strdup(orig_b->password);
481
- }
482
- if (orig_b->key_prefix) {
483
- copy_b->key_prefix = strdup(orig_b->key_prefix);
484
- }
464
+ copy_b->authority = orig_b->authority;
465
+ copy_b->hostname = orig_b->hostname;
466
+ copy_b->pool = orig_b->pool;
467
+ copy_b->bucket = orig_b->bucket;
468
+ copy_b->username = orig_b->username;
469
+ copy_b->password = orig_b->password;
485
470
  copy_b->async = orig_b->async;
486
471
  copy_b->quiet = orig_b->quiet;
487
472
  copy_b->default_format = orig_b->default_format;
@@ -493,9 +478,7 @@ cb_bucket_init_copy(VALUE copy, VALUE orig)
493
478
  if (orig_b->on_error_proc != Qnil) {
494
479
  copy_b->on_error_proc = rb_funcall(orig_b->on_error_proc, cb_id_dup, 0);
495
480
  }
496
- if (orig_b->key_prefix_val != Qnil) {
497
- copy_b->key_prefix_val = rb_funcall(orig_b->key_prefix_val, cb_id_dup, 0);
498
- }
481
+ copy_b->key_prefix_val = orig_b->key_prefix_val;
499
482
 
500
483
  do_connect(copy_b);
501
484
 
@@ -724,8 +707,7 @@ cb_bucket_key_prefix_set(VALUE self, VALUE val)
724
707
  {
725
708
  struct cb_bucket_st *bucket = DATA_PTR(self);
726
709
 
727
- bucket->key_prefix = strdup(StringValueCStr(val));
728
- bucket->key_prefix_val = STR_NEW_CSTR(bucket->key_prefix);
710
+ bucket->key_prefix_val = rb_str_dup_frozen(StringValue(val));
729
711
 
730
712
  return bucket->key_prefix_val;
731
713
  }
@@ -740,14 +722,16 @@ cb_bucket_key_prefix_set(VALUE self, VALUE val)
740
722
  cb_bucket_hostname_get(VALUE self)
741
723
  {
742
724
  struct cb_bucket_st *bucket = DATA_PTR(self);
725
+
743
726
  if (bucket->handle) {
744
- xfree(bucket->hostname);
745
- bucket->hostname = strdup(lcb_get_host(bucket->handle));
746
- if (bucket->hostname == NULL) {
747
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
727
+ const char * host = lcb_get_host(bucket->handle);
728
+ unsigned long len = RSTRING_LEN(bucket->hostname);
729
+ if (len != strlen(host) || strncmp(RSTRING_PTR(bucket->hostname), host, len) != 0) {
730
+ bucket->hostname = STR_NEW_CSTR(host);
731
+ rb_str_freeze(bucket->hostname);
748
732
  }
749
733
  }
750
- return STR_NEW_CSTR(bucket->hostname);
734
+ return bucket->hostname;
751
735
  }
752
736
 
753
737
  /* Document-method: port
@@ -776,17 +760,19 @@ cb_bucket_port_get(VALUE self)
776
760
  cb_bucket_authority_get(VALUE self)
777
761
  {
778
762
  struct cb_bucket_st *bucket = DATA_PTR(self);
779
- size_t len;
780
-
781
- (void)cb_bucket_hostname_get(self);
782
- (void)cb_bucket_port_get(self);
783
- len = strlen(bucket->hostname) + 10;
784
- bucket->authority = xcalloc(len, sizeof(char));
785
- if (bucket->authority == NULL) {
786
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for Bucket");
763
+ VALUE old_hostname = bucket->hostname;
764
+ uint16_t old_port = bucket->port;
765
+ VALUE hostname = cb_bucket_hostname_get(self);
766
+ cb_bucket_port_get(self);
767
+
768
+ if (hostname != old_hostname || bucket->port != old_port) {
769
+ char port_s[8];
770
+ snprintf(port_s, sizeof(port_s), ":%u", bucket->port);
771
+ bucket->authority = rb_str_dup(hostname);
772
+ rb_str_cat2(bucket->authority, port_s);
773
+ rb_str_freeze(bucket->authority);
787
774
  }
788
- snprintf(bucket->authority, len, "%s:%u", bucket->hostname, bucket->port);
789
- return STR_NEW_CSTR(bucket->authority);
775
+ return bucket->authority;
790
776
  }
791
777
 
792
778
  /* Document-method: bucket
@@ -799,7 +785,7 @@ cb_bucket_authority_get(VALUE self)
799
785
  cb_bucket_bucket_get(VALUE self)
800
786
  {
801
787
  struct cb_bucket_st *bucket = DATA_PTR(self);
802
- return STR_NEW_CSTR(bucket->bucket);
788
+ return bucket->bucket;
803
789
  }
804
790
 
805
791
  /* Document-method: pool
@@ -812,7 +798,7 @@ cb_bucket_bucket_get(VALUE self)
812
798
  cb_bucket_pool_get(VALUE self)
813
799
  {
814
800
  struct cb_bucket_st *bucket = DATA_PTR(self);
815
- return STR_NEW_CSTR(bucket->pool);
801
+ return bucket->pool;
816
802
  }
817
803
 
818
804
  /* Document-method: username
@@ -826,7 +812,7 @@ cb_bucket_pool_get(VALUE self)
826
812
  cb_bucket_username_get(VALUE self)
827
813
  {
828
814
  struct cb_bucket_st *bucket = DATA_PTR(self);
829
- return STR_NEW_CSTR(bucket->username);
815
+ return bucket->username;
830
816
  }
831
817
 
832
818
  /* Document-method: password
@@ -839,7 +825,7 @@ cb_bucket_username_get(VALUE self)
839
825
  cb_bucket_password_get(VALUE self)
840
826
  {
841
827
  struct cb_bucket_st *bucket = DATA_PTR(self);
842
- return STR_NEW_CSTR(bucket->password);
828
+ return bucket->password;
843
829
  }
844
830
 
845
831
  /* Document-method: environment
@@ -921,11 +907,11 @@ cb_bucket_url_get(VALUE self)
921
907
 
922
908
  (void)cb_bucket_authority_get(self);
923
909
  str = rb_str_buf_new2("http://");
924
- rb_str_buf_cat2(str, bucket->authority);
910
+ rb_str_append(str, bucket->authority);
925
911
  rb_str_buf_cat2(str, "/pools/");
926
- rb_str_buf_cat2(str, bucket->pool);
912
+ rb_str_append(str, bucket->pool);
927
913
  rb_str_buf_cat2(str, "/buckets/");
928
- rb_str_buf_cat2(str, bucket->bucket);
914
+ rb_str_append(str, bucket->bucket);
929
915
  rb_str_buf_cat2(str, "/");
930
916
  return str;
931
917
  }
@@ -951,11 +937,11 @@ cb_bucket_inspect(VALUE self)
951
937
  (void)cb_bucket_authority_get(self);
952
938
  rb_str_buf_cat2(str, buf);
953
939
  rb_str_buf_cat2(str, "http://");
954
- rb_str_buf_cat2(str, bucket->authority);
940
+ rb_str_append(str, bucket->authority);
955
941
  rb_str_buf_cat2(str, "/pools/");
956
- rb_str_buf_cat2(str, bucket->pool);
942
+ rb_str_append(str, bucket->pool);
957
943
  rb_str_buf_cat2(str, "/buckets/");
958
- rb_str_buf_cat2(str, bucket->bucket);
944
+ rb_str_append(str, bucket->bucket);
959
945
  rb_str_buf_cat2(str, "/");
960
946
  snprintf(buf, 150, "\" default_format=:%s, default_flags=0x%x, quiet=%s, connected=%s, timeout=%u",
961
947
  rb_id2name(SYM2ID(bucket->default_format)),
@@ -964,7 +950,7 @@ cb_bucket_inspect(VALUE self)
964
950
  bucket->handle ? "true" : "false",
965
951
  bucket->timeout);
966
952
  rb_str_buf_cat2(str, buf);
967
- if (bucket->key_prefix) {
953
+ if (RTEST(bucket->key_prefix_val)) {
968
954
  rb_str_buf_cat2(str, ", key_prefix=");
969
955
  rb_str_append(str, rb_inspect(bucket->key_prefix_val));
970
956
  }
@@ -1010,7 +996,7 @@ do_run(VALUE *args)
1010
996
  }
1011
997
  }
1012
998
  bucket->async = 1;
1013
- cb_proc_call(proc, 1, self);
999
+ cb_proc_call(bucket, proc, 1, self);
1014
1000
  do_loop(bucket);
1015
1001
  if (bucket->exception != Qnil) {
1016
1002
  exc = bucket->exception;