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.
- data/.travis.yml +1 -1
 - data/Makefile +3 -0
 - data/README.markdown +15 -4
 - data/RELEASE_NOTES.markdown +513 -0
 - data/couchbase.gemspec +0 -1
 - data/ext/couchbase_ext/arguments.c +161 -244
 - data/ext/couchbase_ext/arithmetic.c +29 -37
 - data/ext/couchbase_ext/bucket.c +252 -219
 - data/ext/couchbase_ext/couchbase_ext.c +540 -417
 - data/ext/couchbase_ext/couchbase_ext.h +218 -191
 - data/ext/couchbase_ext/delete.c +30 -27
 - data/ext/couchbase_ext/extconf.rb +15 -3
 - data/ext/couchbase_ext/get.c +45 -37
 - data/ext/couchbase_ext/http.c +95 -74
 - data/ext/couchbase_ext/multithread_plugin.c +1201 -0
 - data/ext/couchbase_ext/observe.c +42 -37
 - data/ext/couchbase_ext/result.c +17 -20
 - data/ext/couchbase_ext/stats.c +30 -28
 - data/ext/couchbase_ext/store.c +46 -39
 - data/ext/couchbase_ext/timer.c +11 -11
 - data/ext/couchbase_ext/touch.c +30 -27
 - data/ext/couchbase_ext/unlock.c +30 -27
 - data/ext/couchbase_ext/utils.c +166 -89
 - data/ext/couchbase_ext/version.c +29 -26
 - data/lib/action_dispatch/middleware/session/couchbase_store.rb +2 -2
 - data/lib/active_support/cache/couchbase_store.rb +6 -6
 - data/lib/couchbase.rb +1 -0
 - data/lib/couchbase/bucket.rb +6 -11
 - data/lib/couchbase/cluster.rb +105 -0
 - data/lib/couchbase/utils.rb +8 -5
 - data/lib/couchbase/version.rb +1 -1
 - data/lib/couchbase/view.rb +51 -5
 - data/lib/couchbase/view_row.rb +1 -1
 - data/lib/ext/multi_json_fix.rb +13 -9
 - data/lib/rack/session/couchbase.rb +11 -7
 - data/tasks/compile.rake +1 -1
 - data/tasks/test.rake +40 -34
 - data/tasks/util.rake +1 -1
 - data/test/setup.rb +9 -2
 - data/test/test_arithmetic.rb +37 -0
 - data/test/test_async.rb +22 -18
 - data/test/test_unlock.rb +0 -1
 - data/test/test_utils.rb +32 -0
 - metadata +13 -23
 - data/HISTORY.markdown +0 -215
 
    
        data/ext/couchbase_ext/timer.c
    CHANGED
    
    | 
         @@ -26,7 +26,7 @@ cb_timer_free(void *ptr) 
     | 
|
| 
       26 
26 
     | 
    
         
             
                void
         
     | 
| 
       27 
27 
     | 
    
         
             
            cb_timer_mark(void *ptr)
         
     | 
| 
       28 
