void
observe_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_observe_resp_t *resp)
{
    struct context_st *ctx = (struct context_st *)cookie;
    struct bucket_st *bucket = ctx->bucket;
    VALUE key, res, *rv = ctx->rv;

    if (resp->v.v0.key) {
        key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
        ctx->exception = cb_check_error(error, "failed to execute observe request", key);
        if (ctx->exception) {
            cb_gc_protect(bucket, ctx->exception);
        }
        res = rb_class_new_instance(0, NULL, cResult);
        rb_ivar_set(res, id_iv_completed, Qfalse);
        rb_ivar_set(res, id_iv_error, ctx->exception);
        rb_ivar_set(res, id_iv_operation, sym_observe);
        rb_ivar_set(res, id_iv_key, key);
        rb_ivar_set(res, id_iv_cas, ULL2NUM(resp->v.v0.cas));
        rb_ivar_set(res, id_iv_from_master, resp->v.v0.from_master ? Qtrue : Qfalse);
        rb_ivar_set(res, id_iv_time_to_persist, ULONG2NUM(resp->v.v0.ttp));
        rb_ivar_set(res, id_iv_time_to_replicate, ULONG2NUM(resp->v.v0.ttr));
        switch (resp->v.v0.status) {
            case LCB_OBSERVE_FOUND:
                rb_ivar_set(res, id_iv_status, sym_found);
                break;
            case LCB_OBSERVE_PERSISTED:
                rb_ivar_set(res, id_iv_status, sym_persisted);
                break;
            case LCB_OBSERVE_NOT_FOUND:
                rb_ivar_set(res, id_iv_status, sym_not_found);
                break;
            default:
                rb_ivar_set(res, id_iv_status, Qnil);
        }
        if (bucket->async) { /* asynchronous */
            if (ctx->proc != Qnil) {
                cb_proc_call(ctx->proc, 1, res);
            }
        } else {             /* synchronous */
            if (NIL_P(ctx->exception)) {
                VALUE stats = rb_hash_aref(*rv, key);
                if (NIL_P(stats)) {
                    stats = rb_ary_new();
                    rb_hash_aset(*rv, key, stats);
                }
                rb_ary_push(stats, res);
            }
        }
    } else {
        if (bucket->async && ctx->proc != Qnil) {
            res = rb_class_new_instance(0, NULL, cResult);
            rb_ivar_set(res, id_iv_completed, Qtrue);
            cb_proc_call(ctx->proc, 1, res);
        }
        ctx->nqueries--;
        cb_gc_unprotect(bucket, ctx->proc);
    }
    (void)handle;
}
    void
arithmetic_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_arithmetic_resp_t *resp)
{
    struct context_st *ctx = (struct context_st *)cookie;
    struct bucket_st *bucket = ctx->bucket;
    VALUE cas, key, val, *rv = ctx->rv, exc, res;
    ID o;

    ctx->nqueries--;
    key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
    strip_key_prefix(bucket, key);

    cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil;
    o = ctx->arith > 0 ? sym_increment : sym_decrement;
    exc = cb_check_error(error, "failed to perform arithmetic operation", key);
    if (exc != Qnil) {
        rb_ivar_set(exc, id_iv_cas, cas);
        rb_ivar_set(exc, id_iv_operation, o);
        if (bucket->async) {
            if (bucket->on_error_proc != Qnil) {
                cb_proc_call(bucket->on_error_proc, 3, o, key, exc);
            } else {
                if (NIL_P(bucket->exception)) {
                    bucket->exception = exc;
                }
            }
        }
        if (NIL_P(ctx->exception)) {
            ctx->exception = cb_gc_protect(bucket, exc);
        }
    }
    val = ULL2NUM(resp->v.v0.value);
    if (bucket->async) {    /* asynchronous */
        if (ctx->proc != Qnil) {
            res = rb_class_new_instance(0, NULL, cResult);
            rb_ivar_set(res, id_iv_error, exc);
            rb_ivar_set(res, id_iv_operation, o);
            rb_ivar_set(res, id_iv_key, key);
            rb_ivar_set(res, id_iv_value, val);
            rb_ivar_set(res, id_iv_cas, cas);
            cb_proc_call(ctx->proc, 1, res);
        }
    } else {                /* synchronous */
        if (NIL_P(exc)) {
            if (ctx->extended) {
                rb_hash_aset(*rv, key, rb_ary_new3(2, val, cas));
            } else {
                rb_hash_aset(*rv, key, val);
            }
        }
    }
    if (ctx->nqueries == 0) {
        cb_gc_unprotect(bucket, ctx->proc);
    }
    (void)handle;
}
void
cb_http_complete_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE key, val, res, exc;
    lcb_http_status_t status;

    ctx->request->completed = 1;

    if (bucket->destroying) {
        cb_context_free(ctx);
        return;
    }

    key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
    val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
    exc = ctx->exception;
    if (!RTEST(exc)) {
        exc = cb_check_error_with_status(error, "failed to execute HTTP request", key, resp->v.v0.status);
        if (exc != Qnil && val != Qnil) {
            rb_ivar_set(exc, cb_id_iv_body, val);
        }
    }
    if (RTEST(exc)) {
        if (rb_obj_is_kind_of(exc, cb_eHTTPError)) {
            rb_funcall(exc, cb_id_parse_body_bang, 0);
        }
        ctx->exception = exc;
    }
    status = resp->v.v0.status;
    if (resp->v.v0.headers) {
        cb_build_headers(ctx, resp->v.v0.headers);
        ctx->headers_val = Qnil;
    }
    if (ctx->extended) {
        res = rb_class_new_instance(0, NULL, cb_cResult);
        rb_ivar_set(res, cb_id_iv_error, ctx->exception);
        rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
        rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
        rb_ivar_set(res, cb_id_iv_key, key);
        rb_ivar_set(res, cb_id_iv_value, val);
        rb_ivar_set(res, cb_id_iv_completed, Qtrue);
        rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
    } else {
        res = val;
    }
    if (ctx->proc != Qnil) {
        cb_proc_call(bucket, ctx->proc, 1, res);
        ctx->proc = Qnil;
    }
    if (!bucket->async && ctx->exception == Qnil) {
        ctx->rv = res;
    }
    if (bucket->async) {
        cb_context_free(ctx);
    }
    (void)handle;
    (void)request;
}
    void
