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