couchbase 1.2.1-x86-mingw32 → 1.2.2-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.
@@ -31,51 +31,52 @@ storage_observe_callback(VALUE args, VALUE cookie)
31
31
  if (!RTEST(ctx->observe_options)) {
32
32
  ctx->nqueries--;
33
33
  if (ctx->nqueries == 0) {
34
- cb_gc_unprotect(bucket, ctx->proc);
34
+ ctx->proc = Qnil;
35
35
  if (bucket->async) {
36
- free(ctx);
36
+ cb_context_free(ctx);
37
37
  }
38
38
  }
39
39
  }
40
40
  return Qnil;
41
41
  }
42
42
 
43
+ VALUE
44
+ storage_opcode_to_sym(lcb_storage_t operation)
45
+ {
46
+ switch(operation) {
47
+ case LCB_ADD:
48
+ return cb_sym_add;
49
+ case LCB_REPLACE:
50
+ return cb_sym_replace;
51
+ case LCB_SET:
52
+ return cb_sym_set;
53
+ case LCB_APPEND:
54
+ return cb_sym_append;
55
+ case LCB_PREPEND:
56
+ return cb_sym_prepend;
57
+ default:
58
+ return Qnil;
59
+ }
60
+ }
61
+
43
62
  void
44
63
  cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation,
45
64
  lcb_error_t error, const lcb_store_resp_t *resp)
46
65
  {
47
66
  struct cb_context_st *ctx = (struct cb_context_st *)cookie;
48
67
  struct cb_bucket_st *bucket = ctx->bucket;
49
- VALUE key, cas, *rv = ctx->rv, exc, res;
68
+ VALUE key, cas, exc, res;
50
69
 
51
70
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
52
71
  cb_strip_key_prefix(bucket, key);
53
72
 
54
73
  cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil;
55
- switch(operation) {
56
- case LCB_ADD:
57
- ctx->operation = cb_sym_add;
58
- break;
59
- case LCB_REPLACE:
60
- ctx->operation = cb_sym_replace;
61
- break;
62
- case LCB_SET:
63
- ctx->operation = cb_sym_set;
64
- break;
65
- case LCB_APPEND:
66
- ctx->operation = cb_sym_append;
67
- break;
68
- case LCB_PREPEND:
69
- ctx->operation = cb_sym_prepend;
70
- break;
71
- default:
72
- ctx->operation = Qnil;
73
- }
74
+ ctx->operation = storage_opcode_to_sym(operation);
74
75
  exc = cb_check_error(error, "failed to store value", key);
75
76
  if (exc != Qnil) {
76
77
  rb_ivar_set(exc, cb_id_iv_cas, cas);
77
78
  rb_ivar_set(exc, cb_id_iv_operation, ctx->operation);
78
- ctx->exception = cb_gc_protect(bucket, exc);
79
+ ctx->exception = exc;
79
80
  }
80
81
 
81
82
  if (bucket->async) { /* asynchronous */
@@ -86,7 +87,7 @@ cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation,
86
87
  args[1] = ctx->observe_options;
87
88
  rb_block_call(bucket->self, cb_id_observe_and_wait, 2, args,
88
89
  storage_observe_callback, (VALUE)ctx);
89
- cb_gc_unprotect(bucket, ctx->observe_options);
90
+ ctx->observe_options = Qnil;
90
91
  } else if (ctx->proc != Qnil) {
91
92
  res = rb_class_new_instance(0, NULL, cb_cResult);
92
93
  rb_ivar_set(res, cb_id_iv_error, exc);
@@ -96,15 +97,15 @@ cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation,
96
97
  cb_proc_call(bucket, ctx->proc, 1, res);
97
98
  }
98
99
  } else { /* synchronous */
99
- rb_hash_aset(*rv, key, cas);
100
+ rb_hash_aset(ctx->rv, key, cas);
100
101
  }
101
102
 
102
103
  if (!RTEST(ctx->observe_options)) {
103
104
  ctx->nqueries--;
104
105
  if (ctx->nqueries == 0) {
105
- cb_gc_unprotect(bucket, ctx->proc);
106
+ ctx->proc = Qnil;
106
107
  if (bucket->async) {
107
- free(ctx);
108
+ cb_context_free(ctx);
108
109
  }
109
110
  }
110
111
  }
