couchbase 1.2.3-x86-mingw32 → 1.3.0-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.
@@ -97,7 +97,7 @@ struct cb_bucket_st
97
97
  uint8_t connected; /* non-zero if instance has been connected. it is possible to defer connection with :async option */
98
98
  uint8_t running; /* non-zero if event loop is running */
99
99
  uint8_t trigger_connect_cb_on_set; /* if non-zero, the on_connect callback will be triggered immediately after set */
100
- VALUE default_format; /* should update +default_flags+ on change */
100
+ VALUE transcoder;
101
101
  uint32_t default_flags;
102
102
  time_t default_ttl;
103
103
  time_t default_observe_timeout;
@@ -127,7 +127,8 @@ struct cb_context_st
127
127
  VALUE rv;
128
128
  VALUE exception;
129
129
  VALUE observe_options;
130
- VALUE force_format;
130
+ VALUE transcoder;
131
+ VALUE transcoder_opts;
131
132
  VALUE operation;
132
133
  VALUE headers_val;
133
134
  int headers_built;
@@ -169,8 +170,10 @@ extern VALUE cb_cTimer;
169
170
  /* Modules */
170
171
  extern VALUE cb_mCouchbase;
171
172
  extern VALUE cb_mError;
173
+ extern VALUE cb_mTranscoder;
174
+ extern VALUE cb_mDocument;
175
+ extern VALUE cb_mPlain;
172
176
  extern VALUE cb_mMarshal;
173
- extern VALUE cb_mMultiJson;
174
177
  extern VALUE cb_mURI;
175
178
  extern VALUE em_m;
176
179
 
@@ -203,6 +206,7 @@ extern ID cb_sym_environment;
203
206
  extern ID cb_sym_eventmachine;
204
207
  extern ID cb_sym_extended;
205
208
  extern ID cb_sym_flags;
209
+ extern ID cb_sym_forced;
206
210
  extern ID cb_sym_format;
207
211
  extern ID cb_sym_found;
208
212
  extern ID cb_sym_get;
@@ -239,6 +243,7 @@ extern ID cb_sym_set;
239
243
  extern ID cb_sym_stats;
240
244
  extern ID cb_sym_timeout;
241
245
  extern ID cb_sym_touch;
246
+ extern ID cb_sym_transcoder;
242
247
  extern ID cb_sym_ttl;
243
248
  extern ID cb_sym_type;
244
249
  extern ID cb_sym_unlock;
@@ -336,10 +341,8 @@ int cb_first_value_i(VALUE key, VALUE value, VALUE arg);
336
341
  void cb_build_headers(struct cb_context_st *ctx, const char * const *headers);
337
342
  void cb_maybe_do_loop(struct cb_bucket_st *bucket);
338
343
  VALUE cb_unify_key(struct cb_bucket_st *bucket, VALUE key, int apply_prefix);
339
- VALUE cb_encode_value(VALUE val, uint32_t flags);
340
- VALUE cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format);
341
- uint32_t cb_flags_set_format(uint32_t flags, ID format);
342
- ID cb_flags_get_format(uint32_t flags);
344
+ VALUE cb_encode_value(VALUE transcoder, VALUE val, uint32_t *flags, VALUE options);
345
+ VALUE cb_decode_value(VALUE transcoder, VALUE blob, uint32_t flags, VALUE options);
343
346
  void cb_async_error_notify(struct cb_bucket_st *bucket, VALUE exc);
344
347
 
345
348
 
@@ -388,6 +391,8 @@ VALUE cb_bucket_connected_p(VALUE self);
388
391
  VALUE cb_bucket_async_p(VALUE self);
389
392
  VALUE cb_bucket_quiet_get(VALUE self);
390
393
  VALUE cb_bucket_quiet_set(VALUE self, VALUE val);
394
+ VALUE cb_bucket_transcoder_get(VALUE self);
395
+ VALUE cb_bucket_transcoder_set(VALUE self, VALUE val);
391
396
  VALUE cb_bucket_default_flags_get(VALUE self);
392
397
  VALUE cb_bucket_default_flags_set(VALUE self, VALUE val);
393
398
  VALUE cb_bucket_default_format_get(VALUE self);