http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp)
{
    struct context_st *ctx = (struct context_st *)cookie;
    struct bucket_st *bucket = ctx->bucket;
    VALUE key, val, res;

    key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
    ctx->exception = cb_check_error_with_status(error,
            "failed to execute HTTP request", key, resp->v.v0.status);
    val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
    if (ctx->exception != Qnil) {
        cb_gc_protect(bucket, ctx->exception);
        lcb_cancel_http_request(bucket->handle, request);
    }
    if (resp->v.v0.headers) {
        cb_build_headers(ctx, resp->v.v0.headers);
    }
    if (ctx->proc != Qnil) {
        if (ctx->extended) {
            res = rb_class_new_instance(0, NULL, cResult);
            rb_ivar_set(res, id_iv_error, ctx->exception);
            rb_ivar_set(res, id_iv_operation, sym_http_request);
            rb_ivar_set(res, id_iv_key, key);
            rb_ivar_set(res, id_iv_value, val);
            rb_ivar_set(res, id_iv_completed, Qfalse);
            rb_ivar_set(res, id_iv_headers, ctx->headers_val);
        } else {
            res = val;
        }
        cb_proc_call(ctx->proc, 1, res);
    }
    (void)handle;
}
Exemple #5
0
    void
cb_storage_callback(lcb_t handle, const void *cookie, lcb_storage_t operation,
        lcb_error_t error, const lcb_store_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE key, cas, exc, res;

    key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
    cb_strip_key_prefix(bucket, key);

    cas = resp->v.v0.cas > 0 ? ULL2NUM(resp->v.v0.cas) : Qnil;
    ctx->operation = storage_opcode_to_sym(operation);
    exc = cb_check_error(error, "failed to store value", key);
    if (exc != Qnil) {
        rb_ivar_set(exc, cb_id_iv_cas, cas);
        rb_ivar_set(exc, cb_id_iv_operation, ctx->operation);
        ctx->exception = exc;
    }

    if (bucket->async) { /* asynchronous */
        if (RTEST(ctx->observe_options)) {
            VALUE args[2]; /* it's ok to pass pointer to stack struct here */
            args[0] = rb_hash_new();
            rb_hash_aset(args[0], key, cas);
            args[1] = ctx->observe_options;
            rb_block_call(bucket->self, cb_id_observe_and_wait, 2, args,
                    storage_observe_callback, (VALUE)ctx);
            ctx->observe_options = Qnil;
        } else if (ctx->proc != Qnil) {
            res = rb_class_new_instance(0, NULL, cb_cResult);
            rb_ivar_set(res, cb_id_iv_error, exc);
            rb_ivar_set(res, cb_id_iv_key, key);
            rb_ivar_set(res, cb_id_iv_operation, ctx->operation);
            rb_ivar_set(res, cb_id_iv_cas, cas);
            cb_proc_call(bucket, ctx->proc, 1, res);
        }
    } else {             /* synchronous */
        rb_hash_aset(ctx->rv, key, cas);
    }

    if (!RTEST(ctx->observe_options)) {
        ctx->nqueries--;
        if (ctx->nqueries == 0) {
            ctx->proc = Qnil;
            if (bucket->async) {
                cb_context_free(ctx);
            }
        }
    }
    (void)handle;
}
void
cb_http_data_callback(lcb_http_request_t request, lcb_t handle, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE key, val, res;
    lcb_http_status_t status;

    key = STR_NEW((const char*)resp->v.v0.path, resp->v.v0.npath);
    val = resp->v.v0.nbytes ? STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes) : Qnil;
    status = resp->v.v0.status;
    if (NIL_P(ctx->exception)) {
        ctx->exception = cb_check_error_with_status(error,
                         "failed to execute HTTP request", key, resp->v.v0.status);
        if (ctx->exception != Qnil) {
            VALUE body_str = rb_ivar_get(ctx->exception, cb_id_iv_body);
            if (NIL_P(body_str)) {
                rb_ivar_set(ctx->exception, cb_id_iv_body, val);
            } else {
                rb_str_concat(body_str, val);
            }
            return;
        }
    }
    if (resp->v.v0.headers) {
        cb_build_headers(ctx, resp->v.v0.headers);
    }
    if (ctx->proc != Qnil) {
        if (ctx->extended) {
            res = rb_class_new_instance(0, NULL, cb_cResult);
            rb_ivar_set(res, cb_id_iv_error, Qnil);
            rb_ivar_set(res, cb_id_iv_status, status ? INT2FIX(status) : Qnil);
            rb_ivar_set(res, cb_id_iv_operation, cb_sym_http_request);
            rb_ivar_set(res, cb_id_iv_key, key);
            rb_ivar_set(res, cb_id_iv_value, val);
            rb_ivar_set(res, cb_id_iv_completed, Qfalse);
            rb_ivar_set(res, cb_id_iv_headers, ctx->headers_val);
        } else {
            res = val;
        }
        cb_proc_call(bucket, ctx->proc, 1, res);
    }
    (void)handle;
}
    void
