couchbase 1.1.5-x86-mingw32 → 1.2.0.beta-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.
Files changed (52) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +12 -1
  3. data/HISTORY.markdown +112 -1
  4. data/README.markdown +149 -6
  5. data/couchbase.gemspec +5 -1
  6. data/ext/couchbase_ext/.gitignore +4 -0
  7. data/ext/couchbase_ext/arguments.c +973 -0
  8. data/ext/couchbase_ext/arithmetic.c +322 -0
  9. data/ext/couchbase_ext/bucket.c +1092 -0
  10. data/ext/couchbase_ext/couchbase_ext.c +618 -3247
  11. data/ext/couchbase_ext/couchbase_ext.h +519 -0
  12. data/ext/couchbase_ext/delete.c +167 -0
  13. data/ext/couchbase_ext/extconf.rb +24 -5
  14. data/ext/couchbase_ext/get.c +301 -0
  15. data/ext/couchbase_ext/gethrtime.c +124 -0
  16. data/ext/couchbase_ext/http.c +402 -0
  17. data/ext/couchbase_ext/observe.c +174 -0
  18. data/ext/couchbase_ext/result.c +126 -0
  19. data/ext/couchbase_ext/stats.c +169 -0
  20. data/ext/couchbase_ext/store.c +522 -0
  21. data/ext/couchbase_ext/timer.c +192 -0
  22. data/ext/couchbase_ext/touch.c +190 -0
  23. data/ext/couchbase_ext/unlock.c +180 -0
  24. data/ext/couchbase_ext/utils.c +471 -0
  25. data/ext/couchbase_ext/version.c +147 -0
  26. data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
  27. data/lib/active_support/cache/couchbase_store.rb +356 -0
  28. data/lib/couchbase.rb +24 -3
  29. data/lib/couchbase/bucket.rb +372 -9
  30. data/lib/couchbase/result.rb +26 -0
  31. data/lib/couchbase/utils.rb +59 -0
  32. data/lib/couchbase/version.rb +1 -1
  33. data/lib/couchbase/view.rb +305 -0
  34. data/lib/couchbase/view_row.rb +230 -0
  35. data/lib/ext/multi_json_fix.rb +47 -0
  36. data/lib/rack/session/couchbase.rb +104 -0
  37. data/tasks/compile.rake +5 -14
  38. data/test/setup.rb +6 -2
  39. data/test/test_arithmetic.rb +32 -2
  40. data/test/test_async.rb +18 -4
  41. data/test/test_bucket.rb +11 -1
  42. data/test/test_cas.rb +13 -3
  43. data/test/test_couchbase_rails_cache_store.rb +294 -0
  44. data/test/test_delete.rb +60 -3
  45. data/test/test_format.rb +28 -17
  46. data/test/test_get.rb +91 -14
  47. data/test/test_store.rb +31 -1
  48. data/test/{test_flush.rb → test_timer.rb} +11 -18
  49. data/test/test_touch.rb +33 -5
  50. data/test/test_unlock.rb +120 -0
  51. data/test/test_utils.rb +26 -0
  52. metadata +102 -12
@@ -15,3344 +15,528 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- #include <ruby.h>
19
- #ifndef RUBY_ST_H
20
- #include <st.h>
21
- #endif
22
18
 
23
- #include <time.h>
24
- #include <libcouchbase/couchbase.h>
25
- #include "couchbase_config.h"
19
+ #include "couchbase_ext.h"
20
+
21
+ /* Classes */
22
+ VALUE cBucket;
23
+ VALUE cCouchRequest;
24
+ VALUE cResult;
25
+ VALUE cTimer;
26
+
27
+ /* Modules */
28
+ VALUE mCouchbase;
29
+ VALUE mError;
30
+ VALUE mMarshal;
31
+ VALUE mMultiJson;
32
+ VALUE mURI;
33
+
34
+ /* Symbols */
35
+ ID sym_add;
36
+ ID sym_append;
37
+ ID sym_assemble_hash;
38
+ ID sym_body;
39
+ ID sym_bucket;
40
+ ID sym_cas;
41
+ ID sym_chunked;
42
+ ID sym_content_type;
43
+ ID sym_create;
44
+ ID sym_decrement;
45
+ ID sym_default_flags;
46
+ ID sym_default_format;
47
+ ID sym_default_observe_timeout;
48
+ ID sym_default_ttl;
49
+ ID sym_delete;
50
+ ID sym_delta;
51
+ ID sym_development;
52
+ ID sym_document;
53
+ ID sym_environment;
54
+ ID sym_extended;
55
+ ID sym_flags;
56
+ ID sym_format;
57
+ ID sym_found;
58
+ ID sym_get;
59
+ ID sym_hostname;
60
+ ID sym_http_request;
61
+ ID sym_increment;
62
+ ID sym_initial;
63
+ ID sym_key_prefix;
64
+ ID sym_lock;
65
+ ID sym_management;
66
+ ID sym_marshal;
67
+ ID sym_method;
68
+ ID sym_node_list;
69
+ ID sym_not_found;
70
+ ID sym_num_replicas;
71
+ ID sym_observe;
72
+ ID sym_password;
73
+ ID sym_periodic;
74
+ ID sym_persisted;
75
+ ID sym_plain;
76
+ ID sym_pool;
77
+ ID sym_port;
78
+ ID sym_post;
79
+ ID sym_prepend;
80
+ ID sym_production;
81
+ ID sym_put;
82
+ ID sym_quiet;
83
+ ID sym_replace;
84
+ ID sym_replica;
85
+ ID sym_send_threshold;
86
+ ID sym_set;
87
+ ID sym_stats;
88
+ ID sym_timeout;
89
+ ID sym_touch;
90
+ ID sym_ttl;
91
+ ID sym_type;
92
+ ID sym_unlock;
93
+ ID sym_username;
94
+ ID sym_version;
95
+ ID sym_view;
96
+ ID id_arity;
97
+ ID id_call;
98
+ ID id_delete;
99
+ ID id_dump;
100
+ ID id_dup;
101
+ ID id_flatten_bang;
102
+ ID id_has_key_p;
103
+ ID id_host;
104
+ ID id_iv_cas;
105
+ ID id_iv_completed;
106
+ ID id_iv_error;
107
+ ID id_iv_flags;
108
+ ID id_iv_from_master;
109
+ ID id_iv_headers;
110
+ ID id_iv_key;
111
+ ID id_iv_node;
112
+ ID id_iv_operation;
113
+ ID id_iv_status;
114
+ ID id_iv_time_to_persist;
115
+ ID id_iv_time_to_replicate;
116
+ ID id_iv_value;
117
+ ID id_load;
118
+ ID id_match;
119
+ ID id_observe_and_wait;
120
+ ID id_parse;
121
+ ID id_password;
122
+ ID id_path;
123
+ ID id_port;
124
+ ID id_scheme;
125
+ ID id_to_s;
126
+ ID id_user;
127
+ ID id_verify_observe_options;
128
+
129
+ /* Errors */
130
+ VALUE eBaseError;
131
+ VALUE eValueFormatError;
132
+ /* LCB_SUCCESS = 0x00 */
133
+ /* LCB_AUTH_CONTINUE = 0x01 */
134
+ VALUE eAuthError; /* LCB_AUTH_ERROR = 0x02 */
135
+ VALUE eDeltaBadvalError; /* LCB_DELTA_BADVAL = 0x03 */
136
+ VALUE eTooBigError; /* LCB_E2BIG = 0x04 */
137
+ VALUE eBusyError; /* LCB_EBUSY = 0x05 */
138
+ VALUE eInternalError; /* LCB_EINTERNAL = 0x06 */
139
+ VALUE eInvalidError; /* LCB_EINVAL = 0x07 */
140
+ VALUE eNoMemoryError; /* LCB_ENOMEM = 0x08 */
141
+ VALUE eRangeError; /* LCB_ERANGE = 0x09 */
142
+ VALUE eLibcouchbaseError; /* LCB_ERROR = 0x0a */
143
+ VALUE eTmpFailError; /* LCB_ETMPFAIL = 0x0b */
144
+ VALUE eKeyExistsError; /* LCB_KEY_EEXISTS = 0x0c */
145
+ VALUE eNotFoundError; /* LCB_KEY_ENOENT = 0x0d */
146
+ VALUE eLibeventError; /* LCB_LIBEVENT_ERROR = 0x0e */
147
+ VALUE eNetworkError; /* LCB_NETWORK_ERROR = 0x0f */
148
+ VALUE eNotMyVbucketError; /* LCB_NOT_MY_VBUCKET = 0x10 */
149
+ VALUE eNotStoredError; /* LCB_NOT_STORED = 0x11 */
150
+ VALUE eNotSupportedError; /* LCB_NOT_SUPPORTED = 0x12 */
151
+ VALUE eUnknownCommandError; /* LCB_UNKNOWN_COMMAND = 0x13 */
152
+ VALUE eUnknownHostError; /* LCB_UNKNOWN_HOST = 0x14 */
153
+ VALUE eProtocolError; /* LCB_PROTOCOL_ERROR = 0x15 */
154
+ VALUE eTimeoutError; /* LCB_ETIMEDOUT = 0x16 */
155
+ VALUE eConnectError; /* LCB_CONNECT_ERROR = 0x17 */
156
+ VALUE eBucketNotFoundError; /* LCB_BUCKET_ENOENT = 0x18 */
157
+ VALUE eClientNoMemoryError; /* LCB_CLIENT_ENOMEM = 0x19 */
158
+ VALUE eClientTmpFailError; /* LCB_CLIENT_ETMPFAIL = 0x20 */
26
159
 
