couchbase 1.1.2-x86-mingw32 → 1.1.3-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY.markdown CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.1.3 / 2012-07-27
2
+
3
+ * RCBC-59 Replicate flags in Bucket#cas operation
4
+ * calloc -> xcalloc, free -> xfree
5
+ * RCBC-64 Fix Couchbase::Bucket#dup
6
+ * Make object_space GC protector per-bucket object
7
+ * RCBC-60 Protect exceptions from GC
8
+
1
9
  ## 1.1.2 / 2012-06-05
2
10
 
3
11
  * Upgrade libcouchbase dependency up to 1.0.4
@@ -64,6 +64,7 @@ typedef struct
64
64
  uint32_t timeout;
65
65
  VALUE exception; /* error delivered by error_callback */
66
66
  VALUE on_error_proc; /* is using to deliver errors in async mode */
67
+ VALUE object_space;
67
68
  } bucket_t;
68
69
 
69
70
  typedef struct
@@ -93,7 +94,6 @@ struct key_traits
93
94
  };
94
95
 
95
96
  static VALUE mCouchbase, mError, mJSON, mURI, mMarshal, cBucket, cResult;
96
- static VALUE object_space;
97
97
 
98
98
  static ID sym_add,
99
99
  sym_append,
@@ -142,6 +142,7 @@ static ID sym_add,
142
142
  id_iv_node,
143
143
  id_iv_operation,
144
144
  id_iv_value,
145
+ id_dup,
145
146
  id_load,
146
147
  id_match,
147
148
  id_parse,
@@ -183,6 +184,18 @@ static VALUE eTimeoutError; /*LIBCOUCHBASE_ETIMEDOUT = 0x16*/
183
184
  static VALUE eConnectError; /*LIBCOUCHBASE_CONNECT_ERROR = 0x17*/
184
185
  static VALUE eBucketNotFoundError; /*LIBCOUCHBASE_BUCKET_ENOENT = 0x18*/
185
186
 
187
+ static void
188
+ cb_gc_protect(bucket_t *bucket, VALUE val)
189
+ {
190
+ rb_hash_aset(bucket->object_space, val|1, val);
191
+ }
192
+
193
+ static void
194
+ cb_gc_unprotect(bucket_t *bucket, VALUE val)
195
+ {
196
+ rb_hash_delete(bucket->object_space, val|1);
197
+ }
198
+
186
199
  static VALUE
187
200
  cb_proc_call(VALUE recv, int argc, ...)