cb_version_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_server_version_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE node, val, exc, res;

    node = resp->v.v0.server_endpoint ? STR_NEW_CSTR(resp->v.v0.server_endpoint) : Qnil;
    exc = cb_check_error(error, "failed to get version", node);
    if (exc != Qnil) {
        rb_ivar_set(exc, cb_id_iv_operation, cb_sym_version);
        ctx->exception = exc;
    }

    if (node != Qnil) {
        val = STR_NEW((const char*)resp->v.v0.vstring, resp->v.v0.nvstring);
        if (bucket->async) {    /* asynchronous */
            if (ctx->proc != Qnil) {
                res = rb_class_new_instance(0, NULL, cb_cResult);
                rb_ivar_set(res, cb_id_iv_error, exc);
                rb_ivar_set(res, cb_id_iv_operation, cb_sym_version);
                rb_ivar_set(res, cb_id_iv_node, node);
                rb_ivar_set(res, cb_id_iv_value, val);
                cb_proc_call(bucket, ctx->proc, 1, res);
            }
        } else {                /* synchronous */
            if (NIL_P(exc)) {
                rb_hash_aset(ctx->rv, node, val);
            }
        }
    } else {
        ctx->nqueries--;
        ctx->proc = Qnil;
        if (bucket->async) {
            cb_context_free(ctx);
        }
    }

    (void)handle;
}
Exemple #8
0
    static VALUE
storage_observe_callback(VALUE args, VALUE cookie)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE res = rb_ary_shift(args);

    if (ctx->proc != Qnil) {
        rb_ivar_set(res, cb_id_iv_operation, ctx->operation);
        cb_proc_call(bucket, ctx->proc, 1, res);
    }
    if (!RTEST(ctx->observe_options)) {
        ctx->nqueries--;
        if (ctx->nqueries == 0) {
            ctx->proc = Qnil;
            if (bucket->async) {
                cb_context_free(ctx);
            }
        }
    }
    return Qnil;
}
    void
