couchbase 1.2.0.beta-x86-mingw32 → 1.2.0-x86-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 (45) hide show
  1. data/.travis.yml +1 -1
  2. data/Makefile +3 -0
  3. data/README.markdown +15 -4
  4. data/RELEASE_NOTES.markdown +513 -0
  5. data/couchbase.gemspec +0 -1
  6. data/ext/couchbase_ext/arguments.c +161 -244
  7. data/ext/couchbase_ext/arithmetic.c +29 -37
  8. data/ext/couchbase_ext/bucket.c +252 -219
  9. data/ext/couchbase_ext/couchbase_ext.c +540 -417
  10. data/ext/couchbase_ext/couchbase_ext.h +218 -191
  11. data/ext/couchbase_ext/delete.c +30 -27
  12. data/ext/couchbase_ext/extconf.rb +15 -3
  13. data/ext/couchbase_ext/get.c +45 -37
  14. data/ext/couchbase_ext/http.c +95 -74
  15. data/ext/couchbase_ext/multithread_plugin.c +1201 -0
  16. data/ext/couchbase_ext/observe.c +42 -37
  17. data/ext/couchbase_ext/result.c +17 -20
  18. data/ext/couchbase_ext/stats.c +30 -28
  19. data/ext/couchbase_ext/store.c +46 -39
  20. data/ext/couchbase_ext/timer.c +11 -11
  21. data/ext/couchbase_ext/touch.c +30 -27
  22. data/ext/couchbase_ext/unlock.c +30 -27
  23. data/ext/couchbase_ext/utils.c +166 -89
  24. data/ext/couchbase_ext/version.c +29 -26
  25. data/lib/action_dispatch/middleware/session/couchbase_store.rb +2 -2
  26. data/lib/active_support/cache/couchbase_store.rb +6 -6
  27. data/lib/couchbase.rb +1 -0
  28. data/lib/couchbase/bucket.rb +6 -11
  29. data/lib/couchbase/cluster.rb +105 -0
  30. data/lib/couchbase/utils.rb +8 -5
  31. data/lib/couchbase/version.rb +1 -1
  32. data/lib/couchbase/view.rb +51 -5
  33. data/lib/couchbase/view_row.rb +1 -1
  34. data/lib/ext/multi_json_fix.rb +13 -9
  35. data/lib/rack/session/couchbase.rb +11 -7
  36. data/tasks/compile.rake +1 -1
  37. data/tasks/test.rake +40 -34
  38. data/tasks/util.rake +1 -1
  39. data/test/setup.rb +9 -2
  40. data/test/test_arithmetic.rb +37 -0
  41. data/test/test_async.rb +22 -18
  42. data/test/test_unlock.rb +0 -1
  43. data/test/test_utils.rb +32 -0
  44. metadata +13 -23
  45. data/HISTORY.markdown +0 -215
@@ -18,38 +18,39 @@
18
18
  #include "couchbase_ext.h"
19
19
 
20
20
  void
21
- delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_remove_resp_t *resp)
21
+ cb_delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_remove_resp_t *resp)
22
22
  {
23
- struct context_st *ctx = (struct context_st *)cookie;
24
- struct bucket_st *bucket = ctx->bucket;
23
+ struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
+ struct cb_bucket_st *bucket = ctx->bucket;
25
25
  VALUE key, *rv = ctx->rv, exc = Qnil, res;
26
26
 
27
27
  ctx->nqueries--;
28
28
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
29
- strip_key_prefix(bucket, key);
29
+ cb_strip_key_prefix(bucket, key);
30
30
 
31
31
  if (error != LCB_KEY_ENOENT || !ctx->quiet) {
32
32
  exc = cb_check_error(error, "failed to remove value", key);
33
33
  if (exc != Qnil) {
34
- rb_ivar_set(exc, id_iv_operation, sym_delete);
35
- if (NIL_P(ctx->exception)) {
36
- ctx->exception = cb_gc_protect(bucket, exc);
37
- }
34
+ rb_ivar_set(exc, cb_id_iv_operation, cb_sym_delete);
35
+ ctx->exception = cb_gc_protect(bucket, exc);
38
36
  }
39
37
  }
40
38
  if (bucket->async) { /* asynchronous */
41
39
  if (ctx->proc != Qnil) {
42
- res = rb_class_new_instance(0, NULL, cResult);
43
- rb_ivar_set(res, id_iv_error, exc);
44
- rb_ivar_set(res, id_iv_operation, sym_delete);
45
- rb_ivar_set(res, id_iv_key, key);
46
- cb_proc_call(ctx->proc, 1, res);
40
+ res = rb_class_new_instance(0, NULL, cb_cResult);
41
+ rb_ivar_set(res, cb_id_iv_error, exc);
42
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_delete);
43
+ rb_ivar_set(res, cb_id_iv_key, key);
44
+ cb_proc_call(bucket, ctx->proc, 1, res);
47
45
  }
48
46
  } else { /* synchronous */
49
47
  rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
50
48
  }