188
201
  {
@@ -504,18 +517,18 @@ cb_args_scan_keys(long argc, VALUE argv, bucket_t *bucket, struct key_traits *tr
504
517
  if (nn == 1 && TYPE(keys_ptr[0]) == T_HASH) {
505
518
  /* hash of key-ttl pairs */
506
519
  nn = RHASH_SIZE(keys_ptr[0]);
507
- traits->keys = calloc(nn, sizeof(char *));
508
- traits->lens = calloc(nn, sizeof(size_t));
520
+ traits->keys = xcalloc(nn, sizeof(char *));
521
+ traits->lens = xcalloc(nn, sizeof(size_t));
509
522
  traits->explicit_ttl = 1;
510
523
  traits->mgat = 1;
511
- traits->ttls = calloc(nn, sizeof(time_t));
524
+ traits->ttls = xcalloc(nn, sizeof(time_t));
512
525
  rb_hash_foreach(keys_ptr[0], cb_extract_keys_i, (VALUE)traits);
513
526
  } else {
514
527
  /* the list of keys */
515
528
  traits->nkeys = nn;
516
- traits->keys = calloc(nn, sizeof(char *));
517
- traits->lens = calloc(nn, sizeof(size_t));
518
- traits->ttls = calloc(nn, sizeof(time_t));
529
+ traits->keys = xcalloc(nn, sizeof(char *));
530
+ traits->lens = xcalloc(nn, sizeof(size_t));
531
+ traits->ttls = xcalloc(nn, sizeof(time_t));
519
532
  for (ii = 0; ii < nn; ii++) {
520
533
  key = unify_key(keys_ptr[ii]);
521
534
  rb_ary_push(traits->keys_ary, key);
@@ -577,6 +590,7 @@ storage_callback(libcouchbase_t handle, const void *cookie,
577
590
  rb_ivar_set(exc, id_iv_operation, o);
578
591
  if (NIL_P(ctx->exception)) {
579
592
  ctx->exception = exc;
593
+ cb_gc_protect(bucket, ctx->exception);
580
594
  }
581
595
  }
582
596
  if (bucket->async) { /* asynchronous */
@@ -594,7 +608,7 @@ storage_callback(libcouchbase_t handle, const void *cookie,
594
608
 
595
609
  if (bucket->seqno == 0) {
596
610
  bucket->io->stop_event_loop(bucket->io);
597
- rb_hash_delete(object_space, ctx->proc|1);
611
+ cb_gc_unprotect(bucket, ctx->proc);
598
612
  }
599
613
  (void)handle;
600
614
  }
@@ -617,6 +631,7 @@ delete_callback(libcouchbase_t handle, const void *cookie,
617
631
  rb_ivar_set(exc, id_iv_operation, sym_delete);
618
632
  if (NIL_P(ctx->exception)) {
619
633
  ctx->exception = exc;
634
+ cb_gc_protect(bucket, ctx->exception);
620
635
  }
621
636
  }
622
637
  }
@@ -633,7 +648,7 @@ delete_callback(libcouchbase_t handle, const void *cookie,
633
648
  }
634
649
  if (bucket->seqno == 0) {
635
650
  bucket->io->stop_event_loop(bucket->io);
636
- rb_hash_delete(object_space, ctx->proc|1);
651
+ cb_gc_unprotect(bucket, ctx->proc);
637
652
  }
638
653
  (void)handle;
639
654
  }
@@ -658,26 +673,27 @@ get_callback(libcouchbase_t handle, const void *cookie,
658
673
  rb_ivar_set(exc, id_iv_operation, sym_get);
659
674
  if (NIL_P(ctx->exception)) {
660
675
  ctx->exception = exc;
676
+ cb_gc_protect(bucket, ctx->exception);
661
677
  }
662
678
  }
663
679
  }
664
680
 
665
681
  f = ULONG2NUM(flags);
666
682
  c = ULL2NUM(cas);
683
+ v = Qnil;
667
684
  if (nbytes != 0) {
668
685
  v = decode_value(rb_str_new((const char*)bytes, nbytes), flags, ctx->force_format);
669
686
  if (v == Qundef) {
687
+ if (ctx->exception != Qnil) {
688
+ cb_gc_unprotect(bucket, ctx->exception);
689
+ }
670
690
  ctx->exception = rb_exc_new2(eValueFormatError, "unable to convert value");
671
691
  rb_ivar_set(ctx->exception, id_iv_operation, sym_get);
672
692
  rb_ivar_set(ctx->exception, id_iv_key, k);
673
- v = Qnil;
674
- }
675
- } else {
676
- if (flags_get_format(flags) == sym_plain) {
677
- v = rb_str_new2("");
678
- } else {
679
- v = Qnil;
693
+ cb_gc_protect(bucket, ctx->exception);
680
694
  }
695
+ } else if (flags_get_format(flags) == sym_plain) {
696
+ v = rb_str_new2("");
681
697
  }
682
698
  if (bucket->async) { /* asynchronous */
683
699
  if (ctx->proc != Qnil) {
@@ -702,7 +718,7 @@ get_callback(libcouchbase_t handle, const void *cookie,
702
718
 
703
719
  if (bucket->seqno == 0) {
704
720
  bucket->io->stop_event_loop(bucket->io);
705
- rb_hash_delete(object_space, ctx->proc|1);
721
+ cb_gc_unprotect(bucket, ctx->proc);
706
722
  }
707
723
  (void)handle;
708
724
  }
@@ -721,6 +737,7 @@ flush_callback(libcouchbase_t handle, const void* cookie,
721
737
  rb_ivar_set(exc, id_iv_operation, sym_flush);
722
738
  if (NIL_P(ctx->exception)) {
723
739
  ctx->exception = exc;
740
+ cb_gc_protect(bucket, ctx->exception);
724
741
  }
725
742
  success = Qfalse;
726
743
  }
@@ -744,7 +761,7 @@ flush_callback(libcouchbase_t handle, const void* cookie,
744
761
  bucket->seqno--;
745
762
  if (bucket->seqno == 0) {
746
763
  bucket->io->stop_event_loop(bucket->io);
747
- rb_hash_delete(object_space, ctx->proc|1);
764
+ cb_gc_unprotect(bucket, ctx->proc);
748
765
  }
749
766
  }
750
767
 
@@ -766,6 +783,7 @@ version_callback(libcouchbase_t handle, const void *cookie,
766
783
  rb_ivar_set(exc, id_iv_operation, sym_flush);
767
784
  if (NIL_P(ctx->exception)) {
768
785
  ctx->exception = exc;
786
+ cb_gc_protect(bucket, ctx->exception);
769
787
  }
770
788
  }
771
789
 
@@ -789,7 +807,7 @@ version_callback(libcouchbase_t handle, const void *cookie,
789
807
  bucket->seqno--;
790
808
  if (bucket->seqno == 0) {
791
809
  bucket->io->stop_event_loop(bucket->io);
792
- rb_hash_delete(object_space, ctx->proc|1);
810
+ cb_gc_unprotect(bucket, ctx->proc);
793
811
  }
794
812
  }
795
813
 
@@ -812,6 +830,7 @@ stat_callback(libcouchbase_t handle, const void* cookie,
812
830
  rb_ivar_set(exc, id_iv_operation, sym_stats);
813
831
  if (NIL_P(ctx->exception)) {
814
832
  ctx->exception = exc;
833
+ cb_gc_protect(bucket, ctx->exception);
815
834
  }
816
835
  }
817
836
  if (authority) {
@@ -841,7 +860,7 @@ stat_callback(libcouchbase_t handle, const void* cookie,
841
860
  bucket->seqno--;
842
861
  if (bucket->seqno == 0) {
843
862
  bucket->io->stop_event_loop(bucket->io);
844
- rb_hash_delete(object_space, ctx->proc|1);
863
+ cb_gc_unprotect(bucket, ctx->proc);
845
864
  }
846
865
  }
847
866
  (void)handle;
@@ -864,6 +883,7 @@ touch_callback(libcouchbase_t handle, const void *cookie,
864
883
  rb_ivar_set(exc, id_iv_operation, sym_touch);
865
884
  if (NIL_P(ctx->exception)) {
866
885
  ctx->exception = exc;
886
+ cb_gc_protect(bucket, ctx->exception);
867
887
  }
868
888
  }
869
889
  }
@@ -884,7 +904,7 @@ touch_callback(libcouchbase_t handle, const void *cookie,
884
904
  }
885
905
  if (bucket->seqno == 0) {
886
906
  bucket->io->stop_event_loop(bucket->io);
887
- rb_hash_delete(object_space, ctx->proc|1);
907
+ cb_gc_unprotect(bucket, ctx->proc);
888
908
  }
889
909
  (void)handle;
890
910
  }
@@ -920,6 +940,7 @@ arithmetic_callback(libcouchbase_t handle, const void *cookie,
920
940
  }
921
941
  if (NIL_P(ctx->exception)) {
922
942
  ctx->exception = exc;
943
+ cb_gc_protect(bucket, ctx->exception);
923
944
  }
924
945
  }
925
946
  v = ULL2NUM(value);
@@ -944,7 +965,7 @@ arithmetic_callback(libcouchbase_t handle, const void *cookie,
944
965
  }
945
966
  if (bucket->seqno == 0) {
946
967
  bucket->io->stop_event_loop(bucket->io);
947
- rb_hash_delete(object_space, ctx->proc|1);
968
+ cb_gc_unprotect(bucket, ctx->proc);
948
969
  }
949
970
  (void)handle;
950
971
  }
@@ -980,13 +1001,13 @@ cb_bucket_free(void *ptr)
980
1001
  if (bucket->handle) {
981
1002
  libcouchbase_destroy(bucket->handle);
982
1003
  }
983
- free(bucket->authority);
984
- free(bucket->hostname);
985
- free(bucket->pool);
986
- free(bucket->bucket);
987
- free(bucket->username);
988
- free(bucket->password);
989
- free(bucket);
1004
+ xfree(bucket->authority);
1005
+ xfree(bucket->hostname);
1006
+ xfree(bucket->pool);
1007
+ xfree(bucket->bucket);
1008
+ xfree(bucket->username);
1009
+ xfree(bucket->password);
1010
+ xfree(bucket);
990
1011
  }