27
- #ifdef HAVE_RUBY_ENCODING_H
28
- #include "ruby/encoding.h"
29
- #define STR_NEW(ptr, len) rb_external_str_new((ptr), (len))
30
- #define STR_NEW_CSTR(str) rb_external_str_new_cstr((str))
31
- #else
32
- #define STR_NEW(ptr, len) rb_str_new((ptr), (len))
33
- #define STR_NEW_CSTR(str) rb_str_new2((str))
34
- #endif
35
-
36
- #ifdef HAVE_STDARG_PROTOTYPES
37
- #include <stdarg.h>
38
- #define va_init_list(a,b) va_start(a,b)
39
- #else
40
- #include <varargs.h>
41
- #define va_init_list(a,b) va_start(a)
42
- #endif
43
-
44
- #define debug_object(OBJ) \
45
- rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("object_id"), 0)); \
46
- rb_funcall(rb_stderr, rb_intern("print"), 1, STR_NEW_CSTR(" ")); \
47
- rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("class"), 0)); \
48
- rb_funcall(rb_stderr, rb_intern("print"), 1, STR_NEW_CSTR(" ")); \
49
- rb_funcall(rb_stderr, rb_intern("puts"), 1, rb_funcall(OBJ, rb_intern("inspect"), 0));
50
-
51
- #define FMT_MASK 0x3
52
- #define FMT_DOCUMENT 0x0
53
- #define FMT_MARSHAL 0x1
54
- #define FMT_PLAIN 0x2
55
-
56
- typedef struct
57
- {
58
- libcouchbase_t handle;
59
- struct libcouchbase_io_opt_st *io;
60
- uint16_t port;
61
- char *authority;
62
- char *hostname;
63
- char *pool;
64
- char *bucket;
65
- char *username;
66
- char *password;
67
- int async;
68
- int quiet;
69
- long seqno;
70
- VALUE default_format; /* should update +default_flags+ on change */
71
- uint32_t default_flags;
72
- time_t default_ttl;
73
- uint32_t timeout;
74
- VALUE exception; /* error delivered by error_callback */
75
- VALUE on_error_proc; /* is using to deliver errors in async mode */
76
- VALUE object_space;
77
- char *node_list;
78
- } bucket_t;
79
-
80
- typedef struct
81
- {
82
- bucket_t* bucket;
83
- int extended;
84
- VALUE proc;
85
- void *rv;
86
- VALUE exception;
87
- VALUE force_format;
88
- int quiet;
89
- int arithm; /* incr: +1, decr: -1, other: 0 */
90
- } context_t;
91
-
92
- struct key_traits
93
- {
94
- VALUE keys_ary;
95
- size_t nkeys;
96
- char **keys;
97
- libcouchbase_size_t *lens;
98
- time_t *ttls;
99
- int extended;
100
- int explicit_ttl;
101
- int quiet;
102
- int mgat;
103
- VALUE force_format;
104
- };
105
-
106
- static VALUE mCouchbase, mError, mJSON, mURI, mMarshal, cBucket, cResult;
107
-
108
- static ID sym_add,
109
- sym_append,
110
- sym_bucket,
111
- sym_cas,
112
- sym_create,
113
- sym_decrement,
114
- sym_default_flags,
115
- sym_default_format,
116
- sym_default_ttl,
117
- sym_delete,
118
- sym_document,
119
- sym_extended,
120
- sym_flags,
121
- sym_flush,
122
- sym_format,
123
- sym_get,
124
- sym_hostname,
125
- sym_increment,
126
- sym_initial,
127
- sym_marshal,
128
- sym_node_list,
129
- sym_password,
130
- sym_plain,
131
- sym_pool,
132
- sym_port,
133
- sym_prepend,
134
- sym_quiet,
135
- sym_replace,
136
- sym_set,
137
- sym_stats,
138
- sym_timeout,
139
- sym_touch,
140
- sym_ttl,
141
- sym_username,
142
- sym_version,
143
- id_arity,
144
- id_call,
145
- id_dump,
146
- id_flatten_bang,
147
- id_has_key_p,
148
- id_host,
149
- id_iv_cas,
150
- id_iv_error,
151
- id_iv_flags,
152
- id_iv_key,
153
- id_iv_node,
154
- id_iv_operation,
155
- id_iv_value,
156
- id_dup,
157
- id_load,
158
- id_match,
159
- id_parse,
160
- id_password,
161
- id_path,
162
- id_port,
163
- id_scheme,
164
- id_to_s,
165
- id_user;
166
-
167
- /* base error */
168
- static VALUE eBaseError;
169
- static VALUE eValueFormatError;
170
-
171
- /* libcouchbase errors */
172
- /*LIBCOUCHBASE_SUCCESS = 0x00*/
173
- /*LIBCOUCHBASE_AUTH_CONTINUE = 0x01*/
174
- static VALUE eAuthError; /*LIBCOUCHBASE_AUTH_ERROR = 0x02*/
175
- static VALUE eDeltaBadvalError; /*LIBCOUCHBASE_DELTA_BADVAL = 0x03*/
176
- static VALUE eTooBigError; /*LIBCOUCHBASE_E2BIG = 0x04*/
177
- static VALUE eBusyError; /*LIBCOUCHBASE_EBUSY = 0x05*/
178
- static VALUE eInternalError; /*LIBCOUCHBASE_EINTERNAL = 0x06*/
179
- static VALUE eInvalidError; /*LIBCOUCHBASE_EINVAL = 0x07*/
180
- static VALUE eNoMemoryError; /*LIBCOUCHBASE_ENOMEM = 0x08*/
181
- static VALUE eRangeError; /*LIBCOUCHBASE_ERANGE = 0x09*/
182
- static VALUE eLibcouchbaseError; /*LIBCOUCHBASE_ERROR = 0x0a*/
183
- static VALUE eTmpFailError; /*LIBCOUCHBASE_ETMPFAIL = 0x0b*/
184
- static VALUE eKeyExistsError; /*LIBCOUCHBASE_KEY_EEXISTS = 0x0c*/
185
- static VALUE eNotFoundError; /*LIBCOUCHBASE_KEY_ENOENT = 0x0d*/
186
- static VALUE eLibeventError; /*LIBCOUCHBASE_LIBEVENT_ERROR = 0x0e*/
187
- static VALUE eNetworkError; /*LIBCOUCHBASE_NETWORK_ERROR = 0x0f*/
188
- static VALUE eNotMyVbucketError; /*LIBCOUCHBASE_NOT_MY_VBUCKET = 0x10*/
189
- static VALUE eNotStoredError; /*LIBCOUCHBASE_NOT_STORED = 0x11*/
190
- static VALUE eNotSupportedError; /*LIBCOUCHBASE_NOT_SUPPORTED = 0x12*/
191
- static VALUE eUnknownCommandError; /*LIBCOUCHBASE_UNKNOWN_COMMAND = 0x13*/
192
- static VALUE eUnknownHostError; /*LIBCOUCHBASE_UNKNOWN_HOST = 0x14*/
193
- static VALUE eProtocolError; /*LIBCOUCHBASE_PROTOCOL_ERROR = 0x15*/
194
- static VALUE eTimeoutError; /*LIBCOUCHBASE_ETIMEDOUT = 0x16*/
195
- static VALUE eConnectError; /*LIBCOUCHBASE_CONNECT_ERROR = 0x17*/
196
- static VALUE eBucketNotFoundError; /*LIBCOUCHBASE_BUCKET_ENOENT = 0x18*/
197
-
198
- static void
199
- cb_gc_protect(bucket_t *bucket, VALUE val)
200
- {
201
- rb_hash_aset(bucket->object_space, val|1, val);
202
- }
203
-
204
- static void
205
- cb_gc_unprotect(bucket_t *bucket, VALUE val)
206
- {
207
- rb_hash_delete(bucket->object_space, val|1);
208
- }
209
-
210
- static VALUE
211
- cb_proc_call(VALUE recv, int argc, ...)
212
- {
213
- VALUE *argv;
214
- va_list ar;
215
- int arity;
216
- int ii;
217
-
218
- arity = FIX2INT(rb_funcall(recv, id_arity, 0));
219
- if (arity < 0) {
220
- arity = argc;
221
- }
222
- if (arity > 0) {
223
- va_init_list(ar, argc);
224
- argv = ALLOCA_N(VALUE, argc);
225
- for (ii = 0; ii < arity; ++ii) {
226
- if (ii < argc) {
227
- argv[ii] = va_arg(ar, VALUE);
228
- } else {
229
- argv[ii] = Qnil;
230
- }
231
- }
232
- va_end(ar);
233
- } else {
234
- argv = NULL;
235
- }
236
- return rb_funcall2(recv, id_call, arity, argv);
237
- }
238
-
239
- /* Helper to conver return code from libcouchbase to meaningful exception.
240
- * Returns nil if the code considering successful and exception object
241
- * otherwise. Store given string to exceptions as message, and also
242
- * initialize +error+ attribute with given return code. */
243
- static VALUE
244
- cb_check_error(libcouchbase_error_t rc, const char *msg, VALUE key)
245
- {
246
- VALUE klass, exc, str;
247
- char buf[300];
248
-
249
- if (rc == LIBCOUCHBASE_SUCCESS || rc == LIBCOUCHBASE_AUTH_CONTINUE) {
250
- return Qnil;
251
- }
252
- switch (rc) {
253
- case LIBCOUCHBASE_AUTH_ERROR:
254
- klass = eAuthError;
255
- break;
256
- case LIBCOUCHBASE_DELTA_BADVAL:
257
- klass = eDeltaBadvalError;
258
- break;
259
- case LIBCOUCHBASE_E2BIG:
260
- klass = eTooBigError;
261
- break;
262
- case LIBCOUCHBASE_EBUSY:
263
- klass = eBusyError;
264
- break;
265
- case LIBCOUCHBASE_EINTERNAL:
266
- klass = eInternalError;
267
- break;
268
- case LIBCOUCHBASE_EINVAL:
269
- klass = eInvalidError;
270
- break;
271
- case LIBCOUCHBASE_ENOMEM:
272
- klass = eNoMemoryError;
273
- break;
274
- case LIBCOUCHBASE_ERANGE:
275
- klass = eRangeError;
276
- break;
277
- case LIBCOUCHBASE_ETMPFAIL:
278
- klass = eTmpFailError;
279
- break;
280
- case LIBCOUCHBASE_KEY_EEXISTS:
281
- klass = eKeyExistsError;
282
- break;
283
- case LIBCOUCHBASE_KEY_ENOENT:
284
- klass = eNotFoundError;
285
- break;
286
- case LIBCOUCHBASE_LIBEVENT_ERROR:
287
- klass = eLibeventError;
288
- break;
289
- case LIBCOUCHBASE_NETWORK_ERROR:
290
- klass = eNetworkError;
291
- break;
292
- case LIBCOUCHBASE_NOT_MY_VBUCKET:
293
- klass = eNotMyVbucketError;
294
- break;
295
- case LIBCOUCHBASE_NOT_STORED:
296
- klass = eNotStoredError;
297
- break;
298
- case LIBCOUCHBASE_NOT_SUPPORTED:
299
- klass = eNotSupportedError;
300
- break;
301
- case LIBCOUCHBASE_UNKNOWN_COMMAND:
302
- klass = eUnknownCommandError;
303
- break;
304
- case LIBCOUCHBASE_UNKNOWN_HOST:
305
- klass = eUnknownHostError;
306
- break;
307
- case LIBCOUCHBASE_PROTOCOL_ERROR:
308
- klass = eProtocolError;
309
- break;
310
- case LIBCOUCHBASE_ETIMEDOUT:
311
- klass = eTimeoutError;
312
- break;
313
- case LIBCOUCHBASE_CONNECT_ERROR:
314
- klass = eConnectError;
315
- break;
316
- case LIBCOUCHBASE_BUCKET_ENOENT:
317
- klass = eBucketNotFoundError;
318
- break;
319
- case LIBCOUCHBASE_ERROR:
320
- /* fall through */
321
- default:
322
- klass = eLibcouchbaseError;
323
- }
324
-
325
- str = rb_str_buf_new2(msg ? msg : "");
326
- rb_str_buf_cat2(str, " (");
327
- if (key != Qnil) {
328
- snprintf(buf, 300, "key=\"%s\", ", RSTRING_PTR(key));
329
- rb_str_buf_cat2(str, buf);
330
- }
331
- snprintf(buf, 300, "error=0x%02x)", rc);
332
- rb_str_buf_cat2(str, buf);
333
- exc = rb_exc_new3(klass, str);
334
- rb_ivar_set(exc, id_iv_error, INT2FIX(rc));
335
- rb_ivar_set(exc, id_iv_key, key);
336
- rb_ivar_set(exc, id_iv_cas, Qnil);
337
- rb_ivar_set(exc, id_iv_operation, Qnil);
338
- return exc;
339
- }
340
-
341
- static inline uint32_t
342
- flags_set_format(uint32_t flags, ID format)
343
- {
344
- flags &= ~((uint32_t)FMT_MASK); /* clear format bits */
345
-
346
- if (format == sym_document) {
347
- return flags | FMT_DOCUMENT;
348
- } else if (format == sym_marshal) {
349
- return flags | FMT_MARSHAL;
350
- } else if (format == sym_plain) {
351
- return flags | FMT_PLAIN;
352
- }
353
- return flags; /* document is the default */
354
- }
355
-
356
- static inline ID
357
- flags_get_format(uint32_t flags)
358
- {
359
- flags &= FMT_MASK; /* select format bits */
360
-
361
- switch (flags) {
362
- case FMT_DOCUMENT:
363
- return sym_document;
364
- case FMT_MARSHAL:
365
- return sym_marshal;
366
- case FMT_PLAIN:
367
- /* fall through */
368
- default:
369
- /* all other formats treated as plain */
370
- return sym_plain;
371
- }
372
- }
373
-
374
-
375
- static VALUE
376
- do_encode(VALUE *args)
377
- {
378
- VALUE val = args[0];
379
- uint32_t flags = ((uint32_t)args[1] & FMT_MASK);
380
-
381
- switch (flags) {
382
- case FMT_DOCUMENT:
383
- return rb_funcall(mJSON, id_dump, 1, val);
384
- case FMT_MARSHAL:
385
- return rb_funcall(mMarshal, id_dump, 1, val);
386
- case FMT_PLAIN:
387
- /* fall through */
388
- default:
389
- /* all other formats treated as plain */
390
- return val;
391
- }
392
- }
393
-
394
- static VALUE
395
- do_decode(VALUE *args)
396
- {
397
- VALUE blob = args[0];
398
- VALUE force_format = args[2];
399
-
400
- if (TYPE(force_format) == T_SYMBOL) {
401
- if (force_format == sym_document) {
402
- return rb_funcall(mJSON, id_load, 1, blob);
403
- } else if (force_format == sym_marshal) {
404
- return rb_funcall(mMarshal, id_load, 1, blob);
405
- } else { /* sym_plain and any other symbol */
406
- return blob;
407
- }
408
- } else {
409
- uint32_t flags = ((uint32_t)args[1] & FMT_MASK);
410
-
411
- switch (flags) {
412
- case FMT_DOCUMENT:
413
- return rb_funcall(mJSON, id_load, 1, blob);
414
- case FMT_MARSHAL:
415
- return rb_funcall(mMarshal, id_load, 1, blob);
416
- case FMT_PLAIN:
417
- /* fall through */
418
- default:
419
- /* all other formats treated as plain */
420
- return blob;
421
- }
422
- }
423
- }
424
-
425
- static VALUE
426
- coding_failed(void)
427
- {
428
- return Qundef;
429
- }
430
-
431
- static VALUE
432
- encode_value(VALUE val, uint32_t flags)
433
- {
434
- VALUE blob, args[2];
435
-
436
- args[0] = val;
437
- args[1] = (VALUE)flags;
438
- blob = rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
439
- /* it must be bytestring after all */
440
- if (TYPE(blob) != T_STRING) {
441
- return Qundef;
442
- }
443
- return blob;
444
- }
445
-
446
- static VALUE
447
- decode_value(VALUE blob, uint32_t flags, VALUE force_format)
448
- {
449
- VALUE val, args[3];
450
-
451
- /* first it must be bytestring */
452
- if (TYPE(blob) != T_STRING) {
453
- return Qundef;
454
- }
455
- args[0] = blob;
456
- args[1] = (VALUE)flags;
457
- args[2] = (VALUE)force_format;
458
- val = rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
459
- return val;
460
- }
461
-
462
- static VALUE
463
- unify_key(VALUE key)
464
- {
465
- switch (TYPE(key)) {
466
- case T_STRING:
467
- return key;
468
- case T_SYMBOL:
469
- return STR_NEW_CSTR(rb_id2name(SYM2ID(key)));
470
- default: /* call #to_str or raise error */
471
- return StringValue(key);
472
- }
473
- }
474
-
475
- static int
476
- cb_extract_keys_i(VALUE key, VALUE value, VALUE arg)
477
- {
478
- struct key_traits *traits = (struct key_traits *)arg;
479
- key = unify_key(key);
480
- rb_ary_push(traits->keys_ary, key);
481
- traits->keys[traits->nkeys] = RSTRING_PTR(key);
482
- traits->lens[traits->nkeys] = RSTRING_LEN(key);
483
- traits->ttls[traits->nkeys] = NUM2ULONG(value);
484
- traits->nkeys++;
485
- return ST_CONTINUE;
486
- }
487
-
488
- static long
489
- cb_args_scan_keys(long argc, VALUE argv, bucket_t *bucket, struct key_traits *traits)
490
- {
491
- VALUE key, *keys_ptr, opts, ttl, ext;
492
- long nn = 0, ii;
493
- time_t exp;
494
-
495
- traits->keys_ary = rb_ary_new();
496
- traits->quiet = bucket->quiet;
497
- traits->mgat = 0;
498
-
499
- if (argc > 0) {
500
- /* keys with custom options */
501
- opts = RARRAY_PTR(argv)[argc-1];
502
- exp = bucket->default_ttl;
503
- ext = Qfalse;
504
- if (argc > 1 && TYPE(opts) == T_HASH) {
505
- (void)rb_ary_pop(argv);
506
- if (RTEST(rb_funcall(opts, id_has_key_p, 1, sym_quiet))) {
507
- traits->quiet = RTEST(rb_hash_aref(opts, sym_quiet));
508
- }
509
- traits->force_format = rb_hash_aref(opts, sym_format);
510
- if (traits->force_format != Qnil) {
511
- Check_Type(traits->force_format, T_SYMBOL);
512
- }
513
- ext = rb_hash_aref(opts, sym_extended);
514
- ttl = rb_hash_aref(opts, sym_ttl);
515
- if (ttl != Qnil) {
516
- traits->explicit_ttl = 1;
517
- exp = NUM2ULONG(ttl);
518
- }
519
- nn = RARRAY_LEN(argv);
520
- } else {
521
- nn = argc;
522
- }
523
- if (nn < 1) {
524
- rb_raise(rb_eArgError, "must be at least one key");
525
- }
526
- keys_ptr = RARRAY_PTR(argv);
527
- traits->extended = RTEST(ext) ? 1 : 0;
528
- if (nn == 1 && TYPE(keys_ptr[0]) == T_HASH) {
529
- /* hash of key-ttl pairs */
530
- nn = RHASH_SIZE(keys_ptr[0]);
531
- traits->keys = xcalloc(nn, sizeof(char *));
532
- traits->lens = xcalloc(nn, sizeof(size_t));
533
- traits->explicit_ttl = 1;
534
- traits->mgat = 1;
535
- traits->ttls = xcalloc(nn, sizeof(time_t));
536
- rb_hash_foreach(keys_ptr[0], cb_extract_keys_i, (VALUE)traits);
537
- } else {
538
- /* the list of keys */
539
- traits->nkeys = nn;
540
- traits->keys = xcalloc(nn, sizeof(char *));
541
- traits->lens = xcalloc(nn, sizeof(size_t));
542
- traits->ttls = xcalloc(nn, sizeof(time_t));
543
- for (ii = 0; ii < nn; ii++) {
544
- key = unify_key(keys_ptr[ii]);
545
- rb_ary_push(traits->keys_ary, key);
546
- traits->keys[ii] = RSTRING_PTR(key);
547
- traits->lens[ii] = RSTRING_LEN(key);
548
- traits->ttls[ii] = exp;
549
- }
550
- }
551
- }
552
-
553
- return nn;
554
- }
555
-
556
- static void
557
- error_callback(libcouchbase_t handle, libcouchbase_error_t error, const char *errinfo)
558
- {
559
- bucket_t *bucket = (bucket_t *)libcouchbase_get_cookie(handle);
560
-
561
- bucket->io->stop_event_loop(bucket->io);
562
- bucket->exception = cb_check_error(error, errinfo, Qnil);
563
- }
564
-
565
- static void
566
- storage_callback(libcouchbase_t handle, const void *cookie,
567
- libcouchbase_storage_t operation, libcouchbase_error_t error,
568
- const void *key, libcouchbase_size_t nkey, libcouchbase_cas_t cas)
569
- {
570
- context_t *ctx = (context_t *)cookie;
571
- bucket_t *bucket = ctx->bucket;
572
- VALUE k, c, *rv = ctx->rv, exc, res;
573
- ID o;
574
-
575
- bucket->seqno--;
576
-
577
- k = STR_NEW((const char*)key, nkey);
578
- c = cas > 0 ? ULL2NUM(cas) : Qnil;
579
- switch(operation) {
580
- case LIBCOUCHBASE_ADD:
581
- o = sym_add;
582
- break;
583
- case LIBCOUCHBASE_REPLACE:
584
- o = sym_replace;
585
- break;
586
- case LIBCOUCHBASE_SET:
587
- o = sym_set;
588
- break;
589
- case LIBCOUCHBASE_APPEND:
590
- o = sym_append;
591
- break;
592
- case LIBCOUCHBASE_PREPEND:
593
- o = sym_prepend;
594
- break;
595
- default:
596
- o = Qnil;
597
- }
598
- exc = cb_check_error(error, "failed to store value", k);
599
- if (exc != Qnil) {
600
- rb_ivar_set(exc, id_iv_cas, c);
601
- rb_ivar_set(exc, id_iv_operation, o);
602
- if (NIL_P(ctx->exception)) {
603
- ctx->exception = exc;
604
- cb_gc_protect(bucket, ctx->exception);
605
- }
606
- }
607
- if (bucket->async) { /* asynchronous */
608
- if (ctx->proc != Qnil) {
609
- res = rb_class_new_instance(0, NULL, cResult);
610
- rb_ivar_set(res, id_iv_error, exc);
611
- rb_ivar_set(res, id_iv_key, k);
612
- rb_ivar_set(res, id_iv_operation, o);
613
- rb_ivar_set(res, id_iv_cas, c);
614
- cb_proc_call(ctx->proc, 1, res);
615
- }
616
- } else { /* synchronous */
617
- *rv = c;
618
- }
619
-
620
- if (bucket->seqno == 0) {
621
- bucket->io->stop_event_loop(bucket->io);
622
- cb_gc_unprotect(bucket, ctx->proc);
623
- }
624
- (void)handle;
625
- }
626
-
627
- static void
628
- delete_callback(libcouchbase_t handle, const void *cookie,
629
- libcouchbase_error_t error, const void *key,
630
- libcouchbase_size_t nkey)
631
- {
632
- context_t *ctx = (context_t *)cookie;
633
- bucket_t *bucket = ctx->bucket;
634
- VALUE k, *rv = ctx->rv, exc = Qnil, res;
635
-
636
- bucket->seqno--;
637
-
638
- k = STR_NEW((const char*)key, nkey);
639
- if (error != LIBCOUCHBASE_KEY_ENOENT || !ctx->quiet) {
640
- exc = cb_check_error(error, "failed to remove value", k);
641
- if (exc != Qnil) {
642
- rb_ivar_set(exc, id_iv_operation, sym_delete);
643
- if (NIL_P(ctx->exception)) {
644
- ctx->exception = exc;
645
- cb_gc_protect(bucket, ctx->exception);
646
- }
647
- }
648
- }
649
- if (bucket->async) { /* asynchronous */
650
- if (ctx->proc != Qnil) {
651
- res = rb_class_new_instance(0, NULL, cResult);
652
- rb_ivar_set(res, id_iv_error, exc);
653
- rb_ivar_set(res, id_iv_operation, sym_delete);
654
- rb_ivar_set(res, id_iv_key, k);
655
- cb_proc_call(ctx->proc, 1, res);
656
- }
657
- } else { /* synchronous */
658
- *rv = (error == LIBCOUCHBASE_SUCCESS) ? Qtrue : Qfalse;
659
- }
660
- if (bucket->seqno == 0) {
661
- bucket->io->stop_event_loop(bucket->io);
662
- cb_gc_unprotect(bucket, ctx->proc);
663
- }
664
- (void)handle;
665
- }
666
-
667
- static void
668
- get_callback(libcouchbase_t handle, const void *cookie,
669
- libcouchbase_error_t error, const void *key,
670
- libcouchbase_size_t nkey, const void *bytes,
671
- libcouchbase_size_t nbytes, libcouchbase_uint32_t flags,
672
- libcouchbase_cas_t cas)
673
- {
674
- context_t *ctx = (context_t *)cookie;
675
- bucket_t *bucket = ctx->bucket;
676
- VALUE k, v, f, c, *rv = ctx->rv, exc = Qnil, res;
677
-
678
- bucket->seqno--;
679
-
680
- k = STR_NEW((const char*)key, nkey);
681
- if (error != LIBCOUCHBASE_KEY_ENOENT || !ctx->quiet) {
682
- exc = cb_check_error(error, "failed to get value", k);
683
- if (exc != Qnil) {
684
- rb_ivar_set(exc, id_iv_operation, sym_get);
685
- if (NIL_P(ctx->exception)) {
686
- ctx->exception = exc;
687
- cb_gc_protect(bucket, ctx->exception);
688
- }
689
- }
690
- }
691
-
692
- f = ULONG2NUM(flags);
693
- c = ULL2NUM(cas);
694
- v = Qnil;
695
- if (nbytes != 0) {
696
- v = decode_value(STR_NEW((const char*)bytes, nbytes), flags, ctx->force_format);
697
- if (v == Qundef) {
698
- if (ctx->exception != Qnil) {
699
- cb_gc_unprotect(bucket, ctx->exception);
700
- }
701
- ctx->exception = rb_exc_new2(eValueFormatError, "unable to convert value");
702
- rb_ivar_set(ctx->exception, id_iv_operation, sym_get);
703
- rb_ivar_set(ctx->exception, id_iv_key, k);
704
- cb_gc_protect(bucket, ctx->exception);
705
- }
706
- } else if (flags_get_format(flags) == sym_plain) {
707
- v = STR_NEW_CSTR("");
708
- }
709
- if (bucket->async) { /* asynchronous */
710
- if (ctx->proc != Qnil) {
711
- res = rb_class_new_instance(0, NULL, cResult);
712
- rb_ivar_set(res, id_iv_error, exc);
713
- rb_ivar_set(res, id_iv_operation, sym_get);
714
- rb_ivar_set(res, id_iv_key, k);
715
- rb_ivar_set(res, id_iv_value, v);
716
- rb_ivar_set(res, id_iv_flags, f);
717
- rb_ivar_set(res, id_iv_cas, c);
718
- cb_proc_call(ctx->proc, 1, res);
719
- }
720
- } else { /* synchronous */
721
- if (NIL_P(exc) && error != LIBCOUCHBASE_KEY_ENOENT) {
722
- if (ctx->extended) {
723
- rb_hash_aset(*rv, k, rb_ary_new3(3, v, f, c));
724
- } else {
725
- rb_hash_aset(*rv, k, v);
726
- }
727
- }
728
- }
729
-
730
- if (bucket->seqno == 0) {
731
- bucket->io->stop_event_loop(bucket->io);
732
- cb_gc_unprotect(bucket, ctx->proc);
733
- }
734
- (void)handle;
735
- }
736
-
737
- static void
738
- flush_callback(libcouchbase_t handle, const void* cookie,
739
- const char* authority, libcouchbase_error_t error)
740
- {
741
- context_t *ctx = (context_t *)cookie;
742
- bucket_t *bucket = ctx->bucket;
743
- VALUE node, success = Qtrue, *rv = ctx->rv, exc, res;
744
-
745
- node = authority ? STR_NEW_CSTR(authority) : Qnil;
746
- exc = cb_check_error(error, "failed to flush bucket", node);
747
- if (exc != Qnil) {
748
- rb_ivar_set(exc, id_iv_operation, sym_flush);
749
- if (NIL_P(ctx->exception)) {
750
- ctx->exception = exc;
751
- cb_gc_protect(bucket, ctx->exception);
752
- }
753
- success = Qfalse;
754
- }
755
-
756
- if (authority) {
757
- if (bucket->async) { /* asynchronous */
758
- if (ctx->proc != Qnil) {
759
- res = rb_class_new_instance(0, NULL, cResult);
760
- rb_ivar_set(res, id_iv_error, exc);
761
- rb_ivar_set(res, id_iv_operation, sym_flush);
762
- rb_ivar_set(res, id_iv_node, node);
763
- cb_proc_call(ctx->proc, 1, res);
764
- }
765
- } else { /* synchronous */
766
- if (RTEST(*rv)) {
767
- /* rewrite status for positive values only */
768
- *rv = success;
769
- }
770
- }
771
- } else {
772
- bucket->seqno--;
773
- if (bucket->seqno == 0) {
774
- bucket->io->stop_event_loop(bucket->io);
775
- cb_gc_unprotect(bucket, ctx->proc);
776
- }
777
- }
778
-
779
- (void)handle;
780
- }
781
-
782
- static void
783
- version_callback(libcouchbase_t handle, const void *cookie,
784
- const char *authority, libcouchbase_error_t error,
785
- const char *bytes, libcouchbase_size_t nbytes)
786
- {
787
- context_t *ctx = (context_t *)cookie;
788
- bucket_t *bucket = ctx->bucket;
789
- VALUE node, v, *rv = ctx->rv, exc, res;
790
-
791
- node = authority ? STR_NEW_CSTR(authority) : Qnil;
792
- exc = cb_check_error(error, "failed to get version", node);
793
- if (exc != Qnil) {
794
- rb_ivar_set(exc, id_iv_operation, sym_flush);
795
- if (NIL_P(ctx->exception)) {
796
- ctx->exception = exc;
797
- cb_gc_protect(bucket, ctx->exception);
798
- }
799
- }
800
-
801
- if (authority) {
802
- v = STR_NEW((const char*)bytes, nbytes);
803
- if (bucket->async) { /* asynchronous */
804
- if (ctx->proc != Qnil) {
805
- res = rb_class_new_instance(0, NULL, cResult);
806
- rb_ivar_set(res, id_iv_error, exc);
807
- rb_ivar_set(res, id_iv_operation, sym_version);
808
- rb_ivar_set(res, id_iv_node, node);
809
- rb_ivar_set(res, id_iv_value, v);
810
- cb_proc_call(ctx->proc, 1, res);
811
- }
812
- } else { /* synchronous */
813
- if (NIL_P(exc)) {
814
- rb_hash_aset(*rv, node, v);
815
- }
816
- }
817
- } else {
818
- bucket->seqno--;
819
- if (bucket->seqno == 0) {
820
- bucket->io->stop_event_loop(bucket->io);
821
- cb_gc_unprotect(bucket, ctx->proc);
822
- }
823
- }
824
-
825
- (void)handle;
826
- }
827
-
828
- static void
829
- stat_callback(libcouchbase_t handle, const void* cookie,
830
- const char* authority, libcouchbase_error_t error, const void* key,
831
- libcouchbase_size_t nkey, const void* bytes,
832
- libcouchbase_size_t nbytes)
833
- {
834
- context_t *ctx = (context_t *)cookie;
835
- bucket_t *bucket = ctx->bucket;
836
- VALUE stats, node, k, v, *rv = ctx->rv, exc = Qnil, res;
837
-
838
- node = authority ? STR_NEW_CSTR(authority) : Qnil;
839
- exc = cb_check_error(error, "failed to fetch stats", node);
840
- if (exc != Qnil) {
841
- rb_ivar_set(exc, id_iv_operation, sym_stats);
842
- if (NIL_P(ctx->exception)) {
843
- ctx->exception = exc;
844
- cb_gc_protect(bucket, ctx->exception);
845
- }
846
- }
847
- if (authority) {
848
- k = STR_NEW((const char*)key, nkey);
849
- v = STR_NEW((const char*)bytes, nbytes);
850
- if (bucket->async) { /* asynchronous */
851
- if (ctx->proc != Qnil) {
852
- res = rb_class_new_instance(0, NULL, cResult);
853
- rb_ivar_set(res, id_iv_error, exc);
854
- rb_ivar_set(res, id_iv_operation, sym_stats);
855
- rb_ivar_set(res, id_iv_node, node);
856
- rb_ivar_set(res, id_iv_key, k);
857
- rb_ivar_set(res, id_iv_value, v);
858
- cb_proc_call(ctx->proc, 1, res);
859
- }
860
- } else { /* synchronous */
861
- if (NIL_P(exc)) {
862
- stats = rb_hash_aref(*rv, k);
863
- if (NIL_P(stats)) {
864
- stats = rb_hash_new();
865
- rb_hash_aset(*rv, k, stats);
866
- }
867
- rb_hash_aset(stats, node, v);
868
- }
869
- }
870
- } else {
871
- bucket->seqno--;
872
- if (bucket->seqno == 0) {
873
- bucket->io->stop_event_loop(bucket->io);
874
- cb_gc_unprotect(bucket, ctx->proc);
875
- }
876
- }
877
- (void)handle;
878
- }
879
-
880
- static void
881
- touch_callback(libcouchbase_t handle, const void *cookie,
882
- libcouchbase_error_t error, const void *key,
883
- libcouchbase_size_t nkey)
884
- {
885
- context_t *ctx = (context_t *)cookie;
886
- bucket_t *bucket = ctx->bucket;
887
- VALUE k, success, *rv = ctx->rv, exc = Qnil, res;
888
-
889
- bucket->seqno--;
890
- k = STR_NEW((const char*)key, nkey);
891
- if (error != LIBCOUCHBASE_KEY_ENOENT || !ctx->quiet) {
892
- exc = cb_check_error(error, "failed to touch value", k);
893
- if (exc != Qnil) {
894
- rb_ivar_set(exc, id_iv_operation, sym_touch);
895
- if (NIL_P(ctx->exception)) {
896
- ctx->exception = exc;
897
- cb_gc_protect(bucket, ctx->exception);
898
- }
899
- }
900
- }
901
-
902
- if (bucket->async) { /* asynchronous */
903
- if (ctx->proc != Qnil) {
904
- res = rb_class_new_instance(0, NULL, cResult);
905
- rb_ivar_set(res, id_iv_error, exc);
906
- rb_ivar_set(res, id_iv_operation, sym_touch);
907
- rb_ivar_set(res, id_iv_key, k);
908
- cb_proc_call(ctx->proc, 1, res);
909
- }
910
- } else { /* synchronous */
911
- if (NIL_P(exc)) {
912
- success = (error == LIBCOUCHBASE_KEY_ENOENT) ? Qfalse : Qtrue;
913
- rb_hash_aset(*rv, k, success);
914
- }
915
- }
916
- if (bucket->seqno == 0) {
917
- bucket->io->stop_event_loop(bucket->io);
918
- cb_gc_unprotect(bucket, ctx->proc);
919
- }
920
- (void)handle;
921
- }
922
-
923
- static void
924
- arithmetic_callback(libcouchbase_t handle, const void *cookie,
925
- libcouchbase_error_t error, const void *key,
926
- libcouchbase_size_t nkey, libcouchbase_uint64_t value,
927
- libcouchbase_cas_t cas)
928
- {
929
- context_t *ctx = (context_t *)cookie;
930
- bucket_t *bucket = ctx->bucket;
931
- VALUE c, k, v, *rv = ctx->rv, exc, res;
932
- ID o;
933
-
934
- bucket->seqno--;
935
-
936
- k = STR_NEW((const char*)key, nkey);
937
- c = cas > 0 ? ULL2NUM(cas) : Qnil;
938
- o = ctx->arithm > 0 ? sym_increment : sym_decrement;
939
- exc = cb_check_error(error, "failed to perform arithmetic operation", k);
940
- if (exc != Qnil) {
941
- rb_ivar_set(exc, id_iv_cas, c);
942
- rb_ivar_set(exc, id_iv_operation, o);
943
- if (bucket->async) {
944
- if (bucket->on_error_proc != Qnil) {
945
- cb_proc_call(bucket->on_error_proc, 3, o, k, exc);
946
- } else {
947
- if (NIL_P(bucket->exception)) {
948
- bucket->exception = exc;
949
- }
950
- }
951
- }
952
- if (NIL_P(ctx->exception)) {
953
- ctx->exception = exc;
954
- cb_gc_protect(bucket, ctx->exception);
955
- }
956
- }
957
- v = ULL2NUM(value);
958
- if (bucket->async) { /* asynchronous */
959
- if (ctx->proc != Qnil) {
960
- res = rb_class_new_instance(0, NULL, cResult);
961
- rb_ivar_set(res, id_iv_error, exc);
962
- rb_ivar_set(res, id_iv_operation, o);
963
- rb_ivar_set(res, id_iv_key, k);
964
- rb_ivar_set(res, id_iv_value, v);
965
- rb_ivar_set(res, id_iv_cas, c);
966
- cb_proc_call(ctx->proc, 1, res);
967
- }
968
- } else { /* synchronous */
969
- if (NIL_P(exc)) {
970
- if (ctx->extended) {
971
- *rv = rb_ary_new3(2, v, c);
972
- } else {
973
- *rv = v;
974
- }
975
- }
976
- }
977
- if (bucket->seqno == 0) {
978
- bucket->io->stop_event_loop(bucket->io);
979
- cb_gc_unprotect(bucket, ctx->proc);
980
- }
981
- (void)handle;
982
- }
983
-
984
- static int
985
- cb_first_value_i(VALUE key, VALUE value, VALUE arg)
986
- {
987
- VALUE *val = (VALUE *)arg;
988
-
989
- *val = value;
990
- (void)key;
991
- return ST_STOP;
992
- }
993
-
994
- /*
995
- * @private
996
- * @return [Fixnum] number of scheduled operations
997
- */
998
- static VALUE
999
- cb_bucket_seqno(VALUE self)
1000
- {
1001
- bucket_t *bucket = DATA_PTR(self);
1002
-
1003
- return LONG2FIX(bucket->seqno);
1004
- }
1005
-
1006
- void
1007
- cb_bucket_free(void *ptr)
1008
- {
1009
- bucket_t *bucket = ptr;
1010
-
1011
- if (bucket) {
1012
- if (bucket->handle) {
1013
- libcouchbase_destroy(bucket->handle);
1014
- }
1015
- xfree(bucket->authority);
1016
- xfree(bucket->hostname);
1017
- xfree(bucket->pool);
1018
- xfree(bucket->bucket);
1019
- xfree(bucket->username);
1020
- xfree(bucket->password);
1021
- xfree(bucket);
1022
- }
1023
- }
1024
-
1025
- void
1026
- cb_bucket_mark(void *ptr)
1027
- {
1028
- bucket_t *bucket = ptr;
1029
-
1030
- if (bucket) {
1031
- rb_gc_mark(bucket->exception);
1032
- rb_gc_mark(bucket->on_error_proc);
1033
- rb_gc_mark(bucket->object_space);
1034
- }
1035
- }
1036
-
1037
- static void
1038
- do_scan_connection_options(bucket_t *bucket, int argc, VALUE *argv)
1039
- {
1040
- VALUE uri, opts, arg;
1041
- size_t len;
1042
-
1043
- if (rb_scan_args(argc, argv, "02", &uri, &opts) > 0) {
1044
- if (TYPE(uri) == T_HASH && argc == 1) {
1045
- opts = uri;
1046
- uri = Qnil;
1047
- }
1048
- if (uri != Qnil) {
1049
- const char path_re[] = "^(/pools/([A-Za-z0-9_.-]+)(/buckets/([A-Za-z0-9_.-]+))?)?";
1050
- VALUE match, uri_obj, re;
1051
-
1052
- Check_Type(uri, T_STRING);
1053
- uri_obj = rb_funcall(mURI, id_parse, 1, uri);
1054
-
1055
- arg = rb_funcall(uri_obj, id_scheme, 0);
1056
- if (arg == Qnil || rb_str_cmp(arg, STR_NEW_CSTR("http"))) {
1057
- rb_raise(rb_eArgError, "invalid URI: invalid scheme");
1058
- }
1059
-
1060
- arg = rb_funcall(uri_obj, id_user, 0);
1061
- if (arg != Qnil) {
1062
- xfree(bucket->username);
1063
- bucket->username = strdup(RSTRING_PTR(arg));
1064
- if (bucket->username == NULL) {
1065
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1066
- }
1067
- }
1068
-
1069
- arg = rb_funcall(uri_obj, id_password, 0);
1070
- if (arg != Qnil) {
1071
- xfree(bucket->password);
1072
- bucket->password = strdup(RSTRING_PTR(arg));
1073
- if (bucket->password == NULL) {
1074
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1075
- }
1076
- }
1077
- arg = rb_funcall(uri_obj, id_host, 0);
1078
- if (arg != Qnil) {
1079
- xfree(bucket->hostname);
1080
- bucket->hostname = strdup(RSTRING_PTR(arg));
1081
- if (bucket->hostname == NULL) {
1082
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1083
- }
1084
- } else {
1085
- rb_raise(rb_eArgError, "invalid URI: missing hostname");
1086
- }
1087
-
1088
- arg = rb_funcall(uri_obj, id_port, 0);
1089
- bucket->port = NIL_P(arg) ? 8091 : (uint16_t)NUM2UINT(arg);
1090
-
1091
- arg = rb_funcall(uri_obj, id_path, 0);
1092
- re = rb_reg_new(path_re, sizeof(path_re) - 1, 0);
1093
- match = rb_funcall(re, id_match, 1, arg);
1094
- arg = rb_reg_nth_match(2, match);
1095
- xfree(bucket->pool);
1096
- bucket->pool = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
1097
- arg = rb_reg_nth_match(4, match);
1098
- xfree(bucket->bucket);
1099
- bucket->bucket = strdup(NIL_P(arg) ? "default" : RSTRING_PTR(arg));
1100
- }
1101
- if (TYPE(opts) == T_HASH) {
1102
- arg = rb_hash_aref(opts, sym_node_list);
1103
- if (arg != Qnil) {
1104
- VALUE tt;
1105
- free(bucket->node_list);
1106
- Check_Type(arg, T_ARRAY);
1107
- tt = rb_ary_join(arg, rb_str_new2(";"));
1108
- bucket->node_list = strdup(StringValueCStr(tt));
1109
- }
1110
- arg = rb_hash_aref(opts, sym_hostname);
1111
- if (arg != Qnil) {
1112
- if (bucket->hostname) {
1113
- xfree(bucket->hostname);
1114
- }
1115
- bucket->hostname = strdup(StringValueCStr(arg));
1116
- }
1117
- arg = rb_hash_aref(opts, sym_pool);
1118
- if (arg != Qnil) {
1119
- if (bucket->pool) {
1120
- xfree(bucket->pool);
1121
- }
1122
- bucket->pool = strdup(StringValueCStr(arg));
1123
- }
1124
- arg = rb_hash_aref(opts, sym_bucket);
1125
- if (arg != Qnil) {
1126
- if (bucket->bucket) {
1127
- xfree(bucket->bucket);
1128
- }
1129
- bucket->bucket = strdup(StringValueCStr(arg));
1130
- }
1131
- arg = rb_hash_aref(opts, sym_username);
1132
- if (arg != Qnil) {
1133
- if (bucket->username) {
1134
- xfree(bucket->username);
1135
- }
1136
- bucket->username = strdup(StringValueCStr(arg));
1137
- }
1138
- arg = rb_hash_aref(opts, sym_password);
1139
- if (arg != Qnil) {
1140
- if (bucket->password) {
1141
- xfree(bucket->password);
1142
- }
1143
- bucket->password = strdup(StringValueCStr(arg));
1144
- }
1145
- arg = rb_hash_aref(opts, sym_port);
1146
- if (arg != Qnil) {
1147
- bucket->port = (uint16_t)NUM2UINT(arg);
1148
- }
1149
- if (RTEST(rb_funcall(opts, id_has_key_p, 1, sym_quiet))) {
1150
- bucket->quiet = RTEST(rb_hash_aref(opts, sym_quiet));
1151
- }
1152
- arg = rb_hash_aref(opts, sym_timeout);
1153
- if (arg != Qnil) {
1154
- bucket->timeout = (uint32_t)NUM2ULONG(arg);
1155
- }
1156
- arg = rb_hash_aref(opts, sym_default_ttl);
1157
- if (arg != Qnil) {
1158
- bucket->default_ttl = (uint32_t)NUM2ULONG(arg);
1159
- }
1160
- arg = rb_hash_aref(opts, sym_default_flags);
1161
- if (arg != Qnil) {
1162
- bucket->default_flags = (uint32_t)NUM2ULONG(arg);
1163
- }
1164
- arg = rb_hash_aref(opts, sym_default_format);
1165
- if (arg != Qnil) {
1166
- if (TYPE(arg) == T_FIXNUM) {
1167
- switch (FIX2INT(arg)) {
1168
- case FMT_DOCUMENT:
1169
- arg = sym_document;
1170
- break;
1171
- case FMT_MARSHAL:
1172
- arg = sym_marshal;
1173
- break;
1174
- case FMT_PLAIN:
1175
- arg = sym_plain;
1176
- break;
1177
- }
1178
- }
1179
- if (arg == sym_document || arg == sym_marshal || arg == sym_plain) {
1180
- bucket->default_format = arg;
1181
- bucket->default_flags = flags_set_format(bucket->default_flags, arg);
1182
- }
1183
- }
1184
- } else {
1185
- opts = Qnil;
1186
- }
1187
- }
1188
- len = strlen(bucket->hostname) + 10;
1189
- if (bucket->authority) {
1190
- xfree(bucket->authority);
1191
- }
1192
- bucket->authority = xcalloc(len, sizeof(char));
1193
- if (bucket->authority == NULL) {
1194
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1195
- }
1196
- snprintf(bucket->authority, len, "%s:%u", bucket->hostname, bucket->port);
1197
- }
1198
-
1199
- static void
1200
- do_connect(bucket_t *bucket)
1201
- {
1202
- libcouchbase_error_t err;
1203
-
1204
- if (bucket->handle) {
1205
- libcouchbase_destroy(bucket->handle);
1206
- bucket->handle = NULL;
1207
- bucket->io = NULL;
1208
- }
1209
- bucket->io = libcouchbase_create_io_ops(LIBCOUCHBASE_IO_OPS_DEFAULT, NULL, &err);
1210
- if (bucket->io == NULL && err != LIBCOUCHBASE_SUCCESS) {
1211
- rb_exc_raise(cb_check_error(err, "failed to create IO instance", Qnil));
1212
- }
1213
- bucket->handle = libcouchbase_create(bucket->node_list ? bucket-> node_list : bucket->authority,
1214
- bucket->username, bucket->password, bucket->bucket, bucket->io);
1215
- if (bucket->handle == NULL) {
1216
- rb_raise(eLibcouchbaseError, "failed to create libcouchbase instance");
1217
- }
1218
- libcouchbase_set_cookie(bucket->handle, bucket);
1219
- (void)libcouchbase_set_error_callback(bucket->handle, error_callback);
1220
- (void)libcouchbase_set_storage_callback(bucket->handle, storage_callback);
1221
- (void)libcouchbase_set_get_callback(bucket->handle, get_callback);
1222
- (void)libcouchbase_set_touch_callback(bucket->handle, touch_callback);
1223
- (void)libcouchbase_set_remove_callback(bucket->handle, delete_callback);
1224
- (void)libcouchbase_set_stat_callback(bucket->handle, stat_callback);
1225
- (void)libcouchbase_set_flush_callback(bucket->handle, flush_callback);
1226
- (void)libcouchbase_set_arithmetic_callback(bucket->handle, arithmetic_callback);
1227
- (void)libcouchbase_set_version_callback(bucket->handle, version_callback);
1228
-
1229
- err = libcouchbase_connect(bucket->handle);
1230
- if (err != LIBCOUCHBASE_SUCCESS) {
1231
- libcouchbase_destroy(bucket->handle);
1232
- bucket->handle = NULL;
1233
- bucket->io = NULL;
1234
- rb_exc_raise(cb_check_error(err, "failed to connect libcouchbase instance to server", Qnil));
1235
- }
1236
- bucket->exception = Qnil;
1237
- libcouchbase_wait(bucket->handle);
1238
- if (bucket->exception != Qnil) {
1239
- libcouchbase_destroy(bucket->handle);
1240
- bucket->handle = NULL;
1241
- bucket->io = NULL;
1242
- rb_exc_raise(bucket->exception);
1243
- }
1244
-
1245
- if (bucket->timeout > 0) {
1246
- libcouchbase_set_timeout(bucket->handle, bucket->timeout);
1247
- } else {
1248
- bucket->timeout = libcouchbase_get_timeout(bucket->handle);
1249
- }
1250
- }
1251
-
1252
- static VALUE
1253
- cb_bucket_alloc(VALUE klass)
1254
- {
1255
- VALUE obj;
1256
- bucket_t *bucket;
1257
-
1258
- /* allocate new bucket struct and set it to zero */
1259
- obj = Data_Make_Struct(klass, bucket_t, cb_bucket_mark, cb_bucket_free,
1260
- bucket);
1261
- return obj;
1262
- }
1263
-
1264
- /*
1265
- * Initialize new Bucket.
1266
- *
1267
- * @overload initialize(url, options = {})
1268
- * Initialize bucket using URI of the cluster and options. It is possible
1269
- * to override some parts of URI using the options keys (e.g. :host or
1270
- * :port)
1271
- *
1272
- * @param [String] url The full URL of management API of the cluster.
1273
- * @param [Hash] options The options for connection. See options definition
1274
- * below.
1275
- *
1276
- * @overload initialize(options = {})
1277
- * Initialize bucket using options only.
1278
- *
1279
- * @param [Hash] options The options for operation for connection
1280
- * @option options [Array] :node_list (nil) the list of nodes to connect
1281
- * to. If specified it takes precedence over +:host+ option. The list
1282
- * must be array of strings in form of host names or host names with
1283
- * ports (in first case port 8091 will be used, see examples).
1284
- * @option options [String] :host ("localhost") the hostname or IP address
1285
- * of the node
1286
- * @option options [Fixnum] :port (8091) the port of the managemenent API
1287
- * @option options [String] :pool ("default") the pool name
1288
- * @option options [String] :bucket ("default") the bucket name
1289
- * @option options [Fixnum] :default_ttl (0) the TTL used by default during
1290
- * storing key-value pairs.
1291
- * @option options [Fixnum] :default_flags (0) the default flags.
1292
- * @option options [Symbol] :default_format (:document) the format, which
1293
- * will be used for values by default. Note that changing format will
1294
- * amend flags. (see {Bucket#default_format})
1295
- * @option options [String] :username (nil) the user name to connect to the
1296
- * cluster. Used to authenticate on management API.
1297
- * @option options [String] :password (nil) the password of the user.
1298
- * @option options [Boolean] :quiet (true) the flag controlling if raising
1299
- * exception when the client executes operations on unexising keys. If it
1300
- * is +true+ it will raise {Couchbase::Error::NotFound} exceptions. The
1301
- * default behaviour is to return +nil+ value silently (might be useful in
1302
- * Rails cache).
1303
- *
1304
- * @example Initialize connection using default options
1305
- * Couchbase.new
1306
- *
1307
- * @example Select custom bucket
1308
- * Couchbase.new(:bucket => 'foo')
1309
- * Couchbase.new('http://localhost:8091/pools/default/buckets/foo')
1310
- *
1311
- * @example Connect to protected bucket
1312
- * Couchbase.new(:bucket => 'protected', :username => 'protected', :password => 'secret')
1313
- * Couchbase.new('http://localhost:8091/pools/default/buckets/protected',
1314
- * :username => 'protected', :password => 'secret')
1315
- *
1316
- * @example Use list of nodes, in case some nodes might be dead
1317
- * Couchbase.new(:node_list => ['example.com:8091', 'example.org:8091', 'example.net'])
1318
- *
1319
- * @return [Bucket]
1320
- */
1321
- static VALUE
1322
- cb_bucket_init(int argc, VALUE *argv, VALUE self)
1323
- {
1324
- bucket_t *bucket = DATA_PTR(self);
1325
-
1326
- bucket->exception = Qnil;
1327
- bucket->hostname = strdup("localhost");
1328
- bucket->port = 8091;
1329
- bucket->pool = strdup("default");
1330
- bucket->bucket = strdup("default");
1331
- bucket->async = 0;
1332
- bucket->quiet = 1;
1333
- bucket->default_ttl = 0;
1334
- bucket->default_flags = 0;
1335
- bucket->default_format = sym_document;
1336
- bucket->on_error_proc = Qnil;
1337
- bucket->timeout = 0;
1338
- bucket->object_space = rb_hash_new();
1339
- bucket->node_list = NULL;
1340
-
1341
- do_scan_connection_options(bucket, argc, argv);
1342
- do_connect(bucket);
1343
-
1344
- return self;
1345
- }
1346
-
1347
- /*
1348
- * Initialize copy
1349
- *
1350
- * Initializes copy of the object, used by {Couchbase::Bucket#dup}
1351
- *
1352
- * @param orig [Couchbase::Bucket] the source for copy
1353
- *
1354
- * @return [Couchbase::Bucket]
1355
- */
1356
- static VALUE
1357
- cb_bucket_init_copy(VALUE copy, VALUE orig)
1358
- {
1359
- bucket_t *copy_b;
1360
- bucket_t *orig_b;
1361
-
1362
- if (copy == orig)
1363
- return copy;
1364
-
1365
- if (TYPE(orig) != T_DATA || TYPE(copy) != T_DATA ||
1366
- RDATA(orig)->dfree != (RUBY_DATA_FUNC)cb_bucket_free) {
1367
- rb_raise(rb_eTypeError, "wrong argument type");
1368
- }
1369
-
1370
- copy_b = DATA_PTR(copy);
1371
- orig_b = DATA_PTR(orig);
1372
-
1373
- copy_b->port = orig_b->port;
1374
- copy_b->authority = strdup(orig_b->authority);
1375
- copy_b->hostname = strdup(orig_b->hostname);
1376
- copy_b->pool = strdup(orig_b->pool);
1377
- copy_b->bucket = strdup(orig_b->bucket);
1378
- if (orig_b->username) {
1379
- copy_b->username = strdup(orig_b->username);
1380
- }
1381
- if (orig_b->password) {
1382
- copy_b->password = strdup(orig_b->password);
1383
- }
1384
- copy_b->async = orig_b->async;
1385
- copy_b->quiet = orig_b->quiet;
1386
- copy_b->seqno = orig_b->seqno;
1387
- copy_b->default_format = orig_b->default_format;
1388
- copy_b->default_flags = orig_b->default_flags;
1389
- copy_b->default_ttl = orig_b->default_ttl;
1390
- copy_b->timeout = orig_b->timeout;
1391
- copy_b->exception = Qnil;
1392
- if (orig_b->on_error_proc != Qnil) {
1393
- copy_b->on_error_proc = rb_funcall(orig_b->on_error_proc, id_dup, 0);
1394
- }
1395
-
1396
- do_connect(copy_b);
1397
-
1398
- return copy;
1399
- }
1400
-
1401
- /*
1402
- * Reconnect the bucket
1403
- *
1404
- * Reconnect the bucket using initial configuration with optional
1405
- * redefinition.
1406
- *
1407
- * @overload reconnect(url, options = {})
1408
- * see {Bucket#initialize Bucket#initialize(url, options)}
1409
- *
1410
- * @overload reconnect(options = {})
1411
- * see {Bucket#initialize Bucket#initialize(options)}
1412
- *
1413
- * @example reconnect with current parameters
1414
- * c.reconnect
1415
- *
1416
- * @example reconnect the instance to another bucket
1417
- * c.reconnect(:bucket => 'new')
1418
- */
1419
- static VALUE
1420
- cb_bucket_reconnect(int argc, VALUE *argv, VALUE self)
1421
- {
1422
- bucket_t *bucket = DATA_PTR(self);
1423
-
1424
- do_scan_connection_options(bucket, argc, argv);
1425
- do_connect(bucket);
1426
-
1427
- return self;
1428
- }
1429
-
1430
- /* Document-method: connected?
1431
- * Check whether the instance connected to the cluster.
1432
- *
1433
- * @return [Boolean] +true+ if the instance connected to the cluster
1434
- */
1435
- static VALUE
1436
- cb_bucket_connected_p(VALUE self)
1437
- {
1438
- bucket_t *bucket = DATA_PTR(self);
1439
- return bucket->handle ? Qtrue : Qfalse;
1440
- }
1441
-
1442
- /* Document-method: async?
1443
- * Check whether the connection asynchronous.
1444
- *
1445
- * By default all operations are synchronous and block waiting for
1446
- * results, but you can make them asynchronous and run event loop
1447
- * explicitly. (see {Bucket#run})
1448
- *
1449
- * @example Return value of #get operation depending on async flag
1450
- * connection = Connection.new
1451
- * connection.async? #=> false
1452
- *
1453
- * connection.run do |conn|
1454
- * conn.async? #=> true
1455
- * end
1456
- *
1457
- * @return [Boolean] +true+ if the connection if asynchronous
1458
- *
1459
- * @see Bucket#run
1460
- */
1461
- static VALUE
1462
- cb_bucket_async_p(VALUE self)
1463
- {
1464
- bucket_t *bucket = DATA_PTR(self);
1465
- return bucket->async ? Qtrue : Qfalse;
1466
- }
1467
-
1468
- static VALUE
1469
- cb_bucket_quiet_get(VALUE self)
1470
- {
1471
- bucket_t *bucket = DATA_PTR(self);
1472
- return bucket->quiet ? Qtrue : Qfalse;
1473
- }
1474
-
1475
- static VALUE
1476
- cb_bucket_quiet_set(VALUE self, VALUE val)
1477
- {
1478
- bucket_t *bucket = DATA_PTR(self);
1479
- VALUE new;
1480
-
1481
- bucket->quiet = RTEST(val);
1482
- new = bucket->quiet ? Qtrue : Qfalse;
1483
- return new;
1484
- }
1485
-
1486
- static VALUE
1487
- cb_bucket_default_flags_get(VALUE self)
1488
- {
1489
- bucket_t *bucket = DATA_PTR(self);
1490
- return ULONG2NUM(bucket->default_flags);
1491
- }
1492
-
1493
- static VALUE
1494
- cb_bucket_default_flags_set(VALUE self, VALUE val)
1495
- {
1496
- bucket_t *bucket = DATA_PTR(self);
1497
-
1498
- bucket->default_flags = (uint32_t)NUM2ULONG(val);
1499
- bucket->default_format = flags_get_format(bucket->default_flags);
1500
- return val;
1501
- }
1502
-
1503
- static VALUE
1504
- cb_bucket_default_format_get(VALUE self)
1505
- {
1506
- bucket_t *bucket = DATA_PTR(self);
1507
- return bucket->default_format;
1508
- }
1509
-
1510
- static VALUE
1511
- cb_bucket_default_format_set(VALUE self, VALUE val)
1512
- {
1513
- bucket_t *bucket = DATA_PTR(self);
1514
-
1515
- if (TYPE(val) == T_FIXNUM) {
1516
- switch (FIX2INT(val)) {
1517
- case FMT_DOCUMENT:
1518
- val = sym_document;
1519
- break;
1520
- case FMT_MARSHAL:
1521
- val = sym_marshal;
1522
- break;
1523
- case FMT_PLAIN:
1524
- val = sym_plain;
1525
- break;
1526
- }
1527
- }
1528
- if (val == sym_document || val == sym_marshal || val == sym_plain) {
1529
- bucket->default_format = val;
1530
- bucket->default_flags = flags_set_format(bucket->default_flags, val);
1531
- }
1532
-
1533
- return val;
1534
- }
1535
-
1536
- static VALUE
1537
- cb_bucket_on_error_set(VALUE self, VALUE val)
1538
- {
1539
- bucket_t *bucket = DATA_PTR(self);
1540
-
1541
- if (rb_respond_to(val, id_call)) {
1542
- bucket->on_error_proc = val;
1543
- } else {
1544
- bucket->on_error_proc = Qnil;
1545
- }
1546
-
1547
- return bucket->on_error_proc;
1548
- }
1549
-
1550
- static VALUE
1551
- cb_bucket_on_error_get(VALUE self)
1552
- {
1553
- bucket_t *bucket = DATA_PTR(self);
1554
-
1555
- if (rb_block_given_p()) {
1556
- return cb_bucket_on_error_set(self, rb_block_proc());
1557
- } else {
1558
- return bucket->on_error_proc;
1559
- }
1560
- }
1561
-
1562
- static VALUE
1563
- cb_bucket_timeout_get(VALUE self)
1564
- {
1565
- bucket_t *bucket = DATA_PTR(self);
1566
- return ULONG2NUM(bucket->timeout);
1567
- }
1568
-
1569
- static VALUE
1570
- cb_bucket_timeout_set(VALUE self, VALUE val)
1571
- {
1572
- bucket_t *bucket = DATA_PTR(self);
1573
- VALUE tmval;
1574
-
1575
- bucket->timeout = (uint32_t)NUM2ULONG(val);
1576
- libcouchbase_set_timeout(bucket->handle, bucket->timeout);
1577
- tmval = ULONG2NUM(bucket->timeout);
1578
-
1579
- return tmval;
1580
- }
1581
-
1582
- /* Document-method: hostname
1583
- * @return [String] the host name of the management interface (default: "localhost")
1584
- */
1585
- static VALUE
1586
- cb_bucket_hostname_get(VALUE self)
1587
- {
1588
- bucket_t *bucket = DATA_PTR(self);
1589
- if (bucket->handle) {
1590
- if (bucket->hostname) {
1591
- xfree(bucket->hostname);
1592
- bucket->hostname = NULL;
1593
- }
1594
- bucket->hostname = strdup(libcouchbase_get_host(bucket->handle));
1595
- if (bucket->hostname == NULL) {
1596
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1597
- }
1598
- }
1599
- return STR_NEW_CSTR(bucket->hostname);
1600
- }
1601
-
1602
- /* Document-method: port
1603
- * @return [Fixnum] the port number of the management interface (default: 8091)
1604
- */
1605
- static VALUE
1606
- cb_bucket_port_get(VALUE self)
1607
- {
1608
- bucket_t *bucket = DATA_PTR(self);
1609
- if (bucket->handle) {
1610
- bucket->port = atoi(libcouchbase_get_port(bucket->handle));
1611
- }
1612
- return UINT2NUM(bucket->port);
1613
- }
1614
-
1615
- /* Document-method: authority
1616
- * @return [String] host with port
1617
- */
1618
- static VALUE
1619
- cb_bucket_authority_get(VALUE self)
1620
- {
1621
- bucket_t *bucket = DATA_PTR(self);
1622
- size_t len;
1623
-
1624
- (void)cb_bucket_hostname_get(self);
1625
- (void)cb_bucket_port_get(self);
1626
- len = strlen(bucket->hostname) + 10;
1627
- bucket->authority = xcalloc(len, sizeof(char));
1628
- if (bucket->authority == NULL) {
1629
- rb_raise(eNoMemoryError, "failed to allocate memory for Bucket");
1630
- }
1631
- snprintf(bucket->authority, len, "%s:%u", bucket->hostname, bucket->port);
1632
- return STR_NEW_CSTR(bucket->authority);
1633
- }
1634
-
1635
- /* Document-method: bucket
1636
- * @return [String] the bucket name
1637
- */
1638
- static VALUE
1639
- cb_bucket_bucket_get(VALUE self)
1640
- {
1641
- bucket_t *bucket = DATA_PTR(self);
1642
- return STR_NEW_CSTR(bucket->bucket);
1643
- }
1644
-
1645
- /* Document-method: pool
1646
- * @return [String] the pool name (usually "default")
1647
- */
1648
- static VALUE
1649
- cb_bucket_pool_get(VALUE self)
1650
- {
1651
- bucket_t *bucket = DATA_PTR(self);
1652
- return STR_NEW_CSTR(bucket->pool);
1653
- }
1654
-
1655
- /* Document-method: username
1656
- * @return [String] the username for protected buckets (usually matches
1657
- * the bucket name)
1658
- */
1659
- static VALUE
1660
- cb_bucket_username_get(VALUE self)
1661
- {
1662
- bucket_t *bucket = DATA_PTR(self);
1663
- return STR_NEW_CSTR(bucket->username);
1664
- }
1665
-
1666
- /* Document-method: password
1667
- * @return [String] the password for protected buckets
1668
- */
1669
- static VALUE
1670
- cb_bucket_password_get(VALUE self)
1671
- {
1672
- bucket_t *bucket = DATA_PTR(self);
1673
- return STR_NEW_CSTR(bucket->password);
1674
- }
1675
-
1676
- /* Document-method: url
1677
- * @return [String] the address of the cluster management interface
1678
- */
1679
- static VALUE
1680
- cb_bucket_url_get(VALUE self)
1681
- {
1682
- bucket_t *bucket = DATA_PTR(self);
1683
- VALUE str;
1684
-
1685
- (void)cb_bucket_authority_get(self);
1686
- str = rb_str_buf_new2("http://");
1687
- rb_str_buf_cat2(str, bucket->authority);
1688
- rb_str_buf_cat2(str, "/pools/");
1689
- rb_str_buf_cat2(str, bucket->pool);
1690
- rb_str_buf_cat2(str, "/buckets/");
1691
- rb_str_buf_cat2(str, bucket->bucket);
1692
- rb_str_buf_cat2(str, "/");
1693
- return str;
1694
- }
1695
-
1696
- /*
1697
- * Returns a string containing a human-readable representation of the
1698
- * Bucket.
1699
- *
1700
- * @return [String]
1701
- */
1702
- static VALUE
1703
- cb_bucket_inspect(VALUE self)
1704
- {
1705
- VALUE str;
1706
- bucket_t *bucket = DATA_PTR(self);
1707
- char buf[200];
1708
-
1709
- str = rb_str_buf_new2("#<");
1710
- rb_str_buf_cat2(str, rb_obj_classname(self));
1711
- snprintf(buf, 25, ":%p \"", (void *)self);
1712
- (void)cb_bucket_authority_get(self);
1713
- rb_str_buf_cat2(str, buf);
1714
- rb_str_buf_cat2(str, "http://");
1715
- rb_str_buf_cat2(str, bucket->authority);
1716
- rb_str_buf_cat2(str, "/pools/");
1717
- rb_str_buf_cat2(str, bucket->pool);
1718
- rb_str_buf_cat2(str, "/buckets/");
1719
- rb_str_buf_cat2(str, bucket->bucket);
1720
- rb_str_buf_cat2(str, "/");
1721
- snprintf(buf, 150, "\" default_format=:%s, default_flags=0x%x, quiet=%s, connected=%s, timeout=%u>",
1722
- rb_id2name(SYM2ID(bucket->default_format)),
1723
- bucket->default_flags,
1724
- bucket->quiet ? "true" : "false",
1725
- bucket->handle ? "true" : "false",
1726
- bucket->timeout);
1727
- rb_str_buf_cat2(str, buf);
1728
-
1729
- return str;
1730
- }
1731
-
1732
- /*
1733
- * Delete the specified key
1734
- *
1735
- * @overload delete(key, options = {})
1736
- * @param key [String, Symbol] Key used to reference the value.
1737
- * @param options [Hash] Options for operation.
1738
- * @option options [Boolean] :quiet (self.quiet) If set to +true+, the
1739
- * operation won't raise error for missing key, it will return +nil+.
1740
- * Otherwise it will raise error in synchronous mode. In asynchronous
1741
- * mode this option ignored.
1742
- * @option options [Fixnum] :cas The CAS value for an object. This value
1743
- * created on the server and is guaranteed to be unique for each value of
1744
- * a given key. This value is used to provide simple optimistic
1745
- * concurrency control when multiple clients or threads try to
1746
- * update/delete an item simultaneously.
1747
- *
1748
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
1749
- * @raise [ArgumentError] when passing the block in synchronous mode
1750
- * @raise [Couchbase::Error::KeyExists] on CAS mismatch
1751
- * @raise [Couchbase::Error::NotFound] if key is missing in verbose mode
1752
- *
1753
- * @example Delete the key in quiet mode (default)
1754
- * c.set("foo", "bar")
1755
- * c.delete("foo") #=> true
1756
- * c.delete("foo") #=> false
1757
- *
1758
- * @example Delete the key verbosely
1759
- * c.set("foo", "bar")
1760
- * c.delete("foo", :quiet => false) #=> true
1761
- * c.delete("foo", :quiet => false) #=> will raise Couchbase::Error::NotFound
1762
- *
1763
- * @example Delete the key with version check
1764
- * ver = c.set("foo", "bar") #=> 5992859822302167040
1765
- * c.delete("foo", :cas => 123456) #=> will raise Couchbase::Error::KeyExists
1766
- * c.delete("foo", :cas => ver) #=> true
1767
- */
1768
- static VALUE
1769
- cb_bucket_delete(int argc, VALUE *argv, VALUE self)
1770
- {
1771
- bucket_t *bucket = DATA_PTR(self);
1772
- context_t *ctx;
1773
- VALUE k, c, rv, proc, exc, opts;
1774
- char *key;
1775
- size_t nkey;
1776
- libcouchbase_cas_t cas = 0;
1777
- libcouchbase_error_t err;
1778
- long seqno;
1779
-
1780
- if (bucket->handle == NULL) {
1781
- rb_raise(eConnectError, "closed connection");
1782
- }
1783
- rb_scan_args(argc, argv, "11&", &k, &opts, &proc);
1784
- if (!bucket->async && proc != Qnil) {
1785
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
1786
- }
1787
- k = unify_key(k);
1788
- key = RSTRING_PTR(k);
1789
- nkey = RSTRING_LEN(k);
1790
- ctx = xcalloc(1, sizeof(context_t));
1791
- ctx->quiet = bucket->quiet;
1792
- if (ctx == NULL) {
1793
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
1794
- }
1795
- if (opts != Qnil) {
1796
- if (TYPE(opts) == T_BIGNUM || TYPE(opts) == T_FIXNUM) {
1797
- cas = NUM2ULL(opts);
1798
- } else {
1799
- Check_Type(opts, T_HASH);
1800
- if ((c = rb_hash_aref(opts, sym_cas)) != Qnil) {
1801
- cas = NUM2ULL(c);
1802
- }
1803
- if (RTEST(rb_funcall(opts, id_has_key_p, 1, sym_quiet))) {
1804
- ctx->quiet = RTEST(rb_hash_aref(opts, sym_quiet));
1805
- }
1806
- }
1807
- }
1808
- ctx->proc = proc;
1809
- cb_gc_protect(bucket, ctx->proc);
1810
- rv = rb_ary_new();
1811
- ctx->rv = &rv;
1812
- ctx->bucket = bucket;
1813
- ctx->exception = Qnil;
1814
- seqno = bucket->seqno;
1815
- bucket->seqno++;
1816
- err = libcouchbase_remove(bucket->handle, (const void *)ctx,
1817
- (const void *)key, nkey, cas);
1818
- exc = cb_check_error(err, "failed to schedule delete request", Qnil);
1819
- if (exc != Qnil) {
1820
- xfree(ctx);
1821
- rb_exc_raise(exc);
1822
- }
1823
- if (bucket->async) {
1824
- return Qnil;
1825
- } else {
1826
- if (bucket->seqno - seqno > 0) {
1827
- /* we have some operations pending */
1828
- bucket->io->run_event_loop(bucket->io);
1829
- }
1830
- exc = ctx->exception;
1831
- xfree(ctx);
1832
- if (exc != Qnil) {
1833
- cb_gc_unprotect(bucket, exc);
1834
- rb_exc_raise(exc);
1835
- }
1836
- return rv;
1837
- }
1838
- }
1839
-
1840
- static inline VALUE
1841
- cb_bucket_store(libcouchbase_storage_t cmd, int argc, VALUE *argv, VALUE self)
1842
- {
1843
- bucket_t *bucket = DATA_PTR(self);
1844
- context_t *ctx;
1845
- VALUE k, v, arg, opts, rv, proc, exc, fmt;
1846
- char *key, *bytes;
1847
- size_t nkey, nbytes;
1848
- uint32_t flags;
1849
- time_t exp = 0;
1850
- libcouchbase_cas_t cas = 0;
1851
- libcouchbase_error_t err;
1852
- long seqno;
1853
-
1854
- if (bucket->handle == NULL) {
1855
- rb_raise(eConnectError, "closed connection");
1856
- }
1857
- rb_scan_args(argc, argv, "21&", &k, &v, &opts, &proc);
1858
- if (!bucket->async && proc != Qnil) {
1859
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
1860
- }
1861
- k = unify_key(k);
1862
- flags = bucket->default_flags;
1863
- if (opts != Qnil) {
1864
- Check_Type(opts, T_HASH);
1865
- arg = rb_hash_aref(opts, sym_flags);
1866
- if (arg != Qnil) {
1867
- flags = (uint32_t)NUM2ULONG(arg);
1868
- }
1869
- arg = rb_hash_aref(opts, sym_ttl);
1870
- if (arg != Qnil) {
1871
- exp = NUM2ULONG(arg);
1872
- }
1873
- arg = rb_hash_aref(opts, sym_cas);
1874
- if (arg != Qnil) {
1875
- cas = NUM2ULL(arg);
1876
- }
1877
- fmt = rb_hash_aref(opts, sym_format);
1878
- if (fmt != Qnil) { /* rewrite format bits */
1879
- flags = flags_set_format(flags, fmt);
1880
- }
1881
- }
1882
- key = RSTRING_PTR(k);
1883
- nkey = RSTRING_LEN(k);
1884
- v = encode_value(v, flags);
1885
- if (v == Qundef) {
1886
- rb_raise(eValueFormatError,
1887
- "unable to convert value for key '%s'", key);
1888
- }
1889
- bytes = RSTRING_PTR(v);
1890
- nbytes = RSTRING_LEN(v);
1891
- ctx = xcalloc(1, sizeof(context_t));
1892
- if (ctx == NULL) {
1893
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
1894
- }
1895
- rv = Qnil;
1896
- ctx->rv = &rv;
1897
- ctx->bucket = bucket;
1898
- ctx->proc = proc;
1899
- cb_gc_protect(bucket, ctx->proc);
1900
- ctx->exception = Qnil;
1901
- seqno = bucket->seqno;
1902
- bucket->seqno++;
1903
- err = libcouchbase_store(bucket->handle, (const void *)ctx, cmd,
1904
- (const void *)key, nkey, bytes, nbytes, flags, exp, cas);
1905
- exc = cb_check_error(err, "failed to schedule set request", Qnil);
1906
- if (exc != Qnil) {
1907
- xfree(ctx);
1908
- rb_exc_raise(exc);
1909
- }
1910
- if (bucket->async) {
1911
- return Qnil;
1912
- } else {
1913
- if (bucket->seqno - seqno > 0) {
1914
- /* we have some operations pending */
1915
- bucket->io->run_event_loop(bucket->io);
1916
- }
1917
- exc = ctx->exception;
1918
- xfree(ctx);
1919
- if (exc != Qnil) {
1920
- cb_gc_unprotect(bucket, exc);
1921
- rb_exc_raise(exc);
1922
- }
1923
- if (bucket->exception != Qnil) {
1924
- rb_exc_raise(bucket->exception);
1925
- }
1926
- return rv;
1927
- }
1928
- }
1929
-
1930
- static inline VALUE
1931
- cb_bucket_arithmetic(int sign, int argc, VALUE *argv, VALUE self)
1932
- {
1933
- bucket_t *bucket = DATA_PTR(self);
1934
- context_t *ctx;
1935
- VALUE k, d, arg, opts, rv, proc, exc;
1936
- char *key;
1937
- size_t nkey;
1938
- time_t exp;
1939
- uint64_t delta = 0, initial = 0;
1940
- int create = 0;
1941
- libcouchbase_error_t err;
1942
- long seqno;
1943
-
1944
- if (bucket->handle == NULL) {
1945
- rb_raise(eConnectError, "closed connection");
1946
- }
1947
- rb_scan_args(argc, argv, "12&", &k, &d, &opts, &proc);
1948
- if (!bucket->async && proc != Qnil) {
1949
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
1950
- }
1951
- k = unify_key(k);
1952
- ctx = xcalloc(1, sizeof(context_t));
1953
- if (ctx == NULL) {
1954
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
1955
- }
1956
- if (argc == 2 && TYPE(d) == T_HASH) {
1957
- opts = d;
1958
- d = Qnil;
1959
- }
1960
- exp = bucket->default_ttl;
1961
- if (opts != Qnil) {
1962
- Check_Type(opts, T_HASH);
1963
- create = RTEST(rb_hash_aref(opts, sym_create));
1964
- ctx->extended = RTEST(rb_hash_aref(opts, sym_extended));
1965
- arg = rb_hash_aref(opts, sym_ttl);
1966
- if (arg != Qnil) {
1967
- exp = NUM2ULONG(arg);
1968
- }
1969
- arg = rb_hash_aref(opts, sym_initial);
1970
- if (arg != Qnil) {
1971
- initial = NUM2ULL(arg);
1972
- create = 1;
1973
- }
1974
- }
1975
- key = RSTRING_PTR(k);
1976
- nkey = RSTRING_LEN(k);
1977
- if (NIL_P(d)) {
1978
- delta = 1 * sign;
1979
- } else {
1980
- delta = NUM2ULL(d) * sign;
1981
- }
1982
- rv = Qnil;
1983
- ctx->rv = &rv;
1984
- ctx->bucket = bucket;
1985
- ctx->proc = proc;
1986
- cb_gc_protect(bucket, ctx->proc);
1987
- ctx->exception = Qnil;
1988
- ctx->arithm = sign;
1989
- seqno = bucket->seqno;
1990
- bucket->seqno++;
1991
- err = libcouchbase_arithmetic(bucket->handle, (const void *)ctx,
1992
- (const void *)key, nkey, delta, exp, create, initial);
1993
- exc = cb_check_error(err, "failed to schedule arithmetic request", k);
1994
- if (exc != Qnil) {
1995
- xfree(ctx);
1996
- rb_exc_raise(exc);
1997
- }
1998
- if (bucket->async) {
1999
- return Qnil;
2000
- } else {
2001
- if (bucket->seqno - seqno > 0) {
2002
- /* we have some operations pending */
2003
- bucket->io->run_event_loop(bucket->io);
2004
- }
2005
- exc = ctx->exception;
2006
- xfree(ctx);
2007
- if (exc != Qnil) {
2008
- cb_gc_unprotect(bucket, exc);
2009
- rb_exc_raise(exc);
2010
- }
2011
- return rv;
2012
- }
2013
- }
2014
-
2015
- /*
2016
- * Increment the value of an existing numeric key
2017
- *
2018
- * The increment methods enable you to increase a given stored integer
2019
- * value. These are the incremental equivalent of the decrement operations
2020
- * and work on the same basis; updating the value of a key if it can be
2021
- * parsed to an integer. The update operation occurs on the server and is
2022
- * provided at the protocol level. This simplifies what would otherwise be a
2023
- * two-stage get and set operation.
2024
- *
2025
- * @note that server values stored and transmitted as unsigned numbers,
2026
- * therefore if you try to store negative number and then increment or
2027
- * decrement it will cause overflow. (see "Integer overflow" example
2028
- * below)
2029
- *
2030
- * @overload incr(key, delta = 1, options = {})
2031
- * @param key [String, Symbol] Key used to reference the value.
2032
- * @param delta [Fixnum] Integer (up to 64 bits) value to increment
2033
- * @param options [Hash] Options for operation.
2034
- * @option options [Boolean] :create (false) If set to +true+, it will
2035
- * initialize the key with zero value and zero flags (use +:initial+
2036
- * option to set another initial value). Note: it won't increment the
2037
- * missing value.
2038
- * @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
2039
- * missing key initialization. This option imply +:create+ option is
2040
- * +true+.
2041
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2042
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2043
- * absolute times (from the epoch). This option ignored for existent
2044
- * keys.
2045
- * @option options [Boolean] :extended (false) If set to +true+, the
2046
- * operation will return tuple +[value, cas]+, otherwise (by default) it
2047
- * returns just value.
2048
- *
2049
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2050
- * (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
2051
- *
2052
- * @return [Fixnum] the actual value of the key.
2053
- *
2054
- * @raise [Couchbase::Error::NotFound] if key is missing and +:create+
2055
- * option isn't +true+.
2056
- *
2057
- * @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
2058
- * value
2059
- *
2060
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2061
- *
2062
- * @raise [ArgumentError] when passing the block in synchronous mode
2063
- *
2064
- * @example Increment key by one
2065
- * c.incr("foo")
2066
- *
2067
- * @example Increment key by 50
2068
- * c.incr("foo", 50)
2069
- *
2070
- * @example Increment key by one <b>OR</b> initialize with zero
2071
- * c.incr("foo", :create => true) #=> will return old+1 or 0
2072
- *
2073
- * @example Increment key by one <b>OR</b> initialize with three
2074
- * c.incr("foo", 50, :initial => 3) #=> will return old+50 or 3
2075
- *
2076
- * @example Increment key and get its CAS value
2077
- * val, cas = c.incr("foo", :extended => true)
2078
- *
2079
- * @example Integer overflow
2080
- * c.set("foo", -100)
2081
- * c.get("foo") #=> -100
2082
- * c.incr("foo") #=> 18446744073709551517
2083
- *
2084
- * @example Asynchronous invocation
2085
- * c.run do
2086
- * c.incr("foo") do |ret|
2087
- * ret.operation #=> :increment
2088
- * ret.success? #=> true
2089
- * ret.key #=> "foo"
2090
- * ret.value
2091
- * ret.cas
2092
- * end
2093
- * end
2094
- *
2095
- */
2096
- static VALUE
2097
- cb_bucket_incr(int argc, VALUE *argv, VALUE self)
2098
- {
2099
- return cb_bucket_arithmetic(+1, argc, argv, self);
2100
- }
2101
-
2102
- /*
2103
- * Decrement the value of an existing numeric key
2104
- *
2105
- * The decrement methods reduce the value of a given key if the
2106
- * corresponding value can be parsed to an integer value. These operations
2107
- * are provided at a protocol level to eliminate the need to get, update,
2108
- * and reset a simple integer value in the database. It supports the use of
2109
- * an explicit offset value that will be used to reduce the stored value in
2110
- * the database.
2111
- *
2112
- * @note that server values stored and transmitted as unsigned numbers,
2113
- * therefore if you try to decrement negative or zero key, you will always
2114
- * get zero.
2115
- *
2116
- * @overload decr(key, delta = 1, options = {})
2117
- * @param key [String, Symbol] Key used to reference the value.
2118
- * @param delta [Fixnum] Integer (up to 64 bits) value to decrement
2119
- * @param options [Hash] Options for operation.
2120
- * @option options [Boolean] :create (false) If set to +true+, it will
2121
- * initialize the key with zero value and zero flags (use +:initial+
2122
- * option to set another initial value). Note: it won't decrement the
2123
- * missing value.
2124
- * @option options [Fixnum] :initial (0) Integer (up to 64 bits) value for
2125
- * missing key initialization. This option imply +:create+ option is
2126
- * +true+.
2127
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2128
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2129
- * absolute times (from the epoch). This option ignored for existent
2130
- * keys.
2131
- * @option options [Boolean] :extended (false) If set to +true+, the
2132
- * operation will return tuple +[value, cas]+, otherwise (by default) it
2133
- * returns just value.
2134
- *
2135
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2136
- * (valid attributes: +error+, +operation+, +key+, +value+, +cas+).
2137
- *
2138
- * @return [Fixnum] the actual value of the key.
2139
- *
2140
- * @raise [Couchbase::Error::NotFound] if key is missing and +:create+
2141
- * option isn't +true+.
2142
- *
2143
- * @raise [Couchbase::Error::DeltaBadval] if the key contains non-numeric
2144
- * value
2145
- *
2146
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2147
- *
2148
- * @raise [ArgumentError] when passing the block in synchronous mode
2149
- *
2150
- * @example Decrement key by one
2151
- * c.decr("foo")
2152
- *
2153
- * @example Decrement key by 50
2154
- * c.decr("foo", 50)
2155
- *
2156
- * @example Decrement key by one <b>OR</b> initialize with zero
2157
- * c.decr("foo", :create => true) #=> will return old-1 or 0
2158
- *
2159
- * @example Decrement key by one <b>OR</b> initialize with three
2160
- * c.decr("foo", 50, :initial => 3) #=> will return old-50 or 3
2161
- *
2162
- * @example Decrement key and get its CAS value
2163
- * val, cas = c.decr("foo", :extended => true)
2164
- *
2165
- * @example Decrementing zero
2166
- * c.set("foo", 0)
2167
- * c.decrement("foo", 100500) #=> 0
2168
- *
2169
- * @example Decrementing negative value
2170
- * c.set("foo", -100)
2171
- * c.decrement("foo", 100500) #=> 0
2172
- *
2173
- * @example Asynchronous invocation
2174
- * c.run do
2175
- * c.decr("foo") do |ret|
2176
- * ret.operation #=> :decrement
2177
- * ret.success? #=> true
2178
- * ret.key #=> "foo"
2179
- * ret.value
2180
- * ret.cas
2181
- * end
2182
- * end
2183
- *
2184
- */
2185
- static VALUE
2186
- cb_bucket_decr(int argc, VALUE *argv, VALUE self)
2187
- {
2188
- return cb_bucket_arithmetic(-1, argc, argv, self);
2189
- }
2190
-
2191
- /*
2192
- * Obtain an object stored in Couchbase by given key.
2193
- *
2194
- * @overload get(*keys, options = {})
2195
- * @param keys [String, Symbol, Array] One or several keys to fetch
2196
- * @param options [Hash] Options for operation.
2197
- * @option options [Boolean] :extended (false) If set to +true+, the
2198
- * operation will return tuple +[value, flags, cas]+, otherwise (by
2199
- * default) it returns just value.
2200
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2201
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2202
- * absolute times (from the epoch).
2203
- * @option options [Boolean] :quiet (self.quiet) If set to +true+, the
2204
- * operation won't raise error for missing key, it will return +nil+.
2205
- * Otherwise it will raise error in synchronous mode. In asynchronous
2206
- * mode this option ignored.
2207
- * @option options [Symbol] :format (nil) Explicitly choose the decoder
2208
- * for this key (+:plain+, +:document+, +:marshal+). See
2209
- * {Bucket#default_format}.
2210
- *
2211
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2212
- * (valid attributes: +error+, +operation+, +key+, +value+, +flags+,
2213
- * +cas+).
2214
- *
2215
- * @return [Object, Array, Hash] the value(s) (or tuples in extended mode)
2216
- * assiciated with the key.
2217
- *
2218
- * @raise [Couchbase::Error::NotFound] if the key is missing in the
2219
- * bucket.
2220
- *
2221
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2222
- *
2223
- * @raise [ArgumentError] when passing the block in synchronous mode
2224
- *
2225
- * @example Get single value in quite mode (the default)
2226
- * c.get("foo") #=> the associated value or nil
2227
- *
2228
- * @example Use alternative hash-like syntax
2229
- * c["foo"] #=> the associated value or nil
2230
- *
2231
- * @example Get single value in verbose mode
2232
- * c.get("missing-foo", :quiet => false) #=> raises Couchbase::NotFound
2233
- *
2234
- * @example Get and touch single value. The key won't be accessible after 10 seconds
2235
- * c.get("foo", :ttl => 10)
2236
- *
2237
- * @example Extended get
2238
- * val, flags, cas = c.get("foo", :extended => true)
2239
- *
2240
- * @example Get multiple keys
2241
- * c.get("foo", "bar", "baz") #=> [val1, val2, val3]
2242
- *
2243
- * @example Extended get multiple keys
2244
- * c.get("foo", "bar", :extended => true)
2245
- * #=> {"foo" => [val1, flags1, cas1], "bar" => [val2, flags2, cas2]}
2246
- *
2247
- * @example Asynchronous get
2248
- * c.run do
2249
- * c.get("foo", "bar", "baz") do |res|
2250
- * ret.operation #=> :get
2251
- * ret.success? #=> true
2252
- * ret.key #=> "foo", "bar" or "baz" in separate calls
2253
- * ret.value
2254
- * ret.flags
2255
- * ret.cas
2256
- * end
2257
- * end
2258
- *
2259
- * @overload get(keys, options = {})
2260
- * When the method receive hash map, it will behave like it receive list
2261
- * of keys (+keys.keys+), but also touch each key setting expiry time to
2262
- * the corresponding value. But unlike usual get this command always
2263
- * return hash map +{key => value}+ or +{key => [value, flags, cas]}+.
2264
- *
2265
- * @param keys [Hash] Map key-ttl
2266
- * @param options [Hash] Options for operation. (see options definition
2267
- * above)
2268
- *
2269
- * @return [Hash] the values (or tuples in extended mode) assiciated with
2270
- * the keys.
2271
- *
2272
- * @example Get and touch multiple keys
2273
- * c.get("foo" => 10, "bar" => 20) #=> {"foo" => val1, "bar" => val2}
2274
- *
2275
- * @example Extended get and touch multiple keys
2276
- * c.get({"foo" => 10, "bar" => 20}, :extended => true)
2277
- * #=> {"foo" => [val1, flags1, cas1], "bar" => [val2, flags2, cas2]}
2278
- */
2279
- static VALUE
2280
- cb_bucket_get(int argc, VALUE *argv, VALUE self)
2281
- {
2282
- bucket_t *bucket = DATA_PTR(self);
2283
- context_t *ctx;
2284
- VALUE args, rv, proc, exc, keys;
2285
- long nn;
2286
- libcouchbase_error_t err;
2287
- struct key_traits *traits;
2288
- int extended, mgat;
2289
- long seqno;
2290
-
2291
- if (bucket->handle == NULL) {
2292
- rb_raise(eConnectError, "closed connection");
2293
- }
2294
- rb_scan_args(argc, argv, "0*&", &args, &proc);
2295
- if (!bucket->async && proc != Qnil) {
2296
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2297
- }
2298
- rb_funcall(args, id_flatten_bang, 0);
2299
- traits = xcalloc(1, sizeof(struct key_traits));
2300
- nn = cb_args_scan_keys(RARRAY_LEN(args), args, bucket, traits);
2301
- ctx = xcalloc(1, sizeof(context_t));
2302
- if (ctx == NULL) {
2303
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
2304
- }
2305
- mgat = traits->mgat;
2306
- keys = traits->keys_ary;
2307
- ctx->proc = proc;
2308
- cb_gc_protect(bucket, ctx->proc);
2309
- ctx->bucket = bucket;
2310
- ctx->extended = traits->extended;
2311
- ctx->quiet = traits->quiet;
2312
- ctx->force_format = traits->force_format;
2313
- rv = rb_hash_new();
2314
- ctx->rv = &rv;
2315
- ctx->exception = Qnil;
2316
- seqno = bucket->seqno;
2317
- bucket->seqno += nn;
2318
- err = libcouchbase_mget(bucket->handle, (const void *)ctx,
2319
- traits->nkeys, (const void * const *)traits->keys,
2320
- traits->lens, (traits->explicit_ttl) ? traits->ttls : NULL);
2321
- xfree(traits->keys);
2322
- xfree(traits->lens);
2323
- xfree(traits->ttls);
2324
- xfree(traits);
2325
- exc = cb_check_error(err, "failed to schedule get request", Qnil);
2326
- if (exc != Qnil) {
2327
- xfree(ctx);
2328
- rb_exc_raise(exc);
2329
- }
2330
- if (bucket->async) {
2331
- return Qnil;
2332
- } else {
2333
- if (bucket->seqno - seqno > 0) {
2334
- /* we have some operations pending */
2335
- bucket->io->run_event_loop(bucket->io);
2336
- }
2337
- exc = ctx->exception;
2338
- extended = ctx->extended;
2339
- xfree(ctx);
2340
- if (exc != Qnil) {
2341
- cb_gc_unprotect(bucket, exc);
2342
- rb_exc_raise(exc);
2343
- }
2344
- if (bucket->exception != Qnil) {
2345
- rb_exc_raise(bucket->exception);
2346
- }
2347
- if (mgat || (extended && nn > 1)) {
2348
- return rv; /* return as a hash {key => [value, flags, cas], ...} */
2349
- }
2350
- if (nn > 1) {
2351
- long ii;
2352
- VALUE *keys_ptr, ret;
2353
- ret = rb_ary_new();
2354
- keys_ptr = RARRAY_PTR(keys);
2355
- for (ii = 0; ii < nn; ii++) {
2356
- rb_ary_push(ret, rb_hash_aref(rv, keys_ptr[ii]));
2357
- }
2358
- return ret; /* return as an array [value1, value2, ...] */
2359
- } else {
2360
- VALUE vv = Qnil;
2361
- rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv);
2362
- return vv;
2363
- }
2364
- }
2365
- }
2366
-
2367
- /*
2368
- * Update the expiry time of an item
2369
- *
2370
- * The +touch+ method allow you to update the expiration time on a given
2371
- * key. This can be useful for situations where you want to prevent an item
2372
- * from expiring without resetting the associated value. For example, for a
2373
- * session database you might want to keep the session alive in the database
2374
- * each time the user accesses a web page without explicitly updating the
2375
- * session value, keeping the user's session active and available.
2376
- *
2377
- * @overload touch(key, options = {})
2378
- * @param key [String, Symbol] Key used to reference the value.
2379
- * @param options [Hash] Options for operation.
2380
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2381
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2382
- * absolute times (from the epoch).
2383
- *
2384
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2385
- * (valid attributes: +error+, +operation+, +key+).
2386
- *
2387
- * @return [Boolean] +true+ if the operation was successful and +false+
2388
- * otherwise.
2389
- *
2390
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2391
- *
2392
- * @raise [ArgumentError] when passing the block in synchronous mode
2393
- *
2394
- * @example Touch value using +default_ttl+
2395
- * c.touch("foo")
2396
- *
2397
- * @example Touch value using custom TTL (10 seconds)
2398
- * c.touch("foo", :ttl => 10)
2399
- *
2400
- * @overload touch(keys)
2401
- * @param keys [Hash] The Hash where keys represent the keys in the
2402
- * database, values -- the expiry times for corresponding key. See
2403
- * description of +:ttl+ argument above for more information about TTL
2404
- * values.
2405
- *
2406
- * @yieldparam ret [Result] the result of operation for each key in
2407
- * asynchronous mode (valid attributes: +error+, +operation+, +key+).
2408
- *
2409
- * @return [Hash] Mapping keys to result of touch operation (+true+ if the
2410
- * operation was successful and +false+ otherwise)
2411
- *
2412
- * @example Touch several values
2413
- * c.touch("foo" => 10, :bar => 20) #=> {"foo" => true, "bar" => true}
2414
- *
2415
- * @example Touch several values in async mode
2416
- * c.run do
2417
- * c.touch("foo" => 10, :bar => 20) do |ret|
2418
- * ret.operation #=> :touch
2419
- * ret.success? #=> true
2420
- * ret.key #=> "foo" and "bar" in separate calls
2421
- * end
2422
- * end
2423
- *
2424
- * @example Touch single value
2425
- * c.touch("foo" => 10) #=> true
2426
- *
2427
- */
2428
- static VALUE
2429
- cb_bucket_touch(int argc, VALUE *argv, VALUE self)
2430
- {
2431
- bucket_t *bucket = DATA_PTR(self);
2432
- context_t *ctx;
2433
- VALUE args, rv, proc, exc;
2434
- size_t nn;
2435
- libcouchbase_error_t err;
2436
- struct key_traits *traits;
2437
- long seqno;
2438
-
2439
- if (bucket->handle == NULL) {
2440
- rb_raise(eConnectError, "closed connection");
2441
- }
2442
- rb_scan_args(argc, argv, "0*&", &args, &proc);
2443
- if (!bucket->async && proc != Qnil) {
2444
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2445
- }
2446
- rb_funcall(args, id_flatten_bang, 0);
2447
- traits = xcalloc(1, sizeof(struct key_traits));
2448
- nn = cb_args_scan_keys(RARRAY_LEN(args), args, bucket, traits);
2449
- ctx = xcalloc(1, sizeof(context_t));
2450
- if (ctx == NULL) {
2451
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
2452
- }
2453
- ctx->proc = proc;
2454
- cb_gc_protect(bucket, ctx->proc);
2455
- ctx->bucket = bucket;
2456
- rv = rb_hash_new();
2457
- ctx->rv = &rv;
2458
- ctx->exception = Qnil;
2459
- seqno = bucket->seqno;
2460
- bucket->seqno += nn;
2461
- err = libcouchbase_mtouch(bucket->handle, (const void *)ctx,
2462
- traits->nkeys, (const void * const *)traits->keys,
2463
- traits->lens, traits->ttls);
2464
- xfree(traits->keys);
2465
- xfree(traits->lens);
2466
- xfree(traits);
2467
- exc = cb_check_error(err, "failed to schedule touch request", Qnil);
2468
- if (exc != Qnil) {
2469
- xfree(ctx);
2470
- rb_exc_raise(exc);
2471
- }
2472
- if (bucket->async) {
2473
- return Qnil;
2474
- } else {
2475
- if (bucket->seqno - seqno > 0) {
2476
- /* we have some operations pending */
2477
- bucket->io->run_event_loop(bucket->io);
2478
- }
2479
- exc = ctx->exception;
2480
- xfree(ctx);
2481
- if (exc != Qnil) {
2482
- cb_gc_unprotect(bucket, exc);
2483
- rb_exc_raise(exc);
2484
- }
2485
- if (bucket->exception != Qnil) {
2486
- rb_exc_raise(bucket->exception);
2487
- }
2488
- if (nn > 1) {
2489
- return rv; /* return as a hash {key => true, ...} */
2490
- } else {
2491
- VALUE vv = Qnil;
2492
- rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv);
2493
- return vv;
2494
- }
2495
- }
2496
- }
2497
-
2498
- /*
2499
- * Deletes all values from a server
2500
- *
2501
- * @overload flush
2502
- * @yieldparam [Result] ret the object with +error+, +node+ and +operation+
2503
- * attributes.
2504
- *
2505
- * @return [Boolean] +true+ on success
2506
- *
2507
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2508
- * @raise [ArgumentError] when passing the block in synchronous mode
2509
- *
2510
- * @example Simple flush the bucket
2511
- * c.flush #=> true
2512
- *
2513
- * @example Asynchronous flush
2514
- * c.run do
2515
- * c.flush do |ret|
2516
- * ret.operation #=> :flush
2517
- * ret.success? #=> true
2518
- * ret.node #=> "localhost:11211"
2519
- * end
2520
- * end
2521
- */
2522
- static VALUE
2523
- cb_bucket_flush(VALUE self)
2524
- {
2525
- bucket_t *bucket = DATA_PTR(self);
2526
- context_t *ctx;
2527
- VALUE rv, exc;
2528
- libcouchbase_error_t err;
2529
- long seqno;
2530
-
2531
- if (bucket->handle == NULL) {
2532
- rb_raise(eConnectError, "closed connection");
2533
- }
2534
- if (!bucket->async && rb_block_given_p()) {
2535
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2536
- }
2537
- ctx = xcalloc(1, sizeof(context_t));
2538
- if (ctx == NULL) {
2539
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
2540
- }
2541
- rv = Qtrue; /* optimistic by default */
2542
- ctx->rv = &rv;
2543
- ctx->bucket = bucket;
2544
- ctx->exception = Qnil;
2545
- if (rb_block_given_p()) {
2546
- ctx->proc = rb_block_proc();
2547
- } else {
2548
- ctx->proc = Qnil;
2549
- }
2550
- cb_gc_protect(bucket, ctx->proc);
2551
- seqno = bucket->seqno;
2552
- bucket->seqno++;
2553
- err = libcouchbase_flush(bucket->handle, (const void *)ctx);
2554
- exc = cb_check_error(err, "failed to schedule flush request", Qnil);
2555
- if (exc != Qnil) {
2556
- xfree(ctx);
2557
- rb_exc_raise(exc);
2558
- }
2559
- if (bucket->async) {
2560
- return Qnil;
2561
- } else {
2562
- if (bucket->seqno - seqno > 0) {
2563
- /* we have some operations pending */
2564
- bucket->io->run_event_loop(bucket->io);
2565
- }
2566
- exc = ctx->exception;
2567
- xfree(ctx);
2568
- if (exc != Qnil) {
2569
- cb_gc_unprotect(bucket, exc);
2570
- rb_exc_raise(exc);
2571
- }
2572
- return rv;
2573
- }
2574
- }
2575
-
2576
- /*
2577
- * Returns versions of the server for each node in the cluster
2578
- *
2579
- * @overload version
2580
- * @yieldparam [Result] ret the object with +error+, +node+, +operation+
2581
- * and +value+ attributes.
2582
- *
2583
- * @return [Hash] node-version pairs
2584
- *
2585
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2586
- * @raise [ArgumentError] when passing the block in synchronous mode
2587
- *
2588
- * @example Synchronous version request
2589
- * c.version #=> will render version
2590
- *
2591
- * @example Asynchronous version request
2592
- * c.run do
2593
- * c.version do |ret|
2594
- * ret.operation #=> :version
2595
- * ret.success? #=> true
2596
- * ret.node #=> "localhost:11211"
2597
- * ret.value #=> will render version
2598
- * end
2599
- * end
2600
- */
2601
- static VALUE
2602
- cb_bucket_version(VALUE self)
2603
- {
2604
- bucket_t *bucket = DATA_PTR(self);
2605
- context_t *ctx;
2606
- VALUE rv, exc;
2607
- libcouchbase_error_t err;
2608
- long seqno;
2609
-
2610
- if (bucket->handle == NULL) {
2611
- rb_raise(eConnectError, "closed connection");
2612
- }
2613
- if (!bucket->async && rb_block_given_p()) {
2614
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2615
- }
2616
- ctx = xcalloc(1, sizeof(context_t));
2617
- if (ctx == NULL) {
2618
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
2619
- }
2620
- rv = rb_hash_new();
2621
- ctx->rv = &rv;
2622
- ctx->bucket = bucket;
2623
- ctx->exception = Qnil;
2624
- if (rb_block_given_p()) {
2625
- ctx->proc = rb_block_proc();
2626
- } else {
2627
- ctx->proc = Qnil;
2628
- }
2629
- cb_gc_protect(bucket, ctx->proc);
2630
- seqno = bucket->seqno;
2631
- bucket->seqno++;
2632
- err = libcouchbase_server_versions(bucket->handle, (const void *)ctx);
2633
- exc = cb_check_error(err, "failed to schedule version request", Qnil);
2634
- if (exc != Qnil) {
2635
- xfree(ctx);
2636
- rb_exc_raise(exc);
2637
- }
2638
- if (bucket->async) {
2639
- return Qnil;
2640
- } else {
2641
- if (bucket->seqno - seqno > 0) {
2642
- /* we have some operations pending */
2643
- bucket->io->run_event_loop(bucket->io);
2644
- }
2645
- exc = ctx->exception;
2646
- xfree(ctx);
2647
- if (exc != Qnil) {
2648
- cb_gc_unprotect(bucket, exc);
2649
- rb_exc_raise(exc);
2650
- }
2651
- return rv;
2652
- }
2653
- }
2654
-
2655
- /*
2656
- * Request server statistics.
2657
- *
2658
- * Fetches stats from each node in cluster. Without a key specified the
2659
- * server will respond with a "default" set of statistical information. In
2660
- * asynchronous mode each statistic is returned in separate call where the
2661
- * Result object yielded (+#key+ contains the name of the statistical item
2662
- * and the +#value+ contains the value, the +#node+ will indicate the server
2663
- * address). In synchronous mode it returns the hash of stats keys and
2664
- * node-value pairs as a value.
2665
- *
2666
- * @overload stats(arg = nil)
2667
- * @param [String] arg argument to STATS query
2668
- * @yieldparam [Result] ret the object with +node+, +key+ and +value+
2669
- * attributes.
2670
- *
2671
- * @example Found how many items in the bucket
2672
- * total = 0
2673
- * c.stats["total_items"].each do |key, value|
2674
- * total += value.to_i
2675
- * end
2676
- *
2677
- * @example Found total items number asynchronously
2678
- * total = 0
2679
- * c.run do
2680
- * c.stats do |ret|
2681
- * if ret.key == "total_items"
2682
- * total += ret.value.to_i
2683
- * end
2684
- * end
2685
- * end
2686
- *
2687
- * @example Get memory stats (works on couchbase buckets)
2688
- * c.stats(:memory) #=> {"mem_used"=>{...}, ...}
2689
- *
2690
- * @return [Hash] where keys are stat keys, values are host-value pairs
2691
- *
2692
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2693
- * @raise [ArgumentError] when passing the block in synchronous mode
2694
- */
2695
- static VALUE
2696
- cb_bucket_stats(int argc, VALUE *argv, VALUE self)
2697
- {
2698
- bucket_t *bucket = DATA_PTR(self);
2699
- context_t *ctx;
2700
- VALUE rv, exc, arg, proc;
2701
- char *key;
2702
- size_t nkey;
2703
- libcouchbase_error_t err;
2704
- long seqno;
2705
-
2706
- if (bucket->handle == NULL) {
2707
- rb_raise(eConnectError, "closed connection");
2708
- }
2709
- rb_scan_args(argc, argv, "01&", &arg, &proc);
2710
- if (!bucket->async && proc != Qnil) {
2711
- rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
2712
- }
2713
-
2714
- ctx = xcalloc(1, sizeof(context_t));
2715
- if (ctx == NULL) {
2716
- rb_raise(eNoMemoryError, "failed to allocate memory for context");
2717
- }
2718
- rv = rb_hash_new();
2719
- ctx->rv = &rv;
2720
- ctx->bucket = bucket;
2721
- ctx->proc = proc;
2722
- cb_gc_protect(bucket, ctx->proc);
2723
- ctx->exception = Qnil;
2724
- if (arg != Qnil) {
2725
- arg = unify_key(arg);
2726
- key = RSTRING_PTR(arg);
2727
- nkey = RSTRING_LEN(arg);
2728
- } else {
2729
- key = NULL;
2730
- nkey = 0;
2731
- }
2732
- seqno = bucket->seqno;
2733
- bucket->seqno++;
2734
- err = libcouchbase_server_stats(bucket->handle, (const void *)ctx,
2735
- key, nkey);
2736
- exc = cb_check_error(err, "failed to schedule stat request", Qnil);
2737
- if (exc != Qnil) {
2738
- xfree(ctx);
2739
- rb_exc_raise(exc);
2740
- }
2741
- if (bucket->async) {
2742
- return Qnil;
2743
- } else {
2744
- if (bucket->seqno - seqno > 0) {
2745
- /* we have some operations pending */
2746
- bucket->io->run_event_loop(bucket->io);
2747
- }
2748
- exc = ctx->exception;
2749
- xfree(ctx);
2750
- if (exc != Qnil) {
2751
- cb_gc_unprotect(bucket, exc);
2752
- rb_exc_raise(exc);
2753
- }
2754
- if (bucket->exception != Qnil) {
2755
- rb_exc_raise(bucket->exception);
2756
- }
2757
- return rv;
2758
- }
2759
-
2760
- return Qnil;
2761
- }
2762
-
2763
- static VALUE
2764
- do_run(VALUE *args)
2765
- {
2766
- VALUE self = args[0], proc = args[1], exc;
2767
- bucket_t *bucket = DATA_PTR(self);
2768
- time_t tm;
2769
- uint32_t old_tmo, new_tmo, diff;
2770
-
2771
- if (bucket->handle == NULL) {
2772
- rb_raise(eConnectError, "closed connection");
2773
- }
2774
- if (bucket->async) {
2775
- rb_raise(eInvalidError, "nested #run");
2776
- }
2777
- bucket->seqno = 0;
2778
- bucket->async = 1;
2779
-
2780
- tm = time(NULL);
2781
- cb_proc_call(proc, 1, self);
2782
- if (bucket->seqno > 0) {
2783
- old_tmo = libcouchbase_get_timeout(bucket->handle);
2784
- diff = (uint32_t)(time(NULL) - tm + 1);
2785
- diff *= 1000000;
2786
- new_tmo = bucket->timeout += diff;
2787
- libcouchbase_set_timeout(bucket->handle, bucket->timeout);
2788
- bucket->io->run_event_loop(bucket->io);
2789
- /* restore timeout if it wasn't changed */
2790
- if (bucket->timeout == new_tmo) {
2791
- libcouchbase_set_timeout(bucket->handle, old_tmo);
2792
- }
2793
- if (bucket->exception != Qnil) {
2794
- exc = bucket->exception;
2795
- bucket->exception = Qnil;
2796
- rb_exc_raise(exc);
2797
- }
2798
- }
2799
- return Qnil;
2800
- }
2801
-
2802
- static VALUE
2803
- ensure_run(VALUE *args)
2804
- {
2805
- VALUE self = args[0];
2806
- bucket_t *bucket = DATA_PTR(self);
2807
-
2808
- bucket->async = 0;
2809
- return Qnil;
2810
- }
2811
-
2812
- /*
2813
- * Run the event loop.
2814
- *
2815
- * @yieldparam [Bucket] bucket the bucket instance
2816
- *
2817
- * @example Use block to run the loop
2818
- * c = Couchbase.new
2819
- * c.run do
2820
- * c.get("foo") {|ret| puts ret.value}
2821
- * end
2822
- *
2823
- * @example Use lambda to run the loop
2824
- * c = Couchbase.new
2825
- * operations = lambda do |c|
2826
- * c.get("foo") {|ret| puts ret.value}
2827
- * end
2828
- * c.run(&operations)
2829
- *
2830
- * @return [nil]
2831
- *
2832
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2833
- */
2834
- static VALUE
2835
- cb_bucket_run(VALUE self)
2836
- {
2837
- VALUE args[2];
2838
-
2839
- rb_need_block();
2840
- args[0] = self;
2841
- args[1] = rb_block_proc();
2842
- rb_ensure(do_run, (VALUE)args, ensure_run, (VALUE)args);
2843
- return Qnil;
2844
- }
2845
-
2846
- /*
2847
- * Unconditionally store the object in the Couchbase
2848
- *
2849
- * @overload set(key, value, options = {})
2850
- *
2851
- * @param key [String, Symbol] Key used to reference the value.
2852
- * @param value [Object] Value to be stored
2853
- * @param options [Hash] Options for operation.
2854
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2855
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2856
- * absolute times (from the epoch).
2857
- * @option options [Fixnum] :flags (self.default_flags) Flags for storage
2858
- * options. Flags are ignored by the server but preserved for use by the
2859
- * client. For more info see {Bucket#default_flags}.
2860
- * @option options [Symbol] :format (self.default_format) The
2861
- * representation for storing the value in the bucket. For more info see
2862
- * {Bucket#default_format}.
2863
- * @option options [Fixnum] :cas The CAS value for an object. This value
2864
- * created on the server and is guaranteed to be unique for each value of
2865
- * a given key. This value is used to provide simple optimistic
2866
- * concurrency control when multiple clients or threads try to update an
2867
- * item simultaneously.
2868
- *
2869
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2870
- * (valid attributes: +error+, +operation+, +key+).
2871
- *
2872
- * @return [Fixnum] The CAS value of the object.
2873
- *
2874
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect}).
2875
- * @raise [Couchbase::Error::KeyExists] if the key already exists on the
2876
- * server.
2877
- * @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
2878
- * with chosen encoder, e.g. if you try to store the Hash in +:plain+
2879
- * mode.
2880
- * @raise [ArgumentError] when passing the block in synchronous mode
2881
- *
2882
- * @example Store the key which will be expired in 2 seconds using relative TTL.
2883
- * c.set("foo", "bar", :ttl => 2)
2884
- *
2885
- * @example Store the key which will be expired in 2 seconds using absolute TTL.
2886
- * c.set("foo", "bar", :ttl => Time.now.to_i + 2)
2887
- *
2888
- * @example Force JSON document format for value
2889
- * c.set("foo", {"bar" => "baz}, :format => :document)
2890
- *
2891
- * @example Use hash-like syntax to store the value
2892
- * c.set["foo"] = {"bar" => "baz}
2893
- *
2894
- * @example Use extended hash-like syntax
2895
- * c["foo", {:flags => 0x1000, :format => :plain}] = "bar"
2896
- * c["foo", :flags => 0x1000] = "bar" # for ruby 1.9.x only
2897
- *
2898
- * @example Set application specific flags (note that it will be OR-ed with format flags)
2899
- * c.set("foo", "bar", :flags => 0x1000)
2900
- *
2901
- * @example Perform optimistic locking by specifying last known CAS version
2902
- * c.set("foo", "bar", :cas => 8835713818674332672)
2903
- *
2904
- * @example Perform asynchronous call
2905
- * c.run do
2906
- * c.set("foo", "bar") do |ret|
2907
- * ret.operation #=> :set
2908
- * ret.success? #=> true
2909
- * ret.key #=> "foo"
2910
- * ret.cas
2911
- * end
2912
- * end
2913
- */
2914
- static VALUE
2915
- cb_bucket_set(int argc, VALUE *argv, VALUE self)
2916
- {
2917
- return cb_bucket_store(LIBCOUCHBASE_SET, argc, argv, self);
2918
- }
2919
-
2920
- /*
2921
- * Add the item to the database, but fail if the object exists already
2922
- *
2923
- * @overload add(key, value, options = {})
2924
- * @param key [String, Symbol] Key used to reference the value.
2925
- * @param value [Object] Value to be stored
2926
- * @param options [Hash] Options for operation.
2927
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2928
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2929
- * absolute times (from the epoch).
2930
- * @option options [Fixnum] :flags (self.default_flags) Flags for storage
2931
- * options. Flags are ignored by the server but preserved for use by the
2932
- * client. For more info see {Bucket#default_flags}.
2933
- * @option options [Symbol] :format (self.default_format) The
2934
- * representation for storing the value in the bucket. For more info see
2935
- * {Bucket#default_format}.
2936
- * @option options [Fixnum] :cas The CAS value for an object. This value
2937
- * created on the server and is guaranteed to be unique for each value of
2938
- * a given key. This value is used to provide simple optimistic
2939
- * concurrency control when multiple clients or threads try to update an
2940
- * item simultaneously.
2941
- *
2942
- * @yieldparam ret [Result] the result of operation in asynchronous mode
2943
- * (valid attributes: +error+, +operation+, +key+).
2944
- *
2945
- * @return [Fixnum] The CAS value of the object.
2946
- *
2947
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2948
- * @raise [Couchbase::Error::KeyExists] if the key already exists on the
2949
- * server
2950
- * @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
2951
- * with chosen encoder, e.g. if you try to store the Hash in +:plain+
2952
- * mode.
2953
- * @raise [ArgumentError] when passing the block in synchronous mode
2954
- *
2955
- * @example Add the same key twice
2956
- * c.add("foo", "bar") #=> stored successully
2957
- * c.add("foo", "baz") #=> will raise Couchbase::Error::KeyExists: failed to store value (key="foo", error=0x0c)
2958
- */
2959
- static VALUE
2960
- cb_bucket_add(int argc, VALUE *argv, VALUE self)
2961
- {
2962
- return cb_bucket_store(LIBCOUCHBASE_ADD, argc, argv, self);
2963
- }
2964
-
2965
- /*
2966
- * Replace the existing object in the database
2967
- *
2968
- * @overload replace(key, value, options = {})
2969
- * @param key [String, Symbol] Key used to reference the value.
2970
- * @param value [Object] Value to be stored
2971
- * @param options [Hash] Options for operation.
2972
- * @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
2973
- * Values larger than 30*24*60*60 seconds (30 days) are interpreted as
2974
- * absolute times (from the epoch).
2975
- * @option options [Fixnum] :flags (self.default_flags) Flags for storage
2976
- * options. Flags are ignored by the server but preserved for use by the
2977
- * client. For more info see {Bucket#default_flags}.
2978
- * @option options [Symbol] :format (self.default_format) The
2979
- * representation for storing the value in the bucket. For more info see
2980
- * {Bucket#default_format}.
2981
- *
2982
- * @return [Fixnum] The CAS value of the object.
2983
- *
2984
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
2985
- * @raise [Couchbase::Error::NotFound] if the key doesn't exists
2986
- * @raise [Couchbase::Error::KeyExists] on CAS mismatch
2987
- * @raise [ArgumentError] when passing the block in synchronous mode
2988
- *
2989
- * @example Replacing missing key
2990
- * c.replace("foo", "baz") #=> will raise Couchbase::Error::NotFound: failed to store value (key="foo", error=0x0d)
2991
- */
2992
- static VALUE
2993
- cb_bucket_replace(int argc, VALUE *argv, VALUE self)
2994
- {
2995
- return cb_bucket_store(LIBCOUCHBASE_REPLACE, argc, argv, self);
2996
- }
2997
-
2998
- /*
2999
- * Append this object to the existing object
3000
- *
3001
- * @note This operation is kind of data-aware from server point of view.
3002
- * This mean that the server treats value as binary stream and just
3003
- * perform concatenation, therefore it won't work with +:marshal+ and
3004
- * +:document+ formats, because of lack of knowledge how to merge values
3005
- * in these formats. See Bucket#cas for workaround.
3006
- *
3007
- * @overload append(key, value, options = {})
3008
- * @param key [String, Symbol] Key used to reference the value.
3009
- * @param value [Object] Value to be stored
3010
- * @param options [Hash] Options for operation.
3011
- * @option options [Fixnum] :cas The CAS value for an object. This value
3012
- * created on the server and is guaranteed to be unique for each value of
3013
- * a given key. This value is used to provide simple optimistic
3014
- * concurrency control when multiple clients or threads try to update an
3015
- * item simultaneously.
3016
- * @option options [Symbol] :format (self.default_format) The
3017
- * representation for storing the value in the bucket. For more info see
3018
- * {Bucket#default_format}.
3019
- *
3020
- * @return [Fixnum] The CAS value of the object.
3021
- *
3022
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
3023
- * @raise [Couchbase::Error::KeyExists] on CAS mismatch
3024
- * @raise [Couchbase::Error::NotStored] if the key doesn't exist
3025
- * @raise [ArgumentError] when passing the block in synchronous mode
3026
- *
3027
- * @example Simple append
3028
- * c.set("foo", "aaa")
3029
- * c.append("foo", "bbb")
3030
- * c.get("foo") #=> "aaabbb"
3031
- *
3032
- * @example Implementing sets using append
3033
- * def set_add(key, *values)
3034
- * encoded = values.flatten.map{|v| "+#{v} "}.join
3035
- * append(key, encoded)
3036
- * end
3037
- *
3038
- * def set_remove(key, *values)
3039
- * encoded = values.flatten.map{|v| "-#{v} "}.join
3040
- * append(key, encoded)
3041
- * end
3042
- *
3043
- * def set_get(key)
3044
- * encoded = get(key)
3045
- * ret = Set.new
3046
- * encoded.split(' ').each do |v|
3047
- * op, val = v[0], v[1..-1]
3048
- * case op
3049
- * when "-"
3050
- * ret.delete(val)
3051
- * when "+"
3052
- * ret.add(val)
3053
- * end
3054
- * end
3055
- * ret
3056
- * end
3057
- *
3058
- * @example Using optimistic locking. The operation will fail on CAS mismatch
3059
- * ver = c.set("foo", "aaa")
3060
- * c.append("foo", "bbb", :cas => ver)
3061
- */
3062
- static VALUE
3063
- cb_bucket_append(int argc, VALUE *argv, VALUE self)
3064
- {
3065
- return cb_bucket_store(LIBCOUCHBASE_APPEND, argc, argv, self);
3066
- }
3067
-
3068
- /*
3069
- * Prepend this object to the existing object
3070
- *
3071
- * @note This operation is kind of data-aware from server point of view.
3072
- * This mean that the server treats value as binary stream and just
3073
- * perform concatenation, therefore it won't work with +:marshal+ and
3074
- * +:document+ formats, because of lack of knowledge how to merge values
3075
- * in these formats. See Bucket#cas for workaround.
3076
- *
3077
- * @overload prepend(key, value, options = {})
3078
- * @param key [String, Symbol] Key used to reference the value.
3079
- * @param value [Object] Value to be stored
3080
- * @param options [Hash] Options for operation.
3081
- * @option options [Fixnum] :cas The CAS value for an object. This value
3082
- * created on the server and is guaranteed to be unique for each value of
3083
- * a given key. This value is used to provide simple optimistic
3084
- * concurrency control when multiple clients or threads try to update an
3085
- * item simultaneously.
3086
- * @option options [Symbol] :format (self.default_format) The
3087
- * representation for storing the value in the bucket. For more info see
3088
- * {Bucket#default_format}.
3089
- *
3090
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
3091
- * @raise [Couchbase::Error::KeyExists] on CAS mismatch
3092
- * @raise [Couchbase::Error::NotStored] if the key doesn't exist
3093
- * @raise [ArgumentError] when passing the block in synchronous mode
3094
- *
3095
- * @example Simple prepend example
3096
- * c.set("foo", "aaa")
3097
- * c.prepend("foo", "bbb")
3098
- * c.get("foo") #=> "bbbaaa"
3099
- *
3100
- * @example Using explicit format option
3101
- * c.default_format #=> :document
3102
- * c.set("foo", {"y" => "z"})
3103
- * c.prepend("foo", '[', :format => :plain)
3104
- * c.append("foo", ', {"z": "y"}]', :format => :plain)
3105
- * c.get("foo") #=> [{"y"=>"z"}, {"z"=>"y"}]
3106
- *
3107
- * @example Using optimistic locking. The operation will fail on CAS mismatch
3108
- * ver = c.set("foo", "aaa")
3109
- * c.prepend("foo", "bbb", :cas => ver)
3110
- */
3111
- static VALUE
3112
- cb_bucket_prepend(int argc, VALUE *argv, VALUE self)
3113
- {
3114
- return cb_bucket_store(LIBCOUCHBASE_PREPEND, argc, argv, self);
3115
- }
3116
-
3117
- static VALUE
3118
- cb_bucket_aset(int argc, VALUE *argv, VALUE self)
3119
- {
3120
- VALUE temp;
3121
-
3122
- if (argc == 3) {
3123
- /* swap opts and value, because value goes last for []= */
3124
- temp = argv[2];
3125
- argv[2] = argv[1];
3126
- argv[1] = temp;
3127
- }
3128
- return cb_bucket_set(argc, argv, self);
3129
- }
3130
-
3131
- /*
3132
- * Close the connection to the cluster
3133
- *
3134
- * @return [true]
3135
- *
3136
- * @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
3137
- */
3138
- static VALUE
3139
- cb_bucket_disconnect(VALUE self)
3140
- {
3141
- bucket_t *bucket = DATA_PTR(self);
3142
-
3143
- if (bucket->handle) {
3144
- libcouchbase_destroy(bucket->handle);
3145
- bucket->handle = NULL;
3146
- bucket->io = NULL;
3147
- return Qtrue;
3148
- } else {
3149
- rb_raise(eConnectError, "closed connection");
3150
- }
3151
- }
3152
-
3153
- /*
3154
- * Check if result of operation was successful.
3155
- *
3156
- * @return [Boolean] +false+ if there is an +error+ object attached,
3157
- * +false+ otherwise.
3158
- */
3159
- static VALUE
3160
- cb_result_success_p(VALUE self)
3161
- {
3162
- return RTEST(rb_ivar_get(self, id_iv_error)) ? Qfalse : Qtrue;
3163
- }
3164
-
3165
- /*
3166
- * Returns a string containing a human-readable representation of the Result.
3167
- *
3168
- * @return [String]
3169
- */
3170
- static VALUE
3171
- cb_result_inspect(VALUE self)
3172
- {
3173
- VALUE str, attr, error;
3174
- char buf[100];
3175
-
3176
- str = rb_str_buf_new2("#<");
3177
- rb_str_buf_cat2(str, rb_obj_classname(self));
3178
- snprintf(buf, 100, ":%p", (void *)self);
3179
- rb_str_buf_cat2(str, buf);
3180
-
3181
- attr = rb_ivar_get(self, id_iv_error);
3182
- if (RTEST(attr)) {
3183
- error = rb_ivar_get(attr, id_iv_error);
3184
- } else {
3185
- error = INT2FIX(0);
3186
- }
3187
- rb_str_buf_cat2(str, " error=0x");
3188
- rb_str_append(str, rb_funcall(error, id_to_s, 1, INT2FIX(16)));
3189
-
3190
- attr = rb_ivar_get(self, id_iv_key);
3191
- if (RTEST(attr)) {
3192
- rb_str_buf_cat2(str, " key=");
3193
- rb_str_append(str, rb_inspect(attr));
3194
- }
3195
-
3196
- attr = rb_ivar_get(self, id_iv_cas);
3197
- if (RTEST(attr)) {
3198
- rb_str_buf_cat2(str, " cas=");
3199
- rb_str_append(str, rb_inspect(attr));
3200
- }
3201
-
3202
- attr = rb_ivar_get(self, id_iv_flags);
3203
- if (RTEST(attr)) {
3204
- rb_str_buf_cat2(str, " flags=0x");
3205
- rb_str_append(str, rb_funcall(attr, id_to_s, 1, INT2FIX(16)));
3206
- }
3207
-
3208
- attr = rb_ivar_get(self, id_iv_node);
3209
- if (RTEST(attr)) {
3210
- rb_str_buf_cat2(str, " node=");
3211
- rb_str_append(str, rb_inspect(attr));
3212
- }
3213
- rb_str_buf_cat2(str, ">");
3214
-
3215
- return str;
3216
- }
3217
160
 
