Ejemplo n.º 1
0
 static naming::id_type call(naming::id_type const& targetgid,
     naming::id_type const& initial)
 {
     // The following get yields control while the action above
     // is executed and the result is returned to the future
     return call_async(targetgid, initial).get();
 }
/* 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);
    }
}