991
1012
  }
992
1013
 
@@ -998,6 +1019,7 @@ cb_bucket_mark(void *ptr)
998
1019
  if (bucket) {
999
1020
  rb_gc_mark(bucket->exception);
1000
1021
  rb_gc_mark(bucket->on_error_proc);
1022
+ rb_gc_mark(bucket->object_space);
1001
1023
  }
1002
1024
  }
1003
1025
 
@@ -1026,7 +1048,7 @@ do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1026
1048
 
1027
1049
  arg = rb_funcall(uri_obj, id_user, 0);
1028
1050
  if (arg != Qnil) {
1029
- free(bucket->username);
1051
+ xfree(bucket->username);
1030
1052
  bucket->username = strdup(RSTRING_PTR(arg));
1031
1053
  if (bucket->username == NULL) {
1032
1054
  rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
@@ -1035,7 +1057,7 @@ do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1035
1057
 
1036
1058
  arg = rb_funcall(uri_obj, id_password, 0);
1037
1059
  if (arg != Qnil) {
1038
- free(bucket->password);
1060
+ xfree(bucket->password);
1039
1061
  bucket->password = strdup(RSTRING_PTR(arg));
1040
1062
  if (bucket->password == NULL) {
1041
1063
  rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
@@ -1043,7 +1065,7 @@ do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1043
1065
  }
1044
1066
  arg = rb_funcall(uri_obj, id_host, 0);
1045
1067
  if (arg != Qnil) {
1046
- free(bucket->hostname);
1068
+ xfree(bucket->hostname);
1047
1069
  bucket->hostname = strdup(RSTRING_PTR(arg));
1048
1070
  if (bucket->hostname == NULL) {
1049
1071
  rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
@@ -1059,45 +1081,45 @@ do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1059
1081
  re = rb_reg_new(path_re, sizeof(path_re) - 1, 0);
1060
1082
  match = rb_funcall(re, id_match, 1, arg);
1061
1083
  arg = rb_reg_nth_match(2, match);
1062
- free(bucket->pool);
1084
+ xfree(bucket->pool);
1063
1085
  bucket->pool = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
1064
1086
  arg = rb_reg_nth_match(4, match);
1065
- free(bucket->bucket);
1087
+ xfree(bucket->bucket);
1066
1088
  bucket->bucket = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
1067
1089
  }
1068
1090
  if (TYPE(opts) == T_HASH) {
1069
1091
  arg = rb_hash_aref(opts, sym_hostname);
1070
1092
  if (arg != Qnil) {
1071
1093
  if (bucket->hostname) {
1072
- free(bucket->hostname);
1094
+ xfree(bucket->hostname);
1073
1095
  }
1074
1096
  bucket->hostname = strdup(StringValueCStr(arg));
1075
1097
  }
1076
1098
  arg = rb_hash_aref(opts, sym_pool);
1077
1099
  if (arg != Qnil) {
1078
1100
  if (bucket->pool) {
1079
- free(bucket->pool);
1101
+ xfree(bucket->pool);
1080
1102
  }
1081
1103
  bucket->pool = strdup(StringValueCStr(arg));
1082
1104
  }
1083
1105
  arg = rb_hash_aref(opts, sym_bucket);
1084
1106
  if (arg != Qnil) {
1085
1107
  if (bucket->bucket) {
1086
- free(bucket->bucket);
1108
+ xfree(bucket->bucket);
1087
1109
  }
1088
1110
  bucket->bucket = strdup(StringValueCStr(arg));
1089
1111
  }
1090
1112
  arg = rb_hash_aref(opts, sym_username);
1091
1113
  if (arg != Qnil) {
1092
1114
  if (bucket->username) {
1093
- free(bucket->username);
1115
+ xfree(bucket->username);
1094
1116
  }
1095
1117
  bucket->username = strdup(StringValueCStr(arg));
1096
1118
  }
1097
1119
  arg = rb_hash_aref(opts, sym_password);
1098
1120
  if (arg != Qnil) {
1099
1121
  if (bucket->password) {
1100
- free(bucket->password);
1122
+ xfree(bucket->password);
1101
1123
  }
1102
1124
  bucket->password = strdup(StringValueCStr(arg));
1103
1125
  }
@@ -1146,9 +1168,9 @@ do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1146
1168
  }
1147
1169
  len = strlen(bucket->hostname) + 10;
1148
1170
  if (bucket->authority) {
1149
- free(bucket->authority);
1171
+ xfree(bucket->authority);
1150
1172
  }
1151
- bucket->authority = calloc(len, sizeof(char));
1173
+ bucket->authority = xcalloc(len, sizeof(char));
1152
1174
  if (bucket->authority == NULL) {
1153
1175
  rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1154
1176
  }
@@ -1208,15 +1230,8 @@ do_connect(bucket_t *bucket)
1208
1230
  }
1209
1231
  }
1210
1232
 
1211
- /*
1212
- * Create and initialize new Bucket.
1213
- *
1214
- * @return [Bucket] new instance
1215
- *
1216
- * @see Bucket#initialize
1217
- */
1218
1233
  static VALUE
1219
- cb_bucket_new(int argc, VALUE *argv, VALUE klass)
1234
+ cb_bucket_alloc(VALUE klass)
1220
1235
  {
1221
1236
  VALUE obj;
1222
1237
  bucket_t *bucket;
@@ -1224,7 +1239,6 @@ cb_bucket_new(int argc, VALUE *argv, VALUE klass)
1224
1239
  /* allocate new bucket struct and set it to zero */
1225
1240
  obj = Data_Make_Struct(klass, bucket_t, cb_bucket_mark, cb_bucket_free,
1226
1241
  bucket);
1227
- rb_obj_call_init(obj, argc, argv);
1228
1242
  return obj;
1229
1243
  }
1230
1244
 
@@ -1295,6 +1309,7 @@ cb_bucket_init(int argc, VALUE *argv, VALUE self)
1295
1309
  bucket->default_format = sym_document;
1296
1310
  bucket->on_error_proc = Qnil;
1297
1311
  bucket->timeout = 0;
1312
+ bucket->object_space = rb_hash_new();
1298
1313
 
1299
1314
  do_scan_connection_options(bucket, argc, argv);
1300
1315
  do_connect(bucket);
@@ -1302,6 +1317,60 @@ cb_bucket_init(int argc, VALUE *argv, VALUE self)
1302
1317
  return self;
1303
1318
  }
1304
1319
 
1320
+ /*
1321
+ * Initialize copy
1322
+ *
1323
+ * Initializes copy of the object, used by {Couchbase::Bucket#dup}
1324
+ *
1325
+ * @param orig [Couchbase::Bucket] the source for copy
1326
+ *
1327
+ * @return [Couchbase::Bucket]
1328
+ */
1329
+ static VALUE
1330
+ cb_bucket_init_copy(VALUE copy, VALUE orig)
1331
+ {
1332
+ bucket_t *copy_b;
1333
+ bucket_t *orig_b;
1334
+
1335
+ if (copy == orig)
1336
+ return copy;
1337
+
1338
+ if (TYPE(orig) != T_DATA || TYPE(copy) != T_DATA ||
1339
+ RDATA(orig)->dfree != (RUBY_DATA_FUNC)cb_bucket_free) {
1340
+ rb_raise(rb_eTypeError, "wrong argument type");
1341
+ }
1342
+
1343
+ copy_b = DATA_PTR(copy);
1344
+ orig_b = DATA_PTR(orig);
1345
+
1346
+ copy_b->port = orig_b->port;
1347
+ copy_b->authority = strdup(orig_b->authority);
1348
+ copy_b->hostname = strdup(orig_b->hostname);
1349
+ copy_b->pool = strdup(orig_b->pool);
1350
+ copy_b->bucket = strdup(orig_b->bucket);
1351
+ if (orig_b->username) {
1352
+ copy_b->username = strdup(orig_b->username);
1353
+ }
1354
+ if (orig_b->password) {
1355
+ copy_b->password = strdup(orig_b->password);
1356
+ }
1357
+ copy_b->async = orig_b->async;
1358
+ copy_b->quiet = orig_b->quiet;
1359
+ copy_b->seqno = orig_b->seqno;
1360
+ copy_b->default_format = orig_b->default_format;
1361
+ copy_b->default_flags = orig_b->default_flags;
1362
+ copy_b->default_ttl = orig_b->default_ttl;
1363
+ copy_b->timeout = orig_b->timeout;
1364
+ copy_b->exception = Qnil;
1365
+ if (orig_b->on_error_proc != Qnil) {
1366
+ copy_b->on_error_proc = rb_funcall(orig_b->on_error_proc, id_dup, 0);
1367
+ }
1368
+
1369
+ do_connect(copy_b);
1370
+
1371
+ return copy;
1372
+ }
1373
+
1305
1374
  /*
1306
1375
  * Reconnect the bucket
1307
1376
  *
@@ -1492,7 +1561,7 @@ cb_bucket_hostname_get(VALUE self)
1492
1561
  bucket_t *bucket = DATA_PTR(self);
1493
1562
  if (bucket->handle) {
1494
1563
  if (bucket->hostname) {
1495
- free(bucket->hostname);
1564
+ xfree(bucket->hostname);
1496
1565
  bucket->hostname = NULL;
1497
1566
  }
1498
1567
  bucket->hostname = strdup(libcouchbase_get_host(bucket->handle));
@@ -1528,7 +1597,7 @@ cb_bucket_authority_get(VALUE self)
1528
1597
  (void)cb_bucket_hostname_get(self);
1529
1598
  (void)cb_bucket_port_get(self);
1530
1599
  len = strlen(bucket->hostname) + 10;
1531
- bucket->authority = calloc(len, sizeof(char));
1600
+ bucket->authority = xcalloc(len, sizeof(char));
1532
1601
  if (bucket->authority == NULL) {
1533
1602
  rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1534
1603
  }
@@ -1691,7 +1760,7 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
1691
1760
  k = unify_key(k);
1692
1761
  key = RSTRING_PTR(k);
1693
1762
  nkey = RSTRING_LEN(k);
1694
- ctx = calloc(1, sizeof(context_t));
1763
+ ctx = xcalloc(1, sizeof(context_t));
1695
1764
  ctx->quiet = bucket->quiet;
1696
1765
  if (ctx == NULL) {
1697
1766
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
@@ -1710,7 +1779,7 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
1710
1779
  }
1711
1780
  }
1712
1781
  ctx->proc = proc;
1713
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
1782
+ cb_gc_protect(bucket, ctx->proc);
1714
1783
  rv = rb_ary_new();
1715
1784
  ctx->rv = &rv;
1716
1785
  ctx->bucket = bucket;
@@ -1721,7 +1790,7 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
1721
1790
  (const void *)key, nkey, cas);
1722
1791
  exc = cb_check_error(err, "failed to schedule delete request", Qnil);
1723
1792
  if (exc != Qnil) {
1724
- free(ctx);
1793
+ xfree(ctx);
1725
1794
  rb_exc_raise(exc);
1726
1795
  }
1727
1796
  if (bucket->async) {
@@ -1732,8 +1801,9 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
1732
1801
  bucket->io->run_event_loop(bucket->io);
1733
1802
  }
1734
1803
  exc = ctx->exception;
1735
- free(ctx);
1804
+ xfree(ctx);
1736
1805
  if (exc != Qnil) {
1806
+ cb_gc_unprotect(bucket, exc);
1737
1807
  rb_exc_raise(exc);
1738
1808
  }
1739
1809
  return rv;
@@ -1791,7 +1861,7 @@ cb_bucket_store(libcouchbase_storage_t cmd, int argc, VALUE *argv, VALUE self)
1791
1861
  }
1792
1862
  bytes = RSTRING_PTR(v);
1793
1863
  nbytes = RSTRING_LEN(v);
1794
- ctx = calloc(1, sizeof(context_t));
1864
+ ctx = xcalloc(1, sizeof(context_t));
1795
1865
  if (ctx == NULL) {
1796
1866
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
1797
1867
  }
@@ -1799,7 +1869,7 @@ cb_bucket_store(libcouchbase_storage_t cmd, int argc, VALUE *argv, VALUE self)
1799
1869
  ctx->rv = &rv;
1800
1870
  ctx->bucket = bucket;
1801
1871
  ctx->proc = proc;
1802
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
1872
+ cb_gc_protect(bucket, ctx->proc);
1803
1873
  ctx->exception = Qnil;
1804
1874
  seqno = bucket->seqno;
1805
1875
  bucket->seqno++;
@@ -1807,7 +1877,7 @@ cb_bucket_store(libcouchbase_storage_t cmd, int argc, VALUE *argv, VALUE self)
1807
1877
  (const void *)key, nkey, bytes, nbytes, flags, exp, cas);
1808
1878
  exc = cb_check_error(err, "failed to schedule set request", Qnil);
1809
1879
  if (exc != Qnil) {
1810
- free(ctx);
1880
+ xfree(ctx);
1811
1881
  rb_exc_raise(exc);
1812
1882
  }
1813
1883
  if (bucket->async) {
@@ -1818,8 +1888,9 @@ cb_bucket_store(libcouchbase_storage_t cmd, int argc, VALUE *argv, VALUE self)
1818
1888
  bucket->io->run_event_loop(bucket->io);
1819
1889
  }
1820
1890
  exc = ctx->exception;
1821
- free(ctx);
1891
+ xfree(ctx);
1822
1892
  if (exc != Qnil) {
1893
+ cb_gc_unprotect(bucket, exc);
1823
1894
  rb_exc_raise(exc);
1824
1895
  }
1825
1896
  if (bucket->exception != Qnil) {
@@ -1851,7 +1922,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
1851
1922
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
1852
1923
  }
1853
1924
  k = unify_key(k);
1854
- ctx = calloc(1, sizeof(context_t));
1925
+ ctx = xcalloc(1, sizeof(context_t));
1855
1926
  if (ctx == NULL) {
1856
1927
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
1857
1928
  }
@@ -1885,7 +1956,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
1885
1956
  ctx->rv = &rv;
1886
1957
  ctx->bucket = bucket;
1887
1958
  ctx->proc = proc;
1888
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
1959
+ cb_gc_protect(bucket, ctx->proc);
1889
1960
  ctx->exception = Qnil;
1890
1961
  ctx->arithm = sign;
1891
1962
  seqno = bucket->seqno;
@@ -1894,7 +1965,7 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
1894
1965
  (const void *)key, nkey, delta, exp, create, initial);
1895
1966
  exc = cb_check_error(err, "failed to schedule arithmetic request", k);
1896
1967
  if (exc != Qnil) {
1897
- free(ctx);
1968
+ xfree(ctx);
1898
1969
  rb_exc_raise(exc);
1899
1970
  }
1900
1971
  if (bucket->async) {
@@ -1905,8 +1976,9 @@ cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
1905
1976
  bucket->io->run_event_loop(bucket->io);
1906
1977
  }
1907
1978
  exc = ctx->exception;
1908
- free(ctx);
1979
+ xfree(ctx);
1909
1980
  if (exc != Qnil) {
1981
+ cb_gc_unprotect(bucket, exc);
1910
1982
  rb_exc_raise(exc);
1911
1983
  }
1912
1984
  return rv;
@@ -2197,16 +2269,16 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
2197
2269
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2198
2270
  }
2199
2271
  rb_funcall(args, id_flatten_bang, 0);
2200
- traits = calloc(1, sizeof(struct key_traits));
2272
+ traits = xcalloc(1, sizeof(struct key_traits));
2201
2273
  nn = cb_args_scan_keys(RARRAY_LEN(args), args, bucket, traits);
2202
- ctx = calloc(1, sizeof(context_t));
2274
+ ctx = xcalloc(1, sizeof(context_t));
2203
2275
  if (ctx == NULL) {
2204
2276
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
2205
2277
  }
2206
2278
  mgat = traits->mgat;
2207
2279
  keys = traits->keys_ary;
2208
2280
  ctx->proc = proc;
2209
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
2281
+ cb_gc_protect(bucket, ctx->proc);
2210
2282
  ctx->bucket = bucket;
2211
2283
  ctx->extended = traits->extended;
2212
2284
  ctx->quiet = traits->quiet;
@@ -2219,13 +2291,13 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
2219
2291
  err = libcouchbase_mget(bucket->handle, (const void *)ctx,
2220
2292
  traits->nkeys, (const void * const *)traits->keys,
2221
2293
  traits->lens, (traits->explicit_ttl) ? traits->ttls : NULL);
2222
- free(traits->keys);
2223
- free(traits->lens);
2224
- free(traits->ttls);
2225
- free(traits);
2294
+ xfree(traits->keys);
2295
+ xfree(traits->lens);
2296
+ xfree(traits->ttls);
2297
+ xfree(traits);
2226
2298
  exc = cb_check_error(err, "failed to schedule get request", Qnil);
2227
2299
  if (exc != Qnil) {
2228
- free(ctx);
2300
+ xfree(ctx);
2229
2301
  rb_exc_raise(exc);
2230
2302
  }
2231
2303
  if (bucket->async) {
@@ -2237,8 +2309,9 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
2237
2309
  }
2238
2310
  exc = ctx->exception;
2239
2311
  extended = ctx->extended;
2240
- free(ctx);
2312
+ xfree(ctx);
2241
2313
  if (exc != Qnil) {
2314
+ cb_gc_unprotect(bucket, exc);
2242
2315
  rb_exc_raise(exc);
2243
2316
  }
2244
2317
  if (bucket->exception != Qnil) {
@@ -2344,14 +2417,14 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
2344
2417
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2345
2418
  }
2346
2419
  rb_funcall(args, id_flatten_bang, 0);
2347
- traits = calloc(1, sizeof(struct key_traits));
2420
+ traits = xcalloc(1, sizeof(struct key_traits));
2348
2421
  nn = cb_args_scan_keys(RARRAY_LEN(args), args, bucket, traits);
2349
- ctx = calloc(1, sizeof(context_t));
2422
+ ctx = xcalloc(1, sizeof(context_t));
2350
2423
  if (ctx == NULL) {
2351
2424
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
2352
2425
  }
2353
2426
  ctx->proc = proc;
2354
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
2427
+ cb_gc_protect(bucket, ctx->proc);
2355
2428
  ctx->bucket = bucket;
2356
2429
  rv = rb_hash_new();
2357
2430
  ctx->rv = &rv;
@@ -2361,12 +2434,12 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
2361
2434
  err = libcouchbase_mtouch(bucket->handle, (const void *)ctx,
2362
2435
  traits->nkeys, (const void * const *)traits->keys,
2363
2436
  traits->lens, traits->ttls);
2364
- free(traits->keys);
2365
- free(traits->lens);
2366
- free(traits);
2437
+ xfree(traits->keys);
2438
+ xfree(traits->lens);
2439
+ xfree(traits);
2367
2440
  exc = cb_check_error(err, "failed to schedule touch request", Qnil);
2368
2441
  if (exc != Qnil) {
2369
- free(ctx);
2442
+ xfree(ctx);
2370
2443
  rb_exc_raise(exc);
2371
2444
  }
2372
2445
  if (bucket->async) {
@@ -2377,8 +2450,9 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
2377
2450
  bucket->io->run_event_loop(bucket->io);
2378
2451
  }
2379
2452
  exc = ctx->exception;
2380
- free(ctx);
2453
+ xfree(ctx);
2381
2454
  if (exc != Qnil) {
2455
+ cb_gc_unprotect(bucket, exc);
2382
2456
  rb_exc_raise(exc);
2383
2457
  }
2384
2458
  if (bucket->exception != Qnil) {
@@ -2433,7 +2507,7 @@ cb_bucket_flush(VALUE self)
2433
2507
  if (!bucket->async && rb_block_given_p()) {
2434
2508
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2435
2509
  }
2436
- ctx = calloc(1, sizeof(context_t));
2510
+ ctx = xcalloc(1, sizeof(context_t));
2437
2511
  if (ctx == NULL) {
2438
2512
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
2439
2513
  }
@@ -2446,13 +2520,13 @@ cb_bucket_flush(VALUE self)
2446
2520
  } else {
2447
2521
  ctx->proc = Qnil;
2448
2522
  }
2449
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
2523
+ cb_gc_protect(bucket, ctx->proc);
2450
2524
  seqno = bucket->seqno;
2451
2525
  bucket->seqno++;
2452
2526
  err = libcouchbase_flush(bucket->handle, (const void *)ctx);
2453
2527
  exc = cb_check_error(err, "failed to schedule flush request", Qnil);
2454
2528
  if (exc != Qnil) {
2455
- free(ctx);
2529
+ xfree(ctx);
2456
2530
  rb_exc_raise(exc);
2457
2531
  }
2458
2532
  if (bucket->async) {
@@ -2463,8 +2537,9 @@ cb_bucket_flush(VALUE self)
2463
2537
  bucket->io->run_event_loop(bucket->io);
2464
2538
  }
2465
2539
  exc = ctx->exception;
2466
- free(ctx);
2540
+ xfree(ctx);
2467
2541
  if (exc != Qnil) {
2542
+ cb_gc_unprotect(bucket, exc);
2468
2543
  rb_exc_raise(exc);
2469
2544
  }
2470
2545
  return rv;
@@ -2511,7 +2586,7 @@ cb_bucket_version(VALUE self)
2511
2586
  if (!bucket->async && rb_block_given_p()) {
2512
2587
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2513
2588
  }
2514
- ctx = calloc(1, sizeof(context_t));
2589
+ ctx = xcalloc(1, sizeof(context_t));
2515
2590
  if (ctx == NULL) {
2516
2591
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
2517
2592
  }
@@ -2524,13 +2599,13 @@ cb_bucket_version(VALUE self)
2524
2599
  } else {
2525
2600
  ctx->proc = Qnil;
2526
2601
  }
2527
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
2602
+ cb_gc_protect(bucket, ctx->proc);
2528
2603
  seqno = bucket->seqno;
2529
2604
  bucket->seqno++;
2530
2605
  err = libcouchbase_server_versions(bucket->handle, (const void *)ctx);
2531
2606
  exc = cb_check_error(err, "failed to schedule version request", Qnil);
2532
2607
  if (exc != Qnil) {
2533
- free(ctx);
2608
+ xfree(ctx);
2534
2609
  rb_exc_raise(exc);
2535
2610
  }
2536
2611
  if (bucket->async) {
@@ -2541,8 +2616,9 @@ cb_bucket_version(VALUE self)
2541
2616
  bucket->io->run_event_loop(bucket->io);
2542
2617
  }
2543
2618
  exc = ctx->exception;
2544
- free(ctx);
2619
+ xfree(ctx);
2545
2620
  if (exc != Qnil) {
2621
+ cb_gc_unprotect(bucket, exc);
2546
2622
  rb_exc_raise(exc);
2547
2623
  }
2548
2624
  return rv;
@@ -2608,7 +2684,7 @@ cb_bucket_stats(int argc, VALUE *argv, VALUE self)
2608
2684
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2609
2685
  }
2610
2686
 
2611
- ctx = calloc(1, sizeof(context_t));
2687
+ ctx = xcalloc(1, sizeof(context_t));
2612
2688
  if (ctx == NULL) {
2613
2689
  rb_raise(eNoMemoryError, "failed to allocate memory for context");
2614
2690
  }
@@ -2616,7 +2692,7 @@ cb_bucket_stats(int argc, VALUE *argv, VALUE self)
2616
2692
  ctx->rv = &rv;
2617
2693
  ctx->bucket = bucket;
2618
2694
  ctx->proc = proc;
2619
- rb_hash_aset(object_space, ctx->proc|1, ctx->proc);
2695
+ cb_gc_protect(bucket, ctx->proc);
2620
2696
  ctx->exception = Qnil;
2621
2697
  if (arg != Qnil) {
2622
2698
  arg = unify_key(arg);
@@ -2632,7 +2708,7 @@ cb_bucket_stats(int argc, VALUE *argv, VALUE self)
2632
2708
  key, nkey);
2633
2709
  exc = cb_check_error(err, "failed to schedule stat request", Qnil);
2634
2710
  if (exc != Qnil) {
2635
- free(ctx);
2711
+ xfree(ctx);
2636
2712
  rb_exc_raise(exc);
2637
2713
  }
2638
2714
  if (bucket->async) {
@@ -2643,8 +2719,9 @@ cb_bucket_stats(int argc, VALUE *argv, VALUE self)
2643
2719
  bucket->io->run_event_loop(bucket->io);
2644
2720
  }
2645
2721
  exc = ctx->exception;
2646
- free(ctx);
2722
+ xfree(ctx);
2647
2723
  if (exc != Qnil) {
2724
+ cb_gc_unprotect(bucket, exc);
2648
2725
  rb_exc_raise(exc);
2649
2726
  }
2650
2727
  if (bucket->exception != Qnil) {
@@ -3250,9 +3327,6 @@ Init_couchbase_ext(void)
3250
3327
  * This class in charge of all stuff connected to communication with
3251
3328
  * Couchbase. */
3252
3329
  cBucket = rb_define_class_under(mCouchbase, "Bucket", rb_cObject);
3253
- object_space = rb_hash_new();
3254
- /* @private Hack to avoid GC in some cases */
3255
- rb_define_const(cBucket, "OBJECT_SPACE", object_space);
3256
3330
 
3257
3331
  /* 0x03: Bitmask for flag bits responsible for format */
3258
3332
  rb_define_const(cBucket, "FMT_MASK", INT2FIX(FMT_MASK));
@@ -3272,9 +3346,9 @@ Init_couchbase_ext(void)
3272
3346
  * http://dustin.github.com/2011/02/17/memcached-set.html */
3273
3347
  rb_define_const(cBucket, "FMT_PLAIN", INT2FIX(FMT_PLAIN));
3274
3348
 
3275
- rb_define_singleton_method(cBucket, "new", cb_bucket_new, -1);
3276
-
3349
+ rb_define_alloc_func(cBucket, cb_bucket_alloc);
3277
3350
  rb_define_method(cBucket, "initialize", cb_bucket_init, -1);
3351
+ rb_define_method(cBucket, "initialize_copy", cb_bucket_init_copy, 1);
3278
3352
  rb_define_method(cBucket, "inspect", cb_bucket_inspect, 0);
3279
3353
 
3280
3354
  /* Document-method: seqno
@@ -3441,6 +3515,7 @@ Init_couchbase_ext(void)
3441
3515
  id_arity = rb_intern("arity");
3442
3516
  id_call = rb_intern("call");
3443
3517
  id_dump = rb_intern("dump");
3518
+ id_dup = rb_intern("dup");
3444
3519
  id_flatten_bang = rb_intern("flatten!");
3445
3520
  id_has_key_p = rb_intern("has_key?");
3446
3521
  id_host = rb_intern("host");
@@ -57,12 +57,12 @@ module Couchbase
57
57
  if async?
58
58
  get(key, options) do |ret|
59
59
  val = yield(ret) # get new value from caller
60
- set(ret.key, val, :cas => ret.cas)
60
+ set(ret.key, val, :cas => ret.cas, :flags => ret.flags)
61
61
  end
62
62
  else
63
63
  val, flags, ver = get(key, options)
64
64
  val = yield(val) # get new value from caller
65
- set(key, val, :cas => ver)
65
+ set(key, val, :cas => ver, :flags => flags)
66
66
  end
67
67
  end
68
68
  alias :compare_and_swap :cas
@@ -17,5 +17,5 @@
17
17
 
18
18
  # Couchbase ruby client
19
19
  module Couchbase
20
- VERSION = "1.1.2"
20
+ VERSION = "1.1.3"
21
21
  end
data/test/test_cas.rb CHANGED
@@ -56,4 +56,12 @@ class TestCas < MiniTest::Unit::TestCase
56
56
  assert_equal expected, val
57
57
  end
58
58
 
59
+ def test_flags_replication
60
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
61
+ :default_format => :document)
62
+ connection.set(uniq_id, "bar", :flags => 0x100)
63
+ connection.cas(uniq_id) { "baz" }
64
+ _, flags, _ = connection.get(uniq_id, :extended => true)
65
+ assert_equal 0x100, flags
66
+ end
59
67
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  prerelease:
6
6
  platform: x86-mingw32
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-05 00:00:00.000000000 Z
12
+ date: 2012-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yajl-ruby
@@ -200,7 +200,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
200
  version: '0'
201
201
  segments:
202
202
  - 0
203
- hash: -4084903815359585037
203
+ hash: 4465124616763901635
204
204
  required_rubygems_version: !ruby/object:Gem::Requirement
205
205
  none: false
206
206
  requirements:
@@ -209,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
209
  version: '0'
210
210
  segments:
211
211
  - 0
212
- hash: -4084903815359585037
212
+ hash: 4465124616763901635
213
213
  requirements: []
214
214
  rubyforge_project:
215
215
  rubygems_version: 1.8.24