static void obs_ctxfail(lcb_MULTICMD_CTX *mctx) { OBSERVECTX *ctx = CTX_FROM_MULTI(mctx); destroy_requests(ctx); free(ctx); }
static lcb_error_t dset_ctx_add(lcb_MULTICMD_CTX *mctx, const lcb_CMDBASE *cmd) { lcb_DURSET *dset = CTX_FROM_MULTI(mctx); lcb_DURITEM *ent; int vbid, srvix; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } LCB_SSOBUF_ALLOC(&ent, &dset->entries_, lcb_DURITEM); if (!ent) { return LCB_CLIENT_ENOMEM; } mcreq_map_key(&dset->instance->cmdq, &cmd->key, &cmd->_hashkey, MCREQ_PKT_BASESIZE, &vbid, &srvix); /* ok. now let's initialize the entry..*/ memset(ent, 0, sizeof (*ent)); RESFLD(ent, nkey) = cmd->key.contig.nbytes; ent->reqcas = cmd->cas; ent->parent = dset; ent->vbid = vbid; lcb_string_append(&dset->kvbufs, cmd->key.contig.bytes, cmd->key.contig.nbytes); if (DSET_PROCS(dset)->ent_add) { return DSET_PROCS(dset)->ent_add(dset, ent, (lcb_CMDENDURE*)cmd); } else { return LCB_SUCCESS; } }
static lcb_error_t dset_ctx_schedule(lcb_MULTICMD_CTX *mctx, const void *cookie) { unsigned ii; char *kptr; lcb_DURSET *dset = CTX_FROM_MULTI(mctx); kptr = dset->kvbufs.base; for (ii = 0; ii < dset->nentries; ii++) { lcb_DURITEM *ent = dset->entries + ii; RESFLD(ent, key) = kptr; kptr += RESFLD(ent, nkey); if (ent->hashkey.contig.nbytes) { ent->hashkey.contig.bytes = kptr; kptr += ent->hashkey.contig.nbytes; } if (dset->ht) { int mt = genhash_update(dset->ht, RESFLD(ent, key), RESFLD(ent, nkey), ent, 0); if (mt != NEW) { lcb_durability_dset_destroy(dset); return LCB_DUPLICATE_COMMANDS; } } } dset_ref(dset); dset->cookie = cookie; dset->nremaining = dset->nentries; lcb_aspend_add(&dset->instance->pendops, LCB_PENDTYPE_DURABILITY, dset); return poll_once(dset, 1); }
static lcb_error_t dset_ctx_add(lcb_MULTICMD_CTX *mctx, const lcb_CMDBASE *cmd) { lcb_DURSET *dset = CTX_FROM_MULTI(mctx); lcb_DURITEM *ent; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } /* ensure we have enough space first */ if (dset->nentries == 0) { /* First entry. Optimize */ ent = &dset->single.ent; dset->entries = &dset->single.ent; } else if (dset->nentries == 1) { /* More than a single entry */ dset->ents_alloced = 2; dset->entries = malloc(2 * sizeof(*dset->entries)); if (!dset->entries) { return LCB_CLIENT_ENOMEM; } dset->entries[0] = dset->single.ent; ent = &dset->entries[1]; dset->ht = lcb_hashtable_nc_new(16); if (!dset->ht) { return LCB_CLIENT_ENOMEM; } } else if (dset->nentries < dset->ents_alloced) { ent = &dset->entries[dset->nentries]; } else { lcb_DURITEM *newarr; lcb_SIZE newsize = dset->ents_alloced * 1.5; newarr = realloc(dset->entries, sizeof(*ent) * newsize); if (!newarr) { return LCB_CLIENT_ENOMEM; } dset->entries = newarr; dset->ents_alloced = newsize; ent = &dset->entries[dset->nentries]; } /* ok. now let's initialize the entry..*/ memset(ent, 0, sizeof (*ent)); RESFLD(ent, nkey) = cmd->key.contig.nbytes; ent->hashkey = cmd->hashkey; ent->reqcas = cmd->cas; ent->parent = dset; lcb_string_append(&dset->kvbufs, cmd->key.contig.bytes, cmd->key.contig.nbytes); if (cmd->hashkey.contig.nbytes) { lcb_string_append(&dset->kvbufs, cmd->hashkey.contig.bytes, cmd->hashkey.contig.nbytes); } dset->nentries++; return LCB_SUCCESS; }
static lcb_error_t obs_ctxdone(lcb_MULTICMD_CTX *mctx, const void *cookie) { unsigned ii; OBSERVECTX *ctx = CTX_FROM_MULTI(mctx); mc_CMDQUEUE *cq = &ctx->instance->cmdq; for (ii = 0; ii < ctx->nrequests; ii++) { protocol_binary_request_header hdr; mc_PACKET *pkt; mc_PIPELINE *pipeline; lcb_string *rr = ctx->requests + ii; pipeline = cq->pipelines[ii]; if (!rr->nused) { continue; } pkt = mcreq_allocate_packet(pipeline); lcb_assert(pkt); mcreq_reserve_header(pipeline, pkt, MCREQ_PKT_BASESIZE); mcreq_reserve_value2(pipeline, pkt, rr->nused); hdr.request.magic = PROTOCOL_BINARY_REQ; hdr.request.opcode = PROTOCOL_BINARY_CMD_OBSERVE; hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr.request.keylen = 0; hdr.request.cas = 0; hdr.request.vbucket = 0; hdr.request.extlen = 0; hdr.request.opaque = pkt->opaque; hdr.request.bodylen = htonl((lcb_uint32_t)rr->nused); memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes)); memcpy(SPAN_BUFFER(&pkt->u_value.single), rr->base, rr->nused); pkt->flags |= MCREQ_F_REQEXT; pkt->u_rdata.exdata = (mc_REQDATAEX *)ctx; mcreq_sched_add(pipeline, pkt); TRACE_OBSERVE_BEGIN(&hdr, SPAN_BUFFER(&pkt->u_value.single)); } destroy_requests(ctx); ctx->base.start = gethrtime(); ctx->base.cookie = cookie; ctx->base.procs = &obs_procs; if (ctx->nrequests == 0 || ctx->remaining == 0) { free(ctx); return LCB_EINVAL; } else { MAYBE_SCHEDLEAVE(ctx->instance); return LCB_SUCCESS; } }
lcb_MULTICMD_CTX * lcb_observe_ctx_dur_new(lcb_t instance) { lcb_MULTICMD_CTX *mctx = lcb_observe3_ctxnew(instance); if (mctx) { OBSERVECTX *ctx = CTX_FROM_MULTI(mctx); ctx->oflags |= F_DURABILITY; } return mctx; }
static lcb_error_t dset_ctx_schedule(lcb_MULTICMD_CTX *mctx, const void *cookie) { size_t ii; lcb_error_t err; lcb_DURSET *dset = CTX_FROM_MULTI(mctx); char *kptr = dset->kvbufs.base; if (!DSET_COUNT(dset)) { lcbdur_destroy(dset); return LCB_EINVAL; } for (ii = 0; ii < DSET_COUNT(dset); ii++) { lcb_DURITEM *ent = DSET_ENTRIES(dset) + ii; RESFLD(ent, key) = kptr; kptr += RESFLD(ent, nkey); } if (DSET_PROCS(dset)->schedule) { err = DSET_PROCS(dset)->schedule(dset); if (err != LCB_SUCCESS) { lcbdur_destroy(dset); return err; } } lcbdur_ref(dset); dset->cookie = cookie; dset->nremaining = DSET_COUNT(dset); dset->ns_timeout = gethrtime() + LCB_US2NS(DSET_OPTFLD(dset, timeout)); lcb_aspend_add(&dset->instance->pendops, LCB_PENDTYPE_DURABILITY, dset); lcbdur_switch_state(dset, LCBDUR_STATE_INIT); return LCB_SUCCESS; }
static lcb_error_t obs_ctxadd(lcb_MULTICMD_CTX *mctx, const lcb_CMDOBSERVE *cmd) { const void *hk; lcb_SIZE nhk; int vbid; unsigned maxix; int ii; OBSERVECTX *ctx = CTX_FROM_MULTI(mctx); lcb_t instance = ctx->instance; mc_CMDQUEUE *cq = &instance->cmdq; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } if (cq->config == NULL) { return LCB_CLIENT_ETMPFAIL; } if (LCBVB_DISTTYPE(LCBT_VBCONFIG(instance)) != LCBVB_DIST_VBUCKET) { return LCB_NOT_SUPPORTED; } mcreq_extract_hashkey(&cmd->key, &cmd->_hashkey, 24, &hk, &nhk); vbid = lcbvb_k2vb(cq->config, hk, nhk); maxix = LCBVB_NREPLICAS(cq->config); for (ii = -1; ii < (int)maxix; ++ii) { struct observe_st *rr; lcb_U16 vb16, klen16; int ix; if (ii == -1) { ix = lcbvb_vbmaster(cq->config, vbid); if (ix < 0) { return LCB_NO_MATCHING_SERVER; } } else { ix = lcbvb_vbreplica(cq->config, vbid, ii); if (ix < 0) { continue; } } lcb_assert(ix < (int)ctx->nrequests); rr = ctx->requests + ix; if (!rr->allocated) { if (!init_request(rr)) { return LCB_CLIENT_ENOMEM; } } vb16 = htons((lcb_U16)vbid); klen16 = htons((lcb_U16)cmd->key.contig.nbytes); lcb_string_append(&rr->body, &vb16, sizeof vb16); lcb_string_append(&rr->body, &klen16, sizeof klen16); lcb_string_append(&rr->body, cmd->key.contig.bytes, cmd->key.contig.nbytes); ctx->remaining++; if (cmd->cmdflags & LCB_CMDOBSERVE_F_MASTER_ONLY) { break; } } return LCB_SUCCESS; }
void lcbdurctx_set_durstore(lcb_MULTICMD_CTX *mctx, int enabled) { lcb_DURSET *dset = CTX_FROM_MULTI(mctx); dset->is_durstore = enabled; }
static void dset_ctx_fail(lcb_MULTICMD_CTX *mctx) { lcb_DURSET *dset = CTX_FROM_MULTI(mctx); lcbdur_destroy(dset); }
static lcb_error_t obs_ctxadd(lcb_MULTICMD_CTX *mctx, const lcb_CMDBASE *cmdbase) { int vbid, srvix_dummy; unsigned ii; const lcb_CMDOBSERVE *cmd = (const lcb_CMDOBSERVE *)cmdbase; OBSERVECTX *ctx = CTX_FROM_MULTI(mctx); lcb_t instance = ctx->instance; mc_CMDQUEUE *cq = &instance->cmdq; lcb_U16 servers_s[4]; const lcb_U16 *servers; size_t nservers; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } if (cq->config == NULL) { return LCB_CLIENT_ETMPFAIL; } if (LCBVB_DISTTYPE(LCBT_VBCONFIG(instance)) != LCBVB_DIST_VBUCKET) { return LCB_NOT_SUPPORTED; } mcreq_map_key(cq, &cmd->key, &cmd->_hashkey, 24, &vbid, &srvix_dummy); if (cmd->servers_) { servers = cmd->servers_; nservers = cmd->nservers_; } else { nservers = 0; servers = servers_s; /* Replicas are always < 4 */ for (ii = 0; ii < LCBVB_NREPLICAS(cq->config) + 1; ii++) { int ix = lcbvb_vbserver(cq->config, vbid, ii); if (ix < 0) { if (ii == 0) { return LCB_NO_MATCHING_SERVER; } else { continue; } } servers_s[nservers++] = ix; if (cmd->cmdflags & LCB_CMDOBSERVE_F_MASTER_ONLY) { break; /* Only a single server! */ } } } if (nservers == 0) { return LCB_NO_MATCHING_SERVER; } for (ii = 0; ii < nservers; ii++) { lcb_string *rr; lcb_U16 vb16, klen16; lcb_U16 ix = servers[ii]; lcb_assert(ix < ctx->nrequests); rr = ctx->requests + ix; if (0 != lcb_string_reserve(rr, 4 + cmd->key.contig.nbytes)) { return LCB_CLIENT_ENOMEM; } vb16 = htons((lcb_U16)vbid); klen16 = htons((lcb_U16)cmd->key.contig.nbytes); lcb_string_append(rr, &vb16, sizeof vb16); lcb_string_append(rr, &klen16, sizeof klen16); lcb_string_append(rr, cmd->key.contig.bytes, cmd->key.contig.nbytes); ctx->remaining++; } return LCB_SUCCESS; }