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.
- data/.gitignore +2 -1
- data/.travis.yml +12 -1
- data/HISTORY.markdown +112 -1
- data/README.markdown +149 -6
- data/couchbase.gemspec +5 -1
- data/ext/couchbase_ext/.gitignore +4 -0
- data/ext/couchbase_ext/arguments.c +973 -0
- data/ext/couchbase_ext/arithmetic.c +322 -0
- data/ext/couchbase_ext/bucket.c +1092 -0
- data/ext/couchbase_ext/couchbase_ext.c +618 -3247
- data/ext/couchbase_ext/couchbase_ext.h +519 -0
- data/ext/couchbase_ext/delete.c +167 -0
- data/ext/couchbase_ext/extconf.rb +24 -5
- data/ext/couchbase_ext/get.c +301 -0
- data/ext/couchbase_ext/gethrtime.c +124 -0
- data/ext/couchbase_ext/http.c +402 -0
- data/ext/couchbase_ext/observe.c +174 -0
- data/ext/couchbase_ext/result.c +126 -0
- data/ext/couchbase_ext/stats.c +169 -0
- data/ext/couchbase_ext/store.c +522 -0
- data/ext/couchbase_ext/timer.c +192 -0
- data/ext/couchbase_ext/touch.c +190 -0
- data/ext/couchbase_ext/unlock.c +180 -0
- data/ext/couchbase_ext/utils.c +471 -0
- data/ext/couchbase_ext/version.c +147 -0
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
- data/lib/active_support/cache/couchbase_store.rb +356 -0
- data/lib/couchbase.rb +24 -3
- data/lib/couchbase/bucket.rb +372 -9
- data/lib/couchbase/result.rb +26 -0
- data/lib/couchbase/utils.rb +59 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view.rb +305 -0
- data/lib/couchbase/view_row.rb +230 -0
- data/lib/ext/multi_json_fix.rb +47 -0
- data/lib/rack/session/couchbase.rb +104 -0
- data/tasks/compile.rake +5 -14
- data/test/setup.rb +6 -2
- data/test/test_arithmetic.rb +32 -2
- data/test/test_async.rb +18 -4
- data/test/test_bucket.rb +11 -1
- data/test/test_cas.rb +13 -3
- data/test/test_couchbase_rails_cache_store.rb +294 -0
- data/test/test_delete.rb +60 -3
- data/test/test_format.rb +28 -17
- data/test/test_get.rb +91 -14
- data/test/test_store.rb +31 -1
- data/test/{test_flush.rb → test_timer.rb} +11 -18
- data/test/test_touch.rb +33 -5
- data/test/test_unlock.rb +120 -0
- data/test/test_utils.rb +26 -0
- 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
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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
|
-
*
|
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,
|
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, "
|
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 [
|
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
|
-
*
|
3491
|
-
*
|
3492
|
-
*
|
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
|
}
|