@@ -488,6 +493,8 @@ struct cb_params_st
488
493
  lcb_cas_t cas;
489
494
  lcb_datatype_t datatype;
490
495
  VALUE observe;
496
+ VALUE transcoder;
497
+ VALUE transcoder_opts;
491
498
  } store;
492
499
  struct {
493
500
  /* number of items */
@@ -509,7 +516,8 @@ struct cb_params_st
509
516
  /* arguments given in form of hash key-ttl to "get and touch" */
510
517
  unsigned int gat : 1;
511
518
  lcb_time_t ttl;
512
- VALUE forced_format;
519
+ VALUE transcoder;
520
+ VALUE transcoder_opts;
513
521
  VALUE keys_ary;
514
522
  } get;
515
523
  struct {
@@ -526,7 +534,8 @@ struct cb_params_st
526
534
  lcb_uint64_t initial;
527
535
  lcb_uint64_t delta;
528
536
  int sign;
529
- VALUE format;
537
+ VALUE transcoder;
538
+ VALUE transcoder_opts;
530
539
  lcb_datatype_t datatype;
531
540
  } arith;
532
541
  struct {
@@ -22,7 +22,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
22
22
  {
23
23
  struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
24
  struct cb_bucket_st *bucket = ctx->bucket;
25
- VALUE key, val, flags, cas, exc = Qnil, res;
25
+ VALUE key, val, flags, cas, exc = Qnil, res, raw;
26
26
 
27
27
  ctx->nqueries--;
28
28
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
@@ -38,22 +38,17 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
38
38
 
39
39
  flags = ULONG2NUM(resp->v.v0.flags);
40
40
  cas = ULL2NUM(resp->v.v0.cas);
41
- val = Qnil;
42
- if (resp->v.v0.nbytes != 0) {
43
- VALUE raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
44
- val = cb_decode_value(raw, resp->v.v0.flags, ctx->force_format);
45
- if (rb_obj_is_kind_of(val, rb_eStandardError)) {
46
- VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
47
- VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
48
- rb_str_new2("unable to convert value for key '%s': %s"), key, exc_str);
49
- ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
50
- rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
51
- rb_ivar_set(ctx->exception, cb_id_iv_key, key);
52
- rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
53
- val = raw;
54
- }
55
- } else if (cb_flags_get_format(resp->v.v0.flags) == cb_sym_plain) {
56
- val = cb_vStrEmpty;
41
+ raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
42
+ val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts);
43
+ if (rb_obj_is_kind_of(val, rb_eStandardError)) {
44
+ VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
45
+ VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
46
+ rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str);
47
+ ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
48
+ rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
49
+ rb_ivar_set(ctx->exception, cb_id_iv_key, key);
50
+ rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
51
+ val = Qnil;
57
52
  }
