static void
bootstrap_callback(lcb_t instance, lcb_error_t status)
{
    dSP;
    PLCB_t *obj = (PLCB_t*) lcb_get_cookie(instance);
    if (!obj->async) {
        return;
    }
    if (!obj->conncb) {
        warn("Object %p does not have a connect callback!", obj);
        return;
    }
    printf("Invoking callback for connect..!\n");

    ENTER;SAVETMPS;PUSHMARK(SP);

    XPUSHs(sv_2mortal(newRV_inc(obj->selfobj)));
    XPUSHs(sv_2mortal(newSViv(status)));
    PUTBACK;

    call_sv(obj->conncb, G_DISCARD);
    SPAGAIN;
    FREETMPS;LEAVE;
    SvREFCNT_dec(obj->conncb); obj->conncb = NULL;
}
예제 #2
0
static void
end_global_callback(lcb_t instance, pycbc_Bucket *self)
{
    Py_DECREF((PyObject *)(self));

    self = (pycbc_Bucket *)lcb_get_cookie(instance);
    if (self) {
        CB_THR_BEGIN(self);
    }
}
예제 #3
0
static int
start_global_callback(lcb_t instance, pycbc_Bucket **selfptr)
{
    *selfptr = (pycbc_Bucket *)lcb_get_cookie(instance);
    if (!*selfptr) {
        return 0;
    }
    CB_THR_END(*selfptr);
    Py_INCREF((PyObject *)*selfptr);
    return 1;
}
예제 #4
0
static void
error_callback(lcb_t instance, lcb_error_t err, const char *msg)
{
    PyObject *errtuple;
    PyObject *result;
    pycbc_Connection *self = (pycbc_Connection*) lcb_get_cookie(instance);

    CB_THR_END(self);

    pycbc_assert(self->errors);
    errtuple = Py_BuildValue("(i,s)", err, msg);
    pycbc_assert(errtuple);
    result = PyObject_CallMethod(self->errors, "append", "(O)", errtuple);
    pycbc_assert(result);
    Py_DECREF(errtuple);
    Py_DECREF(result);

    CB_THR_BEGIN(self);
}
/* This callback is only ever called for single operation, single key results */
static void
callback_common(lcb_t instance, int cbtype, const lcb_RESPBASE *resp)
{
    AV *resobj = NULL;
    PLCB_t *parent;
    SV *ctxrv = (SV *)resp->cookie;
    plcb_OPCTX *ctx = NUM2PTR(plcb_OPCTX*, SvIVX(SvRV(ctxrv)));

    if (cbtype == LCB_CALLBACK_STATS || cbtype == LCB_CALLBACK_OBSERVE ||
            cbtype == LCB_CALLBACK_HTTP) {
        HE *tmp;

        hv_iterinit(ctx->docs);
        tmp = hv_iternext(ctx->docs);

        if (tmp && HeVAL(tmp) && SvROK(HeVAL(tmp))) {
            resobj = (AV *)SvRV(HeVAL(tmp));
        }
    } else {
        SV **tmp = hv_fetch(ctx->docs, resp->key, resp->nkey, 0);
        if (tmp && SvROK(*tmp)) {
            resobj = (AV*)SvRV(*tmp);
        }
    }

    if (!resobj) {
        warn("Couldn't find matching object!");
        return;
    }

    parent = (PLCB_t *)lcb_get_cookie(instance);
    plcb_doc_set_err(parent, resobj, resp->rc);

    switch (cbtype) {
    case LCB_CALLBACK_GET: {
        const lcb_RESPGET *gresp = (const lcb_RESPGET *)resp;
        if (resp->rc == LCB_SUCCESS) {
            SV *newval = plcb_convert_retrieval(parent,
                resobj, gresp->value, gresp->nvalue, gresp->itmflags);

            av_store(resobj, PLCB_RETIDX_VALUE, newval);
            plcb_doc_set_cas(parent, resobj, &resp->cas);
        }
        break;
    }

    case LCB_CALLBACK_TOUCH:
    case LCB_CALLBACK_REMOVE:
    case LCB_CALLBACK_UNLOCK:
    case LCB_CALLBACK_STORE:
    case LCB_CALLBACK_ENDURE:
        if (resp->cas && resp->rc == LCB_SUCCESS) {
            plcb_doc_set_cas(parent, resobj, &resp->cas);
        }

        if (cbtype == LCB_CALLBACK_STORE && resp->rc == LCB_SUCCESS &&
                chain_endure(parent, resobj, (const lcb_RESPSTORE *)resp)) {
            return; /* Will be handled already */
        }
        break;

    case LCB_CALLBACK_COUNTER: {
        const lcb_RESPCOUNTER *cresp = (const lcb_RESPCOUNTER*)resp;
        plcb_doc_set_numval(parent, resobj, cresp->value, resp->cas);
        break;
    }

    case LCB_CALLBACK_STATS: {
        const lcb_RESPSTATS *sresp = (const void *)resp;
        if (sresp->server) {
            call_helper(resobj, cbtype, (const lcb_RESPBASE *)sresp);
            return;
        }
        break;
    }
    case LCB_CALLBACK_OBSERVE: {
        const lcb_RESPOBSERVE *oresp = (const lcb_RESPOBSERVE*)resp;
        if (oresp->nkey) {
            call_helper(resobj, cbtype, (const lcb_RESPBASE*)oresp);
            return;
        }
        break;
    }
    case LCB_CALLBACK_HTTP: {
        const lcb_RESPHTTP *htresp = (const lcb_RESPHTTP *)resp;

        /* Store the CAS */
        av_store(resobj, PLCB_HTIDX_STATUS, newSViv(htresp->htstatus));
        if (htresp->headers) {
            const char * const * hdr_cur;
            HV *headers = newHV();
            av_store(resobj, PLCB_HTIDX_HEADERS, newRV_noinc((SV*)headers));

            for (hdr_cur = htresp->headers; *hdr_cur; hdr_cur += 2) {
                const char *hdrkey = hdr_cur[0];
                const char *hdrval = hdr_cur[1];
                SV *valsv = newSVpv(hdrval, 0);
                hv_store(headers, hdrkey, 0, valsv, 0);
            }
        }
        if (htresp->nbody) {
            lcb_U32 fmtflags = PLCB_CF_JSON;
            SV *body;
            SV *fmtspec = *av_fetch(resobj, PLCB_RETIDX_VALUE, 1);

            if (SvIOK(fmtspec)) {
                fmtflags = SvUV(fmtspec);
            }

            body = plcb_convert_retrieval_ex(parent, resobj,
                htresp->body, htresp->nbody, fmtflags,
                PLCB_CONVERT_NOCUSTOM);

            av_store(resobj, PLCB_RETIDX_VALUE, body);
        }
        break;
    }

    default:
        abort();
        break;
    }

    ctx->nremaining--;

    if (parent->async) {
        call_async(ctx, resobj);
    } else if (ctx->flags & PLCB_OPCTXf_WAITONE) {
        av_push(ctx->u.ctxqueue, newRV_inc( (SV* )resobj));
        plcb_kv_waitdone(parent);
    }

    if (!ctx->nremaining) {
        SvREFCNT_dec(ctxrv);
        plcb_kv_waitdone(parent);
        plcb_opctx_clear(parent);
    }
}