cb_unlock_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_unlock_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE key, exc = Qnil, res;

    ctx->nqueries--;
    key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
    cb_strip_key_prefix(bucket, key);

    if (error != LCB_KEY_ENOENT || !ctx->quiet) {
        exc = cb_check_error(error, "failed to unlock value", key);
        if (exc != Qnil) {
            rb_ivar_set(exc, cb_id_iv_operation, cb_sym_unlock);
            ctx->exception = exc;
        }
    }

    if (bucket->async) {    /* asynchronous */
        if (ctx->proc != Qnil) {
            res = rb_class_new_instance(0, NULL, cb_cResult);
            rb_ivar_set(res, cb_id_iv_error, exc);
            rb_ivar_set(res, cb_id_iv_operation, cb_sym_unlock);
            rb_ivar_set(res, cb_id_iv_key, key);
            cb_proc_call(bucket, ctx->proc, 1, res);
        }
    } else {                /* synchronous */
        rb_hash_aset(ctx->rv, key, (error == LCB_SUCCESS) ? Qtrue : Qfalse);
    }
    if (ctx->nqueries == 0) {
        ctx->proc = Qnil;
        if (bucket->async) {
            cb_context_free(ctx);
        }
    }
    (void)handle;
}
Exemple #10
0
    void
cb_get_callback(lcb_t handle, const void *cookie, lcb_error_t error, const lcb_get_resp_t *resp)
{
    struct cb_context_st *ctx = (struct cb_context_st *)cookie;
    struct cb_bucket_st *bucket = ctx->bucket;
    VALUE key, val, flags, cas, exc = Qnil, res, raw;

    ctx->nqueries--;
    key = STR_NEW((const char*)resp->v.v0.key, resp->v.v0.nkey);
    cb_strip_key_prefix(bucket, key);

    if (error != LCB_KEY_ENOENT || !ctx->quiet) {
        exc = cb_check_error(error, "failed to get value", key);
        if (exc != Qnil) {
            rb_ivar_set(exc, cb_id_iv_operation, cb_sym_get);
            ctx->exception = exc;
        }
    }

    flags = ULONG2NUM(resp->v.v0.flags);
    cas = ULL2NUM(resp->v.v0.cas);
    raw = STR_NEW((const char*)resp->v.v0.bytes, resp->v.v0.nbytes);
    val = cb_decode_value(ctx->transcoder, raw, resp->v.v0.flags, ctx->transcoder_opts);
    if (rb_obj_is_kind_of(val, rb_eStandardError)) {
        VALUE exc_str = rb_funcall(val, cb_id_to_s, 0);
        VALUE msg = rb_funcall(rb_mKernel, cb_id_sprintf, 3,
                rb_str_new2("unable to convert value for key \"%s\": %s"), key, exc_str);
        ctx->exception = rb_exc_new3(cb_eValueFormatError, msg);
        rb_ivar_set(ctx->exception, cb_id_iv_operation, cb_sym_get);
        rb_ivar_set(ctx->exception, cb_id_iv_key, key);
        rb_ivar_set(ctx->exception, cb_id_iv_inner_exception, val);
        val = Qnil;
    }
    if (bucket->async) { /* asynchronous */
        if (ctx->proc != Qnil) {
            res = rb_class_new_instance(0, NULL, cb_cResult);
            rb_ivar_set(res, cb_id_iv_error, exc);
            rb_ivar_set(res, cb_id_iv_operation, cb_sym_get);
            rb_ivar_set(res, cb_id_iv_key, key);
            rb_ivar_set(res, cb_id_iv_value, val);
            rb_ivar_set(res, cb_id_iv_flags, flags);
            rb_ivar_set(res, cb_id_iv_cas, cas);
            cb_proc_call(bucket, ctx->proc, 1, res);
        }
    } else {                /* synchronous */
        if (NIL_P(exc) && error != LCB_KEY_ENOENT) {
            if (ctx->extended) {
                val = rb_ary_new3(3, val, flags, cas);
            }
            if (ctx->all_replicas) {
                VALUE ary = rb_hash_aref(ctx->rv, key);
                if (NIL_P(ary)) {
                    ary = rb_ary_new();
                    rb_hash_aset(ctx->rv, key, ary);
                }
                rb_ary_push(ary, val);
            } else {
                rb_hash_aset(ctx->rv, key, val);
            }
        }
    }

    if (ctx->nqueries == 0) {
        ctx->proc = Qnil;
        if (bucket->async) {
            cb_context_free(ctx);
        }
    }
    (void)handle;
}
    static VALUE
trigger_timer(VALUE timer)
{
    struct timer_st *tm = DATA_PTR(timer);
    return cb_proc_call(tm->callback, 1, timer);
}