51
49
  if (ctx->nqueries == 0) {
52
50
  cb_gc_unprotect(bucket, ctx->proc);
51
+ if (bucket->async) {
52
+ free(ctx);
53
+ }
53
54
  }
54
55
  (void)handle;
55
56
  }
@@ -99,29 +100,29 @@ delete_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_r
99
100
  VALUE
100
101
  cb_bucket_delete(int argc, VALUE *argv, VALUE self)
101
102
  {
102
- struct bucket_st *bucket = DATA_PTR(self);
103
- struct context_st *ctx;
103
+ struct cb_bucket_st *bucket = DATA_PTR(self);
104
+ struct cb_context_st *ctx;
104
105
  VALUE rv, exc;
105
106
  VALUE args, proc;
106
107
  lcb_error_t err;
107
- struct params_st params;
108
+ struct cb_params_st params;
108
109
 
109
110
  if (bucket->handle == NULL) {
110
- rb_raise(eConnectError, "closed connection");
111
+ rb_raise(cb_eConnectError, "closed connection");
111
112
  }
112
113
  rb_scan_args(argc, argv, "0*&", &args, &proc);
113
114
  if (!bucket->async && proc != Qnil) {
114
115
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
115
116
  }
116
- rb_funcall(args, id_flatten_bang, 0);
117
- memset(&params, 0, sizeof(struct params_st));
118
- params.type = cmd_remove;
117
+ rb_funcall(args, cb_id_flatten_bang, 0);
118
+ memset(&params, 0, sizeof(struct cb_params_st));
119
+ params.type = cb_cmd_remove;
119
120
  params.bucket = bucket;
120
121
  cb_params_build(&params, RARRAY_LEN(args), args);
121
122
 
122
- ctx = xcalloc(1, sizeof(struct context_st));
123
+ ctx = calloc(1, sizeof(struct cb_context_st));
123
124
  if (ctx == NULL) {
124
- rb_raise(eClientNoMemoryError, "failed to allocate memory for context");
125
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
125
126
  }
126
127
  ctx->quiet = params.cmd.remove.quiet;
127
128
  ctx->proc = cb_gc_protect(bucket, proc);
@@ -135,12 +136,12 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
135
136
  cb_params_destroy(&params);
136
137
  exc = cb_check_error(err, "failed to schedule delete request", Qnil);
137
138
  if (exc != Qnil) {
138
- xfree(ctx);
139
+ free(ctx);
139
140
  rb_exc_raise(exc);
140
141
  }
141
142
  bucket->nbytes += params.npayload;
142
143
  if (bucket->async) {
143
- maybe_do_loop(bucket);
144
+ cb_maybe_do_loop(bucket);
144
145
  return Qnil;
145
146
  } else {
146
147
  if (ctx->nqueries > 0) {
@@ -148,12 +149,14 @@ cb_bucket_delete(int argc, VALUE *argv, VALUE self)
148
149
  lcb_wait(bucket->handle);
149
150
  }
150
151
  exc = ctx->exception;
151
- xfree(ctx);
152
+ free(ctx);
152
153
  if (exc != Qnil) {
153
154
  rb_exc_raise(cb_gc_unprotect(bucket, exc));
154
155
  }
155
- if (bucket->exception != Qnil) {
156
- rb_exc_raise(bucket->exception);
156
+ exc = bucket->exception;
157
+ if (exc != Qnil) {
158
+ bucket->exception = Qnil;
159
+ rb_exc_raise(exc);
157
160
  }
158
161
  if (params.cmd.remove.num > 1) {
159
162
  return rv; /* return as a hash {key => true, ...} */
@@ -20,7 +20,7 @@ require 'rbconfig'
20
20
  # This hack is more robust, because in bundler environment bundler touches
21
21
  # all constants from rbconfig.rb before loading any scripts. This is why
22
22
  # RC_ARCHS doesn't work under bundler on MacOS.
23
- if RUBY_PLATFORM =~ /darwin/
23
+ if RUBY_PLATFORM =~ /darwin/ && defined?(RbConfig::ARCHFLAGS)
24
24
  [RbConfig::CONFIG, RbConfig::MAKEFILE_CONFIG].each do |cfg|
25
25
  cfg["CFLAGS"].gsub!(RbConfig::ARCHFLAGS, '')
26
26
  cfg["LDFLAGS"].gsub!(RbConfig::ARCHFLAGS, '')
@@ -119,14 +119,26 @@ if try_compile(<<-SRC)
119
119
  define("HAVE_STDARG_PROTOTYPES")
120
120
  end
121
121
 
122
+ def die(message)
123
+ STDERR.puts "\n#{"*" * 70}"
124
+ STDERR.puts "#{message}"
125
+ STDERR.puts "#{"*" * 70}\n\n"
126
+ abort
127
+ end
122
128
 
123
- have_library("couchbase", "lcb_get", "libcouchbase/couchbase.h") or abort "You should install libcouchbase >= 2.0.0. See http://www.couchbase.com/develop/ for more details"
129
+ have_library("couchbase", "lcb_verify_compiler_setup", "libcouchbase/couchbase.h") or die("You must install libcouchbase >= 2.0.0beta3. See http://www.couchbase.com/develop/ for more details")
124
130
  have_header("mach/mach_time.h")
125
- have_header("stdint.h") or abort "Failed to locate stdint.h"
131
+ have_header("stdint.h") or die("Failed to locate stdint.h")
126
132
  have_header("sys/time.h")
133
+ have_header("fcntl.h")
127
134
  have_func("clock_gettime")
128
135
  have_func("gettimeofday")
129
136
  have_func("QueryPerformanceCounter")
137
+ have_func("rb_hash_lookup2")
138
+ have_func("rb_thread_fd_select")
139
+ have_func("rb_thread_blocking_region")
140
+ have_func("poll", "poll.h")
141
+ have_func("ppoll", "poll.h")
130
142
  define("_GNU_SOURCE")
131
143
  create_header("couchbase_config.h")
132
144
  create_makefile("couchbase_ext")
@@ -18,23 +18,21 @@
18
18
  #include "couchbase_ext.h"
19
19
 
20
20
  void
21
- get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp)
21
+ cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp)
22
22
  {
23
- struct context_st *ctx = (struct context_st *)cookie;
24
- struct bucket_st *bucket = ctx->bucket;
23
+ struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
+ struct cb_bucket_st *bucket = ctx->bucket;
25
25
  VALUE key, val, flags, cas, *rv = ctx->rv, exc = Qnil, res;
26
26
 
27
27
  ctx->nqueries--;
28
28
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
29
- strip_key_prefix(bucket, key);
29
+ cb_strip_key_prefix(bucket, key);
30
30
 
31
31
  if (error != LCB_KEY_ENOENT || !ctx->quiet) {
32
32
  exc = cb_check_error(error, "failed to get value", key);
33
33
  if (exc != Qnil) {
34
- rb_ivar_set(exc, id_iv_operation, sym_get);
35
- if (NIL_P(ctx->exception)) {
36
- ctx->exception = cb_gc_protect(bucket, exc);
37
- }
34
+ rb_ivar_set(exc, cb_id_iv_operation, cb_sym_get);
35
+ ctx->exception = cb_gc_protect(bucket, exc);
38
36
  }
39
37
  }
40
38
 
@@ -42,30 +40,35 @@ get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_
42
40
  cas = ULL2NUM(resp->v.v0.cas);
43
41
  val = Qnil;
44
42
  if (resp->v.v0.nbytes != 0) {
45
- val = decode_value(STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes),
46
- resp->v.v0.flags, ctx->force_format);
47
- if (val == Qundef) {
43
+ VALUE raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
44
+ val = cb_decode_value(raw, resp->v.v0.flags, ctx->force_format);
45
+ if (rb_obj_is_kind_of(val, rb_eStandardError)) {
46
+ VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
47
+ VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
48
+ rb_str_new2("unable to convert value for key '%s': %s"), key, exc_str);
48
49
  if (ctx->exception != Qnil) {
49
50
  cb_gc_unprotect(bucket, ctx->exception);
50
51
  }
51
- ctx->exception = rb_exc_new2(eValueFormatError, "unable to convert value");
52
- rb_ivar_set(ctx->exception, id_iv_operation, sym_get);
53
- rb_ivar_set(ctx->exception, id_iv_key, key);
52
+ ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
53
+ rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
54
+ rb_ivar_set(ctx->exception, cb_id_iv_key, key);
55
+ rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
54
56
  cb_gc_protect(bucket, ctx->exception);
57
+ val = raw;
55
58
  }
56
- } else if (flags_get_format(resp->v.v0.flags) == sym_plain) {
57
- val = STR_NEW_CSTR("");
59
+ } else if (cb_flags_get_format(resp->v.v0.flags) == cb_sym_plain) {
60
+ val = cb_vStrEmpty;
58
61
  }
59
62
  if (bucket->async) { /* asynchronous */
60
63
  if (ctx->proc != Qnil) {
61
- res = rb_class_new_instance(0, NULL, cResult);
62
- rb_ivar_set(res, id_iv_error, exc);
63
- rb_ivar_set(res, id_iv_operation, sym_get);
64
- rb_ivar_set(res, id_iv_key, key);
65
- rb_ivar_set(res, id_iv_value, val);
66
- rb_ivar_set(res, id_iv_flags, flags);
67
- rb_ivar_set(res, id_iv_cas, cas);
68
- cb_proc_call(ctx->proc, 1, res);
64
+ res = rb_class_new_instance(0, NULL, cb_cResult);
65
+ rb_ivar_set(res, cb_id_iv_error, exc);
66
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_get);
67
+ rb_ivar_set(res, cb_id_iv_key, key);
68
+ rb_ivar_set(res, cb_id_iv_value, val);
69
+ rb_ivar_set(res, cb_id_iv_flags, flags);
70
+ rb_ivar_set(res, cb_id_iv_cas, cas);
71
+ cb_proc_call(bucket, ctx->proc, 1, res);
69
72
  }
70
73
  } else { /* synchronous */
71
74
  if (NIL_P(exc) && error != LCB_KEY_ENOENT) {
@@ -79,6 +82,9 @@ get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_
79
82
 
80
83
  if (ctx->nqueries == 0) {
81
84
  cb_gc_unprotect(bucket, ctx->proc);
85
+ if (bucket->async) {
86
+ free(ctx);
87
+ }
82
88
  }
83
89
  (void)handle;
84
90
  }
@@ -214,28 +220,28 @@ get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_
214
220
  VALUE
215
221
  cb_bucket_get(int argc, VALUE *argv, VALUE self)
216
222
  {
217
- struct bucket_st *bucket = DATA_PTR(self);
218
- struct context_st *ctx;
223
+ struct cb_bucket_st *bucket = DATA_PTR(self);
224
+ struct cb_context_st *ctx;
219
225
  VALUE args, rv, proc, exc;
220
226
  size_t ii;
221
227
  lcb_error_t err = LCB_SUCCESS;
222
- struct params_st params;
228
+ struct cb_params_st params;
223
229
 
224
230
  if (bucket->handle == NULL) {
225
- rb_raise(eConnectError, "closed connection");
231
+ rb_raise(cb_eConnectError, "closed connection");
226
232
  }
227
233
  rb_scan_args(argc, argv, "0*&", &args, &proc);
228
234
  if (!bucket->async && proc != Qnil) {
229
235
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
230
236
  }
231
- memset(&params, 0, sizeof(struct params_st));
232
- params.type = cmd_get;
237
+ memset(&params, 0, sizeof(struct cb_params_st));
238
+ params.type = cb_cmd_get;
233
239
  params.bucket = bucket;
234
240
  params.cmd.get.keys_ary = cb_gc_protect(bucket, rb_ary_new());
235
241
  cb_params_build(&params, RARRAY_LEN(args), args);
236
- ctx = xcalloc(1, sizeof(struct context_st));
242
+ ctx = calloc(1, sizeof(struct cb_context_st));
237
243
  if (ctx == NULL) {
238
- rb_raise(eClientNoMemoryError, "failed to allocate memory for context");
244
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
239
245
  }
240
246
  ctx->extended = params.cmd.get.extended;
241
247
  ctx->quiet = params.cmd.get.quiet;
@@ -257,12 +263,12 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
257
263
  cb_gc_unprotect(bucket, params.cmd.get.keys_ary);
258
264
  exc = cb_check_error(err, "failed to schedule get request", Qnil);
259
265
  if (exc != Qnil) {
260
- xfree(ctx);
266
+ free(ctx);
261
267
  rb_exc_raise(exc);
262
268
  }
263
269
  bucket->nbytes += params.npayload;
264
270
  if (bucket->async) {
265
- maybe_do_loop(bucket);
271
+ cb_maybe_do_loop(bucket);
266
272
  return Qnil;
267
273
  } else {
268
274
  if (ctx->nqueries > 0) {
@@ -270,13 +276,15 @@ cb_bucket_get(int argc, VALUE *argv, VALUE self)
270
276
  lcb_wait(bucket->handle);
271
277
  }
272
278
  exc = ctx->exception;
273
- xfree(ctx);
279
+ free(ctx);
274
280
  if (exc != Qnil) {
275
281
  cb_gc_unprotect(bucket, exc);
276
282
  rb_exc_raise(exc);
277
283
  }
278
- if (bucket->exception != Qnil) {
279
- rb_exc_raise(bucket->exception);
284
+ exc = bucket->exception;
285
+ if (exc != Qnil) {
286
+ bucket->exception = Qnil;
287
+ rb_exc_raise(exc);
280
288
  }
281
289
  if (params.cmd.get.gat || params.cmd.get.assemble_hash ||
282
290
  (params.cmd.get.extended && (params.cmd.get.num > 1 || params.cmd.get.array))) {
@@ -18,37 +18,44 @@
18
18
  #include "couchbase_ext.h"
19
19
 
20
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)
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
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;
23
+ struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
+ struct cb_bucket_st *bucket = ctx->bucket;
25
+ VALUE *rv = ctx->rv, key, val, res, exc;
26
+ lcb_http_status_t status;
26
27
 
27
28
  ctx->request->completed = 1;
28
29
  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
30
  val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
31
+ exc = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status);
32
+ if (exc != Qnil) {
33
+ if (val != Qnil) {
34
+ rb_ivar_set(exc, cb_id_iv_body, val);
35
+ }
36
+ rb_funcall(exc, cb_id_parse_body_bang, 0);
37
+ ctx->exception = cb_gc_protect(bucket, exc);
38
+ }
39
+ status = resp->v.v0.status;
35
40
  if (resp->v.v0.headers) {
36
41
  cb_build_headers(ctx, resp->v.v0.headers);
37
42
  cb_gc_unprotect(bucket, ctx->headers_val);
38
43
  }
39
44
  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);
45
+ res = rb_class_new_instance(0, NULL, cb_cResult);
46
+ rb_ivar_set(res, cb_id_iv_error, ctx->exception);
47
+ rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
48
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
49
+ rb_ivar_set(res, cb_id_iv_key, key);
50
+ rb_ivar_set(res, cb_id_iv_value, val);
51
+ rb_ivar_set(res, cb_id_iv_completed, Qtrue);
52
+ rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
47
53
  } else {
48
54
  res = val;
49
55
  }
50
56
  if (ctx->proc != Qnil) {
51
- cb_proc_call(ctx->proc, 1, res);
57
+ cb_proc_call(bucket, ctx->proc, 1, res);
58
+ cb_gc_unprotect(bucket, ctx->proc);
52
59
  }
53
60
  if (!bucket->async && ctx->exception == Qnil) {
54
61
  *rv = res;
@@ -58,36 +65,49 @@ http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *coo
58
65
  }
59
66
 
60
67
  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)
68
+ 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)
62
69
  {
63
- struct context_st *ctx = (struct context_st *)cookie;
64
- struct bucket_st *bucket = ctx->bucket;
70
+ struct cb_context_st *ctx = (struct cb_context_st *)cookie;
71
+ struct cb_bucket_st *bucket = ctx->bucket;
65
72
  VALUE key, val, res;
73
+ lcb_http_status_t status;
66
74
 
67
75
  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
76
  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);
