couchbase 1.3.4-x64-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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +22 -0
- data/.yardopts +5 -0
- data/CONTRIBUTING.markdown +75 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/Makefile +3 -0
- data/README.markdown +649 -0
- data/RELEASE_NOTES.markdown +796 -0
- data/Rakefile +20 -0
- data/couchbase.gemspec +49 -0
- data/examples/chat-em/Gemfile +7 -0
- data/examples/chat-em/README.markdown +45 -0
- data/examples/chat-em/server.rb +82 -0
- data/examples/chat-goliath-grape/Gemfile +5 -0
- data/examples/chat-goliath-grape/README.markdown +50 -0
- data/examples/chat-goliath-grape/app.rb +67 -0
- data/examples/chat-goliath-grape/config/app.rb +20 -0
- data/examples/transcoders/Gemfile +3 -0
- data/examples/transcoders/README.markdown +59 -0
- data/examples/transcoders/cb-zcat +40 -0
- data/examples/transcoders/cb-zcp +45 -0
- data/examples/transcoders/gzip_transcoder.rb +49 -0
- data/examples/transcoders/options.rb +54 -0
- data/ext/couchbase_ext/.gitignore +4 -0
- data/ext/couchbase_ext/arguments.c +956 -0
- data/ext/couchbase_ext/arithmetic.c +307 -0
- data/ext/couchbase_ext/bucket.c +1370 -0
- data/ext/couchbase_ext/context.c +65 -0
- data/ext/couchbase_ext/couchbase_ext.c +1364 -0
- data/ext/couchbase_ext/couchbase_ext.h +644 -0
- data/ext/couchbase_ext/delete.c +163 -0
- data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
- data/ext/couchbase_ext/extconf.rb +168 -0
- data/ext/couchbase_ext/get.c +316 -0
- data/ext/couchbase_ext/gethrtime.c +129 -0
- data/ext/couchbase_ext/http.c +432 -0
- data/ext/couchbase_ext/multithread_plugin.c +1090 -0
- data/ext/couchbase_ext/observe.c +171 -0
- data/ext/couchbase_ext/plugin_common.c +171 -0
- data/ext/couchbase_ext/result.c +129 -0
- data/ext/couchbase_ext/stats.c +163 -0
- data/ext/couchbase_ext/store.c +542 -0
- data/ext/couchbase_ext/timer.c +192 -0
- data/ext/couchbase_ext/touch.c +186 -0
- data/ext/couchbase_ext/unlock.c +176 -0
- data/ext/couchbase_ext/utils.c +551 -0
- data/ext/couchbase_ext/version.c +142 -0
- data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
- data/lib/active_support/cache/couchbase_store.rb +430 -0
- data/lib/couchbase.rb +155 -0
- data/lib/couchbase/bucket.rb +457 -0
- data/lib/couchbase/cluster.rb +119 -0
- data/lib/couchbase/connection_pool.rb +58 -0
- data/lib/couchbase/constants.rb +12 -0
- data/lib/couchbase/result.rb +26 -0
- data/lib/couchbase/transcoder.rb +120 -0
- data/lib/couchbase/utils.rb +62 -0
- data/lib/couchbase/version.rb +21 -0
- data/lib/couchbase/view.rb +506 -0
- data/lib/couchbase/view_row.rb +272 -0
- data/lib/ext/multi_json_fix.rb +56 -0
- data/lib/rack/session/couchbase.rb +108 -0
- data/tasks/benchmark.rake +6 -0
- data/tasks/compile.rake +158 -0
- data/tasks/test.rake +100 -0
- data/tasks/util.rake +21 -0
- data/test/profile/.gitignore +1 -0
- data/test/profile/Gemfile +6 -0
- data/test/profile/benchmark.rb +195 -0
- data/test/setup.rb +178 -0
- data/test/test_arithmetic.rb +185 -0
- data/test/test_async.rb +316 -0
- data/test/test_bucket.rb +250 -0
- data/test/test_cas.rb +235 -0
- data/test/test_couchbase.rb +77 -0
- data/test/test_couchbase_connection_pool.rb +77 -0
- data/test/test_couchbase_rails_cache_store.rb +361 -0
- data/test/test_delete.rb +120 -0
- data/test/test_errors.rb +82 -0
- data/test/test_eventmachine.rb +70 -0
- data/test/test_format.rb +164 -0
- data/test/test_get.rb +407 -0
- data/test/test_stats.rb +57 -0
- data/test/test_store.rb +216 -0
- data/test/test_timer.rb +42 -0
- data/test/test_touch.rb +97 -0
- data/test/test_unlock.rb +119 -0
- data/test/test_utils.rb +58 -0
- data/test/test_version.rb +52 -0
- metadata +336 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
void
|
21
|
+
cb_stat_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_server_stat_resp_t *resp)
|
22
|
+
{
|
23
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
25
|
+
VALUE stats, node, key, val, exc = Qnil, res;
|
26
|
+
|
27
|
+
node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil;
|
28
|
+
exc = cb_check_error(error, "failed to fetch stats", node);
|
29
|
+
if (exc != Qnil) {
|
30
|
+
rb_ivar_set(exc, cb_id_iv_operation, cb_sym_stats);
|
31
|
+
ctx->exception = exc;
|
32
|
+
}
|
33
|
+
if (node != Qnil) {
|
34
|
+
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
35
|
+
val = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
|
36
|
+
if (bucket->async) { /* asynchronous */
|
37
|
+
if (ctx->proc != Qnil) {
|
38
|
+
res = rb_class_new_instance(0, NULL, cb_cResult);
|
39
|
+
rb_ivar_set(res, cb_id_iv_error, exc);
|
40
|
+
rb_ivar_set(res, cb_id_iv_operation, cb_sym_stats);
|
41
|
+
rb_ivar_set(res, cb_id_iv_node, node);
|
42
|
+
rb_ivar_set(res, cb_id_iv_key, key);
|
43
|
+
rb_ivar_set(res, cb_id_iv_value, val);
|
44
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
45
|
+
}
|
46
|
+
} else { /* synchronous */
|
47
|
+
if (NIL_P(exc)) {
|
48
|
+
stats = rb_hash_aref(ctx->rv, key);
|
49
|
+
if (NIL_P(stats)) {
|
50
|
+
stats = rb_hash_new();
|
51
|
+
rb_hash_aset(ctx->rv, key, stats);
|
52
|
+
}
|
53
|
+
rb_hash_aset(stats, node, val);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
} else {
|
57
|
+
ctx->proc = Qnil;
|
58
|
+
if (bucket->async) {
|
59
|
+
cb_context_free(ctx);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
(void)handle;
|
63
|
+
}
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Request server statistics.
|
67
|
+
*
|
68
|
+
* @since 1.0.0
|
69
|
+
*
|
70
|
+
* Fetches stats from each node in cluster. Without a key specified the
|
71
|
+
* server will respond with a "default" set of statistical information. In
|
72
|
+
* asynchronous mode each statistic is returned in separate call where the
|
73
|
+
* Result object yielded (+#key+ contains the name of the statistical item
|
74
|
+
* and the +#value+ contains the value, the +#node+ will indicate the server
|
75
|
+
* address). In synchronous mode it returns the hash of stats keys and
|
76
|
+
* node-value pairs as a value.
|
77
|
+
*
|
78
|
+
* @overload stats(arg = nil)
|
79
|
+
* @param [String] arg argument to STATS query
|
80
|
+
* @yieldparam [Result] ret the object with +node+, +key+ and +value+
|
81
|
+
* attributes.
|
82
|
+
*
|
83
|
+
* @example Found how many items in the bucket
|
84
|
+
* total = 0
|
85
|
+
* c.stats["total_items"].each do |key, value|
|
86
|
+
* total += value.to_i
|
87
|
+
* end
|
88
|
+
*
|
89
|
+
* @example Found total items number asynchronously
|
90
|
+
* total = 0
|
91
|
+
* c.run do
|
92
|
+
* c.stats do |ret|
|
93
|
+
* if ret.key == "total_items"
|
94
|
+
* total += ret.value.to_i
|
95
|
+
* end
|
96
|
+
* end
|
97
|
+
* end
|
98
|
+
*
|
99
|
+
* @example Get memory stats (works on couchbase buckets)
|
100
|
+
* c.stats(:memory) #=> {"mem_used"=>{...}, ...}
|
101
|
+
*
|
102
|
+
* @return [Hash] where keys are stat keys, values are host-value pairs
|
103
|
+
*
|
104
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
105
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
106
|
+
*/
|
107
|
+
VALUE
|
108
|
+
cb_bucket_stats(int argc, VALUE *argv, VALUE self)
|
109
|
+
{
|
110
|
+
struct cb_bucket_st *bucket = DATA_PTR(self);
|
111
|
+
struct cb_context_st *ctx;
|
112
|
+
VALUE rv, exc, proc;
|
113
|
+
lcb_error_t err;
|
114
|
+
struct cb_params_st params;
|
115
|
+
|
116
|
+
if (!cb_bucket_connected_bang(bucket, cb_sym_stats)) {
|
117
|
+
return Qnil;
|
118
|
+
}
|
119
|
+
|
120
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
121
|
+
rb_scan_args(argc, argv, "0*&", ¶ms.args, &proc);
|
122
|
+
if (!bucket->async && proc != Qnil) {
|
123
|
+
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
124
|
+
}
|
125
|
+
params.type = cb_cmd_stats;
|
126
|
+
params.bucket = bucket;
|
127
|
+
cb_params_build(¶ms);
|
128
|
+
ctx = cb_context_alloc_common(bucket, proc, params.cmd.stats.num);
|
129
|
+
err = lcb_server_stats(bucket->handle, (const void *)ctx,
|
130
|
+
params.cmd.stats.num, params.cmd.stats.ptr);
|
131
|
+
exc = cb_check_error(err, "failed to schedule stat request", Qnil);
|
132
|
+
cb_params_destroy(¶ms);
|
133
|
+
if (exc != Qnil) {
|
134
|
+
cb_context_free(ctx);
|
135
|
+
rb_exc_raise(exc);
|
136
|
+
}
|
137
|
+
bucket->nbytes += params.npayload;
|
138
|
+
if (bucket->async) {
|
139
|
+
cb_maybe_do_loop(bucket);
|
140
|
+
return Qnil;
|
141
|
+
} else {
|
142
|
+
if (ctx->nqueries > 0) {
|
143
|
+
/* we have some operations pending */
|
144
|
+
lcb_wait(bucket->handle);
|
145
|
+
}
|
146
|
+
exc = ctx->exception;
|
147
|
+
rv = ctx->rv;
|
148
|
+
cb_context_free(ctx);
|
149
|
+
if (exc != Qnil) {
|
150
|
+
rb_exc_raise(exc);
|
151
|
+
}
|
152
|
+
exc = bucket->exception;
|
153
|
+
if (exc != Qnil) {
|
154
|
+
bucket->exception = Qnil;
|
155
|
+
rb_exc_raise(exc);
|
156
|
+
}
|
157
|
+
return rv;
|
158
|
+
}
|
159
|
+
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
163
|
+
|
@@ -0,0 +1,542 @@
|
|
1
|
+
/* vim: ft=c et ts=8 sts=4 sw=4 cino=
|
2
|
+
*
|
3
|
+
* Copyright 2011, 2012 Couchbase, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include "couchbase_ext.h"
|
19
|
+
|
20
|
+
static VALUE
|
21
|
+
storage_observe_callback(VALUE args, VALUE cookie)
|
22
|
+
{
|
23
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
24
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
25
|
+
VALUE res = rb_ary_shift(args);
|
26
|
+
|
27
|
+
if (ctx->proc != Qnil) {
|
28
|
+
rb_ivar_set(res, cb_id_iv_operation, ctx->operation);
|
29
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
30
|
+
}
|
31
|
+
if (!RTEST(ctx->observe_options)) {
|
32
|
+
ctx->nqueries--;
|
33
|
+
if (ctx->nqueries == 0) {
|
34
|
+
ctx->proc = Qnil;
|
35
|
+
if (bucket->async) {
|
36
|
+
cb_context_free(ctx);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
return Qnil;
|
41
|
+
}
|
42
|
+
|
43
|
+
VALUE
|
44
|
+
storage_opcode_to_sym(lcb_storage_t operation)
|
45
|
+
{
|
46
|
+
switch(operation) {
|
47
|
+
case LCB_ADD:
|
48
|
+
return cb_sym_add;
|
49
|
+
case LCB_REPLACE:
|
50
|
+
return cb_sym_replace;
|
51
|
+
case LCB_SET:
|
52
|
+
return cb_sym_set;
|
53
|
+
case LCB_APPEND:
|
54
|
+
return cb_sym_append;
|
55
|
+
case LCB_PREPEND:
|
56
|
+
return cb_sym_prepend;
|
57
|
+
default:
|
58
|
+
return Qnil;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
void
|
63
|
+
cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation,
|
64
|
+
lcb_error_t error, const lcb_store_resp_t *resp)
|
65
|
+
{
|
66
|
+
struct cb_context_st *ctx = (struct cb_context_st *)cookie;
|
67
|
+
struct cb_bucket_st *bucket = ctx->bucket;
|
68
|
+
VALUE key, cas, exc, res;
|
69
|
+
|
70
|
+
key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
|
71
|
+
cb_strip_key_prefix(bucket, key);
|
72
|
+
|
73
|
+
cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil;
|
74
|
+
ctx->operation = storage_opcode_to_sym(operation);
|
75
|
+
exc = cb_check_error(error, "failed to store value", key);
|
76
|
+
if (exc != Qnil) {
|
77
|
+
rb_ivar_set(exc, cb_id_iv_cas, cas);
|
78
|
+
rb_ivar_set(exc, cb_id_iv_operation, ctx->operation);
|
79
|
+
ctx->exception = exc;
|
80
|
+
}
|
81
|
+
|
82
|
+
if (bucket->async) { /* asynchronous */
|
83
|
+
if (RTEST(ctx->observe_options)) {
|
84
|
+
VALUE args[2]; /* it's ok to pass pointer to stack struct here */
|
85
|
+
args[0] = rb_hash_new();
|
86
|
+
rb_hash_aset(args[0], key, cas);
|
87
|
+
args[1] = ctx->observe_options;
|
88
|
+
rb_block_call(bucket->self, cb_id_observe_and_wait, 2, args,
|
89
|
+
storage_observe_callback, (VALUE)ctx);
|
90
|
+
ctx->observe_options = Qnil;
|
91
|
+
} else if (ctx->proc != Qnil) {
|
92
|
+
res = rb_class_new_instance(0, NULL, cb_cResult);
|
93
|
+
rb_ivar_set(res, cb_id_iv_error, exc);
|
94
|
+
rb_ivar_set(res, cb_id_iv_key, key);
|
95
|
+
rb_ivar_set(res, cb_id_iv_operation, ctx->operation);
|
96
|
+
rb_ivar_set(res, cb_id_iv_cas, cas);
|
97
|
+
cb_proc_call(bucket, ctx->proc, 1, res);
|
98
|
+
}
|
99
|
+
} else { /* synchronous */
|
100
|
+
rb_hash_aset(ctx->rv, key, cas);
|
101
|
+
}
|
102
|
+
|
103
|
+
if (!RTEST(ctx->observe_options)) {
|
104
|
+
ctx->nqueries--;
|
105
|
+
if (ctx->nqueries == 0) {
|
106
|
+
ctx->proc = Qnil;
|
107
|
+
if (bucket->async) {
|
108
|
+
cb_context_free(ctx);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
(void)handle;
|
113
|
+
}
|
114
|
+
|
115
|
+
static inline VALUE
|
116
|
+
cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
|
117
|
+
{
|
118
|
+
struct cb_bucket_st *bucket = DATA_PTR(self);
|
119
|
+
struct cb_context_st *ctx;
|
120
|
+
VALUE rv, proc, exc, obs = Qnil;
|
121
|
+
lcb_error_t err;
|
122
|
+
struct cb_params_st params;
|
123
|
+
|
124
|
+
if (!cb_bucket_connected_bang(bucket, storage_opcode_to_sym(cmd))) {
|
125
|
+
return Qnil;
|
126
|
+
}
|
127
|
+
memset(¶ms, 0, sizeof(struct cb_params_st));
|
128
|
+
rb_scan_args(argc, argv, "0*&", ¶ms.args, &proc);
|
129
|
+
if (!bucket->async && proc != Qnil) {
|
130
|
+
rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
|
131
|
+
}
|
132
|
+
params.type = cb_cmd_store;
|
133
|
+
params.bucket = bucket;
|
134
|
+
params.cmd.store.operation = cmd;
|
135
|
+
cb_params_build(¶ms);
|
136
|
+
obs = params.cmd.store.observe;
|
137
|
+
ctx = cb_context_alloc(bucket);
|
138
|
+
if (!bucket->async) {
|
139
|
+
ctx->rv = rb_hash_new();
|
140
|
+
ctx->observe_options = obs;
|
141
|
+
}
|
142
|
+
ctx->proc = proc;
|
143
|
+
ctx->nqueries = params.cmd.store.num;
|
144
|
+
err = lcb_store(bucket->handle, (const void *)ctx,
|
145
|
+
params.cmd.store.num, params.cmd.store.ptr);
|
146
|
+
cb_params_destroy(¶ms);
|
147
|
+
exc = cb_check_error(err, "failed to schedule set request", Qnil);
|
148
|
+
if (exc != Qnil) {
|
149
|
+
cb_context_free(ctx);
|
150
|
+
rb_exc_raise(exc);
|
151
|
+
}
|
152
|
+
bucket->nbytes += params.npayload;
|
153
|
+
if (bucket->async) {
|
154
|
+
cb_maybe_do_loop(bucket);
|
155
|
+
return Qnil;
|
156
|
+
} else {
|
157
|
+
if (ctx->nqueries > 0) {
|
158
|
+
/* we have some operations pending */
|
159
|
+
lcb_wait(bucket->handle);
|
160
|
+
}
|
161
|
+
exc = ctx->exception;
|
162
|
+
rv = ctx->rv;
|
163
|
+
cb_context_free(ctx);
|
164
|
+
if (exc != Qnil) {
|
165
|
+
rb_exc_raise(exc);
|
166
|
+
}
|
167
|
+
exc = bucket->exception;
|
168
|
+
if (exc != Qnil) {
|
169
|
+
bucket->exception = Qnil;
|
170
|
+
rb_exc_raise(exc);
|
171
|
+
}
|
172
|
+
if (RTEST(obs)) {
|
173
|
+
rv = rb_funcall(bucket->self, cb_id_observe_and_wait, 2, rv, obs);
|
174
|
+
}
|
175
|
+
if (params.cmd.store.num > 1) {
|
176
|
+
return rv; /* return as a hash {key => cas, ...} */
|
177
|
+
} else {
|
178
|
+
VALUE vv = Qnil;
|
179
|
+
rb_hash_foreach(rv, cb_first_value_i, (VALUE)&vv);
|
180
|
+
return vv;
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
/*
|
186
|
+
* Unconditionally store the object in the Couchbase
|
187
|
+
*
|
188
|
+
* @since 1.0.0
|
189
|
+
*
|
190
|
+
* @overload set(key, value, options = {})
|
191
|
+
*
|
192
|
+
* @param key [String, Symbol] Key used to reference the value.
|
193
|
+
* @param value [Object] Value to be stored
|
194
|
+
* @param options [Hash] Options for operation.
|
195
|
+
* @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
196
|
+
* Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
197
|
+
* absolute times (from the epoch).
|
198
|
+
* @option options [Fixnum] :flags (self.default_flags) Flags for storage
|
199
|
+
* options. Flags are ignored by the server but preserved for use by the
|
200
|
+
* client. For more info see {Bucket#default_flags}.
|
201
|
+
* @option options [Symbol] :format (self.default_format) The
|
202
|
+
* representation for storing the value in the bucket. For more info see
|
203
|
+
* {Bucket#default_format}.
|
204
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value is
|
205
|
+
* created on the server and is guaranteed to be unique for each value of
|
206
|
+
* a given key. This value is used to provide simple optimistic
|
207
|
+
* concurrency control when multiple clients or threads try to update an
|
208
|
+
* item simultaneously.
|
209
|
+
* @option options [Hash] :observe Apply persistence condition before
|
210
|
+
* returning result. When this option specified the library will observe
|
211
|
+
* given condition. See {Bucket#observe_and_wait}.
|
212
|
+
*
|
213
|
+
* @yieldparam ret [Result] the result of operation in asynchronous mode
|
214
|
+
* (valid attributes: +error+, +operation+, +key+).
|
215
|
+
*
|
216
|
+
* @return [Fixnum] The CAS value of the object.
|
217
|
+
*
|
218
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect}).
|
219
|
+
* @raise [Couchbase::Error::KeyExists] if the key already exists on the
|
220
|
+
* server.
|
221
|
+
* @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
|
222
|
+
* with chosen encoder, e.g. if you try to store the Hash in +:plain+
|
223
|
+
* mode.
|
224
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
225
|
+
* @raise [Couchbase::Error::Timeout] if timeout interval for observe
|
226
|
+
* exceeds
|
227
|
+
*
|
228
|
+
* @example Store the key which will be expired in 2 seconds using relative TTL.
|
229
|
+
* c.set("foo", "bar", :ttl => 2)
|
230
|
+
*
|
231
|
+
* @example Perform multi-set operation. It takes a Hash store its keys/values into the bucket
|
232
|
+
* c.set("foo1" => "bar1", "foo2" => "bar2")
|
233
|
+
* #=> {"foo1" => cas1, "foo2" => cas2}
|
234
|
+
*
|
235
|
+
* @example More advanced multi-set using asynchronous mode
|
236
|
+
* c.run do
|
237
|
+
* # fire and forget
|
238
|
+
* c.set("foo1", "bar1", :ttl => 10)
|
239
|
+
* # receive result into the callback
|
240
|
+
* c.set("foo2", "bar2", :ttl => 10) do |ret|
|
241
|
+
* if ret.success?
|
242
|
+
* puts ret.cas
|
243
|
+
* end
|
244
|
+
* end
|
245
|
+
* end
|
246
|
+
*
|
247
|
+
* @example Store the key which will be expired in 2 seconds using absolute TTL.
|
248
|
+
* c.set("foo", "bar", :ttl => Time.now.to_i + 2)
|
249
|
+
*
|
250
|
+
* @example Force JSON document format for value
|
251
|
+
* c.set("foo", {"bar" => "baz}, :format => :document)
|
252
|
+
*
|
253
|
+
* @example Use hash-like syntax to store the value
|
254
|
+
* c["foo"] = {"bar" => "baz}
|
255
|
+
*
|
256
|
+
* @example Use extended hash-like syntax
|
257
|
+
* c["foo", {:flags => 0x1000, :format => :plain}] = "bar"
|
258
|
+
* c["foo", :flags => 0x1000] = "bar" # for ruby 1.9.x only
|
259
|
+
*
|
260
|
+
* @example Set application specific flags (note that it will be OR-ed with format flags)
|
261
|
+
* c.set("foo", "bar", :flags => 0x1000)
|
262
|
+
*
|
263
|
+
* @example Perform optimistic locking by specifying last known CAS version
|
264
|
+
* c.set("foo", "bar", :cas => 8835713818674332672)
|
265
|
+
*
|
266
|
+
* @example Perform asynchronous call
|
267
|
+
* c.run do
|
268
|
+
* c.set("foo", "bar") do |ret|
|
269
|
+
* ret.operation #=> :set
|
270
|
+
* ret.success? #=> true
|
271
|
+
* ret.key #=> "foo"
|
272
|
+
* ret.cas
|
273
|
+
* end
|
274
|
+
* end
|
275
|
+
*
|
276
|
+
* @example Ensure that the key will be persisted at least on the one node
|
277
|
+
* c.set("foo", "bar", :observe => {:persisted => 1})
|
278
|
+
*/
|
279
|
+
VALUE
|
280
|
+
cb_bucket_set(int argc, VALUE *argv, VALUE self)
|
281
|
+
{
|
282
|
+
return cb_bucket_store(LCB_SET, argc, argv, self);
|
283
|
+
}
|
284
|
+
|
285
|
+
/*
|
286
|
+
* Add the item to the database, but fail if the object exists already
|
287
|
+
*
|
288
|
+
* @since 1.0.0
|
289
|
+
*
|
290
|
+
* @overload add(key, value, options = {})
|
291
|
+
*
|
292
|
+
* @param key [String, Symbol] Key used to reference the value.
|
293
|
+
* @param value [Object] Value to be stored
|
294
|
+
* @param options [Hash] Options for operation.
|
295
|
+
* @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
296
|
+
* Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
297
|
+
* absolute times (from the epoch).
|
298
|
+
* @option options [Fixnum] :flags (self.default_flags) Flags for storage
|
299
|
+
* options. Flags are ignored by the server but preserved for use by the
|
300
|
+
* client. For more info see {Bucket#default_flags}.
|
301
|
+
* @option options [Symbol] :format (self.default_format) The
|
302
|
+
* representation for storing the value in the bucket. For more info see
|
303
|
+
* {Bucket#default_format}.
|
304
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value
|
305
|
+
* created on the server and is guaranteed to be unique for each value of
|
306
|
+
* a given key. This value is used to provide simple optimistic
|
307
|
+
* concurrency control when multiple clients or threads try to update an
|
308
|
+
* item simultaneously.
|
309
|
+
* @option options [Hash] :observe Apply persistence condition before
|
310
|
+
* returning result. When this option specified the library will observe
|
311
|
+
* given condition. See {Bucket#observe_and_wait}.
|
312
|
+
*
|
313
|
+
* @yieldparam ret [Result] the result of operation in asynchronous mode
|
314
|
+
* (valid attributes: +error+, +operation+, +key+).
|
315
|
+
*
|
316
|
+
* @return [Fixnum] The CAS value of the object.
|
317
|
+
*
|
318
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
319
|
+
* @raise [Couchbase::Error::KeyExists] if the key already exists on the
|
320
|
+
* server
|
321
|
+
* @raise [Couchbase::Error::ValueFormat] if the value cannot be serialized
|
322
|
+
* with chosen encoder, e.g. if you try to store the Hash in +:plain+
|
323
|
+
* mode.
|
324
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
325
|
+
* @raise [Couchbase::Error::Timeout] if timeout interval for observe
|
326
|
+
* exceeds
|
327
|
+
*
|
328
|
+
* @example Add the same key twice
|
329
|
+
* c.add("foo", "bar") #=> stored successully
|
330
|
+
* c.add("foo", "baz") #=> will raise Couchbase::Error::KeyExists: failed to store value (key="foo", error=0x0c)
|
331
|
+
*
|
332
|
+
* @example Ensure that the key will be persisted at least on the one node
|
333
|
+
* c.add("foo", "bar", :observe => {:persisted => 1})
|
334
|
+
*/
|
335
|
+
VALUE
|
336
|
+
cb_bucket_add(int argc, VALUE *argv, VALUE self)
|
337
|
+
{
|
338
|
+
return cb_bucket_store(LCB_ADD, argc, argv, self);
|
339
|
+
}
|
340
|
+
|
341
|
+
/*
|
342
|
+
* Replace the existing object in the database
|
343
|
+
*
|
344
|
+
* @since 1.0.0
|
345
|
+
*
|
346
|
+
* @overload replace(key, value, options = {})
|
347
|
+
* @param key [String, Symbol] Key used to reference the value.
|
348
|
+
* @param value [Object] Value to be stored
|
349
|
+
* @param options [Hash] Options for operation.
|
350
|
+
* @option options [Fixnum] :ttl (self.default_ttl) Expiry time for key.
|
351
|
+
* Values larger than 30*24*60*60 seconds (30 days) are interpreted as
|
352
|
+
* absolute times (from the epoch).
|
353
|
+
* @option options [Fixnum] :flags (self.default_flags) Flags for storage
|
354
|
+
* options. Flags are ignored by the server but preserved for use by the
|
355
|
+
* client. For more info see {Bucket#default_flags}.
|
356
|
+
* @option options [Symbol] :format (self.default_format) The
|
357
|
+
* representation for storing the value in the bucket. For more info see
|
358
|
+
* {Bucket#default_format}.
|
359
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value
|
360
|
+
* created on the server and is guaranteed to be unique for each value of
|
361
|
+
* a given key. This value is used to provide simple optimistic
|
362
|
+
* concurrency control when multiple clients or threads try to update an
|
363
|
+
* item simultaneously.
|
364
|
+
* @option options [Hash] :observe Apply persistence condition before
|
365
|
+
* returning result. When this option specified the library will observe
|
366
|
+
* given condition. See {Bucket#observe_and_wait}.
|
367
|
+
*
|
368
|
+
* @return [Fixnum] The CAS value of the object.
|
369
|
+
*
|
370
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
371
|
+
* @raise [Couchbase::Error::NotFound] if the key doesn't exists
|
372
|
+
* @raise [Couchbase::Error::KeyExists] on CAS mismatch
|
373
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
374
|
+
* @raise [Couchbase::Error::Timeout] if timeout interval for observe
|
375
|
+
* exceeds
|
376
|
+
*
|
377
|
+
* @example Replacing missing key
|
378
|
+
* c.replace("foo", "baz") #=> will raise Couchbase::Error::NotFound: failed to store value (key="foo", error=0x0d)
|
379
|
+
*
|
380
|
+
* @example Ensure that the key will be persisted at least on the one node
|
381
|
+
* c.replace("foo", "bar", :observe => {:persisted => 1})
|
382
|
+
*/
|
383
|
+
VALUE
|
384
|
+
cb_bucket_replace(int argc, VALUE *argv, VALUE self)
|
385
|
+
{
|
386
|
+
return cb_bucket_store(LCB_REPLACE, argc, argv, self);
|
387
|
+
}
|
388
|
+
|
389
|
+
/*
|
390
|
+
* Append this object to the existing object
|
391
|
+
*
|
392
|
+
* @since 1.0.0
|
393
|
+
*
|
394
|
+
* @note This operation is kind of data-aware from server point of view.
|
395
|
+
* This mean that the server treats value as binary stream and just
|
396
|
+
* perform concatenation, therefore it won't work with +:marshal+ and
|
397
|
+
* +:document+ formats, because of lack of knowledge how to merge values
|
398
|
+
* in these formats. See {Bucket#cas} for workaround.
|
399
|
+
*
|
400
|
+
* @overload append(key, value, options = {})
|
401
|
+
* @param key [String, Symbol] Key used to reference the value.
|
402
|
+
* @param value [Object] Value to be stored
|
403
|
+
* @param options [Hash] Options for operation.
|
404
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value
|
405
|
+
* created on the server and is guaranteed to be unique for each value of
|
406
|
+
* a given key. This value is used to provide simple optimistic
|
407
|
+
* concurrency control when multiple clients or threads try to update an
|
408
|
+
* item simultaneously.
|
409
|
+
* @option options [Symbol] :format (self.default_format) The
|
410
|
+
* representation for storing the value in the bucket. For more info see
|
411
|
+
* {Bucket#default_format}.
|
412
|
+
* @option options [Hash] :observe Apply persistence condition before
|
413
|
+
* returning result. When this option specified the library will observe
|
414
|
+
* given condition. See {Bucket#observe_and_wait}.
|
415
|
+
*
|
416
|
+
* @return [Fixnum] The CAS value of the object.
|
417
|
+
*
|
418
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
419
|
+
* @raise [Couchbase::Error::KeyExists] on CAS mismatch
|
420
|
+
* @raise [Couchbase::Error::NotStored] if the key doesn't exist
|
421
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
422
|
+
* @raise [Couchbase::Error::Timeout] if timeout interval for observe
|
423
|
+
* exceeds
|
424
|
+
*
|
425
|
+
* @example Simple append
|
426
|
+
* c.set("foo", "aaa")
|
427
|
+
* c.append("foo", "bbb")
|
428
|
+
* c.get("foo") #=> "aaabbb"
|
429
|
+
*
|
430
|
+
* @example Implementing sets using append
|
431
|
+
* def set_add(key, *values)
|
432
|
+
* encoded = values.flatten.map{|v| "+#{v} "}.join
|
433
|
+
* append(key, encoded)
|
434
|
+
* end
|
435
|
+
*
|
436
|
+
* def set_remove(key, *values)
|
437
|
+
* encoded = values.flatten.map{|v| "-#{v} "}.join
|
438
|
+
* append(key, encoded)
|
439
|
+
* end
|
440
|
+
*
|
441
|
+
* def set_get(key)
|
442
|
+
* encoded = get(key)
|
443
|
+
* ret = Set.new
|
444
|
+
* encoded.split(' ').each do |v|
|
445
|
+
* op, val = v[0], v[1..-1]
|
446
|
+
* case op
|
447
|
+
* when "-"
|
448
|
+
* ret.delete(val)
|
449
|
+
* when "+"
|
450
|
+
* ret.add(val)
|
451
|
+
* end
|
452
|
+
* end
|
453
|
+
* ret
|
454
|
+
* end
|
455
|
+
*
|
456
|
+
* @example Using optimistic locking. The operation will fail on CAS mismatch
|
457
|
+
* ver = c.set("foo", "aaa")
|
458
|
+
* c.append("foo", "bbb", :cas => ver)
|
459
|
+
*
|
460
|
+
* @example Ensure that the key will be persisted at least on the one node
|
461
|
+
* c.append("foo", "bar", :observe => {:persisted => 1})
|
462
|
+
*/
|
463
|
+
VALUE
|
464
|
+
cb_bucket_append(int argc, VALUE *argv, VALUE self)
|
465
|
+
{
|
466
|
+
return cb_bucket_store(LCB_APPEND, argc, argv, self);
|
467
|
+
}
|
468
|
+
|
469
|
+
/*
|
470
|
+
* Prepend this object to the existing object
|
471
|
+
*
|
472
|
+
* @since 1.0.0
|
473
|
+
*
|
474
|
+
* @note This operation is kind of data-aware from server point of view.
|
475
|
+
* This mean that the server treats value as binary stream and just
|
476
|
+
* perform concatenation, therefore it won't work with +:marshal+ and
|
477
|
+
* +:document+ formats, because of lack of knowledge how to merge values
|
478
|
+
* in these formats. See {Bucket#cas} for workaround.
|
479
|
+
*
|
480
|
+
* @overload prepend(key, value, options = {})
|
481
|
+
* @param key [String, Symbol] Key used to reference the value.
|
482
|
+
* @param value [Object] Value to be stored
|
483
|
+
* @param options [Hash] Options for operation.
|
484
|
+
* @option options [Fixnum] :cas The CAS value for an object. This value
|
485
|
+
* created on the server and is guaranteed to be unique for each value of
|
486
|
+
* a given key. This value is used to provide simple optimistic
|
487
|
+
* concurrency control when multiple clients or threads try to update an
|
488
|
+
* item simultaneously.
|
489
|
+
* @option options [Symbol] :format (self.default_format) The
|
490
|
+
* representation for storing the value in the bucket. For more info see
|
491
|
+
* {Bucket#default_format}.
|
492
|
+
* @option options [Hash] :observe Apply persistence condition before
|
493
|
+
* returning result. When this option specified the library will observe
|
494
|
+
* given condition. See {Bucket#observe_and_wait}.
|
495
|
+
*
|
496
|
+
* @raise [Couchbase::Error::Connect] if connection closed (see {Bucket#reconnect})
|
497
|
+
* @raise [Couchbase::Error::KeyExists] on CAS mismatch
|
498
|
+
* @raise [Couchbase::Error::NotStored] if the key doesn't exist
|
499
|
+
* @raise [ArgumentError] when passing the block in synchronous mode
|
500
|
+
* @raise [Couchbase::Error::Timeout] if timeout interval for observe
|
501
|
+
* exceeds
|
502
|
+
*
|
503
|
+
* @example Simple prepend example
|
504
|
+
* c.set("foo", "aaa")
|
505
|
+
* c.prepend("foo", "bbb")
|
506
|
+
* c.get("foo") #=> "bbbaaa"
|
507
|
+
*
|
508
|
+
* @example Using explicit format option
|
509
|
+
* c.default_format #=> :document
|
510
|
+
* c.set("foo", {"y" => "z"})
|
511
|
+
* c.prepend("foo", '[', :format => :plain)
|
512
|
+
* c.append("foo", ', {"z": "y"}]', :format => :plain)
|
513
|
+
* c.get("foo") #=> [{"y"=>"z"}, {"z"=>"y"}]
|
514
|
+
*
|
515
|
+
* @example Using optimistic locking. The operation will fail on CAS mismatch
|
516
|
+
* ver = c.set("foo", "aaa")
|
517
|
+
* c.prepend("foo", "bbb", :cas => ver)
|
518
|
+
*
|
519
|
+
* @example Ensure that the key will be persisted at least on the one node
|
520
|
+
* c.prepend("foo", "bar", :observe => {:persisted => 1})
|
521
|
+
*/
|
522
|
+
VALUE
|
523
|
+
cb_bucket_prepend(int argc, VALUE *argv, VALUE self)
|
524
|
+
{
|
525
|
+
return cb_bucket_store(LCB_PREPEND, argc, argv, self);
|
526
|
+
}
|
527
|
+
|
528
|
+
VALUE
|
529
|
+
cb_bucket_aset(int argc, VALUE *argv, VALUE self)
|
530
|
+
{
|
531
|
+
VALUE temp;
|
532
|
+
|
533
|
+
if (argc == 3) {
|
534
|
+
/* swap opts and value, because value goes last for []= */
|
535
|
+
temp = argv[2];
|
536
|
+
argv[2] = argv[1];
|
537
|
+
argv[1] = temp;
|
538
|
+
}
|
539
|
+
return cb_bucket_set(argc, argv, self);
|
540
|
+
}
|
541
|
+
|
542
|
+
|