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.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +22 -0
  4. data/.yardopts +5 -0
  5. data/CONTRIBUTING.markdown +75 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +201 -0
  8. data/Makefile +3 -0
  9. data/README.markdown +649 -0
  10. data/RELEASE_NOTES.markdown +796 -0
  11. data/Rakefile +20 -0
  12. data/couchbase.gemspec +49 -0
  13. data/examples/chat-em/Gemfile +7 -0
  14. data/examples/chat-em/README.markdown +45 -0
  15. data/examples/chat-em/server.rb +82 -0
  16. data/examples/chat-goliath-grape/Gemfile +5 -0
  17. data/examples/chat-goliath-grape/README.markdown +50 -0
  18. data/examples/chat-goliath-grape/app.rb +67 -0
  19. data/examples/chat-goliath-grape/config/app.rb +20 -0
  20. data/examples/transcoders/Gemfile +3 -0
  21. data/examples/transcoders/README.markdown +59 -0
  22. data/examples/transcoders/cb-zcat +40 -0
  23. data/examples/transcoders/cb-zcp +45 -0
  24. data/examples/transcoders/gzip_transcoder.rb +49 -0
  25. data/examples/transcoders/options.rb +54 -0
  26. data/ext/couchbase_ext/.gitignore +4 -0
  27. data/ext/couchbase_ext/arguments.c +956 -0
  28. data/ext/couchbase_ext/arithmetic.c +307 -0
  29. data/ext/couchbase_ext/bucket.c +1370 -0
  30. data/ext/couchbase_ext/context.c +65 -0
  31. data/ext/couchbase_ext/couchbase_ext.c +1364 -0
  32. data/ext/couchbase_ext/couchbase_ext.h +644 -0
  33. data/ext/couchbase_ext/delete.c +163 -0
  34. data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
  35. data/ext/couchbase_ext/extconf.rb +168 -0
  36. data/ext/couchbase_ext/get.c +316 -0
  37. data/ext/couchbase_ext/gethrtime.c +129 -0
  38. data/ext/couchbase_ext/http.c +432 -0
  39. data/ext/couchbase_ext/multithread_plugin.c +1090 -0
  40. data/ext/couchbase_ext/observe.c +171 -0
  41. data/ext/couchbase_ext/plugin_common.c +171 -0
  42. data/ext/couchbase_ext/result.c +129 -0
  43. data/ext/couchbase_ext/stats.c +163 -0
  44. data/ext/couchbase_ext/store.c +542 -0
  45. data/ext/couchbase_ext/timer.c +192 -0
  46. data/ext/couchbase_ext/touch.c +186 -0
  47. data/ext/couchbase_ext/unlock.c +176 -0
  48. data/ext/couchbase_ext/utils.c +551 -0
  49. data/ext/couchbase_ext/version.c +142 -0
  50. data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
  51. data/lib/active_support/cache/couchbase_store.rb +430 -0
  52. data/lib/couchbase.rb +155 -0
  53. data/lib/couchbase/bucket.rb +457 -0
  54. data/lib/couchbase/cluster.rb +119 -0
  55. data/lib/couchbase/connection_pool.rb +58 -0
  56. data/lib/couchbase/constants.rb +12 -0
  57. data/lib/couchbase/result.rb +26 -0
  58. data/lib/couchbase/transcoder.rb +120 -0
  59. data/lib/couchbase/utils.rb +62 -0
  60. data/lib/couchbase/version.rb +21 -0
  61. data/lib/couchbase/view.rb +506 -0
  62. data/lib/couchbase/view_row.rb +272 -0
  63. data/lib/ext/multi_json_fix.rb +56 -0
  64. data/lib/rack/session/couchbase.rb +108 -0
  65. data/tasks/benchmark.rake +6 -0
  66. data/tasks/compile.rake +158 -0
  67. data/tasks/test.rake +100 -0
  68. data/tasks/util.rake +21 -0
  69. data/test/profile/.gitignore +1 -0
  70. data/test/profile/Gemfile +6 -0
  71. data/test/profile/benchmark.rb +195 -0
  72. data/test/setup.rb +178 -0
  73. data/test/test_arithmetic.rb +185 -0
  74. data/test/test_async.rb +316 -0
  75. data/test/test_bucket.rb +250 -0
  76. data/test/test_cas.rb +235 -0
  77. data/test/test_couchbase.rb +77 -0
  78. data/test/test_couchbase_connection_pool.rb +77 -0
  79. data/test/test_couchbase_rails_cache_store.rb +361 -0
  80. data/test/test_delete.rb +120 -0
  81. data/test/test_errors.rb +82 -0
  82. data/test/test_eventmachine.rb +70 -0
  83. data/test/test_format.rb +164 -0
  84. data/test/test_get.rb +407 -0
  85. data/test/test_stats.rb +57 -0
  86. data/test/test_store.rb +216 -0
  87. data/test/test_timer.rb +42 -0
  88. data/test/test_touch.rb +97 -0
  89. data/test/test_unlock.rb +119 -0
  90. data/test/test_utils.rb +58 -0
  91. data/test/test_version.rb +52 -0
  92. metadata +336 -0
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ # Author:: Couchbase <info@couchbase.com>
3
+ # Copyright:: 2013 Couchbase, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'bundler'
20
+ Bundler.setup
21
+
22
+ require 'couchbase'
23
+
24
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
25
+ require 'gzip_transcoder'
26
+ require 'options'
27
+
28
+ STDERR.puts "Run with arguments: #{OPTIONS.inspect}"
29
+ begin
30
+ conn = Couchbase.connect(OPTIONS)
31
+ conn.transcoder = GzipTranscoder.new
32
+
33
+ ARGV.each do |filename|
34
+ STDERR.print "store \"#{filename}\" ... "
35
+ if File.exists?(filename)
36
+ conn.set(filename, File.read(filename))
37
+ STDERR.puts "ok"
38
+ else
39
+ STDERR.puts "not found"
40
+ end
41
+ end
42
+ rescue Couchbase::Error::Base => ex
43
+ STDERR.puts "ERROR: #{ex}"
44
+ exit 1
45
+ end
@@ -0,0 +1,49 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
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
+ require 'zlib'
19
+ require 'stringio'
20
+
21
+ # This class wraps any other transcoder and performs compression
22
+ # using zlib
23
+ class GzipTranscoder
24
+ FMT_GZIP = 0x04
25
+
26
+ def initialize(base = nil)
27
+ @base = base || Couchbase::Transcoder::Plain
28
+ end
29
+
30
+ def dump(obj, flags, options = {})
31
+ obj, flags = @base.dump(obj, flags, options)
32
+ io = StringIO.new
33
+ gz = Zlib::GzipWriter.new(io)
34
+ gz.write(obj)
35
+ gz.close
36
+ [io.string, flags|FMT_GZIP]
37
+ end
38
+
39
+ def load(blob, flags, options = {})
40
+ # decompress value only if gzip flag set
41
+ if (flags & FMT_GZIP) == FMT_GZIP
42
+ io = StringIO.new(blob)
43
+ gz = Zlib::GzipReader.new(io)
44
+ blob = gz.read
45
+ gz.close
46
+ end
47
+ @base.load(blob, flags, options)
48
+ end
49
+ end
@@ -0,0 +1,54 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2013 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
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
+ require 'optparse'
19
+
20
+ # just output extra empty line on CTRL-C
21
+ trap("INT") do
22
+ STDERR.puts
23
+ exit
24
+ end
25
+
26
+ OPTIONS = {
27
+ :bucket => "default",
28
+ :hostname => "127.0.0.1",
29
+ :port => 8091,
30
+ :username => nil,
31
+ :password => nil
32
+ }
33
+
34
+ OptionParser.new do |opts|
35
+ opts.banner = "Usage: #{$0} [options] keys"
36
+ opts.on("-h", "--hostname HOSTNAME", "Hostname to connect to (default: #{OPTIONS[:hostname]}:#{OPTIONS[:port]})") do |v|
37
+ host, port = v.split(':')
38
+ OPTIONS[:hostname] = host.empty? ? '127.0.0.1' : host
39
+ OPTIONS[:port] = port.to_i > 0 ? port.to_i : 8091
40
+ end
41
+ opts.on("-u", "--user USERNAME", "Username to log with (default: none)") do |v|
42
+ OPTIONS[:username] = v
43
+ end
44
+ opts.on("-p", "--password PASSWORD", "Password to log with (default: none)") do |v|
45
+ OPTIONS[:password] = v
46
+ end
47
+ opts.on("-b", "--bucket NAME", "Name of the bucket to connect to (default: #{OPTIONS[:bucket]})") do |v|
48
+ OPTIONS[:bucket] = v
49
+ end
50
+ opts.on_tail("-?", "--help", "Show this message") do
51
+ STDERR.puts opts
52
+ exit
53
+ end
54
+ end.parse!
@@ -0,0 +1,4 @@
1
+ *.log
2
+ *.o
3
+ Makefile
4
+ couchbase_config.h
@@ -0,0 +1,956 @@
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
+ #define _alloc_data_for_s(type, _type, size, items, ptr) do {\
21
+ lcb_size_t ii; \
22
+ \
23
+ params->cmd.type.num = size; \
24
+ params->cmd.type.items = calloc(size, sizeof(_type)); \
25
+ if (params->cmd.type.items == NULL) { \
26
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments"); \
27
+ } \
28
+ params->cmd.type.ptr = calloc(size, sizeof(_type *)); \
29
+ if (params->cmd.type.ptr == NULL) { \
30
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for arguments"); \
31
+ } \
32
+ for (ii = 0; ii < size; ++ii) { \
33
+ params->cmd.type.ptr[ii] = params->cmd.type.items + ii; \
34
+ } \
35
+ } while(0)
36
+
37
+ #define _alloc_data_for(type, _type) _alloc_data_for_s(type, _type, size, items, ptr)
38
+
39
+
40
+ #define _release_data_for_s(type, items, ptr) \
41
+ free(params->cmd.type.items); \
42
+ free(params->cmd.type.ptr);
43
+
44
+ #define _release_data_for(type) _release_data_for_s(type, items, ptr)
45
+
46
+ static VALUE
47
+ get_transcoder(struct cb_bucket_st *bucket, VALUE override, int compat, VALUE opts)
48
+ {
49
+ VALUE ret = Qundef;
50
+
51
+ /* override with symbol */
52
+ if (TYPE(override) == T_SYMBOL) {
53
+ if (override == cb_sym_document) {
54
+ ret = cb_mDocument;
55
+ } else if (override == cb_sym_marshal) {
56
+ ret = cb_mMarshal;
57
+ } else if (override == cb_sym_plain) {
58
+ ret = cb_mPlain;
59
+ }
60
+ } else if (!compat) {
61
+ /* override with transcoder */
62
+ if (rb_respond_to(override, cb_id_dump)
63
+ && rb_respond_to(override, cb_id_load)) {
64
+ ret = override;
65
+ }
66
+ /* nil is also valid */
67
+ if (NIL_P(override)) {
68
+ ret = Qnil;
69
+ }
70
+ }
71
+ if (ret == Qundef) {
72
+ return bucket->transcoder;
73
+ } else {
74
+ rb_hash_aset(opts, cb_sym_forced, Qtrue);
75
+ return ret;
76
+ }
77
+ }
78
+
79
+ /* TOUCH */
80
+
81
+ static void
82
+ cb_params_touch_alloc(struct cb_params_st *params, lcb_size_t size)
83
+ {
84
+ _alloc_data_for(touch, lcb_touch_cmd_t);
85
+ }
86
+
87
+ static void
88
+ cb_params_touch_init_item(struct cb_params_st *params, lcb_size_t idx, VALUE key_obj, lcb_time_t exptime)
89
+ {
90
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
91
+ rb_ary_push(params->ensurance, key_obj);
92
+ params->cmd.touch.items[idx].v.v0.key = RSTRING_PTR(key_obj);
93
+ params->cmd.touch.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
94
+ params->cmd.touch.items[idx].v.v0.exptime = exptime;
95
+ params->npayload += RSTRING_LEN(key_obj) + sizeof(exptime);
96
+ }
97
+
98
+ static int
99
+ cb_params_touch_extract_keys_i(VALUE key, VALUE value, VALUE arg)
100
+ {
101
+ struct cb_params_st *params = (struct cb_params_st *)arg;
102
+ cb_params_touch_init_item(params, params->idx++, key, NUM2ULONG(value));
103
+ return ST_CONTINUE;
104
+ }
105
+
106
+ static void
107
+ cb_params_touch_parse_options(struct cb_params_st *params, VALUE options)
108
+ {
109
+ VALUE tmp;
110
+
111
+ if (NIL_P(options)) {
112
+ return;
113
+ }
114
+ tmp = rb_hash_aref(options, cb_sym_ttl);
115
+ if (tmp != Qnil) {
116
+ params->cmd.touch.ttl = NUM2ULONG(tmp);
117
+ }
118
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
119
+ if (tmp != Qundef) {
120
+ params->cmd.touch.quiet = RTEST(tmp);
121
+ }
122
+ }
123
+
124
+ static void
125
+ cb_params_touch_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
126
+ {
127
+ lcb_size_t ii;
128
+
129
+ if (argc < 1) {
130
+ rb_raise(rb_eArgError, "must be at least one key");
131
+ }
132
+ if (argc == 1) {
133
+ VALUE keys = rb_ary_entry(argv, 0);
134
+ switch(TYPE(keys)) {
135
+ case T_ARRAY:
136
+ /* array of keys as a first argument */
137
+ params->cmd.touch.array = 1;
138
+ cb_params_touch_alloc(params, RARRAY_LEN(keys));
139
+ for (ii = 0; ii < params->cmd.touch.num; ++ii) {
140
+ cb_params_touch_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.touch.ttl);
141
+ }
142
+ break;
143
+ case T_HASH:
144
+ /* key-ttl pairs */
145
+ cb_params_touch_alloc(params, RHASH_SIZE(keys));
146
+ rb_hash_foreach(keys, cb_params_touch_extract_keys_i,
147
+ (VALUE)params);
148
+ break;
149
+ default:
150
+ /* single key */
151
+ cb_params_touch_alloc(params, 1);
152
+ cb_params_touch_init_item(params, 0, keys, params->cmd.touch.ttl);
153
+ }
154
+ } else {
155
+ /* just list of arguments */
156
+ cb_params_touch_alloc(params, argc);
157
+ for (ii = 0; ii < params->cmd.touch.num; ++ii) {
158
+ cb_params_touch_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.touch.ttl);
159
+ }
160
+ }
161
+ }
162
+
163
+
164
+ /* REMOVE */
165
+
166
+ static void
167
+ cb_params_remove_alloc(struct cb_params_st *params, lcb_size_t size)
168
+ {
169
+ _alloc_data_for(remove, lcb_remove_cmd_t);
170
+ }
171
+
172
+ static void
173
+ cb_params_remove_init_item(struct cb_params_st *params, lcb_size_t idx, VALUE key_obj, lcb_cas_t cas)
174
+ {
175
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
176
+ rb_ary_push(params->ensurance, key_obj);
177
+ params->cmd.remove.items[idx].v.v0.key = RSTRING_PTR(key_obj);
178
+ params->cmd.remove.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
179
+ params->cmd.remove.items[idx].v.v0.cas = cas;
180
+ params->npayload += RSTRING_LEN(key_obj);
181
+ }
182
+
183
+ static int
184
+ cb_params_remove_extract_keys_i(VALUE key, VALUE value, VALUE arg)
185
+ {
186
+ struct cb_params_st *params = (struct cb_params_st *)arg;
187
+ cb_params_remove_init_item(params, params->idx++, key, NUM2ULL(value));
188
+ return ST_CONTINUE;
189
+ }
190
+
191
+ static void
192
+ cb_params_remove_parse_options(struct cb_params_st *params, VALUE options)
193
+ {
194
+ VALUE tmp;
195
+
196
+ if (NIL_P(options)) {
197
+ return;
198
+ }
199
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
200
+ if (tmp != Qundef) {
201
+ params->cmd.remove.quiet = RTEST(tmp);
202
+ }
203
+ tmp = rb_hash_aref(options, cb_sym_cas);
204
+ if (tmp != Qnil) {
205
+ params->cmd.remove.cas = NUM2ULL(tmp);
206
+ }
207
+ }
208
+
209
+ static void
210
+ cb_params_remove_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
211
+ {
212
+ lcb_size_t ii;
213
+
214
+ if (argc < 1) {
215
+ rb_raise(rb_eArgError, "must be at least one key");
216
+ }
217
+ if (argc == 1) {
218
+ VALUE keys = rb_ary_entry(argv, 0);
219
+ switch(TYPE(keys)) {
220
+ case T_ARRAY:
221
+ /* array of keys as a first argument */
222
+ params->cmd.remove.array = 1;
223
+ cb_params_remove_alloc(params, RARRAY_LEN(keys));
224
+ for (ii = 0; ii < params->cmd.remove.num; ++ii) {
225
+ cb_params_remove_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.remove.cas);
226
+ }
227
+ break;
228
+ case T_HASH:
229
+ /* key-cas pairs */
230
+ cb_params_remove_alloc(params, RHASH_SIZE(keys));
231
+ rb_hash_foreach(keys, cb_params_remove_extract_keys_i,
232
+ (VALUE)params);
233
+ break;
234
+ default:
235
+ /* single key */
236
+ cb_params_remove_alloc(params, 1);
237
+ cb_params_remove_init_item(params, 0, keys, params->cmd.remove.cas);
238
+ }
239
+ } else {
240
+ /* just list of arguments */
241
+ cb_params_remove_alloc(params, argc);
242
+ for (ii = 0; ii < params->cmd.remove.num; ++ii) {
243
+ cb_params_remove_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.remove.cas);
244
+ }
245
+ }
246
+ }
247
+
248
+
249
+ /* STORE */
250
+ static void
251
+ cb_params_store_alloc(struct cb_params_st *params, lcb_size_t size)
252
+ {
253
+ _alloc_data_for(store, lcb_store_cmd_t);
254
+ }
255
+
256
+ static void
257
+ cb_params_store_init_item(struct cb_params_st *params, lcb_size_t idx,
258
+ VALUE key_obj, VALUE value_obj, lcb_uint32_t flags, lcb_cas_t cas,
259
+ lcb_time_t exptime)
260
+ {
261
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
262
+ value_obj = cb_encode_value(params->cmd.store.transcoder, value_obj, &flags, params->cmd.store.transcoder_opts);
263
+ if (rb_obj_is_kind_of(value_obj, rb_eStandardError)) {
264
+ VALUE exc_str = rb_funcall(value_obj, cb_id_to_s, 0);
265
+ VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
266
+ rb_str_new2("unable to convert value for key \"%s\": %s"), key_obj, exc_str);
267
+ VALUE exc = rb_exc_new3(cb_eValueFormatError, msg);
268
+ rb_ivar_set(exc, cb_id_iv_inner_exception, value_obj);
269
+ rb_exc_raise(exc);
270
+ }
271
+ /* the value must be string after conversion */
272
+ if (TYPE(value_obj) != T_STRING) {
273
+ VALUE val = rb_any_to_s(value_obj);
274
+ rb_raise(cb_eValueFormatError, "unable to convert value for key \"%s\" to string: %s", RSTRING_PTR(key_obj), RSTRING_PTR(val));
275
+ }
276
+ rb_ary_push(params->ensurance, key_obj);
277
+ rb_ary_push(params->ensurance, value_obj);
278
+ params->cmd.store.items[idx].v.v0.datatype = params->cmd.store.datatype;
279
+ params->cmd.store.items[idx].v.v0.operation = params->cmd.store.operation;
280
+ params->cmd.store.items[idx].v.v0.key = RSTRING_PTR(key_obj);
281
+ params->cmd.store.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
282
+ params->cmd.store.items[idx].v.v0.bytes = RSTRING_PTR(value_obj);
283
+ params->cmd.store.items[idx].v.v0.nbytes = RSTRING_LEN(value_obj);
284
+ params->cmd.store.items[idx].v.v0.flags = flags;
285
+ params->cmd.store.items[idx].v.v0.cas = cas;
286
+ params->cmd.store.items[idx].v.v0.exptime = exptime;
287
+ params->npayload += RSTRING_LEN(key_obj) + RSTRING_LEN(value_obj) + sizeof(flags) + sizeof(exptime);
288
+ }
289
+
290
+ static int
291
+ cb_params_store_extract_keys_i(VALUE key, VALUE value, VALUE arg)
292
+ {
293
+ struct cb_params_st *params = (struct cb_params_st *)arg;
294
+ cb_params_store_init_item(params, params->idx++, key, value,
295
+ params->cmd.store.flags, 0, params->cmd.store.ttl);
296
+ return ST_CONTINUE;
297
+ }
298
+
299
+ static void
300
+ cb_params_store_parse_options(struct cb_params_st *params, VALUE options)
301
+ {
302
+ VALUE tmp;
303
+
304
+ if (NIL_P(options)) {
305
+ return;
306
+ }
307
+ tmp = rb_hash_aref(options, cb_sym_flags);
308
+ if (tmp != Qnil) {
309
+ params->cmd.store.flags = (lcb_uint32_t)NUM2ULONG(tmp);
310
+ }
311
+ tmp = rb_hash_aref(options, cb_sym_ttl);
312
+ if (tmp != Qnil) {
313
+ params->cmd.store.ttl = NUM2ULONG(tmp);
314
+ }
315
+ tmp = rb_hash_aref(options, cb_sym_cas);
316
+ if (tmp != Qnil) {
317
+ params->cmd.store.cas = NUM2ULL(tmp);
318
+ }
319
+ tmp = rb_hash_aref(options, cb_sym_observe);
320
+ if (tmp != Qnil) {
321
+ Check_Type(tmp, T_HASH);
322
+ rb_funcall(params->bucket->self, cb_id_verify_observe_options, 1, tmp);
323
+ params->cmd.store.observe = tmp;
324
+ }
325
+ tmp = rb_hash_aref(options, cb_sym_format);
326
+ if (tmp != Qnil) {
327
+ params->cmd.store.transcoder = get_transcoder(params->bucket,
328
+ tmp, 1, params->cmd.store.transcoder_opts);
329
+ }
330
+ tmp = rb_hash_lookup2(options, cb_sym_transcoder, Qundef);
331
+ if (tmp != Qundef) {
332
+ params->cmd.store.transcoder = get_transcoder(params->bucket,
333
+ tmp, 0, params->cmd.store.transcoder_opts);
334
+ }
335
+ }
336
+
337
+ static void
338
+ cb_params_store_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
339
+ {
340
+ VALUE keys;
341
+
342
+ if (argc < 1) {
343
+ rb_raise(rb_eArgError, "the key and value must be specified");
344
+ }
345
+ switch (argc) {
346
+ case 1:
347
+ keys = rb_ary_entry(argv, 0);
348
+ switch(TYPE(keys)) {
349
+ case T_HASH:
350
+ /* key-value pairs */
351
+ cb_params_store_alloc(params, RHASH_SIZE(keys));
352
+ rb_hash_foreach(keys, cb_params_store_extract_keys_i,
353
+ (VALUE)params);
354
+ break;
355
+ default:
356
+ rb_raise(rb_eArgError, "there must be either Hash with key-value pairs"
357
+ " or two separate arguments: key and value");
358
+ }
359
+ break;
360
+ case 2:
361
+ /* just key and value */
362
+ cb_params_store_alloc(params, 1);
363
+ cb_params_store_init_item(params, 0, rb_ary_entry(argv, 0), rb_ary_entry(argv, 1),
364
+ params->cmd.store.flags, params->cmd.store.cas, params->cmd.store.ttl);
365
+ break;
366
+ default:
367
+ rb_raise(rb_eArgError, "too many arguments");
368
+ }
369
+ }
370
+
371
+
372
+ /* GET */
373
+ static void
374
+ cb_params_get_alloc(struct cb_params_st *params, lcb_size_t size)
375
+ {
376
+ if (RTEST(params->cmd.get.replica)) {
377
+ _alloc_data_for_s(get, lcb_get_replica_cmd_t, size, items_gr, ptr_gr);
378
+ } else {
379
+ _alloc_data_for(get, lcb_get_cmd_t);
380
+ }
381
+ }
382
+
383
+ static void
384
+ cb_params_get_init_item(struct cb_params_st *params, lcb_size_t idx,
385
+ VALUE key_obj, lcb_time_t exptime)
386
+ {
387
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
388
+ rb_ary_push(params->ensurance, key_obj);
389
+ if (RTEST(params->cmd.get.replica)) {
390
+ params->cmd.get.items_gr[idx].version = 1;
391
+ params->cmd.get.items_gr[idx].v.v1.key = RSTRING_PTR(key_obj);
392
+ params->cmd.get.items_gr[idx].v.v1.nkey = RSTRING_LEN(key_obj);
393
+ if (params->cmd.get.replica == cb_sym_first || params->cmd.get.replica == Qtrue) {
394
+ params->cmd.get.items_gr[idx].v.v1.strategy = LCB_REPLICA_FIRST;
395
+ } else if (params->cmd.get.replica == cb_sym_all) {
396
+ params->cmd.get.items_gr[idx].v.v1.strategy = LCB_REPLICA_ALL;
397
+ } else {
398
+ params->cmd.get.items_gr[idx].v.v1.strategy = LCB_REPLICA_SELECT;
399
+ params->cmd.get.items_gr[idx].v.v1.index = FIX2INT(params->cmd.get.replica);
400
+ }
401
+ } else {
402
+ params->cmd.get.items[idx].v.v0.key = RSTRING_PTR(key_obj);
403
+ params->cmd.get.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
404
+ params->cmd.get.items[idx].v.v0.exptime = exptime;
405
+ params->cmd.get.items[idx].v.v0.lock = params->cmd.get.lock;
406
+ params->npayload += sizeof(exptime);
407
+ }
408
+ params->npayload += RSTRING_LEN(key_obj);
409
+ }
410
+
411
+ static int
412
+ cb_params_get_extract_keys_i(VALUE key, VALUE value, VALUE arg)
413
+ {
414
+ struct cb_params_st *params = (struct cb_params_st *)arg;
415
+ rb_ary_push(params->cmd.get.keys_ary, key);
416
+ cb_params_get_init_item(params, params->idx++, key, NUM2ULONG(value));
417
+ return ST_CONTINUE;
418
+ }
419
+
420
+ static void
421
+ cb_params_get_parse_options(struct cb_params_st *params, VALUE options)
422
+ {
423
+ VALUE tmp;
424
+
425
+ if (NIL_P(options)) {
426
+ return;
427
+ }
428
+ tmp = rb_hash_aref(options, cb_sym_replica);
429
+ if (tmp == Qtrue || tmp == cb_sym_all || tmp == cb_sym_first) {
430
+ params->cmd.get.replica = tmp;
431
+ } else if (TYPE(tmp) == T_FIXNUM) {
432
+ int nr = NUM2INT(tmp);
433
+ int max = lcb_get_num_replicas(params->bucket->handle);
434
+ if (nr < 0 || nr >= max) {
435
+ rb_raise(rb_eArgError, "replica index should be in interval 0...%d", max);
436
+ }
437
+ params->cmd.get.replica = tmp;
438
+ }
439
+ params->cmd.get.extended = RTEST(rb_hash_aref(options, cb_sym_extended));
440
+ params->cmd.get.assemble_hash = RTEST(rb_hash_aref(options, cb_sym_assemble_hash));
441
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
442
+ if (tmp != Qundef) {
443
+ params->cmd.get.quiet = RTEST(tmp);
444
+ }
445
+ tmp = rb_hash_aref(options, cb_sym_format);
446
+ if (tmp != Qnil) {
447
+ params->cmd.get.transcoder = get_transcoder(params->bucket,
448
+ tmp, 1, params->cmd.get.transcoder_opts);
449
+ }
450
+ tmp = rb_hash_lookup2(options, cb_sym_transcoder, Qundef);
451
+ if (tmp != Qundef) {
452
+ params->cmd.get.transcoder = get_transcoder(params->bucket,
453
+ tmp, 0, params->cmd.get.transcoder_opts);
454
+ }
455
+ tmp = rb_hash_aref(options, cb_sym_ttl);
456
+ if (tmp != Qnil) {
457
+ params->cmd.get.ttl = NUM2ULONG(tmp);
458
+ }
459
+ /* boolean or number of seconds to lock */
460
+ tmp = rb_hash_aref(options, cb_sym_lock);
461
+ if (tmp != Qnil) {
462
+ params->cmd.get.lock = RTEST(tmp);
463
+ if (TYPE(tmp) == T_FIXNUM) {
464
+ params->cmd.get.ttl = NUM2ULONG(tmp);
465
+ }
466
+ }
467
+ }
468
+
469
+ static void
470
+ cb_params_get_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
471
+ {
472
+ lcb_size_t ii;
473
+
474
+ if (argc < 1) {
475
+ rb_raise(rb_eArgError, "must be at least one key");
476
+ }
477
+ if (argc == 1) {
478
+ VALUE keys = rb_ary_entry(argv, 0);
479
+ switch(TYPE(keys)) {
480
+ case T_ARRAY:
481
+ /* array of keys as a first argument */
482
+ params->cmd.get.array = 1;
483
+ cb_params_get_alloc(params, RARRAY_LEN(keys));
484
+ for (ii = 0; ii < params->cmd.get.num; ++ii) {
485
+ rb_ary_push(params->cmd.get.keys_ary, rb_ary_entry(keys, ii));
486
+ cb_params_get_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.get.ttl);
487
+ }
488
+ break;
489
+ case T_HASH:
490
+ /* key-ttl pairs */
491
+ if (params->cmd.get.replica) {
492
+ rb_raise(rb_eArgError, "must be either list of key or single key");
493
+ }
494
+ params->cmd.get.gat = 1;
495
+ cb_params_get_alloc(params, RHASH_SIZE(keys));
496
+ rb_hash_foreach(keys, cb_params_get_extract_keys_i, (VALUE)params);
497
+ break;
498
+ default:
499
+ /* single key */
500
+ cb_params_get_alloc(params, 1);
501
+ rb_ary_push(params->cmd.get.keys_ary, keys);
502
+ cb_params_get_init_item(params, 0, keys, params->cmd.get.ttl);
503
+ }
504
+ } else {
505
+ /* just list of arguments */
506
+ cb_params_get_alloc(params, argc);
507
+ for (ii = 0; ii < params->cmd.get.num; ++ii) {
508
+ rb_ary_push(params->cmd.get.keys_ary, rb_ary_entry(argv, ii));
509
+ cb_params_get_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.get.ttl);
510
+ }
511
+ }
512
+ }
513
+
514
+
515
+ /* ARITH */
516
+ static void
517
+ cb_params_arith_alloc(struct cb_params_st *params, lcb_size_t size)
518
+ {
519
+ _alloc_data_for(arith, lcb_arithmetic_cmd_t);
520
+ }
521
+
522
+ static void
523
+ cb_params_arith_init_item(struct cb_params_st *params, lcb_size_t idx,
524
+ VALUE key_obj, lcb_int64_t delta)
525
+ {
526
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
527
+ rb_ary_push(params->ensurance, key_obj);
528
+ params->cmd.arith.items[idx].v.v0.key = RSTRING_PTR(key_obj);
529
+ params->cmd.arith.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
530
+ params->cmd.arith.items[idx].v.v0.delta = delta * params->cmd.arith.sign;
531
+ params->cmd.arith.items[idx].v.v0.exptime = params->cmd.arith.ttl;
532
+ params->cmd.arith.items[idx].v.v0.create = params->cmd.arith.create;
533
+ params->cmd.arith.items[idx].v.v0.initial = params->cmd.arith.initial;
534
+ params->npayload += RSTRING_LEN(key_obj);
535
+ }
536
+
537
+ static int
538
+ cb_params_arith_extract_keys_i(VALUE key, VALUE value, VALUE arg)
539
+ {
540
+ struct cb_params_st *params = (struct cb_params_st *)arg;
541
+ cb_params_arith_init_item(params, params->idx++, key, NUM2ULONG(value) & INT64_MAX);
542
+ return ST_CONTINUE;
543
+ }
544
+
545
+ static void
546
+ cb_params_arith_parse_options(struct cb_params_st *params, VALUE options)
547
+ {
548
+ VALUE tmp;
549
+
550
+ if (NIL_P(options)) {
551
+ return;
552
+ }
553
+ tmp = rb_hash_aref(options, cb_sym_create);
554
+ if (tmp != Qnil) {
555
+ params->cmd.arith.create = RTEST(tmp);
556
+ }
557
+ params->cmd.arith.extended = RTEST(rb_hash_aref(options, cb_sym_extended));
558
+ tmp = rb_hash_aref(options, cb_sym_ttl);
559
+ if (tmp != Qnil) {
560
+ params->cmd.arith.ttl = NUM2ULONG(tmp);
561
+ }
562
+ tmp = rb_hash_aref(options, cb_sym_initial);
563
+ if (tmp != Qnil) {
564
+ params->cmd.arith.initial = NUM2ULL(tmp);
565
+ params->cmd.arith.create = 1;
566
+ }
567
+ tmp = rb_hash_aref(options, cb_sym_delta);
568
+ if (tmp != Qnil) {
569
+ params->cmd.arith.delta = NUM2ULL(tmp) & INT64_MAX;
570
+ }
571
+ tmp = rb_hash_aref(options, cb_sym_format);
572
+ if (tmp != Qnil) {
573
+ params->cmd.arith.transcoder = get_transcoder(params->bucket,
574
+ tmp, 1, params->cmd.arith.transcoder_opts);
575
+ }
576
+ tmp = rb_hash_lookup2(options, cb_sym_transcoder, Qundef);
577
+ if (tmp != Qundef) {
578
+ params->cmd.arith.transcoder = get_transcoder(params->bucket,
579
+ tmp, 0, params->cmd.arith.transcoder_opts);
580
+ }
581
+ }
582
+
583
+ static void
584
+ cb_params_arith_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
585
+ {
586
+ lcb_size_t ii;
587
+
588
+ if (argc < 1) {
589
+ rb_raise(rb_eArgError, "must be at least one key");
590
+ }
591
+ if (argc == 1) {
592
+ VALUE keys = rb_ary_entry(argv, 0);
593
+ switch(TYPE(keys)) {
594
+ case T_ARRAY:
595
+ /* array of keys as a first argument */
596
+ params->cmd.arith.array = 1;
597
+ cb_params_arith_alloc(params, RARRAY_LEN(keys));
598
+ for (ii = 0; ii < params->cmd.arith.num; ++ii) {
599
+ cb_params_arith_init_item(params, ii, rb_ary_entry(keys, ii), params->cmd.arith.delta);
600
+ }
601
+ break;
602
+ case T_HASH:
603
+ /* key-delta pairs */
604
+ cb_params_arith_alloc(params, RHASH_SIZE(keys));
605
+ rb_hash_foreach(keys, cb_params_arith_extract_keys_i, (VALUE)params);
606
+ break;
607
+ default:
608
+ /* single key */
609
+ cb_params_arith_alloc(params, 1);
610
+ cb_params_arith_init_item(params, 0, keys, params->cmd.arith.delta);
611
+ }
612
+ } else {
613
+ /* just list of arguments */
614
+ cb_params_arith_alloc(params, argc);
615
+ for (ii = 0; ii < params->cmd.arith.num; ++ii) {
616
+ cb_params_arith_init_item(params, ii, rb_ary_entry(argv, ii), params->cmd.arith.delta);
617
+ }
618
+ }
619
+ }
620
+
621
+
622
+ /* STATS */
623
+ static void
624
+ cb_params_stats_alloc(struct cb_params_st *params, lcb_size_t size)
625
+ {
626
+ _alloc_data_for(stats, lcb_server_stats_cmd_t);
627
+ }
628
+
629
+ static void
630
+ cb_params_stats_init_item(struct cb_params_st *params, lcb_size_t idx,
631
+ VALUE key_obj)
632
+ {
633
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
634
+ rb_ary_push(params->ensurance, key_obj);
635
+ params->cmd.stats.items[idx].v.v0.name = RSTRING_PTR(key_obj);
636
+ params->cmd.stats.items[idx].v.v0.nname = RSTRING_LEN(key_obj);
637
+ params->npayload += RSTRING_LEN(key_obj);
638
+ }
639
+
640
+ static void
641
+ cb_params_stats_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
642
+ {
643
+ lcb_size_t ii;
644
+
645
+ if (argc == 1) {
646
+ VALUE keys = rb_ary_entry(argv, 0);
647
+ switch(TYPE(keys)) {
648
+ case T_ARRAY:
649
+ /* array of keys as a first argument */
650
+ params->cmd.stats.array = 1;
651
+ cb_params_stats_alloc(params, RARRAY_LEN(keys));
652
+ for (ii = 0; ii < params->cmd.stats.num; ++ii) {
653
+ cb_params_stats_init_item(params, ii, rb_ary_entry(keys, ii));
654
+ }
655
+ break;
656
+ default:
657
+ /* single key */
658
+ cb_params_stats_alloc(params, 1);
659
+ cb_params_stats_init_item(params, 0, keys);
660
+ }
661
+ } else if (argc == 0) {
662
+ /* stat without argument (single empty struct) */
663
+ cb_params_stats_alloc(params, 1);
664
+ } else {
665
+ /* just list of arguments */
666
+ cb_params_stats_alloc(params, argc);
667
+ for (ii = 0; ii < params->cmd.stats.num; ++ii) {
668
+ cb_params_stats_init_item(params, ii, rb_ary_entry(argv, ii));
669
+ }
670
+ }
671
+ }
672
+
673
+
674
+ /* REMOVE */
675
+
676
+ static void
677
+ cb_params_observe_alloc(struct cb_params_st *params, lcb_size_t size)
678
+ {
679
+ _alloc_data_for(observe, lcb_observe_cmd_t);
680
+ }
681
+
682
+ static void
683
+ cb_params_observe_init_item(struct cb_params_st *params, lcb_size_t idx, VALUE key_obj)
684
+ {
685
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
686
+ rb_ary_push(params->ensurance, key_obj);
687
+ params->cmd.observe.items[idx].v.v0.key = RSTRING_PTR(key_obj);
688
+ params->cmd.observe.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
689
+ params->npayload += RSTRING_LEN(key_obj);
690
+ }
691
+
692
+ static void
693
+ cb_params_observe_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
694
+ {
695
+ lcb_size_t ii;
696
+
697
+ if (argc < 1) {
698
+ rb_raise(rb_eArgError, "must be at least one key");
699
+ }
700
+ if (argc == 1) {
701
+ VALUE keys = rb_ary_entry(argv, 0);
702
+ switch(TYPE(keys)) {
703
+ case T_ARRAY:
704
+ /* array of keys as a first argument */
705
+ params->cmd.observe.array = 1;
706
+ cb_params_observe_alloc(params, RARRAY_LEN(keys));
707
+ for (ii = 0; ii < params->cmd.observe.num; ++ii) {
708
+ cb_params_observe_init_item(params, ii, rb_ary_entry(keys, ii));
709
+ }
710
+ break;
711
+ default:
712
+ /* single key */
713
+ cb_params_observe_alloc(params, 1);
714
+ cb_params_observe_init_item(params, 0, keys);
715
+ }
716
+ } else {
717
+ /* just list of arguments */
718
+ cb_params_observe_alloc(params, argc);
719
+ for (ii = 0; ii < params->cmd.observe.num; ++ii) {
720
+ cb_params_observe_init_item(params, ii, rb_ary_entry(argv, ii));
721
+ }
722
+ }
723
+ }
724
+
725
+
726
+ /* UNLOCK */
727
+ static void
728
+ cb_params_unlock_alloc(struct cb_params_st *params, lcb_size_t size)
729
+ {
730
+ _alloc_data_for(unlock, lcb_unlock_cmd_t);
731
+ }
732
+
733
+ static void
734
+ cb_params_unlock_init_item(struct cb_params_st *params, lcb_size_t idx, VALUE key_obj, lcb_cas_t cas)
735
+ {
736
+ key_obj = cb_unify_key(params->bucket, key_obj, 1);
737
+ rb_ary_push(params->ensurance, key_obj);
738
+ params->cmd.unlock.items[idx].v.v0.key = RSTRING_PTR(key_obj);
739
+ params->cmd.unlock.items[idx].v.v0.nkey = RSTRING_LEN(key_obj);
740
+ params->cmd.unlock.items[idx].v.v0.cas = cas;
741
+ params->npayload += RSTRING_LEN(key_obj);
742
+ }
743
+
744
+ static int
745
+ cb_params_unlock_extract_keys_i(VALUE key, VALUE value, VALUE arg)
746
+ {
747
+ struct cb_params_st *params = (struct cb_params_st *)arg;
748
+ cb_params_unlock_init_item(params, params->idx++, key, NUM2ULL(value));
749
+ return ST_CONTINUE;
750
+ }
751
+
752
+ static void
753
+ cb_params_unlock_parse_options(struct cb_params_st *params, VALUE options)
754
+ {
755
+ VALUE tmp;
756
+
757
+ if (NIL_P(options)) {
758
+ return;
759
+ }
760
+ tmp = rb_hash_aref(options, cb_sym_cas);
761
+ if (tmp != Qnil) {
762
+ params->cmd.unlock.cas = NUM2ULL(tmp);
763
+ }
764
+ tmp = rb_hash_lookup2(options, cb_sym_quiet, Qundef);
765
+ if (tmp != Qundef) {
766
+ params->cmd.unlock.quiet = RTEST(tmp);
767
+ }
768
+ }
769
+
770
+ static void
771
+ cb_params_unlock_parse_arguments(struct cb_params_st *params, int argc, VALUE argv)
772
+ {
773
+ if (argc == 1) {
774
+ VALUE keys = rb_ary_entry(argv, 0);
775
+ switch(TYPE(keys)) {
776
+ case T_HASH:
777
+ /* key-cas pairs */
778
+ cb_params_unlock_alloc(params, RHASH_SIZE(keys));
779
+ rb_hash_foreach(keys, cb_params_unlock_extract_keys_i, (VALUE)params);
780
+ break;
781
+ default:
782
+ /* single key */
783
+ cb_params_unlock_alloc(params, 1);
784
+ cb_params_unlock_init_item(params, 0, keys, params->cmd.unlock.cas);
785
+ }
786
+ } else {
787
+ rb_raise(rb_eArgError, "must be either Hash or single key with cas option");
788
+ }
789
+ }
790
+
791
+
792
+ /* VERSION */
793
+ static void
794
+ cb_params_version_alloc(struct cb_params_st *params)
795
+ {
796
+ params->cmd.version.num = 1;
797
+ _alloc_data_for_s(version, lcb_server_version_cmd_t, 1, items, ptr);
798
+ }
799
+
800
+
801
+ /* common stuff */
802
+ void
803
+ cb_params_destroy(struct cb_params_st *params)
804
+ {
805
+ rb_ary_clear(params->ensurance);
806
+ params->ensurance = Qfalse;
807
+ params->args = Qfalse;
808
+ switch (params->type) {
809
+ case cb_cmd_get:
810
+ _release_data_for(get);
811
+ _release_data_for_s(get, items_gr, ptr_gr);
812
+ break;
813
+ case cb_cmd_touch:
814
+ _release_data_for(touch);
815
+ break;
816
+ case cb_cmd_arith:
817
+ _release_data_for(arith);
818
+ break;
819
+ case cb_cmd_remove:
820
+ _release_data_for(remove);
821
+ break;
822
+ case cb_cmd_store:
823
+ _release_data_for(store);
824
+ break;
825
+ case cb_cmd_stats:
826
+ _release_data_for(stats);
827
+ break;
828
+ case cb_cmd_version:
829
+ _release_data_for(version);
830
+ break;
831
+ case cb_cmd_observe:
832
+ _release_data_for(observe);
833
+ break;
834
+ case cb_cmd_unlock:
835
+ _release_data_for(unlock);
836
+ break;
837
+ }
838
+ }
839
+
840
+ static VALUE
841
+ do_params_build(VALUE ptr)
842
+ {
843
+ VALUE opts;
844
+ /* unpack arguments */
845
+ struct cb_params_st *params = (struct cb_params_st*)ptr;
846
+ int argc = RARRAY_LEN(params->args);
847
+ VALUE argv = params->args;
848
+
849
+ /* extract options */
850
+ if (argc > 1 && TYPE(rb_ary_entry(argv, argc-1)) == T_HASH) {
851
+ opts = rb_ary_pop(argv);
852
+ --argc;
853
+ } else {
854
+ opts = Qnil;
855
+ }
856
+
857
+ params->npayload = CB_PACKET_HEADER_SIZE; /* size of packet header */
858
+ switch (params->type) {
859
+ case cb_cmd_touch:
860
+ params->cmd.touch.quiet = params->bucket->quiet;
861
+ params->cmd.touch.ttl = params->bucket->default_ttl;
862
+ cb_params_touch_parse_options(params, opts);
863
+ cb_params_touch_parse_arguments(params, argc, argv);
864
+ break;
865
+ case cb_cmd_remove:
866
+ params->cmd.remove.quiet = params->bucket->quiet;
867
+ if (argc == 2) {
868
+ int type = TYPE(rb_ary_entry(argv, 1));
869
+ if (type == T_FIXNUM || type == T_BIGNUM) {
870
+ /* allow form delete("foo", 0xdeadbeef) */
871
+ --argc;
872
+ params->cmd.remove.cas = NUM2ULL(rb_ary_pop(argv));
873
+ }
874
+ }
875
+ cb_params_remove_parse_options(params, opts);
876
+ cb_params_remove_parse_arguments(params, argc, argv);
877
+ break;
878
+ case cb_cmd_store:
879
+ if (argc == 1 && opts != Qnil) {
880
+ /* put last hash back because it is the value */
881
+ rb_ary_push(argv, opts);
882
+ opts = Qnil;
883
+ ++argc;
884
+ }
885
+ params->cmd.store.datatype = 0x00;
886
+ params->cmd.store.ttl = params->bucket->default_ttl;
887
+ params->cmd.store.flags = params->bucket->default_flags;
888
+ params->cmd.store.observe = Qnil;
889
+ params->cmd.store.transcoder = params->bucket->transcoder;
890
+ params->cmd.store.transcoder_opts = rb_hash_new();
891
+ cb_params_store_parse_options(params, opts);
892
+ cb_params_store_parse_arguments(params, argc, argv);
893
+ break;
894
+ case cb_cmd_get:
895
+ params->cmd.get.quiet = params->bucket->quiet;
896
+ params->cmd.get.transcoder = params->bucket->transcoder;
897
+ params->cmd.get.transcoder_opts = rb_hash_new();
898
+ params->cmd.get.replica = Qfalse;
899
+ cb_params_get_parse_options(params, opts);
900
+ cb_params_get_parse_arguments(params, argc, argv);
901
+ break;
902
+ case cb_cmd_arith:
903
+ params->cmd.arith.transcoder = params->bucket->transcoder;
904
+ params->cmd.arith.transcoder_opts = rb_hash_new();
905
+ params->cmd.arith.create = params->bucket->default_arith_create;
906
+ params->cmd.arith.initial = params->bucket->default_arith_init;
907
+ params->cmd.arith.delta = 1;
908
+ params->cmd.arith.ttl = params->bucket->default_ttl;
909
+ if (argc == 2 && TYPE(rb_ary_entry(argv, 1)) == T_FIXNUM) {
910
+ /* allow form incr("foo", 1) */
911
+ --argc;
912
+ params->cmd.arith.delta = NUM2ULL(rb_ary_pop(argv)) & INT64_MAX;
913
+ }
914
+ cb_params_arith_parse_options(params, opts);
915
+ cb_params_arith_parse_arguments(params, argc, argv);
916
+ break;
917
+ case cb_cmd_stats:
918
+ cb_params_stats_parse_arguments(params, argc, argv);
919
+ break;
920
+ case cb_cmd_version:
921
+ cb_params_version_alloc(params);
922
+ break;
923
+ case cb_cmd_observe:
924
+ cb_params_observe_parse_arguments(params, argc, argv);
925
+ break;
926
+ case cb_cmd_unlock:
927
+ params->cmd.unlock.quiet = params->bucket->quiet;
928
+ if (argc == 2) {
929
+ int type = TYPE(rb_ary_entry(argv, 1));
930
+ if (type == T_FIXNUM || type == T_BIGNUM) {
931
+ /* allow form unlock("foo", 0xdeadbeef) */
932
+ --argc;
933
+ params->cmd.unlock.cas = NUM2ULL(rb_ary_pop(argv));
934
+ }
935
+ }
936
+ cb_params_unlock_parse_options(params, opts);
937
+ cb_params_unlock_parse_arguments(params, argc, argv);
938
+ break;
939
+ }
940
+
941
+ return Qnil;
942
+ }
943
+
944
+ void
945
+ cb_params_build(struct cb_params_st *params)
946
+ {
947
+ int fail = 0;
948
+ params->ensurance = rb_ary_new();
949
+
950
+ rb_protect(do_params_build, (VALUE)params, &fail);
951
+ if (fail) {
952
+ cb_params_destroy(params);
953
+ /* raise exception from protected block */
954
+ rb_jump_tag(fail);
955
+ }
956
+ }