77
+ status = resp->v.v0.status;
78
+ if (NIL_P(ctx->exception)) {
79
+ ctx->exception = cb_check_error_with_status(error,
80
+ "failed to execute HTTP request", key, resp->v.v0.status);
81
+ if (ctx->exception != Qnil) {
82
+ VALUE body_str = rb_ivar_get(ctx->exception, cb_id_iv_body);
83
+ if (NIL_P(body_str)) {
84
+ cb_gc_protect(bucket, ctx->exception);
85
+ rb_ivar_set(ctx->exception, cb_id_iv_body, val);
86
+ } else {
87
+ rb_str_concat(body_str, val);
88
+ }
89
+ if (ctx->http_cancel_on_error) {
90
+ lcb_cancel_http_request(bucket->handle, request);
91
+ }
92
+ }
74
93
  }
75
94
  if (resp->v.v0.headers) {
76
95
  cb_build_headers(ctx, resp->v.v0.headers);
77
96
  }
78
97
  if (ctx->proc != Qnil) {
79
98
  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);
99
+ res = rb_class_new_instance(0, NULL, cb_cResult);
100
+ rb_ivar_set(res, cb_id_iv_error, ctx->exception);
101
+ rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
102
+ rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
103
+ rb_ivar_set(res, cb_id_iv_key, key);
104
+ rb_ivar_set(res, cb_id_iv_value, val);
105
+ rb_ivar_set(res, cb_id_iv_completed, Qfalse);
106
+ rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
87
107
  } else {
88
108
  res = val;
89
109
  }