@@ -116,40 +117,36 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
116
117
  {
117
118
  struct cb_bucket_st *bucket = DATA_PTR(self);
118
119
  struct cb_context_st *ctx;
119
- VALUE args, rv, proc, exc, obs = Qnil;
120
+ VALUE rv, proc, exc, obs = Qnil;
120
121
  lcb_error_t err;
121
122
  struct cb_params_st params;
122
123
 
123
- if (bucket->handle == NULL) {
124
- rb_raise(cb_eConnectError, "closed connection");
124
+ if (!cb_bucket_connected_bang(bucket, storage_opcode_to_sym(cmd))) {
125
+ return Qnil;
125
126
  }
126
- rb_scan_args(argc, argv, "0*&", &args, &proc);
127
+ memset(&params, 0, sizeof(struct cb_params_st));
128
+ rb_scan_args(argc, argv, "0*&", &params.args, &proc);
127
129
  if (!bucket->async && proc != Qnil) {
128
130
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
129
131
  }
130
- memset(&params, 0, sizeof(struct cb_params_st));
131
132
  params.type = cb_cmd_store;
132
133
  params.bucket = bucket;
133
134
  params.cmd.store.operation = cmd;
134
- cb_params_build(&params, RARRAY_LEN(args), args);
135
- ctx = calloc(1, sizeof(struct cb_context_st));
136
- if (ctx == NULL) {
137
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
138
- }
139
- rv = rb_hash_new();
140
- ctx->rv = &rv;
141
- ctx->bucket = bucket;
142
- ctx->proc = cb_gc_protect(bucket, proc);
143
- ctx->observe_options = cb_gc_protect(bucket, obs);
144
- ctx->exception = Qnil;
135
+ cb_params_build(&params);
145
136
  obs = params.cmd.store.observe;
137
+ ctx = cb_context_alloc(bucket);
138
+ if (!bucket->async) {
139
+ ctx->rv = rb_hash_new();
140
+ ctx->observe_options = obs;
141
+ }
142
+ ctx->proc = proc;
146
143
  ctx->nqueries = params.cmd.store.num;
147
144
  err = lcb_store(bucket->handle, (const void *)ctx,
148
145
  params.cmd.store.num, params.cmd.store.ptr);
149
146
  cb_params_destroy(&params);
150
147
  exc = cb_check_error(err, "failed to schedule set request", Qnil);
151
148
  if (exc != Qnil) {
152
- free(ctx);
149
+ cb_context_free(ctx);
153
150
  rb_exc_raise(exc);
154
151
  }
155
152
  bucket->nbytes += params.npayload;
@@ -162,9 +159,9 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
162
159
  lcb_wait(bucket->handle);
163
160
  }
164
161
  exc = ctx->exception;
165
- free(ctx);
162
+ rv = ctx->rv;
163
+ cb_context_free(ctx);
166
164
  if (exc != Qnil) {
167
- cb_gc_unprotect(bucket, exc);
168
165
  rb_exc_raise(exc);
169
166
  }
170
167
  exc = bucket->exception;
@@ -173,7 +170,6 @@ cb_bucket_store(lcb_storage_t cmd, int argc, VALUE *argv, VALUE self)
173
170
  rb_exc_raise(exc);
174
171
  }
175
172
  if (RTEST(obs)) {
176
- cb_gc_unprotect(bucket, obs);
177
173
  rv = rb_funcall(bucket->self, cb_id_observe_and_wait, 2, rv, obs);
178
174
  }
179
175
  if (params.cmd.store.num > 1) {
@@ -22,7 +22,7 @@ cb_touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb
22
22
  {
23
23
  struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
24
  struct cb_bucket_st *bucket = ctx->bucket;
25
- VALUE key, *rv = ctx->rv, exc = Qnil, res;
25
+ VALUE key, exc = Qnil, res;
26
26
 
27
27
  ctx->nqueries--;
28
28
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
@@ -32,7 +32,7 @@ cb_touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb
32
32
  exc = cb_check_error(error, "failed to touch value", key);
33
33
  if (exc != Qnil) {
34
34
  rb_ivar_set(exc, cb_id_iv_operation, cb_sym_touch);
35
- ctx->exception = cb_gc_protect(bucket, exc);
35
+ ctx->exception = exc;
36
36
  }
37
37
  }
38
38
 
@@ -45,12 +45,12 @@ cb_touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb
45
45
  cb_proc_call(bucket, ctx->proc, 1, res);
46
46
  }
47
47
  } else { /* synchronous */
48
- rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
48
+ rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
49
49
  }
50
50
  if (ctx->nqueries == 0) {
51
- cb_gc_unprotect(bucket, ctx->proc);
51
+ ctx->proc = Qnil;
52
52
  if (bucket->async) {
53
- free(ctx);
53
+ cb_context_free(ctx);
54
54
  }
55
55
  }