58
53
  if (bucket->async) { /* asynchronous */
59
54
  if (ctx->proc != Qnil) {
@@ -96,8 +91,8 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
96
91
  * @param keys [String, Symbol, Array] One or several keys to fetch
97
92
  * @param options [Hash] Options for operation.
98
93
  * @option options [true, false] :extended (false) If set to +true+, the
99
- * operation will return tuple +[value, flags, cas]+, otherwise (by
100
- * default) it returns just value.
94
+ * operation will return a tuple +[value, flags, cas]+, otherwise (by
95
+ * default) it returns just the value.
101
96
  * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
102
97
  * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
103
98
  * absolute times (from the epoch).
@@ -128,7 +123,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
128
123
  * +cas+).
129
124
  *
130
125
  * @return [Object, Array, Hash] the value(s) (or tuples in extended mode)
131
- * assiciated with the key.
126
+ * associated with the key.
132
127
  *
133
128
  * @raise [Couchbase::Error::NotFound] if the key is missing in the
134
129
  * bucket.
@@ -137,7 +132,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
137
132
  *
138
133
  * @raise [ArgumentError] when passing the block in synchronous mode
139
134
  *
140
- * @example Get single value in quite mode (the default)
135
+ * @example Get single value in quiet mode (the default)
141
136
  * c.get("foo") #=> the associated value or nil
142
137
  *
143
138
  * @example Use alternative hash-like syntax
@@ -199,7 +194,7 @@ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_g
199
194
  * @param options [Hash] Options for operation. (see options definition
200
195
  * above)
201
196
  *
202
- * @return [Hash] the values (or tuples in extended mode) assiciated with
197
+ * @return [Hash] the values (or tuples in extended mode) associated with
203
198
  * the keys.
204
199
  *
205
200
  * @example Get and touch multiple keys
@@ -239,7 +234,8 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
239
234
  ctx = cb_context_alloc_common(bucket, proc, params.cmd.get.num);
240
235
  ctx->extended = params.cmd.get.extended;
241
236
  ctx->quiet = params.cmd.get.quiet;
242
- ctx->force_format = params.cmd.get.forced_format;
237
+ ctx->transcoder = params.cmd.get.transcoder;
238
+ ctx->transcoder_opts = params.cmd.get.transcoder_opts;
243
239
  if (params.cmd.get.replica) {
244
240
  err = lcb_get_replica(bucket->handle, (const void *)ctx,
245
241
  params.cmd.get.num, params.cmd.get.ptr_gr);
@@ -201,7 +201,7 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
201
201
  * @option options [Symbol] :format (self.default_format) The
202
202
  * representation for storing the value in the bucket. For more info see
203
203
  * {Bucket#default_format}.
204
- * @option options [Fixnum] :cas The CAS value for an object. This value
204
+ * @option options [Fixnum] :cas The CAS value for an object. This value is
205
205
  * created on the server and is guaranteed to be unique for each value of
206
206
  * a given key. This value is used to provide simple optimistic
207
207
  * concurrency control when multiple clients or threads try to update an
@@ -360,89 +360,33 @@ cb_check_error(lcb_error_t rc, const char *msg, VALUE key)
360
360
  return cb_check_error_with_status(rc, msg, key, 0);
361
361
  }
362
362
 
363
-
364
- uint32_t
365
- cb_flags_set_format(uint32_t flags, ID format)
366
- {
367
- flags &= ~((uint32_t)CB_FMT_MASK); /* clear format bits */
368
-
369
- if (format == cb_sym_document) {
370
- return flags | CB_FMT_DOCUMENT;
371
- } else if (format == cb_sym_marshal) {
372
- return flags | CB_FMT_MARSHAL;
373
- } else if (format == cb_sym_plain) {
374
- return flags | CB_FMT_PLAIN;
375
- }
376
- return flags; /* document is the default */
377
- }
378
-
379
- ID
380
- cb_flags_get_format(uint32_t flags)
381
- {
382
- flags &= CB_FMT_MASK; /* select format bits */
383
-
384
- switch (flags) {
385
- case CB_FMT_DOCUMENT:
386
- return cb_sym_document;
387
- case CB_FMT_MARSHAL:
388
- return cb_sym_marshal;
389
- case CB_FMT_PLAIN:
390
- /* fall through */
391
- default:
392
- /* all other formats treated as plain */
393
- return cb_sym_plain;
394
- }
395
- }
396
-
397
-
398
363
  static VALUE
399
364
  do_encode(VALUE *args)
400
365
  {
401
366
  VALUE val = args[0];
402
- uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
403
-
404
- switch (flags) {
405
- case CB_FMT_DOCUMENT:
406
- return rb_funcall(cb_mMultiJson, cb_id_dump, 1, val);
407
- case CB_FMT_MARSHAL:
408
- return rb_funcall(cb_mMarshal, cb_id_dump, 1, val);
409
- case CB_FMT_PLAIN:
410
- /* fall through */
411
- default:
412
- /* all other formats treated as plain */
413
- return val;
367
+ uint32_t *flags = (uint32_t *)args[1];
368
+ VALUE transcoder = args[2];
369
+ VALUE options = args[3];
370
+ VALUE ret;
371
+
372
+ ret = rb_funcall(transcoder, cb_id_dump, 3, val, ULONG2NUM(*flags), options);
373
+ Check_Type(ret, T_ARRAY);
374
+ if (RARRAY_LEN(ret) != 2) {
375
+ rb_raise(rb_eArgError, "#dump method of transcoder should return two items");
414
376
  }
377
+ *flags = NUM2ULONG(RARRAY_PTR(ret)[1]);
378
+ return RARRAY_PTR(ret)[0];
415
379
  }
416
380
 
417
381
  static VALUE
418
382
  do_decode(VALUE *args)
419
383
  {
420
384
  VALUE blob = args[0];
421
- VALUE force_format = args[2];
422
-
423
- if (TYPE(force_format) == T_SYMBOL) {
424
- if (force_format == cb_sym_document) {
425
- return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
426
- } else if (force_format == cb_sym_marshal) {
427
- return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
428
- } else { /* cb_sym_plain and any other cb_symbol */
429
- return blob;
430
- }
431
- } else {
432
- uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
433
-
434
- switch (flags) {
435
- case CB_FMT_DOCUMENT:
436
- return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
437
- case CB_FMT_MARSHAL:
438
- return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
439
- case CB_FMT_PLAIN:
440
- /* fall through */
441
- default:
442
- /* all other formats treated as plain */
443
- return blob;
444
- }
445
- }
385
+ VALUE transcoder = args[2];
386
+ VALUE flags = args[1];
387
+ VALUE options = args[3];
388
+
389
+ return rb_funcall(transcoder, cb_id_load, 3, blob, ULONG2NUM(flags), options);
446
390
  }
447
391
 
448
392
  static VALUE
@@ -453,20 +397,27 @@ coding_failed(VALUE unused, VALUE exc)
453
397
  }
454
398
 
455
399
  VALUE
456
- cb_encode_value(VALUE val, uint32_t flags)
400
+ cb_encode_value(VALUE transcoder, VALUE val, uint32_t *flags, VALUE options)
457
401
  {
458
- VALUE blob, args[2];
402
+ VALUE args[4];
459
403
 
460
404
  args[0] = val;
461
405
  args[1] = (VALUE)flags;
462
- blob = rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
463
- return blob; /* bytestring or exception object */
406
+ args[2] = transcoder;
407
+ args[3] = options;
408
+
409
+ /* if nil, just pass value through */
410
+ if (NIL_P(args[2])) {
411
+ return val;
412
+ }
413
+ /* bytestring or exception object */
414
+ return rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
464
415
  }
465
416
 
466
417
  VALUE
467
- cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format)
418
+ cb_decode_value(VALUE transcoder, VALUE blob, uint32_t flags, VALUE options)
468
419
  {
469
- VALUE val, args[3];
420
+ VALUE args[4];
470
421
 
471
422
  /* first it must be bytestring */
472
423
  if (TYPE(blob) != T_STRING) {
@@ -474,9 +425,15 @@ cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format)
474
425
  }
475
426
  args[0] = blob;
476
427
  args[1] = (VALUE)flags;
477
- args[2] = (VALUE)force_format;
478
- val = rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
479
- return val; /* the value or exception object */
428
+ args[2] = transcoder;
429
+ args[3] = options;
430
+
431
+ /* if nil, just pass blob through */
432
+ if (NIL_P(args[2])) {
433
+ return blob;
434
+ }
435
+ /* the value or exception object */
436
+ return rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
480
437
  }