28 
     | 
    
         
             
            {
         
     | 
| 
       29 
     | 
    
         
            -
                struct  
     | 
| 
      
 29 
     | 
    
         
            +
                struct cb_timer_st *timer = ptr;
         
     | 
| 
       30 
30 
     | 
    
         
             
                if (timer) {
         
     | 
| 
       31 
31 
     | 
    
         
             
                    rb_gc_mark(timer->callback);
         
     | 
| 
       32 
32 
     | 
    
         
             
                }
         
     | 
| 
         @@ -36,10 +36,10 @@ cb_timer_mark(void *ptr) 
     | 
|
| 
       36 
36 
     | 
    
         
             
            cb_timer_alloc(VALUE klass)
         
     | 
| 
       37 
37 
     | 
    
         
             
            {
         
     | 
| 
       38 
38 
     | 
    
         
             
                VALUE obj;
         
     | 
| 
       39 
     | 
    
         
            -
                struct  
     | 
| 
      
 39 
     | 
    
         
            +
                struct cb_timer_st *timer;
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                /* allocate new bucket struct and set it to zero */
         
     | 
| 
       42 
     | 
    
         
            -
                obj = Data_Make_Struct(klass, struct  
     | 
| 
      
 42 
     | 
    
         
            +
                obj = Data_Make_Struct(klass, struct cb_timer_st, cb_timer_mark,
         
     | 
| 
       43 
43 
     | 
    
         
             
                        cb_timer_free, timer);
         
     | 
| 
       44 
44 
     | 
    
         
             
                return obj;
         
     | 
| 
       45 
45 
     | 
    
         
             
            }
         
     | 
| 
         @@ -56,7 +56,7 @@ cb_timer_alloc(VALUE klass) 
     | 
|
| 
       56 
56 
     | 
    
         
             
            cb_timer_inspect(VALUE self)
         
     | 
| 
       57 
57 
     | 
    
         
             
            {
         
     | 
| 
       58 
58 
     | 
    
         
             
                VALUE str;
         
     | 
| 
       59 
     | 
    
         
            -
                struct  
     | 
| 
      
 59 
     | 
    
         
            +
                struct cb_timer_st *tm = DATA_PTR(self);
         
     | 
| 
       60 
60 
     | 
    
         
             
                char buf[200];
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
62 
     | 
    
         
             
                str = rb_str_buf_new2("#<");
         
     | 
| 
         @@ -97,7 +97,7 @@ cb_timer_inspect(VALUE self) 
     | 
|
| 
       97 
97 
     | 
    
         
             
                VALUE
         
     | 
| 
       98 
98 
     | 
    
         
             
            cb_timer_cancel(VALUE self)
         
     | 
| 
       99 
99 
     | 
    
         
             
            {
         
     | 
| 
       100 
     | 
    
         
            -
                struct  
     | 
| 
      
 100 
     | 
    
         
            +
                struct cb_timer_st *tm = DATA_PTR(self);
         
     | 
| 
       101 
101 
     | 
    
         
             
                lcb_timer_destroy(tm->bucket->handle, tm->timer);
         
     | 
| 
       102 
102 
     | 
    
         
             
                return self;
         
     | 
| 
       103 
103 
     | 
    
         
             
            }
         
     | 
| 
         @@ -105,15 +105,15 @@ cb_timer_cancel(VALUE self) 
     | 
|
| 
       105 
105 
     | 
    
         
             
                static VALUE
         
     | 
| 
       106 
106 
     | 
    
         
             
            trigger_timer(VALUE timer)
         
     | 
| 
       107 
107 
     | 
    
         
             
            {
         
     | 
| 
       108 
     | 
    
         
            -
                struct  
     | 
| 
       109 
     | 
    
         
            -
                return cb_proc_call(tm->callback, 1, timer);
         
     | 
| 
      
 108 
     | 
    
         
            +
                struct cb_timer_st *tm = DATA_PTR(timer);
         
     | 
| 
      
 109 
     | 
    
         
            +
                return cb_proc_call(tm->bucket, tm->callback, 1, timer);
         
     | 
| 
       110 
110 
     | 
    
         
             
            }
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
112 
     | 
    
         
             
                static void
         
     | 
| 
       113 
113 
     | 
    
         
             
            timer_callback(lcb_timer_t timer, lcb_t instance,
         
     | 
| 
       114 
114 
     | 
    
         
             
                    const void *cookie)
         
     | 
| 
       115 
115 
     | 
    
         
             
            {
         
     | 
| 
       116 
     | 
    
         
            -
                struct  
     | 
| 
      
 116 
     | 
    
         
            +
                struct cb_timer_st *tm = (struct cb_timer_st *)cookie;
         
     | 
| 
       117 
117 
     | 
    
         
             
                int error = 0;
         
     | 
| 
       118 
118 
     | 
    
         | 
| 
       119 
119 
     | 
    
         
             
                rb_protect(trigger_timer, tm->self, &error);
         
     | 
| 
         @@ -162,14 +162,14 @@ timer_callback(lcb_timer_t timer, lcb_t instance, 
     | 
|
| 
       162 
162 
     | 
    
         
             
                VALUE
         
     | 
| 
       163 
163 
     | 
    
         
             
            cb_timer_init(int argc, VALUE *argv, VALUE self)
         
     | 
| 
       164 
164 
     | 
    
         
             
            {
         
     | 
| 
       165 
     | 
    
         
            -
                struct  
     | 
| 
      
 165 
     | 
    
         
            +
                struct cb_timer_st *tm = DATA_PTR(self);
         
     | 
| 
       166 
166 
     | 
    
         
             
                VALUE bucket, opts, timeout, exc, cb;
         
     | 
| 
       167 
167 
     | 
    
         
             
                lcb_error_t err;
         
     | 
| 
       168 
168 
     | 
    
         | 
| 
       169 
169 
     | 
    
         
             
                rb_need_block();
         
     | 
| 
       170 
170 
     | 
    
         
             
                rb_scan_args(argc, argv, "21&", &bucket, &timeout, &opts, &cb);
         
     | 
| 
       171 
171 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                if (CLASS_OF(bucket) !=  
     | 
| 
      
 172 
     | 
    
         
            +
                if (CLASS_OF(bucket) != cb_cBucket) {
         
     | 
| 
       173 
173 
     | 
    
         
             
                    rb_raise(rb_eTypeError, "wrong argument type (expected Couchbase::Bucket)");
         
     | 
| 
       174 
174 
     | 
    
         
             
                }
         
     | 
| 
       175 
175 
     | 
    
         
             
                tm->self = self;
         
     | 
| 
         @@ -178,7 +178,7 @@ cb_timer_init(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       178 
178 
     | 
    
         
             
                tm->bucket = DATA_PTR(bucket);
         
     | 
| 
       179 
179 
     | 
    
         
             
                if (opts != Qnil) {
         
     | 
| 
       180 
180 
     | 
    
         
             
                    Check_Type(opts, T_HASH);
         
     | 
| 
       181 
     | 
    
         
            -
                    tm->periodic = RTEST(rb_hash_aref(opts,  
     | 
| 
      
 181 
     | 
    
         
            +
                    tm->periodic = RTEST(rb_hash_aref(opts, cb_sym_periodic));
         
     | 
| 
       182 
182 
     | 
    
         
             
                }
         
     | 
| 
       183 
183 
     | 
    
         
             
                tm->timer = lcb_timer_create(tm->bucket->handle, tm, tm->usec,
         
     | 
| 
       184 
184 
     | 
    
         
             
                        tm->periodic, timer_callback, &err);
         
     | 
    
        data/ext/couchbase_ext/touch.c
    CHANGED
    
    | 
         @@ -18,39 +18,40 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
            #include "couchbase_ext.h"
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                void
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
            cb_touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_touch_resp_t *resp)
         
     | 
| 
       22 
22 
     | 
    
         
             
            {
         
     | 
| 
       23 
     | 
    
         
            -
                struct  
     | 
| 
       24 
     | 
    
         
            -
                struct  
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
      
 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 touch value", key);
         
     | 
| 
       33 
33 
     | 
    
         
             
                    if (exc != Qnil) {
         
     | 
| 
       34 
     | 
    
         
            -
                        rb_ivar_set(exc,  
     | 
| 
       35 
     | 
    
         
            -
                         
     | 
| 
       36 
     | 
    
         
            -
                            ctx->exception = cb_gc_protect(bucket, exc);
         
     | 
| 
       37 
     | 
    
         
            -
                        }
         
     | 
| 
      
 34 
     | 
    
         
            +
                        rb_ivar_set(exc, cb_id_iv_operation, cb_sym_touch);
         
     | 
| 
      
 35 
     | 
    
         
            +
                        ctx->exception = cb_gc_protect(bucket, exc);
         
     | 
| 
       38 
36 
     | 
    
         
             
                    }
         
     | 
| 
       39 
37 
     | 
    
         
             
                }
         
     | 
| 
       40 
38 
     | 
    
         | 
| 
       41 
39 
     | 
    
         
             
                if (bucket->async) {    /* asynchronous */
         
     | 
| 
       42 
40 
     | 
    
         
             
                    if (ctx->proc != Qnil) {
         
     | 
| 
       43 
     | 
    
         
            -
                        res = rb_class_new_instance(0, NULL,  
     | 
| 
       44 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       45 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       46 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       47 
     | 
    
         
            -
                        cb_proc_call(ctx->proc, 1, res);
         
     | 
| 
      
 41 
     | 
    
         
            +
                        res = rb_class_new_instance(0, NULL, cb_cResult);
         
     | 
| 
      
 42 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_error, exc);
         
     | 
| 
      
 43 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_operation, cb_sym_touch);
         
     | 
| 
      
 44 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_key, key);
         
     | 
| 
      
 45 
     | 
    
         
            +
                        cb_proc_call(bucket, ctx->proc, 1, res);
         
     | 
| 
       48 
46 
     | 
    
         
             
                    }
         
     | 
| 
       49 
47 
     | 
    
         
             
                } else {                /* synchronous */
         
     | 
| 
       50 
48 
     | 
    
         
             
                    rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
         
     | 
| 
       51 
49 
     | 
    
         
             
                }
         
     | 
| 
       52 
50 
     | 
    
         
             
                if (ctx->nqueries == 0) {
         
     | 
| 
       53 
51 
     | 
    
         
             
                    cb_gc_unprotect(bucket, ctx->proc);
         
     | 
| 
      
 52 
     | 
    
         
            +
                    if (bucket->async) {
         
     | 
| 
      
 53 
     | 
    
         
            +
                        free(ctx);
         
     | 
| 
      
 54 
     | 
    
         
            +
                    }
         
     | 
| 
       54 
55 
     | 
    
         
             
                }
         
     | 
| 
       55 
56 
     | 
    
         
             
                (void)handle;
         
     | 
| 
       56 
57 
     | 
    
         
             
            }
         
     | 
| 
         @@ -123,27 +124,27 @@ touch_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_to 
     | 
|
| 
       123 
124 
     | 
    
         
             
               VALUE
         
     | 
| 
       124 
125 
     | 
    
         
             
            cb_bucket_touch(int argc, VALUE *argv, VALUE self)
         
     | 
| 
       125 
126 
     | 
    
         
             
            {
         
     | 
| 
       126 
     | 
    
         
            -
                struct  
     | 
| 
       127 
     | 
    
         
            -
                struct  
     | 
| 
      
 127 
     | 
    
         
            +
                struct cb_bucket_st *bucket = DATA_PTR(self);
         
     | 
| 
      
 128 
     | 
    
         
            +
                struct cb_context_st *ctx;
         
     | 
| 
       128 
129 
     | 
    
         
             
                VALUE args, rv, proc, exc;
         
     | 
| 
       129 
130 
     | 
    
         
             
                lcb_error_t err;
         
     | 
| 
       130 
     | 
    
         
            -
                struct  
     | 
| 
      
 131 
     | 
    
         
            +
                struct cb_params_st params;
         
     | 
| 
       131 
132 
     | 
    
         | 
| 
       132 
133 
     | 
    
         
             
                if (bucket->handle == NULL) {
         
     | 
| 
       133 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 134 
     | 
    
         
            +
                    rb_raise(cb_eConnectError, "closed connection");
         
     | 
| 
       134 
135 
     | 
    
         
             
                }
         
     | 
| 
       135 
136 
     | 
    
         
             
                rb_scan_args(argc, argv, "0*&", &args, &proc);
         
     | 
| 
       136 
137 
     | 
    
         
             
                if (!bucket->async && proc != Qnil) {
         
     | 
| 
       137 
138 
     | 
    
         
             
                    rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
         
     | 
| 
       138 
139 
     | 
    
         
             
                }
         
     | 
| 
       139 
     | 
    
         
            -
                rb_funcall(args,  
     | 
| 
       140 
     | 
    
         
            -
                memset(¶ms, 0, sizeof(struct  
     | 
| 
       141 
     | 
    
         
            -
                params.type =  
     | 
| 
      
 140 
     | 
    
         
            +
                rb_funcall(args, cb_id_flatten_bang, 0);
         
     | 
| 
      
 141 
     | 
    
         
            +
                memset(¶ms, 0, sizeof(struct cb_params_st));
         
     | 
| 
      
 142 
     | 
    
         
            +
                params.type = cb_cmd_touch;
         
     | 
| 
       142 
143 
     | 
    
         
             
                params.bucket = bucket;
         
     | 
| 
       143 
144 
     | 
    
         
             
                cb_params_build(¶ms, RARRAY_LEN(args), args);
         
     | 
| 
       144 
     | 
    
         
            -
                ctx =  
     | 
| 
      
 145 
     | 
    
         
            +
                ctx = calloc(1, sizeof(struct cb_context_st));
         
     | 
| 
       145 
146 
     | 
    
         
             
                if (ctx == NULL) {
         
     | 
| 
       146 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 147 
     | 
    
         
            +
                    rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
         
     | 
| 
       147 
148 
     | 
    
         
             
                }
         
     | 
| 
       148 
149 
     | 
    
         
             
                ctx->proc = cb_gc_protect(bucket, proc);
         
     | 
| 
       149 
150 
     | 
    
         
             
                ctx->bucket = bucket;
         
     | 
| 
         @@ -157,12 +158,12 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       157 
158 
     | 
    
         
             
                cb_params_destroy(¶ms);
         
     | 
| 
       158 
159 
     | 
    
         
             
                exc = cb_check_error(err, "failed to schedule touch request", Qnil);
         
     | 
| 
       159 
160 
     | 
    
         
             
                if (exc != Qnil) {
         
     | 
| 
       160 
     | 
    
         
            -
                     
     | 
| 
      
 161 
     | 
    
         
            +
                    free(ctx);
         
     | 
| 
       161 
162 
     | 
    
         
             
                    rb_exc_raise(exc);
         
     | 
| 
       162 
163 
     | 
    
         
             
                }
         
     | 
| 
       163 
164 
     | 
    
         
             
                bucket->nbytes += params.npayload;
         
     | 
| 
       164 
165 
     | 
    
         
             
                if (bucket->async) {
         
     | 
| 
       165 
     | 
    
         
            -
                     
     | 
| 
      
 166 
     | 
    
         
            +
                    cb_maybe_do_loop(bucket);
         
     | 
| 
       166 
167 
     | 
    
         
             
                    return Qnil;
         
     | 
| 
       167 
168 
     | 
    
         
             
                } else {
         
     | 
| 
       168 
169 
     | 
    
         
             
                    if (ctx->nqueries > 0) {
         
     | 
| 
         @@ -170,12 +171,14 @@ cb_bucket_touch(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       170 
171 
     | 
    
         
             
                        lcb_wait(bucket->handle);
         
     | 
| 
       171 
172 
     | 
    
         
             
                    }
         
     | 
| 
       172 
173 
     | 
    
         
             
                    exc = ctx->exception;
         
     | 
| 
       173 
     | 
    
         
            -
                     
     | 
| 
      
 174 
     | 
    
         
            +
                    free(ctx);
         
     | 
| 
       174 
175 
     | 
    
         
             
                    if (exc != Qnil) {
         
     | 
| 
       175 
176 
     | 
    
         
             
                        rb_exc_raise(cb_gc_unprotect(bucket, exc));
         
     | 
| 
       176 
177 
     | 
    
         
             
                    }
         
     | 
| 
       177 
     | 
    
         
            -
                     
     | 
| 
       178 
     | 
    
         
            -
             
     | 
| 
      
 178 
     | 
    
         
            +
                    exc = bucket->exception;
         
     | 
| 
      
 179 
     | 
    
         
            +
                    if (exc != Qnil) {
         
     | 
| 
      
 180 
     | 
    
         
            +
                        bucket->exception = Qnil;
         
     | 
| 
      
 181 
     | 
    
         
            +
                        rb_exc_raise(exc);
         
     | 
| 
       179 
182 
     | 
    
         
             
                    }
         
     | 
| 
       180 
183 
     | 
    
         
             
                    if (params.cmd.touch.num > 1) {
         
     | 
| 
       181 
184 
     | 
    
         
             
                        return rv;  /* return as a hash {key => true, ...} */
         
     | 
    
        data/ext/couchbase_ext/unlock.c
    CHANGED
    
    | 
         @@ -18,39 +18,40 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
            #include "couchbase_ext.h"
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                void
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
            cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_unlock_resp_t *resp)
         
     | 
| 
       22 
22 
     | 
    
         
             
            {
         
     | 
| 
       23 
     | 
    
         
            -
                struct  
     | 
| 
       24 
     | 
    
         
            -
                struct  
     | 
| 
      
 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 
     | 
    
         
            -
                 
     | 
| 
      
 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 unlock value", key);
         
     | 
| 
       33 
33 
     | 
    
         
             
                    if (exc != Qnil) {
         
     | 
| 
       34 
     | 
    
         
            -
                        rb_ivar_set(exc,  
     | 
| 
       35 
     | 
    
         
            -
                         
     | 
| 
       36 
     | 
    
         
            -
                            ctx->exception = cb_gc_protect(bucket, exc);
         
     | 
| 
       37 
     | 
    
         
            -
                        }
         
     | 
| 
      
 34 
     | 
    
         
            +
                        rb_ivar_set(exc, cb_id_iv_operation, cb_sym_unlock);
         
     | 
| 
      
 35 
     | 
    
         
            +
                        ctx->exception = cb_gc_protect(bucket, exc);
         
     | 
| 
       38 
36 
     | 
    
         
             
                    }
         
     | 
| 
       39 
37 
     | 
    
         
             
                }
         
     | 
| 
       40 
38 
     | 
    
         | 
| 
       41 
39 
     | 
    
         
             
                if (bucket->async) {    /* asynchronous */
         
     | 
| 
       42 
40 
     | 
    
         
             
                    if (ctx->proc != Qnil) {
         
     | 
| 
       43 
     | 
    
         
            -
                        res = rb_class_new_instance(0, NULL,  
     | 
| 
       44 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       45 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       46 
     | 
    
         
            -
                        rb_ivar_set(res,  
     | 
| 
       47 
     | 
    
         
            -
                        cb_proc_call(ctx->proc, 1, res);
         
     | 
| 
      
 41 
     | 
    
         
            +
                        res = rb_class_new_instance(0, NULL, cb_cResult);
         
     | 
| 
      
 42 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_error, exc);
         
     | 
| 
      
 43 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_operation, cb_sym_unlock);
         
     | 
| 
      
 44 
     | 
    
         
            +
                        rb_ivar_set(res, cb_id_iv_key, key);
         
     | 
| 
      
 45 
     | 
    
         
            +
                        cb_proc_call(bucket, ctx->proc, 1, res);
         
     | 
| 
       48 
46 
     | 
    
         
             
                    }
         
     | 
| 
       49 
47 
     | 
    
         
             
                } else {                /* synchronous */
         
     | 
| 
       50 
48 
     | 
    
         
             
                    rb_hash_aset(*rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
         
     | 
| 
       51 
49 
     | 
    
         
             
                }
         
     | 
| 
       52 
50 
     | 
    
         
             
                if (ctx->nqueries == 0) {
         
     | 
| 
       53 
51 
     | 
    
         
             
                    cb_gc_unprotect(bucket, ctx->proc);
         
     | 
| 
      
 52 
     | 
    
         
            +
                    if (bucket->async) {
         
     | 
| 
      
 53 
     | 
    
         
            +
                        free(ctx);
         
     | 
| 
      
 54 
     | 
    
         
            +
                    }
         
     | 
| 
       54 
55 
     | 
    
         
             
                }
         
     | 
| 
       55 
56 
     | 
    
         
             
                (void)handle;
         
     | 
| 
       56 
57 
     | 
    
         
             
            }
         
     | 
| 
         @@ -113,27 +114,27 @@ unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_u 
     | 
|
| 
       113 
114 
     | 
    
         
             
               VALUE
         
     | 
| 
       114 
115 
     | 
    
         
             
            cb_bucket_unlock(int argc, VALUE *argv, VALUE self)
         
     | 
| 
       115 
116 
     | 
    
         
             
            {
         
     | 
| 
       116 
     | 
    
         
            -
                struct  
     | 
| 
       117 
     | 
    
         
            -
                struct  
     | 
| 
      
 117 
     | 
    
         
            +
                struct cb_bucket_st *bucket = DATA_PTR(self);
         
     | 
| 
      
 118 
     | 
    
         
            +
                struct cb_context_st *ctx;
         
     | 
| 
       118 
119 
     | 
    
         
             
                VALUE args, rv, proc, exc;
         
     | 
| 
       119 
120 
     | 
    
         
             
                lcb_error_t err;
         
     | 
| 
       120 
     | 
    
         
            -
                struct  
     | 
| 
      
 121 
     | 
    
         
            +
                struct cb_params_st params;
         
     | 
| 
       121 
122 
     | 
    
         | 
| 
       122 
123 
     | 
    
         
             
                if (bucket->handle == NULL) {
         
     | 
| 
       123 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 124 
     | 
    
         
            +
                    rb_raise(cb_eConnectError, "closed connection");
         
     | 
| 
       124 
125 
     | 
    
         
             
                }
         
     | 
| 
       125 
126 
     | 
    
         
             
                rb_scan_args(argc, argv, "0*&", &args, &proc);
         
     | 
| 
       126 
127 
     | 
    
         
             
                if (!bucket->async && proc != Qnil) {
         
     | 
| 
       127 
128 
     | 
    
         
             
                    rb_raise(rb_eArgError, "synchronous mode doesn't support callbacks");
         
     | 
| 
       128 
129 
     | 
    
         
             
                }
         
     | 
| 
       129 
     | 
    
         
            -
                rb_funcall(args,  
     | 
| 
       130 
     | 
    
         
            -
                memset(¶ms, 0, sizeof(struct  
     | 
| 
       131 
     | 
    
         
            -
                params.type =  
     | 
| 
      
 130 
     | 
    
         
            +
                rb_funcall(args, cb_id_flatten_bang, 0);
         
     | 
| 
      
 131 
     | 
    
         
            +
                memset(¶ms, 0, sizeof(struct cb_params_st));
         
     | 
| 
      
 132 
     | 
    
         
            +
                params.type = cb_cmd_unlock;
         
     | 
| 
       132 
133 
     | 
    
         
             
                params.bucket = bucket;
         
     | 
| 
       133 
134 
     | 
    
         
             
                cb_params_build(¶ms, RARRAY_LEN(args), args);
         
     | 
| 
       134 
     | 
    
         
            -
                ctx =  
     | 
| 
      
 135 
     | 
    
         
            +
                ctx = calloc(1, sizeof(struct cb_context_st));
         
     | 
| 
       135 
136 
     | 
    
         
             
                if (ctx == NULL) {
         
     | 
| 
       136 
     | 
    
         
            -
                    rb_raise( 
     | 
| 
      
 137 
     | 
    
         
            +
                    rb_raise(cb_eClientNoMemoryError, "failed to allocate memory for context");
         
     | 
| 
       137 
138 
     | 
    
         
             
                }
         
     | 
| 
       138 
139 
     | 
    
         
             
                ctx->proc = cb_gc_protect(bucket, proc);
         
     | 
| 
       139 
140 
     | 
    
         
             
                ctx->bucket = bucket;
         
     | 
| 
         @@ -147,12 +148,12 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       147 
148 
     | 
    
         
             
                cb_params_destroy(¶ms);
         
     | 
| 
       148 
149 
     | 
    
         
             
                exc = cb_check_error(err, "failed to schedule unlock request", Qnil);
         
     | 
| 
       149 
150 
     | 
    
         
             
                if (exc != Qnil) {
         
     | 
| 
       150 
     | 
    
         
            -
                     
     | 
| 
      
 151 
     | 
    
         
            +
                    free(ctx);
         
     | 
| 
       151 
152 
     | 
    
         
             
                    rb_exc_raise(exc);
         
     | 
| 
       152 
153 
     | 
    
         
             
                }
         
     | 
| 
       153 
154 
     | 
    
         
             
                bucket->nbytes += params.npayload;
         
     | 
| 
       154 
155 
     | 
    
         
             
                if (bucket->async) {
         
     | 
| 
       155 
     | 
    
         
            -
                     
     | 
| 
      
 156 
     | 
    
         
            +
                    cb_maybe_do_loop(bucket);
         
     | 
| 
       156 
157 
     | 
    
         
             
                    return Qnil;
         
     | 
| 
       157 
158 
     | 
    
         
             
                } else {
         
     | 
| 
       158 
159 
     | 
    
         
             
                    if (ctx->nqueries > 0) {
         
     | 
| 
         @@ -160,12 +161,14 @@ cb_bucket_unlock(int argc, VALUE *argv, VALUE self) 
     | 
|
| 
       160 
161 
     | 
    
         
             
                        lcb_wait(bucket->handle);
         
     | 
| 
       161 
162 
     | 
    
         
             
                    }
         
     | 
| 
       162 
163 
     | 
    
         
             
                    exc = ctx->exception;
         
     | 
| 
       163 
     | 
    
         
            -
                     
     | 
| 
      
 164 
     | 
    
         
            +
                    free(ctx);
         
     | 
| 
       164 
165 
     | 
    
         
             
                    if (exc != Qnil) {
         
     | 
| 
       165 
166 
     | 
    
         
             
                        rb_exc_raise(cb_gc_unprotect(bucket, exc));
         
     | 
| 
       166 
167 
     | 
    
         
             
                    }
         
     | 
| 
       167 
     | 
    
         
            -
                     
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
      
 168 
     | 
    
         
            +
                    exc = bucket->exception;
         
     | 
| 
      
 169 
     | 
    
         
            +
                    if (exc != Qnil) {
         
     | 
| 
      
 170 
     | 
    
         
            +
                        bucket->exception = Qnil;
         
     | 
| 
      
 171 
     | 
    
         
            +
                        rb_exc_raise(exc);
         
     | 
| 
       169 
172 
     | 
    
         
             
                    }
         
     | 
| 
       170 
173 
     | 
    
         
             
                    if (params.cmd.unlock.num > 1) {
         
     | 
| 
       171 
174 
     | 
    
         
             
                        return rv;  /* return as a hash {key => true, ...} */
         
     | 
    
        data/ext/couchbase_ext/utils.c
    CHANGED
    
    | 
         @@ -18,28 +18,80 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
            #include "couchbase_ext.h"
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                VALUE
         
     | 
| 
       21 
     | 
    
         
            -
            cb_gc_protect(struct  
     | 
| 
      
 21 
     | 
    
         
            +
            cb_gc_protect(struct cb_bucket_st *bucket, VALUE val)
         
     | 
| 
       22 
22 
     | 
    
         
             
            {
         
     | 
| 
       23 
23 
     | 
    
         
             
                rb_hash_aset(bucket->object_space, val|1, val);
         
     | 
| 
       24 
24 
     | 
    
         
             
                return val;
         
     | 
| 
       25 
25 
     | 
    
         
             
            }
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
                VALUE
         
     | 
| 
       28 
     | 
    
         
            -
            cb_gc_unprotect(struct  
     | 
| 
      
 28 
     | 
    
         
            +
            cb_gc_unprotect(struct cb_bucket_st *bucket, VALUE val)
         
     | 
| 
       29 
29 
     | 
    
         
             
            {
         
     | 
| 
       30 
     | 
    
         
            -
                rb_funcall(bucket->object_space,  
     | 
| 
      
 30 
     | 
    
         
            +
                rb_funcall(bucket->object_space, cb_id_delete, 1, val|1);
         
     | 
| 
       31 
31 
     | 
    
         
             
                return val;
         
     | 
| 
       32 
32 
     | 
    
         
             
            }
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
            struct proc_params_st
         
     | 
| 
      
 35 
     | 
    
         
            +
            {
         
     | 
| 
      
 36 
     | 
    
         
            +
                struct cb_bucket_st *bucket;
         
     | 
| 
      
 37 
     | 
    
         
            +
                VALUE recv;
         
     | 
| 
      
 38 
     | 
    
         
            +
                ID mid;
         
     | 
| 
      
 39 
     | 
    
         
            +
                int argc;
         
     | 
| 
      
 40 
     | 
    
         
            +
                VALUE *argv;
         
     | 
| 
      
 41 
     | 
    
         
            +
                VALUE exc;
         
     | 
| 
      
 42 
     | 
    
         
            +
            };
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                static VALUE
         
     | 
| 
      
 45 
     | 
    
         
            +
            do_async_error_notify(VALUE ptr)
         
     | 
| 
      
 46 
     | 
    
         
            +
            {
         
     | 
| 
      
 47 
     | 
    
         
            +
                struct proc_params_st *p = (struct proc_params_st *)ptr;
         
     | 
| 
      
 48 
     | 
    
         
            +
                return rb_funcall(p->bucket->on_error_proc, cb_id_call, 1, p->exc);
         
     | 
| 
      
 49 
     | 
    
         
            +
            }
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                void
         
     | 
| 
      
 52 
     | 
    
         
            +
            cb_async_error_notify(struct cb_bucket_st *bucket, VALUE exc)
         
     | 
| 
      
 53 
     | 
    
         
            +
            {
         
     | 
| 
      
 54 
     | 
    
         
            +
                if (bucket->on_error_proc != Qnil) {
         
     | 
| 
      
 55 
     | 
    
         
            +
                    struct proc_params_st params;
         
     | 
| 
      
 56 
     | 
    
         
            +
                    int fail;
         
     | 
| 
      
 57 
     | 
    
         
            +
                    params.bucket = bucket;
         
     | 
| 
      
 58 
     | 
    
         
            +
                    params.exc = exc;
         
     | 
| 
      
 59 
     | 
    
         
            +
                    rb_protect(do_async_error_notify, (VALUE)¶ms, &fail);
         
     | 
| 
      
 60 
     | 
    
         
            +
                    if (fail) {
         
     | 
| 
      
 61 
     | 
    
         
            +
                        rb_warning("Couchbase::Bucket#on_error shouldn't raise exceptions");
         
     | 
| 
      
 62 
     | 
    
         
            +
                    }
         
     | 
| 
      
 63 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 64 
     | 
    
         
            +
                    if (NIL_P(bucket->exception)) {
         
     | 
| 
      
 65 
     | 
    
         
            +
                        bucket->exception = exc;
         
     | 
| 
      
 66 
     | 
    
         
            +
                    }
         
     | 
| 
      
 67 
     | 
    
         
            +
                }
         
     | 
| 
      
 68 
     | 
    
         
            +
            }
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                static VALUE
         
     | 
| 
      
 71 
     | 
    
         
            +
            func_call_failed(VALUE ptr, VALUE exc)
         
     | 
| 
      
 72 
     | 
    
         
            +
            {
         
     | 
| 
      
 73 
     | 
    
         
            +
                struct proc_params_st *p = (struct proc_params_st *)ptr;
         
     | 
| 
      
 74 
     | 
    
         
            +
                cb_async_error_notify(p->bucket, exc);
         
     | 
| 
      
 75 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 76 
     | 
    
         
            +
            }
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                static VALUE
         
     | 
| 
      
 79 
     | 
    
         
            +
            do_func_call(VALUE ptr)
         
     | 
| 
      
 80 
     | 
    
         
            +
            {
         
     | 
| 
      
 81 
     | 
    
         
            +
                struct proc_params_st *p = (struct proc_params_st *)ptr;
         
     | 
| 
      
 82 
     | 
    
         
            +
                return rb_funcall2(p->recv, p->mid, p->argc, p->argv);
         
     | 
| 
      
 83 
     | 
    
         
            +
            }
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
       34 
85 
     | 
    
         
             
                VALUE
         
     | 
| 
       35 
     | 
    
         
            -
            cb_proc_call(VALUE recv, int argc, ...)
         
     | 
| 
      
 86 
     | 
    
         
            +
            cb_proc_call(struct cb_bucket_st *bucket, VALUE recv, int argc, ...)
         
     | 
| 
       36 
87 
     | 
    
         
             
            {
         
     | 
| 
       37 
88 
     | 
    
         
             
                VALUE *argv;
         
     | 
| 
       38 
89 
     | 
    
         
             
                va_list ar;
         
     | 
| 
       39 
90 
     | 
    
         
             
                int arity;
         
     | 
| 
       40 
91 
     | 
    
         
             
                int ii;
         
     | 
| 
      
 92 
     | 
    
         
            +
                struct proc_params_st params;
         
     | 
| 
       41 
93 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                arity = FIX2INT(rb_funcall(recv,  
     | 
| 
      
 94 
     | 
    
         
            +
                arity = FIX2INT(rb_funcall(recv, cb_id_arity, 0));
         
     | 
| 
       43 
95 
     | 
    
         
             
                if (arity < 0) {
         
     | 
| 
       44 
96 
     | 
    
         
             
                    arity = argc;
         
     | 
| 
       45 
97 
     | 
    
         
             
                }
         
     | 
| 
         @@ -57,13 +109,20 @@ cb_proc_call(VALUE recv, int argc, ...) 
     | 
|
| 
       57 
109 
     | 
    
         
             
                } else {
         
     | 
| 
       58 
110 
     | 
    
         
             
                    argv = NULL;
         
     | 
| 
       59 
111 
     | 
    
         
             
                }
         
     | 
| 
       60 
     | 
    
         
            -
                 
     | 
| 
      
 112 
     | 
    
         
            +
                params.bucket = bucket;
         
     | 
| 
      
 113 
     | 
    
         
            +
                params.recv = recv;
         
     | 
| 
      
 114 
     | 
    
         
            +
                params.mid = cb_id_call;
         
     | 
| 
      
 115 
     | 
    
         
            +
                params.argc = arity;
         
     | 
| 
      
 116 
     | 
    
         
            +
                params.argv = argv;
         
     | 
| 
      
 117 
     | 
    
         
            +
                return rb_rescue2(do_func_call, (VALUE)¶ms,
         
     | 
| 
      
 118 
     | 
    
         
            +
                        func_call_failed, (VALUE)¶ms,
         
     | 
| 
      
 119 
     | 
    
         
            +
                        rb_eException, (VALUE)0);
         
     | 
| 
       61 
120 
     | 
    
         
             
            }
         
     | 
| 
       62 
121 
     | 
    
         | 
| 
       63 
122 
     | 
    
         
             
            VALUE
         
     | 
| 
       64 
123 
     | 
    
         
             
            cb_hash_delete(VALUE hash, VALUE key)
         
     | 
| 
       65 
124 
     | 
    
         
             
            {
         
     | 
| 
       66 
     | 
    
         
            -
                return rb_funcall(hash,  
     | 
| 
      
 125 
     | 
    
         
            +
                return rb_funcall(hash, cb_id_delete, 1, key);
         
     | 
| 
       67 
126 
     | 
    
         
             
            }
         
     | 
| 
       68 
127 
     | 
    
         | 
| 
       69 
128 
     | 
    
         
             
            /* Helper to convert return code from libcouchbase to meaningful exception.
         
     | 
| 
         @@ -77,83 +136,93 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key, 
     | 
|
| 
       77 
136 
     | 
    
         
             
                VALUE klass, exc, str;
         
     | 
| 
       78 
137 
     | 
    
         
             
                char buf[300];
         
     | 
| 
       79 
138 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                if (rc == LCB_SUCCESS ||  
     | 
| 
      
 139 
     | 
    
         
            +
                if ((rc == LCB_SUCCESS && (status == 0 || status / 100 == 2)) ||
         
     | 
| 
      
 140 
     | 
    
         
            +
                        rc == LCB_AUTH_CONTINUE) {
         
     | 
| 
       81 
141 
     | 
    
         
             
                    return Qnil;
         
     | 
| 
       82 
142 
     | 
    
         
             
                }
         
     | 
| 
       83 
143 
     | 
    
         
             
                switch (rc) {
         
     | 
| 
       84 
144 
     | 
    
         
             
                    case LCB_AUTH_ERROR:
         
     | 
| 
       85 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 145 
     | 
    
         
            +
                        klass = cb_eAuthError;
         
     | 
| 
       86 
146 
     | 
    
         
             
                        break;
         
     | 
| 
       87 
147 
     | 
    
         
             
                    case LCB_DELTA_BADVAL:
         
     | 
| 
       88 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 148 
     | 
    
         
            +
                        klass = cb_eDeltaBadvalError;
         
     | 
| 
       89 
149 
     | 
    
         
             
                        break;
         
     | 
| 
       90 
150 
     | 
    
         
             
                    case LCB_E2BIG:
         
     | 
| 
       91 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 151 
     | 
    
         
            +
                        klass = cb_eTooBigError;
         
     | 
| 
       92 
152 
     | 
    
         
             
                        break;
         
     | 
| 
       93 
153 
     | 
    
         
             
                    case LCB_EBUSY:
         
     | 
| 
       94 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 154 
     | 
    
         
            +
                        klass = cb_eBusyError;
         
     | 
| 
       95 
155 
     | 
    
         
             
                        break;
         
     | 
| 
       96 
156 
     | 
    
         
             
                    case LCB_EINTERNAL:
         
     | 
| 
       97 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 157 
     | 
    
         
            +
                        klass = cb_eInternalError;
         
     | 
| 
       98 
158 
     | 
    
         
             
                        break;
         
     | 
| 
       99 
159 
     | 
    
         
             
                    case LCB_EINVAL:
         
     | 
| 
       100 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 160 
     | 
    
         
            +
                        klass = cb_eInvalidError;
         
     | 
| 
       101 
161 
     | 
    
         
             
                        break;
         
     | 
| 
       102 
162 
     | 
    
         
             
                    case LCB_ENOMEM:
         
     | 
| 
       103 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 163 
     | 
    
         
            +
                        klass = cb_eNoMemoryError;
         
     | 
| 
       104 
164 
     | 
    
         
             
                        break;
         
     | 
| 
       105 
165 
     | 
    
         
             
                    case LCB_ERANGE:
         
     | 
| 
       106 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 166 
     | 
    
         
            +
                        klass = cb_eRangeError;
         
     | 
| 
       107 
167 
     | 
    
         
             
                        break;
         
     | 
| 
       108 
168 
     | 
    
         
             
                    case LCB_ETMPFAIL:
         
     | 
| 
       109 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 169 
     | 
    
         
            +
                        klass = cb_eTmpFailError;
         
     | 
| 
       110 
170 
     | 
    
         
             
                        break;
         
     | 
| 
       111 
171 
     | 
    
         
             
                    case LCB_KEY_EEXISTS:
         
     | 
| 
       112 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 172 
     | 
    
         
            +
                        klass = cb_eKeyExistsError;
         
     | 
| 
       113 
173 
     | 
    
         
             
                        break;
         
     | 
| 
       114 
174 
     | 
    
         
             
                    case LCB_KEY_ENOENT:
         
     | 
| 
       115 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 175 
     | 
    
         
            +
                        klass = cb_eNotFoundError;
         
     | 
| 
       116 
176 
     | 
    
         
             
                        break;
         
     | 
| 
       117 
     | 
    
         
            -
                    case  
     | 
| 
       118 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 177 
     | 
    
         
            +
                    case LCB_DLOPEN_FAILED:
         
     | 
| 
      
 178 
     | 
    
         
            +
                        klass = cb_eDlopenFailedError;
         
     | 
| 
      
 179 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 180 
     | 
    
         
            +
                    case LCB_DLSYM_FAILED:
         
     | 
| 
      
 181 
     | 
    
         
            +
                        klass = cb_eDlsymFailedError;
         
     | 
| 
       119 
182 
     | 
    
         
             
                        break;
         
     | 
| 
       120 
183 
     | 
    
         
             
                    case LCB_NETWORK_ERROR:
         
     | 
| 
       121 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 184 
     | 
    
         
            +
                        klass = cb_eNetworkError;
         
     | 
| 
       122 
185 
     | 
    
         
             
                        break;
         
     | 
| 
       123 
186 
     | 
    
         
             
                    case LCB_NOT_MY_VBUCKET:
         
     | 
| 
       124 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 187 
     | 
    
         
            +
                        klass = cb_eNotMyVbucketError;
         
     | 
| 
       125 
188 
     | 
    
         
             
                        break;
         
     | 
| 
       126 
189 
     | 
    
         
             
                    case LCB_NOT_STORED:
         
     | 
| 
       127 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 190 
     | 
    
         
            +
                        klass = cb_eNotStoredError;
         
     | 
| 
       128 
191 
     | 
    
         
             
                        break;
         
     | 
| 
       129 
192 
     | 
    
         
             
                    case LCB_NOT_SUPPORTED:
         
     | 
| 
       130 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 193 
     | 
    
         
            +
                        klass = cb_eNotSupportedError;
         
     | 
| 
       131 
194 
     | 
    
         
             
                        break;
         
     | 
| 
       132 
195 
     | 
    
         
             
                    case LCB_UNKNOWN_COMMAND:
         
     | 
| 
       133 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 196 
     | 
    
         
            +
                        klass = cb_eUnknownCommandError;
         
     | 
| 
       134 
197 
     | 
    
         
             
                        break;
         
     | 
| 
       135 
198 
     | 
    
         
             
                    case LCB_UNKNOWN_HOST:
         
     | 
| 
       136 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 199 
     | 
    
         
            +
                        klass = cb_eUnknownHostError;
         
     | 
| 
       137 
200 
     | 
    
         
             
                        break;
         
     | 
| 
       138 
201 
     | 
    
         
             
                    case LCB_PROTOCOL_ERROR:
         
     | 
| 
       139 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 202 
     | 
    
         
            +
                        klass = cb_eProtocolError;
         
     | 
| 
       140 
203 
     | 
    
         
             
                        break;
         
     | 
| 
       141 
204 
     | 
    
         
             
                    case LCB_ETIMEDOUT:
         
     | 
| 
       142 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 205 
     | 
    
         
            +
                        klass = cb_eTimeoutError;
         
     | 
| 
       143 
206 
     | 
    
         
             
                        break;
         
     | 
| 
       144 
207 
     | 
    
         
             
                    case LCB_CONNECT_ERROR:
         
     | 
| 
       145 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 208 
     | 
    
         
            +
                        klass = cb_eConnectError;
         
     | 
| 
       146 
209 
     | 
    
         
             
                        break;
         
     | 
| 
       147 
210 
     | 
    
         
             
                    case LCB_BUCKET_ENOENT:
         
     | 
| 
       148 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 211 
     | 
    
         
            +
                        klass = cb_eBucketNotFoundError;
         
     | 
| 
       149 
212 
     | 
    
         
             
                        break;
         
     | 
| 
       150 
213 
     | 
    
         
             
                    case LCB_CLIENT_ENOMEM:
         
     | 
| 
       151 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 214 
     | 
    
         
            +
                        klass = cb_eClientNoMemoryError;
         
     | 
| 
      
 215 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 216 
     | 
    
         
            +
                    case LCB_CLIENT_ETMPFAIL:
         
     | 
| 
      
 217 
     | 
    
         
            +
                        klass = cb_eClientTmpFailError;
         
     | 
| 
      
 218 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 219 
     | 
    
         
            +
                    case LCB_EBADHANDLE:
         
     | 
| 
      
 220 
     | 
    
         
            +
                        klass = cb_eBadHandleError;
         
     | 
| 
       152 
221 
     | 
    
         
             
                        break;
         
     | 
| 
       153 
222 
     | 
    
         
             
                    case LCB_ERROR:
         
     | 
| 
       154 
223 
     | 
    
         
             
                        /* fall through */
         
     | 
| 
       155 
224 
     | 
    
         
             
                    default:
         
     | 
| 
       156 
     | 
    
         
            -
                        klass =  
     | 
| 
      
 225 
     | 
    
         
            +
                        klass = cb_eLibcouchbaseError;
         
     | 
| 
       157 
226 
     | 
    
         
             
                }
         
     | 
| 
       158 
227 
     | 
    
         | 
| 
       159 
228 
     | 
    
         
             
                str = rb_str_buf_new2(msg ? msg : "");
         
     | 
| 
         @@ -164,6 +233,7 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key, 
     | 
|
| 
       164 
233 
     | 
    
         
             
                }
         
     | 
| 
       165 
234 
     | 
    
         
             
                if (status > 0) {
         
     | 
| 
       166 
235 
     | 
    
         
             
                    const char *reason = NULL;
         
     | 
| 
      
 236 
     | 
    
         
            +
                    klass = cb_eHTTPError;
         
     | 
| 
       167 
237 
     | 
    
         
             
                    snprintf(buf, 300, "status=\"%d\"", status);
         
     | 
| 
       168 
238 
     | 
    
         
             
                    rb_str_buf_cat2(str, buf);
         
     | 
| 
       169 
239 
     | 
    
         
             
                    switch (status) {
         
     | 
| 
         @@ -261,11 +331,11 @@ cb_check_error_with_status(lcb_error_t rc, const char *msg, VALUE key, 
     | 
|
| 
       261 
331 
     | 
    
         
             
                snprintf(buf, 300, "error=0x%02x)", rc);
         
     | 
| 
       262 
332 
     | 
    
         
             
                rb_str_buf_cat2(str, buf);
         
     | 
| 
       263 
333 
     | 
    
         
             
                exc = rb_exc_new3(klass, str);
         
     | 
| 
       264 
     | 
    
         
            -
                rb_ivar_set(exc,  
     | 
| 
       265 
     | 
    
         
            -
                rb_ivar_set(exc,  
     | 
| 
       266 
     | 
    
         
            -
                rb_ivar_set(exc,  
     | 
| 
       267 
     | 
    
         
            -
                rb_ivar_set(exc,  
     | 
| 
       268 
     | 
    
         
            -
                rb_ivar_set(exc,  
     | 
| 
      
 334 
     | 
    
         
            +
                rb_ivar_set(exc, cb_id_iv_error, INT2FIX(rc));
         
     | 
| 
      
 335 
     | 
    
         
            +
                rb_ivar_set(exc, cb_id_iv_key, key);
         
     | 
| 
      
 336 
     | 
    
         
            +
                rb_ivar_set(exc, cb_id_iv_cas, Qnil);
         
     | 
| 
      
 337 
     | 
    
         
            +
                rb_ivar_set(exc, cb_id_iv_operation, Qnil);
         
     | 
| 
      
 338 
     | 
    
         
            +
                rb_ivar_set(exc, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
         
     | 
| 
       269 
339 
     | 
    
         
             
                return exc;
         
     | 
| 
       270 
340 
     | 
    
         
             
            }
         
     | 
| 
       271 
341 
     | 
    
         | 
| 
         @@ -277,35 +347,35 @@ cb_check_error(lcb_error_t rc, const char *msg, VALUE key) 
     | 
|
| 
       277 
347 
     | 
    
         | 
| 
       278 
348 
     | 
    
         | 
| 
       279 
349 
     | 
    
         
             
                uint32_t
         
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
      
 350 
     | 
    
         
            +
            cb_flags_set_format(uint32_t flags, ID format)
         
     | 
| 
       281 
351 
     | 
    
         
             
            {
         
     | 
| 
       282 
     | 
    
         
            -
                flags &= ~((uint32_t) 
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
                if (format ==  
     | 
| 
       285 
     | 
    
         
            -
                    return flags |  
     | 
| 
       286 
     | 
    
         
            -
                } else if (format ==  
     | 
| 
       287 
     | 
    
         
            -
                    return flags |  
     | 
| 
       288 
     | 
    
         
            -
                } else if (format ==  
     | 
| 
       289 
     | 
    
         
            -
                    return flags |  
     | 
| 
      
 352 
     | 
    
         
            +
                flags &= ~((uint32_t)CB_FMT_MASK); /* clear format bits */
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
                if (format == cb_sym_document) {
         
     | 
| 
      
 355 
     | 
    
         
            +
                    return flags | CB_FMT_DOCUMENT;
         
     | 
| 
      
 356 
     | 
    
         
            +
                } else if (format == cb_sym_marshal) {
         
     | 
| 
      
 357 
     | 
    
         
            +
                    return flags | CB_FMT_MARSHAL;
         
     | 
| 
      
 358 
     | 
    
         
            +
                } else if (format == cb_sym_plain) {
         
     | 
| 
      
 359 
     | 
    
         
            +
                    return flags | CB_FMT_PLAIN;
         
     | 
| 
       290 
360 
     | 
    
         
             
                }
         
     | 
| 
       291 
361 
     | 
    
         
             
                return flags; /* document is the default */
         
     | 
| 
       292 
362 
     | 
    
         
             
            }
         
     | 
| 
       293 
363 
     | 
    
         | 
| 
       294 
364 
     | 
    
         
             
                ID
         
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
      
 365 
     | 
    
         
            +
            cb_flags_get_format(uint32_t flags)
         
     | 
| 
       296 
366 
     | 
    
         
             
            {
         
     | 
| 
       297 
     | 
    
         
            -
                flags &=  
     | 
| 
      
 367 
     | 
    
         
            +
                flags &= CB_FMT_MASK; /* select format bits */
         
     | 
| 
       298 
368 
     | 
    
         | 
| 
       299 
369 
     | 
    
         
             
                switch (flags) {
         
     | 
| 
       300 
     | 
    
         
            -
                    case  
     | 
| 
       301 
     | 
    
         
            -
                        return  
     | 
| 
       302 
     | 
    
         
            -
                    case  
     | 
| 
       303 
     | 
    
         
            -
                        return  
     | 
| 
       304 
     | 
    
         
            -
                    case  
     | 
| 
      
 370 
     | 
    
         
            +
                    case CB_FMT_DOCUMENT:
         
     | 
| 
      
 371 
     | 
    
         
            +
                        return cb_sym_document;
         
     | 
| 
      
 372 
     | 
    
         
            +
                    case CB_FMT_MARSHAL:
         
     | 
| 
      
 373 
     | 
    
         
            +
                        return cb_sym_marshal;
         
     | 
| 
      
 374 
     | 
    
         
            +
                    case CB_FMT_PLAIN:
         
     | 
| 
       305 
375 
     | 
    
         
             
                        /* fall through */
         
     | 
| 
       306 
376 
     | 
    
         
             
                    default:
         
     | 
| 
       307 
377 
     | 
    
         
             
                        /* all other formats treated as plain */
         
     | 
| 
       308 
     | 
    
         
            -
                        return  
     | 
| 
      
 378 
     | 
    
         
            +
                        return cb_sym_plain;
         
     | 
| 
       309 
379 
     | 
    
         
             
                }
         
     | 
| 
       310 
380 
     | 
    
         
             
            }
         
     | 
| 
       311 
381 
     | 
    
         | 
| 
         @@ -314,14 +384,14 @@ flags_get_format(uint32_t flags) 
     | 
|
| 
       314 
384 
     | 
    
         
             
            do_encode(VALUE *args)
         
     | 
| 
       315 
385 
     | 
    
         
             
            {
         
     | 
| 
       316 
386 
     | 
    
         
             
                VALUE val = args[0];
         
     | 
| 
       317 
     | 
    
         
            -
                uint32_t flags = ((uint32_t)args[1] &  
     | 
| 
      
 387 
     | 
    
         
            +
                uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
         
     | 
| 
       318 
388 
     | 
    
         | 
| 
       319 
389 
     | 
    
         
             
                switch (flags) {
         
     | 
| 
       320 
     | 
    
         
            -
                    case  
     | 
| 
       321 
     | 
    
         
            -
                        return rb_funcall( 
     | 
| 
       322 
     | 
    
         
            -
                    case  
     | 
| 
       323 
     | 
    
         
            -
                        return rb_funcall( 
     | 
| 
       324 
     | 
    
         
            -
                    case  
     | 
| 
      
 390 
     | 
    
         
            +
                    case CB_FMT_DOCUMENT:
         
     | 
| 
      
 391 
     | 
    
         
            +
                        return rb_funcall(cb_mMultiJson, cb_id_dump, 1, val);
         
     | 
| 
      
 392 
     | 
    
         
            +
                    case CB_FMT_MARSHAL:
         
     | 
| 
      
 393 
     | 
    
         
            +
                        return rb_funcall(cb_mMarshal, cb_id_dump, 1, val);
         
     | 
| 
      
 394 
     | 
    
         
            +
                    case CB_FMT_PLAIN:
         
     | 
| 
       325 
395 
     | 
    
         
             
                        /* fall through */
         
     | 
| 
       326 
396 
     | 
    
         
             
                    default:
         
     | 
| 
       327 
397 
     | 
    
         
             
                        /* all other formats treated as plain */
         
     | 
| 
         @@ -336,22 +406,22 @@ do_decode(VALUE *args) 
     | 
|
| 
       336 
406 
     | 
    
         
             
                VALUE force_format = args[2];
         
     | 
| 
       337 
407 
     | 
    
         | 
| 
       338 
408 
     | 
    
         
             
                if (TYPE(force_format) == T_SYMBOL) {
         
     | 
| 
       339 
     | 
    
         
            -
                    if (force_format ==  
     | 
| 
       340 
     | 
    
         
            -
                        return rb_funcall( 
     | 
| 
       341 
     | 
    
         
            -
                    } else if (force_format ==  
     | 
| 
       342 
     | 
    
         
            -
                        return rb_funcall( 
     | 
| 
       343 
     | 
    
         
            -
                    } else { /*  
     | 
| 
      
 409 
     | 
    
         
            +
                    if (force_format == cb_sym_document) {
         
     | 
| 
      
 410 
     | 
    
         
            +
                        return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
         
     | 
| 
      
 411 
     | 
    
         
            +
                    } else if (force_format == cb_sym_marshal) {
         
     | 
| 
      
 412 
     | 
    
         
            +
                        return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
         
     | 
| 
      
 413 
     | 
    
         
            +
                    } else { /* cb_sym_plain and any other cb_symbol */
         
     | 
| 
       344 
414 
     | 
    
         
             
                        return blob;
         
     | 
| 
       345 
415 
     | 
    
         
             
                    }
         
     | 
| 
       346 
416 
     | 
    
         
             
                } else {
         
     | 
| 
       347 
     | 
    
         
            -
                    uint32_t flags = ((uint32_t)args[1] &  
     | 
| 
      
 417 
     | 
    
         
            +
                    uint32_t flags = ((uint32_t)args[1] & CB_FMT_MASK);
         
     | 
| 
       348 
418 
     | 
    
         | 
| 
       349 
419 
     | 
    
         
             
                    switch (flags) {
         
     | 
| 
       350 
     | 
    
         
            -
                        case  
     | 
| 
       351 
     | 
    
         
            -
                            return rb_funcall( 
     | 
| 
       352 
     | 
    
         
            -
                        case  
     | 
| 
       353 
     | 
    
         
            -
                            return rb_funcall( 
     | 
| 
       354 
     | 
    
         
            -
                        case  
     | 
| 
      
 420 
     | 
    
         
            +
                        case CB_FMT_DOCUMENT:
         
     | 
| 
      
 421 
     | 
    
         
            +
                            return rb_funcall(cb_mMultiJson, cb_id_load, 1, blob);
         
     | 
| 
      
 422 
     | 
    
         
            +
                        case CB_FMT_MARSHAL:
         
     | 
| 
      
 423 
     | 
    
         
            +
                            return rb_funcall(cb_mMarshal, cb_id_load, 1, blob);
         
     | 
| 
      
 424 
     | 
    
         
            +
                        case CB_FMT_PLAIN:
         
     | 
| 
       355 
425 
     | 
    
         
             
                            /* fall through */
         
     | 
| 
       356 
426 
     | 
    
         
             
                        default:
         
     | 
| 
       357 
427 
     | 
    
         
             
                            /* all other formats treated as plain */
         
     | 
| 
         @@ -361,29 +431,25 @@ do_decode(VALUE *args) 
     | 
|
| 
       361 
431 
     | 
    
         
             
            }
         
     | 
| 
       362 
432 
     | 
    
         | 
| 
       363 
433 
     | 
    
         
             
                static VALUE
         
     | 
| 
       364 
     | 
    
         
            -
            coding_failed( 
     | 
| 
      
 434 
     | 
    
         
            +
            coding_failed(VALUE unused, VALUE exc)
         
     | 
| 
       365 
435 
     | 
    
         
             
            {
         
     | 
| 
       366 
     | 
    
         
            -
                 
     | 
| 
      
 436 
     | 
    
         
            +
                (void)unused;
         
     | 
| 
      
 437 
     | 
    
         
            +
                return exc;
         
     | 
| 
       367 
438 
     | 
    
         
             
            }
         
     | 
| 
       368 
439 
     | 
    
         | 
| 
       369 
440 
     | 
    
         
             
                VALUE
         
     | 
| 
       370 
     | 
    
         
            -
             
     | 
| 
      
 441 
     | 
    
         
            +
            cb_encode_value(VALUE val, uint32_t flags)
         
     | 
| 
       371 
442 
     | 
    
         
             
            {
         
     | 
| 
       372 
443 
     | 
    
         
             
                VALUE blob, args[2];
         
     | 
| 
       373 
444 
     | 
    
         | 
| 
       374 
445 
     | 
    
         
             
                args[0] = val;
         
     | 
| 
       375 
446 
     | 
    
         
             
                args[1] = (VALUE)flags;
         
     | 
| 
       376 
     | 
    
         
            -
                /* FIXME re-raise proper exception */
         
     | 
| 
       377 
447 
     | 
    
         
             
                blob = rb_rescue(do_encode, (VALUE)args, coding_failed, 0);
         
     | 
| 
       378 
     | 
    
         
            -
                 
     | 
| 
       379 
     | 
    
         
            -
                if (TYPE(blob) != T_STRING) {
         
     | 
| 
       380 
     | 
    
         
            -
                    return Qundef;
         
     | 
| 
       381 
     | 
    
         
            -
                }
         
     | 
| 
       382 
     | 
    
         
            -
                return blob;
         
     | 
| 
      
 448 
     | 
    
         
            +
                return blob; /* bytestring or exception object */
         
     | 
| 
       383 
449 
     | 
    
         
             
            }
         
     | 
| 
       384 
450 
     | 
    
         | 
| 
       385 
451 
     | 
    
         
             
                VALUE
         
     | 
| 
       386 
     | 
    
         
            -
             
     | 
| 
      
 452 
     | 
    
         
            +
            cb_decode_value(VALUE blob, uint32_t flags, VALUE force_format)
         
     | 
| 
       387 
453 
     | 
    
         
             
            {
         
     | 
| 
       388 
454 
     | 
    
         
             
                VALUE val, args[3];
         
     | 
| 
       389 
455 
     | 
    
         | 
| 
         @@ -395,23 +461,23 @@ decode_value(VALUE blob, uint32_t flags, VALUE force_format) 
     | 
|
| 
       395 
461 
     | 
    
         
             
                args[1] = (VALUE)flags;
         
     | 
| 
       396 
462 
     | 
    
         
             
                args[2] = (VALUE)force_format;
         
     | 
| 
       397 
463 
     | 
    
         
             
                val = rb_rescue(do_decode, (VALUE)args, coding_failed, 0);
         
     | 
| 
       398 
     | 
    
         
            -
                return val;
         
     | 
| 
      
 464 
     | 
    
         
            +
                return val; /* the value or exception object */
         
     | 
| 
       399 
465 
     | 
    
         
             
            }
         
     | 
| 
       400 
466 
     | 
    
         | 
| 
       401 
467 
     | 
    
         
             
                void
         
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
      
 468 
     | 
    
         
            +
            cb_strip_key_prefix(struct cb_bucket_st *bucket, VALUE key)
         
     | 
| 
       403 
469 
     | 
    
         
             
            {
         
     | 
| 
       404 
     | 
    
         
            -
                if (bucket-> 
     | 
| 
       405 
     | 
    
         
            -
                    rb_str_update(key, 0, RSTRING_LEN(bucket->key_prefix_val),  
     | 
| 
      
 470 
     | 
    
         
            +
                if (RTEST(bucket->key_prefix_val)) {
         
     | 
| 
      
 471 
     | 
    
         
            +
                    rb_str_update(key, 0, RSTRING_LEN(bucket->key_prefix_val), cb_vStrEmpty);
         
     | 
| 
       406 
472 
     | 
    
         
             
                }
         
     | 
| 
       407 
473 
     | 
    
         
             
            }
         
     | 
| 
       408 
474 
     | 
    
         | 
| 
       409 
475 
     | 
    
         
             
                VALUE
         
     | 
| 
       410 
     | 
    
         
            -
             
     | 
| 
      
 476 
     | 
    
         
            +
            cb_unify_key(struct cb_bucket_st *bucket, VALUE key, int apply_prefix)
         
     | 
| 
       411 
477 
     | 
    
         
             
            {
         
     | 
| 
       412 
478 
     | 
    
         
             
                VALUE ret = Qnil, tmp;
         
     | 
| 
       413 
479 
     | 
    
         | 
| 
       414 
     | 
    
         
            -
                if (bucket-> 
     | 
| 
      
 480 
     | 
    
         
            +
                if (RTEST(bucket->key_prefix_val) && apply_prefix) {
         
     | 
| 
       415 
481 
     | 
    
         
             
                    ret = rb_str_dup(bucket->key_prefix_val);
         
     | 
| 
       416 
482 
     | 
    
         
             
                }
         
     | 
| 
       417 
483 
     | 
    
         
             
                switch (TYPE(key)) {
         
     | 
| 
         @@ -427,7 +493,7 @@ unify_key(struct bucket_st *bucket, VALUE key, int apply_prefix) 
     | 
|
| 
       427 
493 
     | 
    
         
             
            }
         
     | 
| 
       428 
494 
     | 
    
         | 
| 
       429 
495 
     | 
    
         
             
                void
         
     | 
| 
       430 
     | 
    
         
            -
            cb_build_headers(struct  
     | 
| 
      
 496 
     | 
    
         
            +
            cb_build_headers(struct cb_context_st *ctx, const char * const *headers)
         
     | 
| 
       431 
497 
     | 
    
         
             
            {
         
     | 
| 
       432 
498 
     | 
    
         
             
                if (!ctx->headers_built) {
         
     | 
| 
       433 
499 
     | 
    
         
             
                    VALUE key = Qnil, val;
         
     | 
| 
         @@ -469,3 +535,14 @@ cb_first_value_i(VALUE key, VALUE value, VALUE arg) 
     | 
|
| 
       469 
535 
     | 
    
         
             
                (void)key;
         
     | 
| 
       470 
536 
     | 
    
         
             
                return ST_STOP;
         
     | 
| 
       471 
537 
     | 
    
         
             
            }
         
     | 
| 
      
 538 
     | 
    
         
            +
             
     | 
| 
      
 539 
     | 
    
         
            +
            #ifndef HAVE_RB_HASH_LOOKUP2
         
     | 
| 
      
 540 
     | 
    
         
            +
                VALUE
         
     | 
| 
      
 541 
     | 
    
         
            +
            rb_hash_lookup2(VALUE hash, VALUE key, VALUE dflt)
         
     | 
| 
      
 542 
     | 
    
         
            +
            {
         
     | 
| 
      
 543 
     | 
    
         
            +
                if (RTEST(rb_funcall2(hash, cb_id_has_key_p, 1, &key))) {
         
     | 
| 
      
 544 
     | 
    
         
            +
                    dflt = rb_hash_aref(hash, key);
         
     | 
| 
      
 545 
     | 
    
         
            +
                }
         
     | 
| 
      
 546 
     | 
    
         
            +
                return dflt;
         
     | 
| 
      
 547 
     | 
    
         
            +
            }
         
     | 
| 
      
 548 
     | 
    
         
            +
            #endif
         
     |