56
56
  (void)handle;
@@ -126,39 +126,31 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
126
126
  {
127
127
  struct cb_bucket_st *bucket = DATA_PTR(self);
128
128
  struct cb_context_st *ctx;
129
- VALUE args, rv, proc, exc;
129
+ VALUE rv, proc, exc;
130
130
  lcb_error_t err;
131
131
  struct cb_params_st params;
132
132
 
133
- if (bucket->handle == NULL) {
134
- rb_raise(cb_eConnectError, "closed connection");
133
+ if (!cb_bucket_connected_bang(bucket, cb_sym_touch)) {
134
+ return Qnil;
135
135
  }
136
- rb_scan_args(argc, argv, "0*&", &args, &proc);
136
+
137
+ memset(&params, 0, sizeof(struct cb_params_st));
138
+ rb_scan_args(argc, argv, "0*&", &params.args, &proc);
137
139
  if (!bucket->async && proc != Qnil) {
138
140
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
139
141
  }
140
- rb_funcall(args, cb_id_flatten_bang, 0);
141
- memset(&params, 0, sizeof(struct cb_params_st));
142
+ rb_funcall(params.args, cb_id_flatten_bang, 0);
142
143
  params.type = cb_cmd_touch;
143
144
  params.bucket = bucket;
144
- cb_params_build(&params, RARRAY_LEN(args), args);
145
- ctx = calloc(1, sizeof(struct cb_context_st));
146
- if (ctx == NULL) {
147
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
148
- }
149
- ctx->proc = cb_gc_protect(bucket, proc);
150
- ctx->bucket = bucket;
151
- rv = rb_hash_new();
152
- ctx->rv = &rv;
153
- ctx->exception = Qnil;
145
+ cb_params_build(&params);
146
+ ctx = cb_context_alloc_common(bucket, proc, params.cmd.touch.num);
154
147
  ctx->quiet = params.cmd.touch.quiet;
155
- ctx->nqueries = params.cmd.touch.num;
156
148
  err = lcb_touch(bucket->handle, (const void *)ctx,
157
149
  params.cmd.touch.num, params.cmd.touch.ptr);
158
150
  cb_params_destroy(&params);
159
151
  exc = cb_check_error(err, "failed to schedule touch request", Qnil);
160
152
  if (exc != Qnil) {
161
- free(ctx);
153
+ cb_context_free(ctx);
162
154
  rb_exc_raise(exc);
163
155
  }
164
156
  bucket->nbytes += params.npayload;
@@ -171,9 +163,10 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self)
171
163
  lcb_wait(bucket->handle);
172
164
  }
173
165
  exc = ctx->exception;
174
- free(ctx);
166
+ rv = ctx->rv;
167
+ cb_context_free(ctx);
175
168
  if (exc != Qnil) {
176
- rb_exc_raise(cb_gc_unprotect(bucket, exc));
169
+ rb_exc_raise(exc);
177
170
  }
178
171
  exc = bucket->exception;
179
172
  if (exc != Qnil) {
@@ -22,7 +22,7 @@ cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
22
22
  {
23
23
  struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
24
  struct cb_bucket_st *bucket = ctx->bucket;
25
- VALUE key, *rv = ctx->rv, exc = Qnil, res;
25
+ VALUE key, exc = Qnil, res;
26
26
 
27
27
  ctx->nqueries--;
28
28
  key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
@@ -32,7 +32,7 @@ cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
32
32
  exc = cb_check_error(error, "failed to unlock value", key);
33
33
  if (exc != Qnil) {
34
34
  rb_ivar_set(exc, cb_id_iv_operation, cb_sym_unlock);
35
- ctx->exception = cb_gc_protect(bucket, exc);
35
+ ctx->exception = exc;
36
36
  }
37
37
  }
38
38
 
@@ -45,12 +45,12 @@ cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lc
45
45
  cb_proc_call(bucket, ctx->proc, 1, res);
46
46
  }
47
47
  } else { /* synchronous */
48
- rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
48
+ rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
49
49
  }
50
50
  if (ctx->nqueries == 0) {
51
- cb_gc_unprotect(bucket, ctx->proc);
51
+ ctx->proc = Qnil;
52
52
  if (bucket->async) {
53
- free(ctx);
53
+ cb_context_free(ctx);
54
54
  }
55
55
  }
56
56
  (void)handle;