3218
161
  /* Ruby Extension initializer */
3219
162
  void
3220
163
  Init_couchbase_ext(void)
3221
164
  {
3222
- mJSON = rb_const_get(rb_cObject, rb_intern("JSON"));
165
+ mMultiJson = rb_const_get(rb_cObject, rb_intern("MultiJson"));
3223
166
  mURI = rb_const_get(rb_cObject, rb_intern("URI"));
3224
167
  mMarshal = rb_const_get(rb_cObject, rb_intern("Marshal"));
3225
168
  mCouchbase = rb_define_module("Couchbase");
3226
169
 
3227
170
  mError = rb_define_module_under(mCouchbase, "Error");
3228
171
  /* Document-class: Couchbase::Error::Base
3229
- * The base error class */
3230
- eBaseError = rb_define_class_under(mError, "Base", rb_eRuntimeError);
172
+ * The base error class
173
+ *
174
+ * @since 1.0.0
175
+ */
176
+ eBaseError = rb_define_class_under(mError, "Base", rb_eStandardError);
3231
177
  /* Document-class: Couchbase::Error::Auth
3232
- * Authentication error */
178
+ * Authentication error
179
+ *
180
+ * @since 1.0.0
181
+ */
3233
182
  eAuthError = rb_define_class_under(mError, "Auth", eBaseError);
3234
183
  /* Document-class: Couchbase::Error::BucketNotFound
3235
- * The given bucket not found in the cluster */
184
+ * The given bucket not found in the cluster
185
+ *
186
+ * @since 1.0.0
187
+ */
3236
188
  eBucketNotFoundError = rb_define_class_under(mError, "BucketNotFound", eBaseError);
3237
189
  /* Document-class: Couchbase::Error::Busy
3238
- * The cluster is too busy now. Try again later */
190
+ * The cluster is too busy now. Try again later
191
+ *
192
+ * @since 1.0.0
193
+ */
3239
194
  eBusyError = rb_define_class_under(mError, "Busy", eBaseError);
3240
195
  /* Document-class: Couchbase::Error::DeltaBadval
3241
- * The given value is not a number */
196
+ * The given value is not a number
197
+ *
198
+ * @since 1.0.0
199
+ */
3242
200
  eDeltaBadvalError = rb_define_class_under(mError, "DeltaBadval", eBaseError);
3243
201
  /* Document-class: Couchbase::Error::Internal
3244
- * Internal error */
202
+ * Internal error
203
+ *
204
+ * @since 1.0.0
205
+ */
3245
206
  eInternalError = rb_define_class_under(mError, "Internal", eBaseError);
3246
207
  /* Document-class: Couchbase::Error::Invalid
3247
- * Invalid arguments */
208
+ * Invalid arguments
209
+ *
210
+ * @since 1.0.0
211
+ */
3248
212
  eInvalidError = rb_define_class_under(mError, "Invalid", eBaseError);
3249
213
  /* Document-class: Couchbase::Error::KeyExists
3250
- * Key already exists */
214
+ * Key already exists
215
+ *
216
+ * @since 1.0.0
217
+ */
3251
218
  eKeyExistsError = rb_define_class_under(mError, "KeyExists", eBaseError);
3252
219
  /* Document-class: Couchbase::Error::Libcouchbase
3253
- * Generic error */
220
+ * Generic error
221
+ *
222
+ * @since 1.0.0
223
+ */
3254
224
  eLibcouchbaseError = rb_define_class_under(mError, "Libcouchbase", eBaseError);
3255
225
  /* Document-class: Couchbase::Error::Libevent
3256
- * Problem using libevent */
226
+ * Problem using libevent
227
+ *
228
+ * @since 1.0.0
229
+ */
3257
230
  eLibeventError = rb_define_class_under(mError, "Libevent", eBaseError);
3258
231
  /* Document-class: Couchbase::Error::Network
3259
- * Network error */
232
+ * Network error
233
+ *
234
+ * @since 1.0.0
235
+ */
3260
236
  eNetworkError = rb_define_class_under(mError, "Network", eBaseError);
3261
237
  /* Document-class: Couchbase::Error::NoMemory
3262
- * Out of memory error */
238
+ * Out of memory error (on Server)
239
+ *
240
+ * @since 1.0.0
241
+ */
3263
242
  eNoMemoryError = rb_define_class_under(mError, "NoMemory", eBaseError);
243
+ /* Document-class: Couchbase::Error::ClientNoMemory
244
+ * Out of memory error (on Client)
245
+ *
246
+ * @since 1.2.0.dp6
247
+ */
248
+ eClientNoMemoryError = rb_define_class_under(mError, "ClientNoMemory", eBaseError);
3264
249
  /* Document-class: Couchbase::Error::NotFound
3265
- * No such key */
250
+ * No such key
251
+ *
252
+ * @since 1.0.0
253
+ */
3266
254
  eNotFoundError = rb_define_class_under(mError, "NotFound", eBaseError);
3267
255
  /* Document-class: Couchbase::Error::NotMyVbucket
3268
- * The vbucket is not located on this server */
256
+ * The vbucket is not located on this server
257
+ *
258
+ * @since 1.0.0
259
+ */
3269
260
  eNotMyVbucketError = rb_define_class_under(mError, "NotMyVbucket", eBaseError);
3270
261
  /* Document-class: Couchbase::Error::NotStored
3271
- * Not stored */
262
+ * Not stored
263
+ *
264
+ * @since 1.0.0
265
+ */
3272
266
  eNotStoredError = rb_define_class_under(mError, "NotStored", eBaseError);
3273
267
  /* Document-class: Couchbase::Error::NotSupported
3274
- * Not supported */
268
+ * Not supported
269
+ *
270
+ * @since 1.0.0
271
+ */
3275
272
  eNotSupportedError = rb_define_class_under(mError, "NotSupported", eBaseError);
3276
273
  /* Document-class: Couchbase::Error::Range
3277
- * Invalid range */
274
+ * Invalid range
275
+ *
276
+ * @since 1.0.0
277
+ */
3278
278
  eRangeError = rb_define_class_under(mError, "Range", eBaseError);
3279
279
  /* Document-class: Couchbase::Error::TemporaryFail
3280
- * Temporary failure. Try again later */
280
+ * Temporary failure. Try again later
281
+ *
282
+ * @since 1.0.0
283
+ */
3281
284
  eTmpFailError = rb_define_class_under(mError, "TemporaryFail", eBaseError);
285
+ /* Document-class: Couchbase::Error::ClientTemporaryFail
286
+ * Temporary failure (on Client)
287
+ *
288
+ * @since 1.2.0
289
+ */
290
+ eClientTmpFailError = rb_define_class_under(mError, "ClientTemporaryFail", eBaseError);
3282
291
  /* Document-class: Couchbase::Error::TooBig
3283
- * Object too big */
292
+ * Object too big
293
+ *
294
+ * @since 1.0.0
295
+ */
3284
296
  eTooBigError = rb_define_class_under(mError, "TooBig", eBaseError);
3285
297
  /* Document-class: Couchbase::Error::UnknownCommand
3286
- * Unknown command */
298
+ * Unknown command
299
+ *
300
+ * @since 1.0.0
301
+ */
3287
302
  eUnknownCommandError = rb_define_class_under(mError, "UnknownCommand", eBaseError);
3288
303
  /* Document-class: Couchbase::Error::UnknownHost
3289
- * Unknown host */
304
+ * Unknown host
305
+ *
306
+ * @since 1.0.0
307
+ */
3290
308
  eUnknownHostError = rb_define_class_under(mError, "UnknownHost", eBaseError);
3291
309
  /* Document-class: Couchbase::Error::ValueFormat
3292
- * Failed to decode or encode value */
310
+ * Failed to decode or encode value
311
+ *
312
+ * @since 1.0.0
313
+ */
3293
314
  eValueFormatError = rb_define_class_under(mError, "ValueFormat", eBaseError);
3294
315
  /* Document-class: Couchbase::Error::Protocol
3295
- * Protocol error */
316
+ * Protocol error
317
+ *
318
+ * @since 1.0.0
319
+ */
3296
320
  eProtocolError = rb_define_class_under(mError, "Protocol", eBaseError);
3297
321
  /* Document-class: Couchbase::Error::Timeout
3298
- * Timeout error */
322
+ * Timeout error
323
+ *
324
+ * @since 1.1.0
325
+ */
3299
326
  eTimeoutError = rb_define_class_under(mError, "Timeout", eBaseError);
3300
327
  /* Document-class: Couchbase::Error::Connect
3301
- * Connect error */
328
+ * Connect error
329
+ *
330
+ * @since 1.1.0
331
+ */
3302
332
  eConnectError = rb_define_class_under(mError, "Connect", eBaseError);
3303
333
 
3304
334
  /* Document-method: error
3305
- * @return [Boolean] the error code from libcouchbase */
335
+ *
336
+ * The underlying libcouchbase library could return one of the following
337
+ * error codes. The ruby client will wrap these errors into appropriate
338
+ * exception class, derived from {Couchbase::Error::Base}.
339
+ *
340
+ * 0x00 :: LCB_SUCCESS (Success)
341
+ * 0x01 :: LCB_AUTH_CONTINUE (Continue authentication)
342
+ * 0x02 :: LCB_AUTH_ERROR (Authentication error)
343
+ * 0x03 :: LCB_DELTA_BADVAL (Not a number)
344
+ * 0x04 :: LCB_E2BIG (Object too big)
345
+ * 0x05 :: LCB_EBUSY (Too busy. Try again later)
346
+ * 0x06 :: LCB_EINTERNAL (Internal error)
347
+ * 0x07 :: LCB_EINVAL (Invalid arguments)
348
+ * 0x08 :: LCB_ENOMEM (Out of memory)
349
+ * 0x09 :: LCB_ERANGE (Invalid range)
350
+ * 0x0a :: LCB_ERROR (Generic error)
351
+ * 0x0b :: LCB_ETMPFAIL (Temporary failure. Try again later)
352
+ * 0x0c :: LCB_KEY_EEXISTS (Key exists (with a different CAS value))
353
+ * 0x0d :: LCB_KEY_ENOENT (No such key)
354
+ * 0x0e :: LCB_LIBEVENT_ERROR (Problem using libevent)
355
+ * 0x0f :: LCB_NETWORK_ERROR (Network error)
356
+ * 0x10 :: LCB_NOT_MY_VBUCKET (The vbucket is not located on this server)
357
+ * 0x11 :: LCB_NOT_STORED (Not stored)
358
+ * 0x12 :: LCB_NOT_SUPPORTED (Not supported)
359
+ * 0x13 :: LCB_UNKNOWN_COMMAND (Unknown command)
360
+ * 0x14 :: LCB_UNKNOWN_HOST (Unknown host)
361
+ * 0x15 :: LCB_PROTOCOL_ERROR (Protocol error)
362
+ * 0x16 :: LCB_ETIMEDOUT (Operation timed out)
363
+ * 0x17 :: LCB_CONNECT_ERROR (Connection failure)
364
+ * 0x18 :: LCB_BUCKET_ENOENT (No such bucket)
365
+ * 0x18 :: LCB_CLIENT_ENOMEM (Out of memory on the client)
366
+ *
367
+ * @since 1.0.0
368
+ *
369
+ * @return [Fixnum] the error code from libcouchbase
370
+ */
3306
371
  rb_define_attr(eBaseError, "error", 1, 0);
3307
372
  id_iv_error = rb_intern("@error");
373
+ /* Document-method: status
374
+ *
375
+ * @since 1.2.0.beta
376
+ *
377
+ * @return [Fixnum] The HTTP status code */
378
+ rb_define_attr(eBaseError, "status", 1, 0);
379
+ id_iv_status = rb_intern("@status");
3308
380
  /* Document-method: key
381
+ *
382
+ * @since 1.0.0
383
+ *
3309
384
  * @return [String] the key which generated error */
3310
385
  rb_define_attr(eBaseError, "key", 1, 0);
3311
386
  id_iv_key = rb_intern("@key");
3312
387
  /* Document-method: cas
388
+ *
389
+ * @since 1.0.0
390
+ *
3313
391
  * @return [Fixnum] the version of the key (+nil+ unless accessible) */
3314
392
  rb_define_attr(eBaseError, "cas", 1, 0);
3315
393
  id_iv_cas = rb_intern("@cas");
3316
394
  /* Document-method: operation
395
+ *
396
+ * @since 1.0.0
397
+ *
3317
398
  * @return [Symbol] the operation (+nil+ unless accessible) */
3318
399
  rb_define_attr(eBaseError, "operation", 1, 0);
3319
400
  id_iv_operation = rb_intern("@operation");
3320
401
 
3321
402
  /* Document-class: Couchbase::Result
3322
- * The object which yielded to asynchronous callbacks */
403
+ *
404
+ * The object which yielded to asynchronous callbacks
405
+ *
406
+ * @since 1.0.0
407
+ */
3323
408
  cResult = rb_define_class_under(mCouchbase, "Result", rb_cObject);
3324
409
  rb_define_method(cResult, "inspect", cb_result_inspect, 0);
3325
410
  rb_define_method(cResult, "success?", cb_result_success_p, 0);
3326
411
  /* Document-method: operation
3327
- * @return [Symbol] */
412
+ *
413
+ * @since 1.0.0
414
+ *
415
+ * @return [Symbol]
416
+ */
3328
417
  rb_define_attr(cResult, "operation", 1, 0);
3329
418
  /* Document-method: error
3330
- * @return [Couchbase::Error::Base] */
419
+ *
420
+ * @since 1.0.0
421
+ *
422
+ * @return [Couchbase::Error::Base]
423
+ */
3331
424
  rb_define_attr(cResult, "error", 1, 0);
3332
425
  /* Document-method: key
3333
- * @return [String] */
426
+ *
427
+ * @since 1.0.0
428
+ *
429
+ * @return [String]
430
+ */
3334
431
  rb_define_attr(cResult, "key", 1, 0);
3335
432
  id_iv_key = rb_intern("@key");
3336
433
  /* Document-method: value
3337
- * @return [String] */
434
+ *
435
+ * @since 1.0.0
436
+ *
437
+ * @return [String]
438
+ */
3338
439
  rb_define_attr(cResult, "value", 1, 0);
3339
440
  id_iv_value = rb_intern("@value");
3340
441
  /* Document-method: cas
3341
- * @return [Fixnum] */
442
+ *
443
+ * @since 1.0.0
444
+ *
445
+ * @return [Fixnum]
446
+ */
3342
447
  rb_define_attr(cResult, "cas", 1, 0);
3343
448
  id_iv_cas = rb_intern("@cas");
3344
449
  /* Document-method: flags
3345
- * @return [Fixnum] */
450
+ *
451
+ * @since 1.0.0
452
+ *
453
+ * @return [Fixnum]
454
+ */
3346
455
  rb_define_attr(cResult, "flags", 1, 0);
3347
456
  id_iv_flags = rb_intern("@flags");
3348
457
  /* Document-method: node
3349
- * @return [String] */
458
+ *
459
+ * @since 1.0.0
460
+ *
461
+ * @return [String]
462
+ */
3350
463
  rb_define_attr(cResult, "node", 1, 0);
3351
464
  id_iv_node = rb_intern("@node");
465
+ /* Document-method: headers
466
+ *
467
+ * @since 1.2.0
468
+ *
469
+ * HTTP headers
470
+ *
471
+ * @return [Hash]
472
+ */
473
+ rb_define_attr(cResult, "headers", 1, 0);
474
+ id_iv_headers = rb_intern("@headers");
475
+ /* Document-method: completed
476
+ * In {Bucket::CouchRequest} operations used to mark the final call
477
+ * @return [Boolean] */
478
+ rb_define_attr(cResult, "completed", 1, 0);
479
+ rb_define_alias(cResult, "completed?", "completed");
480
+ id_iv_completed = rb_intern("@completed");
481
+ /* Document-method: status
482
+ *
483
+ * @since 1.2.0.dp6
484
+ *
485
+ * @see Bucket#observe
486
+ *
487
+ * Status of the key. Possible values:
488
+ * +:found+ :: Key found in cache, but not yet persisted
489
+ * +:persisted+ :: Key found and persisted
490
+ * +:not_found+ :: Key not found
491
+ *
492
+ * @return [Symbol]
493
+ */
494
+ rb_define_attr(cResult, "status", 1, 0);
495
+ id_iv_status = rb_intern("@status");
496
+ /* Document-method: from_master
497
+ *
498
+ * @since 1.2.0.dp6
499
+ *
500
+ * @see Bucket#observe
501
+ *
502
+ * True if key stored on master
503
+ * @return [Boolean]
504
+ */
505
+ rb_define_attr(cResult, "from_master", 1, 0);
506
+ rb_define_alias(cResult, "from_master?", "from_master");
507
+ id_iv_from_master = rb_intern("@from_master");
508
+ /* Document-method: time_to_persist
509
+ *
510
+ * @since 1.2.0.dp6
511
+ *
512
+ * @see Bucket#observe
513
+ *
514
+ * Average time needed to persist key on the disk (zero if unavailable)
515
+ * @return [Fixnum]
516
+ */
517
+ rb_define_attr(cResult, "time_to_persist", 1, 0);
518
+ rb_define_alias(cResult, "ttp", "time_to_persist");
519
+ id_iv_time_to_persist = rb_intern("@time_to_persist");
520
+ /* Document-method: time_to_persist
521
+ *
522
+ * @since 1.2.0.dp6
523
+ *
524
+ * @see Bucket#observe
525
+ *
526
+ * Average time needed to replicate key on the disk (zero if unavailable)
527
+ * @return [Fixnum]
528
+ */
529
+ rb_define_attr(cResult, "time_to_replicate", 1, 0);
530
+ rb_define_alias(cResult, "ttr", "time_to_replicate");
531
+ id_iv_time_to_replicate = rb_intern("@time_to_replicate");
3352
532
 
3353
533
  /* Document-class: Couchbase::Bucket
534
+ *
3354
535
  * This class in charge of all stuff connected to communication with
3355
- * Couchbase. */
536
+ * Couchbase.
537
+ *
538
+ * @since 1.0.0
539
+ */
3356
540
  cBucket = rb_define_class_under(mCouchbase, "Bucket", rb_cObject);
3357
541
 
3358
542
  /* 0x03: Bitmask for flag bits responsible for format */
@@ -3378,27 +562,25 @@ Init_couchbase_ext(void)
3378
562
  rb_define_method(cBucket, "initialize_copy", cb_bucket_init_copy, 1);
3379
563
  rb_define_method(cBucket, "inspect", cb_bucket_inspect, 0);
3380
564
 
3381
- /* Document-method: seqno
3382
- * The number of scheduled commands */
3383
- /* rb_define_attr(cBucket, "seqno", 1, 0); */
3384
- rb_define_method(cBucket, "seqno", cb_bucket_seqno, 0);
3385
-
3386
565
  rb_define_method(cBucket, "add", cb_bucket_add, -1);
3387
566
  rb_define_method(cBucket, "append", cb_bucket_append, -1);
3388
567
  rb_define_method(cBucket, "prepend", cb_bucket_prepend, -1);
3389
568
  rb_define_method(cBucket, "replace", cb_bucket_replace, -1);
3390
569
  rb_define_method(cBucket, "set", cb_bucket_set, -1);
3391
570
  rb_define_method(cBucket, "get", cb_bucket_get, -1);
3392
- rb_define_method(cBucket, "run", cb_bucket_run, 0);
571
+ rb_define_method(cBucket, "run", cb_bucket_run, -1);
572
+ rb_define_method(cBucket, "stop", cb_bucket_stop, 0);
3393
573
  rb_define_method(cBucket, "touch", cb_bucket_touch, -1);
3394
574
  rb_define_method(cBucket, "delete", cb_bucket_delete, -1);
3395
575
  rb_define_method(cBucket, "stats", cb_bucket_stats, -1);
3396
- rb_define_method(cBucket, "flush", cb_bucket_flush, 0);
3397
- rb_define_method(cBucket, "version", cb_bucket_version, 0);
576
+ rb_define_method(cBucket, "version", cb_bucket_version, -1);
3398
577
  rb_define_method(cBucket, "incr", cb_bucket_incr, -1);
3399
578
  rb_define_method(cBucket, "decr", cb_bucket_decr, -1);
579
+ rb_define_method(cBucket, "unlock", cb_bucket_unlock, -1);
3400
580
  rb_define_method(cBucket, "disconnect", cb_bucket_disconnect, 0);
3401
581
  rb_define_method(cBucket, "reconnect", cb_bucket_reconnect, -1);
582
+ rb_define_method(cBucket, "make_http_request", cb_bucket_make_http_request, -1);
583
+ rb_define_method(cBucket, "observe", cb_bucket_observe, -1);
3402
584
 
3403
585
  rb_define_alias(cBucket, "decrement", "decr");
3404
586
  rb_define_alias(cBucket, "increment", "incr");
@@ -3413,6 +595,8 @@ Init_couchbase_ext(void)
3413
595
  /* Document-method: quiet
3414
596
  * Flag specifying behaviour for operations on missing keys
3415
597
  *
598
+ * @since 1.0.0
599
+ *
3416
600
  * If it is +true+, the operations will silently return +nil+ or +false+
3417
601
  * instead of raising {Couchbase::Error::NotFound}.
3418
602
  *
@@ -3424,7 +608,7 @@ Init_couchbase_ext(void)
3424
608
  * connection.quiet = false
3425
609
  * connection.get("miss") #=> will raise Couchbase::Error::NotFound
3426
610
  *
3427
- * @return [Boolean] */
611
+ * @return [true, false] */
3428
612
  /* rb_define_attr(cBucket, "quiet", 1, 1); */
3429
613
  rb_define_method(cBucket, "quiet", cb_bucket_quiet_get, 0);
3430
614
  rb_define_method(cBucket, "quiet=", cb_bucket_quiet_set, 1);
@@ -3433,6 +617,8 @@ Init_couchbase_ext(void)
3433
617
  /* Document-method: default_flags
3434
618
  * Default flags for new values.
3435
619
  *
620
+ * @since 1.0.0
621
+ *
3436
622
  * The library reserves last two lower bits to store the format of the
3437
623
  * value. The can be masked via FMT_MASK constant.
3438
624
  *
@@ -3452,6 +638,10 @@ Init_couchbase_ext(void)
3452
638
  /* Document-method: default_format
3453
639
  * Default format for new values.
3454
640
  *
641
+ * @since 1.0.0
642
+ *
643
+ * @see http://couchbase.com/docs/couchbase-manual-2.0/couchbase-views-datastore.html
644
+ *
3455
645
  * It uses flags field to store the format. It accepts either the Symbol
3456
646
  * (+:document+, +:marshal+, +:plain+) or Fixnum (use constants
3457
647
  * FMT_DOCUMENT, FMT_MARSHAL, FMT_PLAIN) and silently ignores all
@@ -3487,16 +677,31 @@ Init_couchbase_ext(void)
3487
677
  rb_define_method(cBucket, "default_format=", cb_bucket_default_format_set, 1);
3488
678
 
3489
679
  /* Document-method: timeout
3490
- * @return [Fixnum] The timeout for the operations. The client will
3491
- * raise {Couchbase::Error::Timeout} exception for all commands which
3492
- * weren't completed in given timeslot. */
680
+ *
681
+ * @since 1.1.0
682
+ *
683
+ * @return [Fixnum] The timeout for the operations in microseconds. The
684
+ * client will raise {Couchbase::Error::Timeout} exception for all
685
+ * commands which weren't completed in given timeslot. */
3493
686
  /* rb_define_attr(cBucket, "timeout", 1, 1); */
3494
687
  rb_define_method(cBucket, "timeout", cb_bucket_timeout_get, 0);
3495
688
  rb_define_method(cBucket, "timeout=", cb_bucket_timeout_set, 1);
3496
689
 
690
+ /* Document-method: key_prefix
691
+ *
692
+ * @since 1.2.0.dp5
693
+ *
694
+ * @return [String] The library will prepend +key_prefix+ to each key to
695
+ * provide simple namespacing. */
696
+ /* rb_define_attr(cBucket, "key_prefix", 1, 1); */
697
+ rb_define_method(cBucket, "key_prefix", cb_bucket_key_prefix_get, 0);
698
+ rb_define_method(cBucket, "key_prefix=", cb_bucket_key_prefix_set, 1);
699
+
3497
700
  /* Document-method: on_error
3498
701
  * Error callback for asynchronous mode.
3499
702
  *
703
+ * @since 1.0.0
704
+ *
3500
705
  * This callback is using to deliver exceptions in asynchronous mode.
3501
706
  *
3502
707
  * @yieldparam [Symbol] op The operation caused the error
@@ -3520,27 +725,166 @@ Init_couchbase_ext(void)
3520
725
  rb_define_method(cBucket, "on_error", cb_bucket_on_error_get, 0);
3521
726
  rb_define_method(cBucket, "on_error=", cb_bucket_on_error_set, 1);
3522
727
 
728
+ /* Document-method: url
729
+ *
730
+ * The config url for this connection.
731
+ *
732
+ * Generally it is the bootstrap URL, but it could be different after
733
+ * cluster upgrade. This url is used to fetch the cluster
734
+ * configuration.
735
+ *
736
+ * @since 1.0.0
737
+ *
738
+ * @return [String] the address of the cluster management interface
739
+ */
3523
740
  /* rb_define_attr(cBucket, "url", 1, 0); */
3524
741
  rb_define_method(cBucket, "url", cb_bucket_url_get, 0);
742
+ /* Document-method: hostname
743
+ *
744
+ * The hostname of the current node
745
+ *
746
+ * @see Bucket#url
747
+ *
748
+ * @since 1.0.0
749
+ *
750
+ * @return [String] the host name of the management interface (default: "localhost")
751
+ */
3525
752
  /* rb_define_attr(cBucket, "hostname", 1, 0); */
3526
753
  rb_define_method(cBucket, "hostname", cb_bucket_hostname_get, 0);
754
+ /* Document-method: port
755
+ *
756
+ * The port of the current node
757
+ *
758
+ * @see Bucket#url
759
+ *
760
+ * @since 1.0.0
761
+ *
762
+ * @return [Fixnum] the port number of the management interface (default: 8091)
763
+ */
3527
764
  /* rb_define_attr(cBucket, "port", 1, 0); */
3528
765
  rb_define_method(cBucket, "port", cb_bucket_port_get, 0);
766
+ /* Document-method: authority
767
+ *
768
+ * The authority ("hostname:port") of the current node
769
+ *
770
+ * @see Bucket#url
771
+ *
772
+ * @since 1.0.0
773
+ *
774
+ * @return [String] host with port
775
+ */
3529
776
  /* rb_define_attr(cBucket, "authority", 1, 0); */
3530
777
  rb_define_method(cBucket, "authority", cb_bucket_authority_get, 0);
778
+ /* Document-method: bucket
779
+ *
780
+ * The bucket name of the current connection
781
+ *
782
+ * @see Bucket#url
783
+ *
784
+ * @since 1.0.0
785
+ *
786
+ * @return [String] the bucket name
787
+ */
3531
788
  /* rb_define_attr(cBucket, "bucket", 1, 0); */
3532
789
  rb_define_method(cBucket, "bucket", cb_bucket_bucket_get, 0);
3533
790
  rb_define_alias(cBucket, "name", "bucket");
791
+ /* Document-method: pool
792
+ *
793
+ * The pool name of the current connection
794
+ *
795
+ * @see Bucket#url
796
+ *
797
+ * @since 1.0.0
798
+ *
799
+ * @return [String] the pool name (usually "default")
800
+ */
3534
801
  /* rb_define_attr(cBucket, "pool", 1, 0); */
3535
802
  rb_define_method(cBucket, "pool", cb_bucket_pool_get, 0);
803
+ /* Document-method: username
804
+ *
805
+ * The user name used to connect to the cluster
806
+ *
807
+ * @see Bucket#url
808
+ *
809
+ * @since 1.0.0
810
+ *
811
+ * @return [String] the username for protected buckets (usually matches
812
+ * the bucket name)
813
+ */
3536
814
  /* rb_define_attr(cBucket, "username", 1, 0); */
3537
815
  rb_define_method(cBucket, "username", cb_bucket_username_get, 0);
816
+ /* Document-method: password
817
+ *
818
+ * The password used to connect to the cluster
819
+ *
820
+ * @since 1.0.0
821
+ *
822
+ * @return [String] the password for protected buckets
823
+ */
3538
824
  /* rb_define_attr(cBucket, "password", 1, 0); */
3539
825
  rb_define_method(cBucket, "password", cb_bucket_password_get, 0);
826
+ /* Document-method: environment
827
+ *
828
+ * The environment of the connection (+:development+ or +:production+)
829
+ *
830
+ * @since 1.2.0
831
+ *
832
+ * @return [Symbol]
833
+ */
834
+ /* rb_define_attr(cBucket, "environment", 1, 0); */
835
+ rb_define_method(cBucket, "environment", cb_bucket_environment_get, 0);
836
+ /* Document-method: num_replicas
837
+ *
838
+ * @since 1.2.0.dp6
839
+ *
840
+ * The numbers of the replicas for each node in the cluster
841
+ *
842
+ * @return [Fixnum]
843
+ */
844
+ /* rb_define_attr(cBucket, "num_replicas", 1, 0); */
845
+ rb_define_method(cBucket, "num_replicas", cb_bucket_num_replicas_get, 0);
846
+ /* Document-method: default_observe_timeout
847
+ *
848
+ * @since 1.2.0.dp6
849
+ *
850
+ * The default timeout value for {Bucket#observe_and_wait} operation in
851
+ * microseconds
852
+ *
853
+ * @return [Fixnum]
854
+ */
855
+ /* rb_define_attr(cBucket, "default_observe_timeout", 1, 1); */
856
+ rb_define_method(cBucket, "default_observe_timeout", cb_bucket_default_observe_timeout_get, 0);
857
+ rb_define_method(cBucket, "default_observe_timeout=", cb_bucket_default_observe_timeout_set, 1);
858
+
859
+ cCouchRequest = rb_define_class_under(cBucket, "CouchRequest", rb_cObject);
860
+ rb_define_alloc_func(cCouchRequest, cb_http_request_alloc);
861
+
862
+ rb_define_method(cCouchRequest, "initialize", cb_http_request_init, -1);
863
+ rb_define_method(cCouchRequest, "inspect", cb_http_request_inspect, 0);
864
+ rb_define_method(cCouchRequest, "on_body", cb_http_request_on_body, 0);
865
+ rb_define_method(cCouchRequest, "perform", cb_http_request_perform, 0);
866
+ rb_define_method(cCouchRequest, "pause", cb_http_request_pause, 0);
867
+ rb_define_method(cCouchRequest, "continue", cb_http_request_continue, 0);
868
+
869
+ /* rb_define_attr(cCouchRequest, "path", 1, 0); */
870
+ rb_define_method(cCouchRequest, "path", cb_http_request_path_get, 0);
871
+ /* rb_define_attr(cCouchRequest, "extended", 1, 0); */
872
+ rb_define_method(cCouchRequest, "extended", cb_http_request_extended_get, 0);
873
+ rb_define_alias(cCouchRequest, "extended?", "extended");
874
+ /* rb_define_attr(cCouchRequest, "chunked", 1, 0); */
875
+ rb_define_method(cCouchRequest, "chunked", cb_http_request_chunked_get, 0);
876
+ rb_define_alias(cCouchRequest, "chunked?", "chunked");
877
+
878
+ cTimer = rb_define_class_under(mCouchbase, "Timer", rb_cObject);
879
+ rb_define_alloc_func(cTimer, cb_timer_alloc);
880
+ rb_define_method(cTimer, "initialize", cb_timer_init, -1);
881
+ rb_define_method(cTimer, "inspect", cb_timer_inspect, 0);
882
+ rb_define_method(cTimer, "cancel", cb_timer_cancel, 0);
3540
883
 
3541
884
  /* Define symbols */
3542
885
  id_arity = rb_intern("arity");
3543
886
  id_call = rb_intern("call");
887
+ id_delete = rb_intern("delete");
3544
888
  id_dump = rb_intern("dump");
3545
889
  id_dup = rb_intern("dup");
3546
890
  id_flatten_bang = rb_intern("flatten!");
@@ -3548,6 +892,7 @@ Init_couchbase_ext(void)
3548
892
  id_host = rb_intern("host");
3549
893
  id_load = rb_intern("load");
3550
894
  id_match = rb_intern("match");
895
+ id_observe_and_wait = rb_intern("observe_and_wait");
3551
896
  id_parse = rb_intern("parse");
3552
897
  id_password = rb_intern("password");
3553
898
  id_path = rb_intern("path");
@@ -3555,40 +900,66 @@ Init_couchbase_ext(void)
3555
900
  id_scheme = rb_intern("scheme");
3556
901
  id_to_s = rb_intern("to_s");
3557
902
  id_user = rb_intern("user");
903
+ id_verify_observe_options = rb_intern("verify_observe_options");
3558
904
 
3559
905
  sym_add = ID2SYM(rb_intern("add"));
3560
906
  sym_append = ID2SYM(rb_intern("append"));
907
+ sym_assemble_hash = ID2SYM(rb_intern("assemble_hash"));
908
+ sym_body = ID2SYM(rb_intern("body"));
3561
909
  sym_bucket = ID2SYM(rb_intern("bucket"));
3562
910
  sym_cas = ID2SYM(rb_intern("cas"));
911
+ sym_chunked = ID2SYM(rb_intern("chunked"));
912
+ sym_content_type = ID2SYM(rb_intern("content_type"));
3563
913
  sym_create = ID2SYM(rb_intern("create"));
3564
914
  sym_decrement = ID2SYM(rb_intern("decrement"));
3565
915
  sym_default_flags = ID2SYM(rb_intern("default_flags"));
3566
916
  sym_default_format = ID2SYM(rb_intern("default_format"));
3567
917
  sym_default_ttl = ID2SYM(rb_intern("default_ttl"));
3568
918
  sym_delete = ID2SYM(rb_intern("delete"));
919
+ sym_delta = ID2SYM(rb_intern("delta"));
920
+ sym_development = ID2SYM(rb_intern("development"));
3569
921
  sym_document = ID2SYM(rb_intern("document"));
922
+ sym_environment = ID2SYM(rb_intern("environment"));
3570
923
  sym_extended = ID2SYM(rb_intern("extended"));
3571
924
  sym_flags = ID2SYM(rb_intern("flags"));
3572
- sym_flush = ID2SYM(rb_intern("flush"));
3573
925
  sym_format = ID2SYM(rb_intern("format"));
926
+ sym_found = ID2SYM(rb_intern("found"));
3574
927
  sym_get = ID2SYM(rb_intern("get"));
3575
928
  sym_hostname = ID2SYM(rb_intern("hostname"));
929
+ sym_http_request = ID2SYM(rb_intern("http_request"));
3576
930
  sym_increment = ID2SYM(rb_intern("increment"));
3577
931
  sym_initial = ID2SYM(rb_intern("initial"));
932
+ sym_key_prefix = ID2SYM(rb_intern("key_prefix"));
933
+ sym_lock = ID2SYM(rb_intern("lock"));
934
+ sym_management = ID2SYM(rb_intern("management"));
3578
935
  sym_marshal = ID2SYM(rb_intern("marshal"));
936
+ sym_method = ID2SYM(rb_intern("method"));
3579
937
  sym_node_list = ID2SYM(rb_intern("node_list"));
938
+ sym_not_found = ID2SYM(rb_intern("not_found"));
939
+ sym_num_replicas = ID2SYM(rb_intern("num_replicas"));
940
+ sym_observe = ID2SYM(rb_intern("observe"));
3580
941
  sym_password = ID2SYM(rb_intern("password"));
942
+ sym_periodic = ID2SYM(rb_intern("periodic"));
943
+ sym_persisted = ID2SYM(rb_intern("persisted"));
3581
944
  sym_plain = ID2SYM(rb_intern("plain"));
3582
945
  sym_pool = ID2SYM(rb_intern("pool"));
3583
946
  sym_port = ID2SYM(rb_intern("port"));
947
+ sym_post = ID2SYM(rb_intern("post"));
3584
948
  sym_prepend = ID2SYM(rb_intern("prepend"));
949
+ sym_production = ID2SYM(rb_intern("production"));
950
+ sym_put = ID2SYM(rb_intern("put"));
3585
951
  sym_quiet = ID2SYM(rb_intern("quiet"));
3586
952
  sym_replace = ID2SYM(rb_intern("replace"));
953
+ sym_replica = ID2SYM(rb_intern("replica"));
954
+ sym_send_threshold = ID2SYM(rb_intern("send_threshold"));
3587
955
  sym_set = ID2SYM(rb_intern("set"));
3588
956
  sym_stats = ID2SYM(rb_intern("stats"));
3589
957
  sym_timeout = ID2SYM(rb_intern("timeout"));
3590
958
  sym_touch = ID2SYM(rb_intern("touch"));
3591
959
  sym_ttl = ID2SYM(rb_intern("ttl"));
960
+ sym_type = ID2SYM(rb_intern("type"));
961
+ sym_unlock = ID2SYM(rb_intern("unlock"));
3592
962
  sym_username = ID2SYM(rb_intern("username"));
3593
963
  sym_version = ID2SYM(rb_intern("version"));
964
+ sym_view = ID2SYM(rb_intern("view"));
3594
965
  }