couchbase 1.3.4-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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,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 (CLASS_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
|
+
|