Example #1
0
LIBCOUCHBASE_API
lcb_error_t lcb_create_libev_io_opts(int version, lcb_io_opt_t *io, void *arg)
{
    struct ev_loop *loop = arg;
    struct lcb_io_opt_st *ret;
    struct libev_cookie *cookie;
    if (version != 0) {
        return LCB_PLUGIN_VERSION_MISMATCH;
    }
    ret = calloc(1, sizeof(*ret));
    cookie = calloc(1, sizeof(*cookie));
    if (ret == NULL || cookie == NULL) {
        free(ret);
        free(cookie);
        return LCB_CLIENT_ENOMEM;
    }

    /* setup io iops! */
    ret->version = 0;
    ret->dlhandle = NULL;
    ret->destructor = lcb_destroy_io_opts;
    /* consider that struct isn't allocated by the library,
     * `need_cleanup' flag might be set in lcb_create() */
    ret->v.v0.need_cleanup = 0;
    ret->v.v0.delete_event = lcb_io_delete_event;
    ret->v.v0.destroy_event = lcb_io_destroy_event;
    ret->v.v0.create_event = lcb_io_create_event;
    ret->v.v0.update_event = lcb_io_update_event;

    ret->v.v0.delete_timer = lcb_io_delete_timer;
    ret->v.v0.destroy_timer = lcb_io_destroy_timer;
    ret->v.v0.create_timer = lcb_io_create_event;
    ret->v.v0.update_timer = lcb_io_update_timer;

    ret->v.v0.run_event_loop = lcb_io_run_event_loop;
    ret->v.v0.stop_event_loop = lcb_io_stop_event_loop;

    wire_lcb_bsd_impl(ret);

    if (loop == NULL) {
        if ((cookie->loop = ev_loop_new(EVFLAG_AUTO | EVFLAG_NOENV)) == NULL) {
            free(ret);
            free(cookie);
            return LCB_CLIENT_ENOMEM;
        }
        cookie->allocated = 1;
    } else {
        cookie->loop = loop;
        cookie->allocated = 0;
    }
    cookie->suspended = 1;
    ret->v.v0.cookie = cookie;

    *io = ret;
    return LCB_SUCCESS;
}
Example #2
0
LIBCOUCHBASE_API
lcb_error_t lcb_create_io_ops(lcb_io_opt_t *io,
                              const struct lcb_create_io_ops_st *io_opts)
{

    struct lcb_create_io_ops_st options;
    lcb_error_t err;
    plugin_info pi;
    memset(&options, 0, sizeof(options));

    err = lcb_initialize_socket_subsystem();
    if (err != LCB_SUCCESS) {
        return err;
    }

    err = generate_options(&pi, io_opts, &options, NULL);
    if (err != LCB_SUCCESS) {
        return err;
    }

    if (options.version == 1) {
        err = create_v1(io, &options);
    } else if (options.version == 2) {
        err = create_v2(io, &options);
    } else {
        return LCB_NOT_SUPPORTED;
    }

    if (err != LCB_SUCCESS) {
        return err;
    }
    /*XXX:
     * This block of code here because the Ruby SDK relies on undocumented
     * functionality of older versions of libcouchbase in which its send/recv
     * functions assert that the number of IOV elements passed is always going
     * to be 2.
     *
     * This works around the issue by patching the send/recv functions of
     * the ruby implementation at load-time.
     *
     * This block of code will go away once the Ruby SDK is fixed and a released
     * version has been out for enough time that it won't break common existing
     * deployments.
     */
    if (io_opts && io_opts->version == 1 && io_opts->v.v1.symbol != NULL) {
        if (strstr(io_opts->v.v1.symbol, "cb_create_ruby")) {
            wire_lcb_bsd_impl(*io);
        }
    }
    return LCB_SUCCESS;
}
Example #3
0
LIBCOUCHBASE_API
lcb_error_t lcb_create_libevent_io_opts(int version, lcb_io_opt_t *io, void *arg)
{
    struct event_base *base = arg;
    struct lcb_io_opt_st *ret;
    struct libevent_cookie *cookie;
    if (version != 0) {
        return LCB_PLUGIN_VERSION_MISMATCH;
    }

    ret = calloc(1, sizeof(*ret));
    cookie = calloc(1, sizeof(*cookie));
    if (ret == NULL || cookie == NULL) {
        free(ret);
        free(cookie);
        return LCB_CLIENT_ENOMEM;
    }

    /* setup io iops! */
    ret->version = 3;
    ret->dlhandle = NULL;
    ret->destructor = lcb_destroy_io_opts;
    /* consider that struct isn't allocated by the library,
     * `need_cleanup' flag might be set in lcb_create() */
    ret->v.v3.need_cleanup = 0;

    if (base == NULL) {
        if ((cookie->base = event_base_new()) == NULL) {
            free(ret);
            free(cookie);
            return LCB_CLIENT_ENOMEM;
        }
        cookie->allocated = 1;
    } else {
        cookie->base = base;
        cookie->allocated = 0;
    }

    ret->v.v3.cookie = cookie;
    ret->v.v3.get_procs = procs2_lnt_callback;

    /* For back-compat */
    wire_lcb_bsd_impl(ret);

    *io = ret;
    return LCB_SUCCESS;
}
SV *
PLCB_ioprocs_new(SV *options)
{
    plcb_IOPROCS async_s = { NULL }, *async = NULL;
    lcb_io_opt_t cbcio = NULL;
    SV *ptriv, *blessedrv;

    /* First make sure all the options are ok */
    plcb_OPTION argopts[] = {
        #define X(name, t, tgt) PLCB_KWARG(name, t, &async_s.tgt),
        X_IOPROCS_OPTIONS(X)
        #undef X
        { NULL }
    };

    plcb_extract_args(options, argopts);

    /* Verify we have at least the basic functions */
    if (!async_s.cv_evmod) {
        die("Need event_update");
    }
    if (!async_s.cv_timermod) {
        die("Need timer_update");
    }

    if (!async_s.userdata) {
        async_s.userdata = &PL_sv_undef;
    }

    Newxz(cbcio, 1, struct lcb_io_opt_st);
    Newxz(async, 1, plcb_IOPROCS);

    *async = async_s;

    #define X(name, t, tgt) SvREFCNT_inc(async->tgt);
    X_IOPROCS_OPTIONS(X)
    #undef X

    ptriv = newSViv(PTR2IV(async));
    blessedrv = newRV_noinc(ptriv);
    sv_bless(blessedrv, gv_stashpv(PLCB_IOPROCS_CLASS, GV_ADD));

    async->refcount = 1;
    async->iops_ptr = cbcio;
    cbcio->v.v0.cookie = async;

    async->selfrv = newRV_inc(ptriv); sv_rvweaken(async->selfrv);
    async->action_sv = newSViv(0); SvREADONLY_on(async->action_sv);
    async->flags_sv = newSViv(0); SvREADONLY_on(async->flags_sv);
    async->usec_sv = newSVnv(0); SvREADONLY_on(async->usec_sv);
    async->sched_r_sv = newSViv(0); SvREADONLY_on(async->sched_r_sv);
    async->sched_w_sv = newSViv(0); SvREADONLY_on(async->sched_w_sv);
    async->stop_r_sv = newSViv(0); SvREADONLY_on(async->stop_r_sv);
    async->stop_w_sv = newSViv(0); SvREADONLY_on(async->stop_w_sv);

    /* i/o events */
    cbcio->v.v0.create_event = create_event;
    cbcio->v.v0.destroy_event = destroy_event;
    cbcio->v.v0.update_event = update_event;
    cbcio->v.v0.delete_event = delete_event;

    /* timer events */
    cbcio->v.v0.create_timer = create_timer;
    cbcio->v.v0.destroy_timer = destroy_event;
    cbcio->v.v0.delete_timer = delete_timer;
    cbcio->v.v0.update_timer = update_timer;

    wire_lcb_bsd_impl(cbcio);

    cbcio->v.v0.run_event_loop = startstop_dummy;
    cbcio->v.v0.stop_event_loop = startstop_dummy;
    cbcio->v.v0.need_cleanup = 0;

    /* Now all we need to do is return the blessed reference */
    return blessedrv;
}