481
438
 
482
439
  void
@@ -55,9 +55,15 @@ module ActiveSupport
55
55
  options[:default_ttl] ||= options.delete(:expires_in)
56
56
  options[:default_format] ||= :marshal
57
57
  options[:key_prefix] ||= options.delete(:namespace)
58
+ options[:connection_pool] ||= options.delete(:connection_pool)
58
59
  args.push(options)
59
- @data = ::Couchbase::Bucket.new(*args)
60
- @lock = Monitor.new
60
+
61
+ if options[:connection_pool]
62
+ @data = ::Couchbase::ConnectionPool.new(options[:connection_pool], *args)
63
+ else
64
+ @data = ::Couchbase::Bucket.new(*args)
65
+ @data.extend(Threadsafe)
66
+ end
61
67
  end
62
68
 
63
69
  # Fetches data from the cache, using the given key.
@@ -184,9 +190,7 @@ module ActiveSupport
184
190
  options[:format] = :plain
185
191
  end
186
192
  instrument(:read_multi, names, options) do
187
- @lock.synchronize do
188
- @data.get(names, options)
189
- end
193
+ @data.get(names, options)
190
194
  end
191
195
  rescue ::Couchbase::Error::Base => e
192
196
  logger.error("#{e.class}: #{e.message}") if logger
