jmoses-couchbase 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/.gitignore +15 -0
  2. data/.travis.yml +22 -0
  3. data/.yardopts +5 -0
  4. data/CONTRIBUTING.markdown +75 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +201 -0
  7. data/Makefile +3 -0
  8. data/README.markdown +665 -0
  9. data/RELEASE_NOTES.markdown +819 -0
  10. data/Rakefile +20 -0
  11. data/couchbase.gemspec +49 -0
  12. data/examples/chat-em/Gemfile +7 -0
  13. data/examples/chat-em/README.markdown +45 -0
  14. data/examples/chat-em/server.rb +82 -0
  15. data/examples/chat-goliath-grape/Gemfile +5 -0
  16. data/examples/chat-goliath-grape/README.markdown +50 -0
  17. data/examples/chat-goliath-grape/app.rb +67 -0
  18. data/examples/chat-goliath-grape/config/app.rb +20 -0
  19. data/examples/transcoders/Gemfile +3 -0
  20. data/examples/transcoders/README.markdown +59 -0
  21. data/examples/transcoders/cb-zcat +40 -0
  22. data/examples/transcoders/cb-zcp +45 -0
  23. data/examples/transcoders/gzip_transcoder.rb +49 -0
  24. data/examples/transcoders/options.rb +54 -0
  25. data/ext/couchbase_ext/.gitignore +4 -0
  26. data/ext/couchbase_ext/arguments.c +956 -0
  27. data/ext/couchbase_ext/arithmetic.c +316 -0
  28. data/ext/couchbase_ext/bucket.c +1373 -0
  29. data/ext/couchbase_ext/context.c +65 -0
  30. data/ext/couchbase_ext/couchbase_ext.c +1364 -0
  31. data/ext/couchbase_ext/couchbase_ext.h +644 -0
  32. data/ext/couchbase_ext/delete.c +163 -0
  33. data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
  34. data/ext/couchbase_ext/extconf.rb +169 -0
  35. data/ext/couchbase_ext/get.c +316 -0
  36. data/ext/couchbase_ext/gethrtime.c +129 -0
  37. data/ext/couchbase_ext/http.c +432 -0
  38. data/ext/couchbase_ext/multithread_plugin.c +1090 -0
  39. data/ext/couchbase_ext/observe.c +171 -0
  40. data/ext/couchbase_ext/plugin_common.c +171 -0
  41. data/ext/couchbase_ext/result.c +129 -0
  42. data/ext/couchbase_ext/stats.c +163 -0
  43. data/ext/couchbase_ext/store.c +542 -0
  44. data/ext/couchbase_ext/timer.c +192 -0
  45. data/ext/couchbase_ext/touch.c +186 -0
  46. data/ext/couchbase_ext/unlock.c +176 -0
  47. data/ext/couchbase_ext/utils.c +551 -0
  48. data/ext/couchbase_ext/version.c +142 -0
  49. data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
  50. data/lib/active_support/cache/couchbase_store.rb +430 -0
  51. data/lib/couchbase.rb +155 -0
  52. data/lib/couchbase/bucket.rb +457 -0
  53. data/lib/couchbase/cluster.rb +119 -0
  54. data/lib/couchbase/connection_pool.rb +58 -0
  55. data/lib/couchbase/constants.rb +12 -0
  56. data/lib/couchbase/result.rb +26 -0
  57. data/lib/couchbase/transcoder.rb +120 -0
  58. data/lib/couchbase/utils.rb +62 -0
  59. data/lib/couchbase/version.rb +21 -0
  60. data/lib/couchbase/view.rb +506 -0
  61. data/lib/couchbase/view_row.rb +272 -0
  62. data/lib/ext/multi_json_fix.rb +56 -0
  63. data/lib/rack/session/couchbase.rb +108 -0
  64. data/tasks/benchmark.rake +6 -0
  65. data/tasks/compile.rake +160 -0
  66. data/tasks/test.rake +100 -0
  67. data/tasks/util.rake +21 -0
  68. data/test/profile/.gitignore +1 -0
  69. data/test/profile/Gemfile +6 -0
  70. data/test/profile/benchmark.rb +195 -0
  71. data/test/setup.rb +178 -0
  72. data/test/test_arithmetic.rb +185 -0
  73. data/test/test_async.rb +316 -0
  74. data/test/test_bucket.rb +276 -0
  75. data/test/test_cas.rb +235 -0
  76. data/test/test_couchbase.rb +77 -0
  77. data/test/test_couchbase_connection_pool.rb +77 -0
  78. data/test/test_couchbase_rails_cache_store.rb +361 -0
  79. data/test/test_delete.rb +120 -0
  80. data/test/test_errors.rb +82 -0
  81. data/test/test_eventmachine.rb +70 -0
  82. data/test/test_format.rb +164 -0
  83. data/test/test_get.rb +407 -0
  84. data/test/test_stats.rb +57 -0
  85. data/test/test_store.rb +216 -0
  86. data/test/test_timer.rb +42 -0
  87. data/test/test_touch.rb +97 -0
  88. data/test/test_unlock.rb +119 -0
  89. data/test/test_utils.rb +58 -0
  90. data/test/test_version.rb +52 -0
  91. metadata +353 -0