90
- cb_proc_call(ctx->proc, 1, res);
110
+ cb_proc_call(bucket, ctx->proc, 1, res);
91
111
  }
92
112
  (void)handle;
93
113
  }
@@ -95,7 +115,7 @@ http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie,
95
115
  void
96
116
  cb_http_request_free(void *ptr)
97
117
  {
98
- struct http_request_st *request = ptr;
118
+ struct cb_http_request_st *request = ptr;
99
119
  if (request) {
100
120
  request->running = 0;
101
121
  if (TYPE(request->bucket_obj) == T_DATA
@@ -103,17 +123,17 @@ cb_http_request_free(void *ptr)
103
123
  && !request->completed) {
104
124
  lcb_cancel_http_request(request->bucket->handle, request->request);
105
125
  }
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);
126
+ free((char *)request->cmd.v.v0.content_type);
127
+ free((char *)request->cmd.v.v0.path);
128
+ free((char *)request->cmd.v.v0.body);
110
129
  }
130
+ xfree(request);
111
131
  }
112
132
 
113
133
  void
114
134
  cb_http_request_mark(void *ptr)
115
135
  {
116
- struct http_request_st *request = ptr;
136
+ struct cb_http_request_st *request = ptr;
117
137
  if (request) {
118
138
  rb_gc_mark(request->on_body_callback);
119
139
  }
@@ -123,10 +143,10 @@ cb_http_request_mark(void *ptr)
123
143
  cb_http_request_alloc(VALUE klass)
124
144
  {
125
145
  VALUE obj;
126
- struct http_request_st *request;
146
+ struct cb_http_request_st *request;
127
147
 
128
148
  /* allocate new bucket struct and set it to zero */
129
- obj = Data_Make_Struct(klass, struct http_request_st, cb_http_request_mark,
149
+ obj = Data_Make_Struct(klass, struct cb_http_request_st, cb_http_request_mark,
130
150
  cb_http_request_free, request);
131
151
  return obj;
132
152
  }
@@ -143,7 +163,7 @@ cb_http_request_alloc(VALUE klass)
143
163
  cb_http_request_inspect(VALUE self)
144
164
  {
145
165
  VALUE str;
146
- struct http_request_st *req = DATA_PTR(self);
166
+ struct cb_http_request_st *req = DATA_PTR(self);
147
167
  char buf[200];
148
168
 
149
169
  str = rb_str_buf_new2("#<");
@@ -167,14 +187,14 @@ cb_http_request_inspect(VALUE self)
167
187
  VALUE
168
188
  cb_http_request_init(int argc, VALUE *argv, VALUE self)
169
189
  {
170
- struct http_request_st *request = DATA_PTR(self);
190
+ struct cb_http_request_st *request = DATA_PTR(self);
171
191
  VALUE bucket, path, opts, on_body, pp, arg;
172
192
  rb_scan_args(argc, argv, "22", &bucket, &pp, &opts, &on_body);
173
193
 
174
194
  if (NIL_P(on_body) && rb_block_given_p()) {
175
195
  on_body = rb_block_proc();
176
196
  }
177
- if (CLASS_OF(bucket) != cBucket) {
197
+ if (CLASS_OF(bucket) != cb_cBucket) {
178
198
  rb_raise(rb_eTypeError, "wrong argument type (expected Couchbase::Bucket)");
179
199
  }
180
200
  memset(&request->cmd, 0, sizeof(lcb_http_cmd_t));
@@ -191,38 +211,38 @@ cb_http_request_init(int argc, VALUE *argv, VALUE self)
191
211
 
192
212
  if (opts != Qnil) {
193
213
  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) {
214
+ request->extended = RTEST(rb_hash_aref(opts, cb_sym_extended));
215
+ request->cmd.v.v0.chunked = RTEST(rb_hash_aref(opts, cb_sym_chunked));
216
+ if ((arg = rb_hash_aref(opts, cb_sym_type)) != Qnil) {
217
+ if (arg == cb_sym_view) {
198
218
  request->type = LCB_HTTP_TYPE_VIEW;
199
- } else if (arg == sym_management) {
219
+ } else if (arg == cb_sym_management) {
200
220
  request->type = LCB_HTTP_TYPE_MANAGEMENT;
201
221
  } else {
202
222
  rb_raise(rb_eArgError, "unsupported request type");
203
223
  }
204
224
  }
205
- if ((arg = rb_hash_aref(opts, sym_method)) != Qnil) {
206
- if (arg == sym_get) {
225
+ if ((arg = rb_hash_aref(opts, cb_sym_method)) != Qnil) {
226
+ if (arg == cb_sym_get) {
207
227
  request->cmd.v.v0.method = LCB_HTTP_METHOD_GET;
208
- } else if (arg == sym_post) {
228
+ } else if (arg == cb_sym_post) {
209
229
  request->cmd.v.v0.method = LCB_HTTP_METHOD_POST;
210
- } else if (arg == sym_put) {
230
+ } else if (arg == cb_sym_put) {
211
231
  request->cmd.v.v0.method = LCB_HTTP_METHOD_PUT;
212
- } else if (arg == sym_delete) {
232
+ } else if (arg == cb_sym_delete) {
213
233
  request->cmd.v.v0.method = LCB_HTTP_METHOD_DELETE;
214
234
  } else {
215
235
  rb_raise(rb_eArgError, "unsupported HTTP method");
216
236
  }
217
237
  }
218
- if ((arg = rb_hash_aref(opts, sym_body)) != Qnil) {
238
+ if ((arg = rb_hash_aref(opts, cb_sym_body)) != Qnil) {
219
239
  Check_Type(arg, T_STRING);
220
240
  request->cmd.v.v0.body = strdup(RSTRING_PTR(arg));
221
241
  request->cmd.v.v0.nbody = RSTRING_LEN(arg);
222
242
  }
223
- if ((arg = rb_hash_aref(opts, sym_content_type)) != Qnil) {
243
+ if ((arg = rb_hash_aref(opts, cb_sym_content_type)) != Qnil) {
224
244
  Check_Type(arg, T_STRING);
225
- xfree((char *)request->cmd.v.v0.content_type);
245
+ free((char *)request->cmd.v.v0.content_type);
226
246
  request->cmd.v.v0.content_type = strdup(RSTRING_PTR(arg));
227
247
  }
228
248
  }
@@ -238,7 +258,7 @@ cb_http_request_init(int argc, VALUE *argv, VALUE self)
238
258
  VALUE
239
259
  cb_http_request_on_body(VALUE self)
240
260
  {
241
- struct http_request_st *request = DATA_PTR(self);
261
+ struct cb_http_request_st *request = DATA_PTR(self);
242
262
  VALUE old = request->on_body_callback;
243
263
  if (rb_block_given_p()) {
244
264
  request->on_body_callback = rb_block_proc();
@@ -254,30 +274,31 @@ cb_http_request_on_body(VALUE self)
254
274
  VALUE
255
275
  cb_http_request_perform(VALUE self)
256
276
  {
257
- struct http_request_st *req = DATA_PTR(self);
258
- struct context_st *ctx;
277
+ struct cb_http_request_st *req = DATA_PTR(self);
278
+ struct cb_context_st *ctx;
259
279
  VALUE rv, exc;
260
280
  lcb_error_t err;
261
- struct bucket_st *bucket;
281
+ struct cb_bucket_st *bucket;
262
282
 
263
- ctx = xcalloc(1, sizeof(struct context_st));
283
+ ctx = calloc(1, sizeof(struct cb_context_st));
264
284
  if (ctx == NULL) {
265
- rb_raise(eClientNoMemoryError, "failed to allocate memory");
285
+ rb_raise(cb_eClientNoMemoryError, "failed to allocate memory");
266
286
  }
267
287
  rv = Qnil;
268
288
  ctx->rv = &rv;
269
289
  ctx->bucket = bucket = req->bucket;
270
- ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback;
290
+ ctx->proc = rb_block_given_p() ? cb_gc_protect(bucket, rb_block_proc()) : req->on_body_callback;
271
291
  ctx->extended = req->extended;
272
292
  ctx->request = req;
273
293
  ctx->headers_val = cb_gc_protect(bucket, rb_hash_new());
294
+ ctx->exception = Qnil;
274
295
 
275
296
  err = lcb_make_http_request(bucket->handle, (const void *)ctx,
276
297
  req->type, &req->cmd, &req->request);
277
298
  exc = cb_check_error(err, "failed to schedule document request",
278
299
  STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath));
279
300
  if (exc != Qnil) {
280
- xfree(ctx);
301
+ free(ctx);
281
302
  rb_exc_raise(exc);
282
303
  }
283
304
  req->running = 1;
@@ -288,7 +309,7 @@ cb_http_request_perform(VALUE self)
288
309
  lcb_wait(bucket->handle);
289
310
  if (req->completed) {
290
311
  exc = ctx->exception;
291
- xfree(ctx);
312
+ free(ctx);
292
313
  if (exc != Qnil) {
293
314
  cb_gc_unprotect(bucket, exc);
294
315
  rb_exc_raise(exc);
@@ -304,8 +325,8 @@ cb_http_request_perform(VALUE self)
304
325
  VALUE
305
326
  cb_http_request_pause(VALUE self)
306
327
  {
307
- struct http_request_st *req = DATA_PTR(self);
308
- req->bucket->io->stop_event_loop(req->bucket->io);
328
+ struct cb_http_request_st *req = DATA_PTR(self);
329
+ lcb_breakout(req->bucket->handle);
309
330
  return Qnil;
310
331
  }
311
332
 
@@ -313,14 +334,14 @@ cb_http_request_pause(VALUE self)
313
334
  cb_http_request_continue(VALUE self)
314
335
  {
315
336
  VALUE exc, *rv;
316
- struct http_request_st *req = DATA_PTR(self);
337
+ struct cb_http_request_st *req = DATA_PTR(self);
317
338
 
318
339
  if (req->running) {
319
340
  lcb_wait(req->bucket->handle);
320
341
  if (req->completed) {
321
342
  exc = req->ctx->exception;
322
343
  rv = req->ctx->rv;
323
- xfree(req->ctx);
344
+ free(req->ctx);
324
345
  if (exc != Qnil) {
325
346
  cb_gc_unprotect(req->bucket, exc);
326
347
  rb_exc_raise(exc);
@@ -342,7 +363,7 @@ cb_http_request_continue(VALUE self)
342
363
  VALUE
343
364
  cb_http_request_path_get(VALUE self)
344
365
  {
345
- struct http_request_st *req = DATA_PTR(self);
366
+ struct cb_http_request_st *req = DATA_PTR(self);
346
367
  return STR_NEW_CSTR(req->cmd.v.v0.path);
347
368
  }
348
369
 
@@ -356,7 +377,7 @@ cb_http_request_path_get(VALUE self)
356
377
  VALUE
357
378
  cb_http_request_chunked_get(VALUE self)
358
379
  {
359
- struct http_request_st *req = DATA_PTR(self);
380
+ struct cb_http_request_st *req = DATA_PTR(self);
360
381
  return req->cmd.v.v0.chunked ? Qtrue : Qfalse;
361
382
  }
362
383
 
@@ -370,7 +391,7 @@ cb_http_request_chunked_get(VALUE self)
370
391
  VALUE
371
392
  cb_http_request_extended_get(VALUE self)
372
393
  {
373
- struct http_request_st *req = DATA_PTR(self);
394
+ struct cb_http_request_st *req = DATA_PTR(self);
374
395
  return req->extended ? Qtrue : Qfalse;
375
396
  }
376
397
 
@@ -396,7 +417,7 @@ cb_bucket_make_http_request(int argc, VALUE *argv, VALUE self)
396
417
  args[0] = self;
397
418
  rb_scan_args(argc, argv, "11&", &args[1], &args[2], &args[3]);
398
419
 
399
- return rb_class_new_instance(4, args, cCouchRequest);
420
+ return rb_class_new_instance(4, args, cb_cCouchRequest);
400
421
  }
401
422
 
402
423