@@ -247,9 +251,7 @@ module ActiveSupport
247
251
  options[:create] = true
248
252
  instrument(:increment, name, options) do |payload|
249
253
  payload[:amount] = amount if payload
250
- @lock.synchronize do
251
- @data.incr(name, amount, options)
252
- end
254
+ @data.incr(name, amount, options)
253
255
  end
254
256
  rescue ::Couchbase::Error::Base => e
255
257
  logger.error("#{e.class}: #{e.message}") if logger
@@ -281,9 +283,7 @@ module ActiveSupport
281
283
  options[:create] = true
282
284
  instrument(:decrement, name, options) do |payload|
283
285
  payload[:amount] = amount if payload
284
- @lock.synchronize do
285
- @data.decr(name, amount, options)
286
- end
286
+ @data.decr(name, amount, options)
287
287
  end
288
288
  rescue ::Couchbase::Error::Base => e
289
289
  logger.error("#{e.class}: #{e.message}") if logger
@@ -297,18 +297,14 @@ module ActiveSupport
297
297
  #
298
298
  # @return [Hash]
299
299
  def stats(*arg)
300
- @lock.synchronize do
301
- @data.stats(*arg)
302
- end
300
+ @data.stats(*arg)
303
301
  end
304
302
 
305
303
  protected
306
304
 
307
305
  # Read an entry from the cache.
308
306
  def read_entry(key, options) # :nodoc:
309
- @lock.synchronize do
310
- @data.get(key, options)
311
- end
307
+ @data.get(key, options)
312
308
  rescue ::Couchbase::Error::Base => e
313
309
  logger.error("#{e.class}: #{e.message}") if logger
314
310
  raise if @raise_errors
@@ -325,9 +321,7 @@ module ActiveSupport
325
321
  if ttl = options.delete(:expires_in)
326
322
  options[:ttl] ||= ttl
327
323
  end
328
- @lock.synchronize do
329
- @data.send(method, key, value, options)
330
- end
324
+ @data.send(method, key, value, options)
331
325
  rescue ::Couchbase::Error::Base => e
332
326
  logger.error("#{e.class}: #{e.message}") if logger
333
327
  raise if @raise_errors
@@ -336,9 +330,7 @@ module ActiveSupport
336
330
 
337
331
  # Delete an entry from the cache.
338
332
  def delete_entry(key, options) # :nodoc:
339
- @lock.synchronize do
340
- @data.delete(key, options)
341
- end
333
+ @data.delete(key, options)
342
334
  rescue ::Couchbase::Error::Base => e
343
335
  logger.error("#{e.class}: #{e.message}") if logger
344
336
  raise if @raise_errors
@@ -367,6 +359,51 @@ module ActiveSupport
367
359
  key.respond_to?(:to_param) ? key.to_param : key
368
360
  end
369
361
 
362
+ module Threadsafe
363
+ def self.extended(obj)
364
+ obj.init_threadsafe
365
+ end
366
+
367
+ def get(*)
368
+ @lock.synchronize do
369
+ super
370
+ end
371
+ end
372
+
373
+ def send(*)
374
+ @lock.synchronize do
375
+ super
376
+ end
377
+ end
378
+
379
+ def delete(*)
380
+ @lock.synchronize do
381
+ super
382
+ end
383
+ end
384
+
385
+ def incr(*)
386
+ @lock.synchronize do
387
+ super
388
+ end
389
+ end
390
+
391
+ def decr(*)
392
+ @lock.synchronize do
393
+ super
394
+ end
395
+ end
396
+
397
+ def stats(*)
398
+ @lock.synchronize do
399
+ super
400
+ end
401
+ end
402
+
403
+ def init_threadsafe
404
+ @lock = Monitor.new
405
+ end
406
+ end
370
407
  end
371
408
  end
372
409
  end