couchbase 1.2.0.z.beta5 → 1.2.0

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