@@ -116,39 +116,31 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
116
116
  {
117
117
  struct cb_bucket_st *bucket = DATA_PTR(self);
118
118
  struct cb_context_st *ctx;
119
- VALUE args, rv, proc, exc;
119
+ VALUE rv, proc, exc;
120
120
  lcb_error_t err;
121
121
  struct cb_params_st params;
122
122
 
123
- if (bucket->handle == NULL) {
124
- rb_raise(cb_eConnectError, "closed connection");
123
+ if (!cb_bucket_connected_bang(bucket, cb_sym_unlock)) {
124
+ return Qnil;
125
125
  }
126
- rb_scan_args(argc, argv, "0*&", &args, &proc);
126
+
127
+ memset(&params, 0, sizeof(struct cb_params_st));
128
+ rb_scan_args(argc, argv, "0*&", &params.args, &proc);
127
129
  if (!bucket->async && proc != Qnil) {
128
130
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
129
131
  }
130
- rb_funcall(args, cb_id_flatten_bang, 0);
131
- memset(&params, 0, sizeof(struct cb_params_st));
132
+ rb_funcall(params.args, cb_id_flatten_bang, 0);
132
133
  params.type = cb_cmd_unlock;
133
134
  params.bucket = bucket;
134
- cb_params_build(&params, RARRAY_LEN(args), args);
135
- ctx = calloc(1, sizeof(struct cb_context_st));
136
- if (ctx == NULL) {
137
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
138
- }
139
- ctx->proc = cb_gc_protect(bucket, proc);
140
- ctx->bucket = bucket;
141
- rv = rb_hash_new();
142
- ctx->rv = &rv;
143
- ctx->exception = Qnil;
135
+ cb_params_build(&params);
136
+ ctx = cb_context_alloc_common(bucket, proc, params.cmd.unlock.num);
144
137
  ctx->quiet = params.cmd.unlock.quiet;
145
- ctx->nqueries = params.cmd.unlock.num;
146
138
  err = lcb_unlock(bucket->handle, (const void *)ctx,
147
139
  params.cmd.unlock.num, params.cmd.unlock.ptr);
148
140
  cb_params_destroy(&params);
149
141
  exc = cb_check_error(err, "failed to schedule unlock request", Qnil);
150
142
  if (exc != Qnil) {
151
- free(ctx);
143
+ cb_context_free(ctx);
152
144
  rb_exc_raise(exc);
153
145
  }
154
146
  bucket->nbytes += params.npayload;
@@ -161,9 +153,10 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
161
153
  lcb_wait(bucket->handle);
162
154
  }
163
155
  exc = ctx->exception;
164
- free(ctx);
156
+ rv = ctx->rv;
157
+ cb_context_free(ctx);
165
158
  if (exc != Qnil) {
166
- rb_exc_raise(cb_gc_unprotect(bucket, exc));
159
+ rb_exc_raise(exc);
167
160
  }
168
161
  exc = bucket->exception;
169
162
  if (exc != Qnil) {
@@ -17,18 +17,16 @@
17
17
 
18
18
  #include "couchbase_ext.h"
19
19
 
20
- VALUE
21
- cb_gc_protect(struct cb_bucket_st *bucket, VALUE val)
20
+ void
21
+ cb_gc_protect_ptr(struct cb_bucket_st *bucket, void *ptr, mark_f mark_func)
22
22
  {
23
- rb_hash_aset(bucket->object_space, val|1, val);
24
- return val;
23
+ st_insert(bucket->object_space, (st_index_t)ptr, (st_data_t)mark_func);
25
24
  }
26
25
 
27
- VALUE
28
- cb_gc_unprotect(struct cb_bucket_st *bucket, VALUE val)
26
+ void
27
+ cb_gc_unprotect_ptr(struct cb_bucket_st *bucket, void *ptr)
29
28
  {
30
- rb_funcall(bucket->object_space, cb_id_delete, 1, val|1);
31
- return val;
29
+ st_delete(bucket->object_space, (st_index_t*)&ptr, NULL);
32
30
  }
33
31
 
34
32
  struct proc_params_st
@@ -67,6 +65,23 @@ cb_async_error_notify(struct cb_bucket_st *bucket, VALUE exc)
67
65
  }
68
66
  }
69
67
 
68
+ int
69
+ cb_bucket_connected_bang(struct cb_bucket_st *bucket, VALUE operation)
70
+ {
71
+ if (bucket->handle == NULL || !bucket->connected) {
72
+ VALUE exc = rb_exc_new2(cb_eConnectError, "not connected to the server");
73
+ rb_ivar_set(exc, cb_id_iv_operation, operation);
74
+ rb_ivar_set(exc, cb_id_iv_value, bucket->self);
75
+ if (bucket->async) {
76
+ cb_async_error_notify(bucket, exc);
77
+ } else {
78
+ rb_exc_raise(exc);
79
+ }
80
+ return 0;
81
+ }
82
+ return 1;
83
+ }
84
+
70
85
  static VALUE