@@ -0,0 +1,129 @@
1
+ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2010, 2011 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
+ #ifndef HAVE_GETHRTIME
21
+
22
+ #include <stdlib.h>
23
+ #include <time.h>
24
+ #include <assert.h>
25
+
26
+ #ifdef HAVE_MACH_MACH_TIME_H
27
+ #include <mach/mach_time.h>
28
+ #endif
29
+
30
+ #ifdef HAVE_SYS_TIME_H
31
+ #include <sys/time.h>
32
+ #endif
33
+
34
+ /*
35
+ * OS X doesn't have clock_gettime, but for monotonic, we can build
36
+ * one with mach_absolute_time as shown below.
37
+ *
38
+ * Most of the idea came from
39
+ * http://www.wand.net.nz/~smr26/wordpress/2009/01/19/monotonic-time-in-mac-os-x/
40
+ */
41
+
42
+ #if defined(HAVE_MACH_ABSOLUTE_TIME) && !defined(HAVE_CLOCK_GETTIME)
43
+
44
+ #define CLOCK_MONOTONIC 192996728
45
+
46
+ static void mach_absolute_difference(uint64_t start, uint64_t end,
47
+ struct timespec *tp)
48
+ {
49
+ uint64_t difference = end - start;
50
+ static mach_timebase_info_data_t info = {0, 0};
51
+
52
+ if (info.denom == 0) {
53
+ mach_timebase_info(&info);
54
+ }
55
+
56
+ uint64_t elapsednano = difference * (info.numer / info.denom);
57
+
58
+ tp->tv_sec = elapsednano * 1e-9;
59
+ tp->tv_nsec = elapsednano - (tp->tv_sec * 1e9);
60
+ }
61
+
62
+ static int clock_gettime(int which, struct timespec *tp)
63
+ {
64
+ assert(which == CLOCK_MONOTONIC);
65
+
66
+ static uint64_t epoch = 0;
67
+
68
+ if (epoch == 0) {
69
+ epoch = mach_absolute_time();
70
+ }
71
+
72
+ uint64_t now = mach_absolute_time();
73
+
74
+ mach_absolute_difference(epoch, now, tp);
75
+
76
+ return 0;
77
+ }
78
+
79
+ #define HAVE_CLOCK_GETTIME 1
80
+ #endif
81
+
82
+ hrtime_t gethrtime(void)
83
+ {
84
+ #ifdef HAVE_CLOCK_GETTIME
85
+ struct timespec tm;
86
+ if (clock_gettime(CLOCK_MONOTONIC, &tm) == -1) {
87
+ abort();
88
+ }
89
+ return (((hrtime_t)tm.tv_sec) * 1000000000) + (hrtime_t)tm.tv_nsec;
90
+ #elif HAVE_GETTIMEOFDAY
91
+
92
+ hrtime_t ret;
93
+ struct timeval tv;
94
+ if (gettimeofday(&tv, NULL) == -1) {
95
+ return (-1ULL);
96
+ }
97
+
98
+ ret = (hrtime_t)tv.tv_sec * 1000000000;
99
+ ret += tv.tv_usec * 1000;
100
+ return ret;
101
+ #elif defined(HAVE_QUERYPERFORMANCECOUNTER)
102
+ double ret;
103
+ // To fix the potential race condition for the local static variable,
104
+ // gethrtime should be called in a global static variable first.
105
+ // It will guarantee the local static variable will be initialized
106
+ // before any thread calls the function.
107
+ static LARGE_INTEGER pf = { 0 };
108
+ static double freq;
109
+ LARGE_INTEGER currtime;
110
+
111
+ if (pf.QuadPart == 0) {
112
+ if (QueryPerformanceFrequency(&pf)) {
113
+ assert(pf.QuadPart != 0);
114
+ freq = 1.0e9 / (double)pf.QuadPart;
115
+ } else {
116
+ abort();
117
+ }
118
+ }
119
+
120
+ QueryPerformanceCounter(&currtime);
121
+
122
+ ret = (double)currtime.QuadPart * freq ;
123
+ return (hrtime_t)ret;
124
+ #else
125
+ #error "I don't know how to build a highres clock..."
126
+ #endif
127
+ }
128
+
129
+ #endif
@@ -0,0 +1,432 @@
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_http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_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 key, val, res, exc;
26
+ lcb_http_status_t status;
27
+
28
+ ctx->request->completed = 1;
29
+
30
+ if (bucket->destroying) {
31
+ cb_context_free(ctx);
32
+ return;
33
+ }
34
+
35
+ key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
36
+ val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
37
+ exc = ctx->exception;
38
+ if (!RTEST(exc)) {
39
+ exc = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status);
40
+ if (exc != Qnil && val != Qnil) {
41
+ rb_ivar_set(exc, cb_id_iv_body, val);
42
+ }
43
+ }
44
+ if (RTEST(exc)) {
45
+ if (rb_obj_is_kind_of(exc, cb_eHTTPError)) {
46
+ rb_funcall(exc, cb_id_parse_body_bang, 0);
47
+ }
48
+ ctx->exception = exc;
49
+ }
50
+ status = resp->v.v0.status;
51
+ if (resp->v.v0.headers) {
52
+ cb_build_headers(ctx, resp->v.v0.headers);
53
+ ctx->headers_val = Qnil;
54
+ }
55
+ if (ctx->extended) {
56
+ res = rb_class_new_instance(0, NULL, cb_cResult);
57
+ rb_ivar_set(res, cb_id_iv_error, ctx->exception);
58
+ rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
59
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
60
+ rb_ivar_set(res, cb_id_iv_key, key);
61
+ rb_ivar_set(res, cb_id_iv_value, val);
62
+ rb_ivar_set(res, cb_id_iv_completed, Qtrue);
63
+ rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
64
+ } else {
65
+ res = val;
66
+ }
67
+ if (ctx->proc != Qnil) {
68
+ cb_proc_call(bucket, ctx->proc, 1, res);
69
+ ctx->proc = Qnil;
70
+ }
71
+ if (!bucket->async && ctx->exception == Qnil) {
72
+ ctx->rv = res;
73
+ }
74
+ if (bucket->async) {
75
+ cb_context_free(ctx);
76
+ }
77
+ (void)handle;
78
+ (void)request;
79
+ }
80
+
81
+ void
82
+ cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp)
83
+ {
84
+ struct cb_context_st *ctx = (struct cb_context_st *)cookie;
85
+ struct cb_bucket_st *bucket = ctx->bucket;
86
+ VALUE key, val, res;
87
+ lcb_http_status_t status;
88
+
89
+ key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
90
+ val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
91
+ status = resp->v.v0.status;
92
+ if (NIL_P(ctx->exception)) {
93
+ ctx->exception = cb_check_error_with_status(error,
94
+ "failed to execute HTTP request", key, resp->v.v0.status);
95
+ if (ctx->exception != Qnil) {
96
+ VALUE body_str = rb_ivar_get(ctx->exception, cb_id_iv_body);
97
+ if (NIL_P(body_str)) {
98
+ rb_ivar_set(ctx->exception, cb_id_iv_body, val);
99
+ } else {
100
+ rb_str_concat(body_str, val);
101
+ }
102
+ return;
103
+ }
104
+ }
105
+ if (resp->v.v0.headers) {
106
+ cb_build_headers(ctx, resp->v.v0.headers);
107
+ }
108
+ if (ctx->proc != Qnil) {
109
+ if (ctx->extended) {
110
+ res = rb_class_new_instance(0, NULL, cb_cResult);
111
+ rb_ivar_set(res, cb_id_iv_error, Qnil);
112
+ rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
113
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
114
+ rb_ivar_set(res, cb_id_iv_key, key);
115
+ rb_ivar_set(res, cb_id_iv_value, val);
116
+ rb_ivar_set(res, cb_id_iv_completed, Qfalse);
117
+ rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
118
+ } else {
119
+ res = val;
120
+ }
121
+ cb_proc_call(bucket, ctx->proc, 1, res);
122
+ }
123
+ (void)handle;
124
+ (void)request;
125
+ }
126
+
127
+ void
128
+ cb_http_request_free(void *ptr)
129
+ {
130
+ struct cb_http_request_st *request = ptr;
131
+ if (request) {
132
+ request->running = 0;
133
+ if (TYPE(request->bucket_obj) == T_DATA
134
+ && RDATA(request->bucket_obj)->dfree == (RUBY_DATA_FUNC)cb_bucket_free
135
+ && !request->completed) {
136
+ lcb_cancel_http_request(request->bucket->handle, request->request);
137
+ }
138
+ free((char *)request->cmd.v.v0.content_type);
139
+ free((char *)request->cmd.v.v0.path);
140
+ free((char *)request->cmd.v.v0.body);
141
+ }
142
+ xfree(request);
143
+ }
144
+
145
+ void
146
+ cb_http_request_mark(void *ptr)
147
+ {
148
+ struct cb_http_request_st *request = ptr;
149
+ if (request) {
150
+ rb_gc_mark(request->on_body_callback);
151
+ }
152
+ }
153
+
154
+ VALUE
155
+ cb_http_request_alloc(VALUE klass)
156
+ {
157
+ VALUE obj;
158
+ struct cb_http_request_st *request;
159
+
160
+ /* allocate new bucket struct and set it to zero */
161
+ obj = Data_Make_Struct(klass, struct cb_http_request_st, cb_http_request_mark,
162
+ cb_http_request_free, request);
163
+ return obj;
164
+ }
165
+
166
+ /*
167
+ * Returns a string containing a human-readable representation of the
168
+ * CouchRequest.
169
+ *
170
+ * @since 1.2.0
171
+ *
172
+ * @return [String]
173
+ */
174
+ VALUE
175
+ cb_http_request_inspect(VALUE self)
176
+ {
177
+ VALUE str;
178
+ struct cb_http_request_st *req = DATA_PTR(self);
179
+ char buf[200];
180
+
181
+ str = rb_str_buf_new2("#<");
182
+ rb_str_buf_cat2(str, rb_obj_classname(self));
183
+ snprintf(buf, 20, ":%p \"", (void *)self);
184
+ rb_str_buf_cat2(str, buf);
185
+ rb_str_buf_cat2(str, req->cmd.v.v0.path);
186
+ snprintf(buf, 100, "\" chunked:%s>", req->cmd.v.v0.chunked ? "true" : "false");
187
+ rb_str_buf_cat2(str, buf);
188
+
189
+ return str;
190
+ }
191
+
192
+ /*
193
+ * Initialize new CouchRequest
194
+ *
195
+ * @since 1.2.0
196
+ *
197
+ * @return [Bucket::CouchRequest]
198
+ */
199
+ VALUE
200
+ cb_http_request_init(int argc, VALUE *argv, VALUE self)
201
+ {
202
+ struct cb_http_request_st *request = DATA_PTR(self);
203
+ VALUE bucket, path, opts, on_body, pp, arg;
204
+ rb_scan_args(argc, argv, "22", &bucket, &pp, &opts, &on_body);
205
+
206
+ if (NIL_P(on_body) && rb_block_given_p()) {
207
+ on_body = rb_block_proc();
208
+ }
209
+ if (!RTEST(rb_obj_is_kind_of(bucket, cb_cBucket))) {
210
+ rb_raise(rb_eTypeError, "wrong argument type (expected Couchbase::Bucket)");
211
+ }
212
+ memset(&request->cmd, 0, sizeof(lcb_http_cmd_t));
213
+ request->type = LCB_HTTP_TYPE_VIEW;
214
+ request->on_body_callback = on_body;
215
+ request->bucket = DATA_PTR(bucket);
216
+ request->bucket_obj = bucket;
217
+ request->extended = Qfalse;
218
+ path = StringValue(pp); /* convert path to string */
219
+ request->cmd.v.v0.path = strdup(RSTRING_PTR(path));
220
+ request->cmd.v.v0.npath = RSTRING_LEN(path);
221
+ request->cmd.v.v0.method = LCB_HTTP_METHOD_GET;
222
+ request->cmd.v.v0.content_type = strdup("application/json");
223
+
224
+ if (opts != Qnil) {
225
+ Check_Type(opts, T_HASH);
226
+ request->extended = RTEST(rb_hash_aref(opts, cb_sym_extended));
227
+ request->cmd.v.v0.chunked = RTEST(rb_hash_aref(opts, cb_sym_chunked));
228
+ if ((arg = rb_hash_aref(opts, cb_sym_type)) != Qnil) {
229
+ if (arg == cb_sym_view) {
230
+ request->type = LCB_HTTP_TYPE_VIEW;
231
+ } else if (arg == cb_sym_management) {
232
+ request->type = LCB_HTTP_TYPE_MANAGEMENT;
233
+ } else {
234
+ rb_raise(rb_eArgError, "unsupported request type");
235
+ }
236
+ }
237
+ if ((arg = rb_hash_aref(opts, cb_sym_method)) != Qnil) {
238
+ if (arg == cb_sym_get) {
239
+ request->cmd.v.v0.method = LCB_HTTP_METHOD_GET;
240
+ } else if (arg == cb_sym_post) {
241
+ request->cmd.v.v0.method = LCB_HTTP_METHOD_POST;
242
+ } else if (arg == cb_sym_put) {
243
+ request->cmd.v.v0.method = LCB_HTTP_METHOD_PUT;
244
+ } else if (arg == cb_sym_delete) {
245
+ request->cmd.v.v0.method = LCB_HTTP_METHOD_DELETE;
246
+ } else {
247
+ rb_raise(rb_eArgError, "unsupported HTTP method");
248
+ }
249
+ }
250
+ if ((arg = rb_hash_aref(opts, cb_sym_body)) != Qnil) {
251
+ Check_Type(arg, T_STRING);
252
+ request->cmd.v.v0.body = strdup(RSTRING_PTR(arg));
253
+ request->cmd.v.v0.nbody = RSTRING_LEN(arg);
254
+ }
255
+ if ((arg = rb_hash_aref(opts, cb_sym_content_type)) != Qnil) {
256
+ Check_Type(arg, T_STRING);
257
+ free((char *)request->cmd.v.v0.content_type);
258
+ request->cmd.v.v0.content_type = strdup(RSTRING_PTR(arg));
259
+ }
260
+ }
261
+
262
+ return self;
263
+ }
264
+
265
+ /*
266
+ * Set +on_body+ callback
267
+ *
268
+ * @since 1.2.0
269
+ */
270
+ VALUE
271
+ cb_http_request_on_body(VALUE self)
272
+ {
273
+ struct cb_http_request_st *request = DATA_PTR(self);
274
+ VALUE old = request->on_body_callback;
275
+ if (rb_block_given_p()) {
276
+ request->on_body_callback = rb_block_proc();
277
+ }
278
+ return old;
279
+ }
280
+
281
+ /*
282
+ * Execute {Bucket::CouchRequest}
283
+ *
284
+ * @since 1.2.0
285
+ */
286
+ VALUE
287
+ cb_http_request_perform(VALUE self)
288
+ {
289
+ struct cb_http_request_st *req = DATA_PTR(self);
290
+ struct cb_context_st *ctx;
291
+ VALUE rv, exc;
292
+ lcb_error_t err;
293
+ struct cb_bucket_st *bucket = req->bucket;
294
+
295
+ if (!cb_bucket_connected_bang(bucket, cb_sym_http_request)) {
296
+ return Qnil;
297
+ }
298
+
299
+ ctx = cb_context_alloc(bucket);
300
+ ctx->rv = Qnil;
301
+ ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback;
302
+ ctx->extended = req->extended;
303
+ ctx->request = req;
304
+ ctx->headers_val = rb_hash_new();
305
+
306
+ err = lcb_make_http_request(bucket->handle, (const void *)ctx,
307
+ req->type, &req->cmd, &req->request);
308
+ exc = cb_check_error(err, "failed to schedule document request",
309
+ STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath));
310
+ if (exc != Qnil) {
311
+ lcb_cancel_http_request(bucket->handle, req->request);
312
+ rb_exc_raise(exc);
313
+ }
314
+ req->running = 1;
315
+ req->ctx = ctx;
316
+ if (bucket->async) {
317
+ return Qnil;
318
+ } else {
319
+ lcb_wait(bucket->handle);
320
+ if (req->completed) {
321
+ rv = ctx->rv;
322
+ exc = ctx->exception;
323
+ cb_context_free(ctx);
324
+ if (exc != Qnil) {
325
+ rb_exc_raise(exc);
326
+ }
327
+ return rv;
328
+ } else {
329
+ return Qnil;
330
+ }
331
+ }
332
+ return Qnil;
333
+ }
334
+
335
+ VALUE
336
+ cb_http_request_pause(VALUE self)
337
+ {
338
+ struct cb_http_request_st *req = DATA_PTR(self);
339
+ lcb_breakout(req->bucket->handle);
340
+ return Qnil;
341
+ }
342
+
343
+ VALUE
344
+ cb_http_request_continue(VALUE self)
345
+ {
346
+ VALUE exc, rv;
347
+ struct cb_http_request_st *req = DATA_PTR(self);
348
+
349
+ if (req->running) {
350
+ lcb_wait(req->bucket->handle);
351
+ if (req->completed) {
352
+ exc = req->ctx->exception;
353
+ rv = req->ctx->rv;
354
+ cb_context_free(req->ctx);
355
+ if (exc != Qnil) {
356
+ rb_exc_raise(exc);
357
+ }
358
+ return rv;
359
+ }
360
+ } else {
361
+ cb_http_request_perform(self);
362
+ }
363
+ return Qnil;
364
+ }
365
+
366
+ /* Document-method: path
367
+ *
368
+ * @since 1.2.0
369
+ *
370
+ * @return [String] the requested path
371
+ */
372
+ VALUE
373
+ cb_http_request_path_get(VALUE self)
374
+ {
375
+ struct cb_http_request_st *req = DATA_PTR(self);
376
+ return STR_NEW_CSTR(req->cmd.v.v0.path);
377
+ }
378
+
379
+ /* Document-method: chunked
380
+ *
381
+ * @since 1.2.0
382
+ *
383
+ * @return [Boolean] +false+ if library should collect whole response before
384
+ * yielding, +true+ if the client is ready to handle response in chunks.
385
+ */
386
+ VALUE
387
+ cb_http_request_chunked_get(VALUE self)
388
+ {
389
+ struct cb_http_request_st *req = DATA_PTR(self);
390
+ return req->cmd.v.v0.chunked ? Qtrue : Qfalse;
391
+ }
392
+
393
+ /* Document-method: extended
394
+ *
395
+ * @since 1.2.0
396
+ *
397
+ * @return [Boolean] if +false+ the callbacks should receive just the data,
398
+ * and {Couchbase::Result} instance otherwise.
399
+ */
400
+ VALUE
401
+ cb_http_request_extended_get(VALUE self)
402
+ {
403
+ struct cb_http_request_st *req = DATA_PTR(self);
404
+ return req->extended ? Qtrue : Qfalse;
405
+ }
406
+
407
+ /* Document-method: make_http_request(path, options = {})
408
+ *
409
+ * @since 1.2.0
410
+ *
411
+ * @param path [String]
412
+ * @param options [Hash]
413
+ * @option options [Boolean] :extended (false) set it to +true+ if the
414
+ * {Couchbase::Result} object needed. The response chunk will be
415
+ * accessible through +#value+ attribute.
416
+ * @yieldparam [String,Couchbase::Result] res the response chunk if the
417
+ * :extended option is +false+ and result object otherwise
418
+ *
419
+ * @return [Couchbase::Bucket::CouchRequest]
420
+ */
421
+ VALUE
422
+ cb_bucket_make_http_request(int argc, VALUE *argv, VALUE self)
423
+ {
424
+ VALUE args[4]; /* bucket, path, options, block */
425
+
426
+ args[0] = self;
427
+ rb_scan_args(argc, argv, "11&", &args[1], &args[2], &args[3]);
428
+
429
+ return rb_class_new_instance(4, args, cb_cCouchRequest);
430
+ }
431
+
432
+