LIBCOUCHBASE_API lcb_error_t lcb_get(lcb_t instance, const void *command_cookie, lcb_size_t num, const lcb_get_cmd_t *const *items) { unsigned ii; lcb_sched_enter(instance); for (ii = 0; ii < num; ii++) { const lcb_get_cmd_t *src = items[ii]; lcb_CMDGET dst; lcb_error_t err; memset(&dst, 0, sizeof(dst)); dst.key.contig.bytes = src->v.v0.key; dst.key.contig.nbytes = src->v.v0.nkey; dst._hashkey.contig.bytes = src->v.v0.hashkey; dst._hashkey.contig.nbytes = src->v.v0.nhashkey; dst.lock = src->v.v0.lock; dst.exptime = src->v.v0.exptime; err = lcb_get3(instance, command_cookie, &dst); if (err != LCB_SUCCESS) { lcb_sched_fail(instance); return err; } } lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) }
LIBCOUCHBASE_API lcb_error_t lcb_store(lcb_t instance, const void *cookie, lcb_size_t num, const lcb_store_cmd_t * const * items) { unsigned ii; lcb_error_t err = LCB_SUCCESS; lcb_sched_enter(instance); for (ii = 0; ii < num; ii++) { const lcb_store_cmd_t *src = items[ii]; lcb_CMDSTORE dst; memset(&dst, 0, sizeof(dst)); dst.key.contig.bytes = src->v.v0.key; dst.key.contig.nbytes = src->v.v0.nkey; dst._hashkey.contig.bytes = src->v.v0.hashkey; dst._hashkey.contig.nbytes = src->v.v0.nhashkey; dst.value.u_buf.contig.bytes = src->v.v0.bytes; dst.value.u_buf.contig.nbytes = src->v.v0.nbytes; dst.operation = src->v.v0.operation; dst.flags = src->v.v0.flags; dst.datatype = src->v.v0.datatype; dst.cas = src->v.v0.cas; dst.exptime = src->v.v0.exptime; err = lcb_store3(instance, cookie, &dst); if (err != LCB_SUCCESS) { lcb_sched_fail(instance); return err; } } lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) }
LIBCOUCHBASE_API lcb_error_t lcb_get_replica(lcb_t instance, const void *cookie, lcb_size_t num, const lcb_get_replica_cmd_t * const * items) { unsigned ii; lcb_error_t err = LCB_SUCCESS; lcb_sched_enter(instance); for (ii = 0; ii < num; ii++) { const lcb_get_replica_cmd_t *src = items[ii]; lcb_CMDGETREPLICA dst; memset(&dst, 0, sizeof(dst)); dst.key.contig.bytes = src->v.v1.key; dst.key.contig.nbytes = src->v.v1.nkey; dst._hashkey.contig.bytes = src->v.v1.hashkey; dst._hashkey.contig.nbytes = src->v.v1.nhashkey; dst.strategy = src->v.v1.strategy; dst.index = src->v.v1.index; err = lcb_rget3(instance, cookie, &dst); if (err != LCB_SUCCESS) { break; } } if (err == LCB_SUCCESS) { lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) } else {
LIBCOUCHBASE_API lcb_error_t lcb_unlock(lcb_t instance, const void *cookie, lcb_size_t num, const lcb_unlock_cmd_t * const * items) { unsigned ii; lcb_error_t err = LCB_SUCCESS; lcb_sched_enter(instance); for (ii = 0; ii < num; ii++) { const lcb_unlock_cmd_t *src = items[ii]; lcb_CMDUNLOCK dst; memset(&dst, 0, sizeof(dst)); dst.key.contig.bytes = src->v.v0.key; dst.key.contig.nbytes = src->v.v0.nkey; dst._hashkey.contig.bytes = src->v.v0.hashkey; dst._hashkey.contig.nbytes = src->v.v0.nhashkey; dst.cas = src->v.v0.cas; err = lcb_unlock3(instance, cookie, &dst); if (err != LCB_SUCCESS) { break; } } if (err != LCB_SUCCESS) { lcb_sched_fail(instance); return err; } else { lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) } }
static int chain_endure(PLCB_t *obj, AV *resobj, const lcb_RESPSTORE *resp) { lcb_MULTICMD_CTX *mctx = NULL; lcb_CMDENDURE dcmd = { 0 }; lcb_durability_opts_t dopts = { 0 }; char persist_to = 0, replicate_to = 0; lcb_error_t err = LCB_SUCCESS; SV *optsv; optsv = *av_fetch(resobj, PLCB_RETIDX_OPTIONS, 1); if (!SvIOK(optsv)) { return 0; } PLCB_GETDURABILITY(SvUVX(optsv), persist_to, replicate_to); if (persist_to == 0 && replicate_to == 0) { return 0; } if (persist_to < 0 || replicate_to < 0) { dopts.v.v0.cap_max = 1; } dopts.v.v0.persist_to = persist_to; dopts.v.v0.replicate_to = replicate_to; LCB_CMD_SET_KEY(&dcmd, resp->key, resp->nkey); dcmd.cas = resp->cas; mctx = lcb_endure3_ctxnew(obj->instance, &dopts, &err); if (mctx == NULL) { plcb_doc_set_err(obj, resobj, err); return 0; } err = mctx->addcmd(mctx, (lcb_CMDBASE *)&dcmd); if (err != LCB_SUCCESS) { mctx->fail(mctx); return 0; } lcb_sched_enter(obj->instance); err = mctx->done(mctx, resp->cookie); if (err != LCB_SUCCESS) { plcb_doc_set_err(obj, resobj, err); return 0; } lcb_sched_leave(obj->instance); return 1; }
LIBCOUCHBASE_API lcb_error_t lcb_durability_poll(lcb_t instance, const void *cookie, const lcb_durability_opts_t *options, lcb_size_t ncmds, const lcb_durability_cmd_t *const *cmds) { lcb_MULTICMD_CTX *mctx; unsigned ii; lcb_error_t err; if (ncmds == 0) { return LCB_EINVAL; } mctx = lcb_endure3_ctxnew(instance, options, &err); if (!mctx) { return err; } for (ii = 0; ii < ncmds; ii++) { lcb_CMDENDURE cmd = { 0 }; const lcb_DURABILITYCMDv0 *src = &cmds[ii]->v.v0; cmd.key.contig.bytes = src->key; cmd.key.contig.nbytes = src->nkey; cmd._hashkey.contig.bytes = src->hashkey; cmd._hashkey.contig.nbytes = src->nhashkey; cmd.cas = src->cas; err = mctx->addcmd(mctx, (lcb_CMDBASE*)&cmd); if (err != LCB_SUCCESS) { mctx->fail(mctx); return err; } } lcb_sched_enter(instance); err = mctx->done(mctx, cookie); if (err != LCB_SUCCESS) { lcb_sched_fail(instance); return err; } else { lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) } }
LIBCOUCHBASE_API lcb_error_t lcb_observe(lcb_t instance, const void *command_cookie, lcb_size_t num, const lcb_observe_cmd_t *const *items) { unsigned ii; lcb_error_t err; lcb_MULTICMD_CTX *mctx; lcb_sched_enter(instance); mctx = lcb_observe3_ctxnew(instance); if (mctx == NULL) { return LCB_CLIENT_ENOMEM; } for (ii = 0; ii < num; ii++) { lcb_CMDOBSERVE cmd = { 0 }; const lcb_observe_cmd_t *src = items[ii]; if (src->version == 1 && (src->v.v1.options & LCB_OBSERVE_MASTER_ONLY)) { cmd.cmdflags |= LCB_CMDOBSERVE_F_MASTER_ONLY; } LCB_KREQ_SIMPLE(&cmd.key, src->v.v0.key, src->v.v0.nkey); LCB_KREQ_SIMPLE(&cmd._hashkey, src->v.v0.hashkey, src->v.v0.nhashkey); err = mctx->addcmd(mctx, (lcb_CMDBASE *)&cmd); if (err != LCB_SUCCESS) { mctx->fail(mctx); return err; } } lcb_sched_enter(instance); mctx->done(mctx, command_cookie); lcb_sched_leave(instance); SYNCMODE_INTERCEPT(instance) }
static void dur_chain2(pycbc_Bucket *conn, pycbc_MultiResult *mres, pycbc_OperationResult *res, int cbtype, const lcb_RESPBASE *resp) { lcb_error_t err; lcb_durability_opts_t dopts = { 0 }; lcb_CMDENDURE cmd = { 0 }; lcb_MULTICMD_CTX *mctx = NULL; int is_delete = cbtype == LCB_CALLBACK_REMOVE; res->rc = resp->rc; if (resp->rc == LCB_SUCCESS) { const lcb_MUTATION_TOKEN *mutinfo = lcb_resp_get_mutation_token(cbtype, resp); Py_XDECREF(res->mutinfo); if (mutinfo && LCB_MUTATION_TOKEN_ISVALID(mutinfo)) { /* Create the mutation token tuple: (vb,uuid,seqno) */ res->mutinfo = Py_BuildValue("HKKO", LCB_MUTATION_TOKEN_VB(mutinfo), LCB_MUTATION_TOKEN_ID(mutinfo), LCB_MUTATION_TOKEN_SEQ(mutinfo), conn->bucket); } else { Py_INCREF(Py_None); res->mutinfo = Py_None; } res->cas = resp->cas; } /** For remove, we check quiet */ maybe_push_operr(mres, (pycbc_Result*)res, resp->rc, is_delete ? 1 : 0); if ((mres->mropts & PYCBC_MRES_F_DURABILITY) == 0 || resp->rc != LCB_SUCCESS) { operation_completed(conn, mres); CB_THR_BEGIN(conn); return; } if (conn->dur_testhook && conn->dur_testhook != Py_None) { invoke_endure_test_notification(conn, (pycbc_Result *)res); } /** Setup global options */ dopts.v.v0.persist_to = mres->dur.persist_to; dopts.v.v0.replicate_to = mres->dur.replicate_to; dopts.v.v0.timeout = conn->dur_timeout; dopts.v.v0.check_delete = is_delete; if (mres->dur.persist_to < 0 || mres->dur.replicate_to < 0) { dopts.v.v0.cap_max = 1; } lcb_sched_enter(conn->instance); mctx = lcb_endure3_ctxnew(conn->instance, &dopts, &err); if (mctx == NULL) { goto GT_DONE; } cmd.cas = resp->cas; LCB_CMD_SET_KEY(&cmd, resp->key, resp->nkey); err = mctx->addcmd(mctx, (lcb_CMDBASE*)&cmd); if (err != LCB_SUCCESS) { goto GT_DONE; } err = mctx->done(mctx, mres); if (err == LCB_SUCCESS) { mctx = NULL; lcb_sched_leave(conn->instance); } GT_DONE: if (mctx) { mctx->fail(mctx); } if (err != LCB_SUCCESS) { res->rc = err; maybe_push_operr(mres, (pycbc_Result*)res, err, 0); operation_completed(conn, mres); } CB_THR_BEGIN(conn); }
/** Observe stuff */ static void handle_dur_storecb(mc_PIPELINE *pl, mc_PACKET *pkt, lcb_error_t err, const void *arg) { lcb_RESPCALLBACK cb; lcb_RESPSTOREDUR resp = { 0 }; lcb_CMDENDURE dcmd = { 0 }; DURSTORECTX *dctx = (DURSTORECTX *)pkt->u_rdata.exdata; lcb_MULTICMD_CTX *mctx; lcb_durability_opts_t opts = { 0 }; const lcb_RESPSTORE *sresp = (const lcb_RESPSTORE *)arg; if (err != LCB_SUCCESS) { goto GT_BAIL; } if (sresp->rc != LCB_SUCCESS) { err = sresp->rc; goto GT_BAIL; } resp.store_ok = 1; LCB_CMD_SET_KEY(&dcmd, sresp->key, sresp->nkey); dcmd.cas = sresp->cas; if (LCB_SYNCTOKEN_ISVALID(&sresp->synctoken)) { dcmd.synctoken = &sresp->synctoken; } /* Set the options.. */ opts.v.v0.persist_to = dctx->persist_to; opts.v.v0.replicate_to = dctx->replicate_to; mctx = lcb_endure3_ctxnew(dctx->instance, &opts, &err); if (mctx == NULL) { goto GT_BAIL; } lcbdurctx_set_durstore(mctx, 1); err = mctx->addcmd(mctx, (lcb_CMDBASE*)&dcmd); if (err != LCB_SUCCESS) { mctx->fail(mctx); goto GT_BAIL; } lcb_sched_enter(dctx->instance); err = mctx->done(mctx, sresp->cookie); lcb_sched_leave(dctx->instance); if (err == LCB_SUCCESS) { /* Everything OK? */ free(dctx); return; } GT_BAIL: { lcb_RESPENDURE dresp = { 0 }; resp.key = sresp->key; resp.nkey = sresp->nkey; resp.cookie = sresp->cookie; resp.rc = err; resp.dur_resp = &dresp; cb = lcb_find_callback(dctx->instance, LCB_CALLBACK_STOREDUR); cb(dctx->instance, LCB_CALLBACK_STOREDUR, (const lcb_RESPBASE*)&resp); free(dctx); } (void)pl; }
/** * Schedules a single sweep of observe requests. */ static void poll_once(lcb_DURSET *dset) { unsigned ii, n_added = 0; lcb_error_t err; lcb_MULTICMD_CTX *mctx = NULL; /** * We should never be called while an 'iter' operation is still * in progress */ lcb_assert(dset->waiting == 0); dset_ref(dset); mctx = lcb_observe_ctx_dur_new(dset->instance); if (!mctx) { err = LCB_CLIENT_ENOMEM; goto GT_ERR; } for (ii = 0; ii < dset->nentries; ii++) { lcb_CMDOBSERVE cmd = { 0 }; struct lcb_durability_entry_st *ent = dset->entries + ii; if (ent->done) { continue; } /* reset all the per-iteration fields */ RESFLD(ent, persisted_master) = 0; RESFLD(ent, exists_master) = 0; RESFLD(ent, npersisted) = 0; RESFLD(ent, nreplicated) = 0; RESFLD(ent, cas) = 0; RESFLD(ent, rc) = LCB_SUCCESS; LCB_KREQ_SIMPLE(&cmd.key, RESFLD(ent, key), RESFLD(ent, nkey)); cmd.hashkey = ent->hashkey; err = mctx->addcmd(mctx, (lcb_CMDBASE *)&cmd); if (err != LCB_SUCCESS) { goto GT_ERR; } n_added ++; } lcb_assert(n_added == dset->nremaining); if (n_added) { lcb_sched_enter(dset->instance); mctx->done(mctx, dset); lcb_sched_leave(dset->instance); } GT_ERR: if (err != LCB_SUCCESS) { if (mctx) { mctx->fail(mctx); } for (ii = 0; ii < dset->nentries; ii++) { lcb_DURITEM *ent = dset->entries + ii; if (ent->done) { continue; } RESFLD(ent, rc) = err; ent_set_resdone(ent); } } else { dset->waiting = 1; dset_ref(dset); } if (dset->waiting && n_added) { lcb_uint32_t us_now = (lcb_uint32_t)(gethrtime() / 1000); lcb_uint32_t us_tmo; if (dset->us_timeout > us_now) { us_tmo = dset->us_timeout - us_now; } else { us_tmo = 1; } timer_schedule(dset, us_tmo, STATE_TIMEOUT); } else { purge_entries(dset, LCB_ERROR); } dset_unref(dset); }