71
86
  func_call_failed(VALUE ptr, VALUE exc)
72
87
  {
@@ -22,13 +22,13 @@ cb_version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const l
22
22
  {
23
23
  struct cb_context_st *ctx = (struct cb_context_st *)cookie;
24
24
  struct cb_bucket_st *bucket = ctx->bucket;
25
- VALUE node, val, *rv = ctx->rv, exc, res;
25
+ VALUE node, val, exc, res;
26
26
 
27
27
  node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil;
28
28
  exc = cb_check_error(error, "failed to get version", node);
29
29
  if (exc != Qnil) {
30
30
  rb_ivar_set(exc, cb_id_iv_operation, cb_sym_version);
31
- ctx->exception = cb_gc_protect(bucket, exc);
31
+ ctx->exception = exc;
32
32
  }
33
33
 
34
34
  if (node != Qnil) {
@@ -44,14 +44,14 @@ cb_version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const l
44
44
  }
45
45
  } else { /* synchronous */
46
46
  if (NIL_P(exc)) {
47
- rb_hash_aset(*rv, node, val);
47
+ rb_hash_aset(ctx->rv, node, val);
48
48
  }
49
49
  }
50
50
  } else {
51
51
  ctx->nqueries--;
52
- cb_gc_unprotect(bucket, ctx->proc);
52
+ ctx->proc = Qnil;
53
53
  if (bucket->async) {
54
- free(ctx);
54
+ cb_context_free(ctx);
55
55
  }
56
56
  }
57
57
 
@@ -90,37 +90,29 @@ cb_bucket_version(int argc, VALUE *argv, VALUE self)
90
90
  {
91
91
  struct cb_bucket_st *bucket = DATA_PTR(self);
92
92
  struct cb_context_st *ctx;
93
- VALUE rv, exc, args, proc;
93
+ VALUE rv, exc, proc;
94
94
  lcb_error_t err;
95
95
  struct cb_params_st params;
96
96
 
97
- if (bucket->handle == NULL) {
98
- rb_raise(cb_eConnectError, "closed connection");
97
+ if (!cb_bucket_connected_bang(bucket, cb_sym_version)) {
98
+ return Qnil;
99
99
  }
100
- rb_scan_args(argc, argv, "0*&", &args, &proc);
100
+
101
+ memset(&params, 0, sizeof(struct cb_params_st));
102
+ rb_scan_args(argc, argv, "0*&", &params.args, &proc);
101
103
  if (!bucket->async && proc != Qnil) {
102
104
  rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
103
105
  }
104
- memset(&params, 0, sizeof(struct cb_params_st));
105
106
  params.type = cb_cmd_version;
106
107
  params.bucket = bucket;
107
- cb_params_build(&params, RARRAY_LEN(args), args);
108
- ctx = calloc(1, sizeof(struct cb_context_st));
109
- if (ctx == NULL) {
110
- rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
111
- }
112
- rv = rb_hash_new();
113
- ctx->rv = &rv;
114
- ctx->bucket = bucket;
115
- ctx->exception = Qnil;
116
- ctx->proc = cb_gc_protect(bucket, proc);
117
- ctx->nqueries = params.cmd.version.num;
108
+ cb_params_build(&params);
109
+ ctx = cb_context_alloc_common(bucket, proc, params.cmd.version.num);
118
110
  err = lcb_server_versions(bucket->handle, (const void *)ctx,
119
111
  params.cmd.version.num, params.cmd.version.ptr);
120
112
  exc = cb_check_error(err, "failed to schedule version request", Qnil);
121
113
  cb_params_destroy(&params);
122
114
  if (exc != Qnil) {
123
- free(ctx);
115
+ cb_context_free(ctx);
124
116
  rb_exc_raise(exc);
125
117
  }
126
118
  bucket->nbytes += params.npayload;
@@ -133,9 +125,9 @@ cb_bucket_version(int argc, VALUE *argv, VALUE self)
133
125
  lcb_wait(bucket->handle);
134
126
  }
135
127
  exc = ctx->exception;
136
- free(ctx);
128
+ rv = ctx->rv;
129
+ cb_context_free(ctx);
137
130
  if (exc != Qnil) {
138
- cb_gc_unprotect(bucket, exc);
139
131
  rb_exc_raise(exc);
140
132
  }
141
133
  exc = bucket->exception;