LIBCOUCHBASE_API lcb_error_t lcb_get3(lcb_t instance, const void *cookie, const lcb_CMDGET *cmd) { mc_PIPELINE *pl; mc_PACKET *pkt; mc_REQDATA *rdata; mc_CMDQUEUE *q = &instance->cmdq; lcb_error_t err; lcb_uint8_t extlen = 0; lcb_uint8_t opcode = PROTOCOL_BINARY_CMD_GET; protocol_binary_request_gat gcmd; protocol_binary_request_header *hdr = &gcmd.message.header; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } if (cmd->cas) { return LCB_OPTIONS_CONFLICT; } if (cmd->lock) { extlen = 4; opcode = PROTOCOL_BINARY_CMD_GET_LOCKED; } else if (cmd->exptime) { extlen = 4; opcode = PROTOCOL_BINARY_CMD_GAT; } err = mcreq_basic_packet(q, (const lcb_CMDBASE *)cmd, hdr, extlen, &pkt, &pl, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } rdata = &pkt->u_rdata.reqdata; rdata->cookie = cookie; rdata->start = gethrtime(); hdr->request.magic = PROTOCOL_BINARY_REQ; hdr->request.opcode = opcode; hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr->request.bodylen = htonl(extlen + ntohs(hdr->request.keylen)); hdr->request.opaque = pkt->opaque; hdr->request.cas = 0; if (extlen) { gcmd.message.body.expiration = htonl(cmd->exptime); } if (cmd->cmdflags & LCB_CMD_F_INTERNAL_CALLBACK) { pkt->flags |= MCREQ_F_PRIVCALLBACK; } memcpy(SPAN_BUFFER(&pkt->kh_span), gcmd.bytes, MCREQ_PKT_BASESIZE + extlen); mcreq_sched_add(pl, pkt); TRACE_GET_BEGIN(hdr, cmd); return LCB_SUCCESS; }
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; } }
LIBCOUCHBASE_API lcb_error_t lcb_touch3(lcb_t instance, const void *cookie, const lcb_CMDTOUCH *cmd) { protocol_binary_request_touch tcmd; protocol_binary_request_header *hdr = &tcmd.message.header; mc_PIPELINE *pl; mc_PACKET *pkt; lcb_error_t err; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } err = mcreq_basic_packet(&instance->cmdq, cmd, hdr, 4, &pkt, &pl, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } hdr->request.magic = PROTOCOL_BINARY_REQ; hdr->request.opcode = PROTOCOL_BINARY_CMD_TOUCH; hdr->request.cas = 0; hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr->request.opaque = pkt->opaque; hdr->request.bodylen = htonl(4 + ntohs(hdr->request.keylen)); tcmd.message.body.expiration = htonl(cmd->exptime); memcpy(SPAN_BUFFER(&pkt->kh_span), tcmd.bytes, sizeof(tcmd.bytes)); pkt->u_rdata.reqdata.cookie = cookie; pkt->u_rdata.reqdata.start = gethrtime(); mcreq_sched_add(pl, pkt); return LCB_SUCCESS; }
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; }
LIBCOUCHBASE_API lcb_error_t lcb_counter3( lcb_t instance, const void *cookie, const lcb_CMDCOUNTER *cmd) { mc_CMDQUEUE *q = &instance->cmdq; mc_PIPELINE *pipeline; mc_PACKET *packet; mc_REQDATA *rdata; lcb_error_t err; protocol_binary_request_incr acmd; protocol_binary_request_header *hdr = &acmd.message.header; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } err = mcreq_basic_packet(q, (const lcb_CMDBASE *)cmd, hdr, 20, &packet, &pipeline, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } rdata = &packet->u_rdata.reqdata; rdata->cookie = cookie; rdata->start = gethrtime(); hdr->request.magic = PROTOCOL_BINARY_REQ; hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr->request.cas = 0; hdr->request.opaque = packet->opaque; hdr->request.bodylen = htonl(hdr->request.extlen + ntohs(hdr->request.keylen)); acmd.message.body.delta = ntohll((lcb_uint64_t)cmd->delta); acmd.message.body.initial = ntohll(cmd->initial); if (!cmd->create) { memset(&acmd.message.body.expiration, 0xff, sizeof(acmd.message.body.expiration)); } else { acmd.message.body.expiration = htonl(cmd->exptime); } if (cmd->delta < 0) { hdr->request.opcode = PROTOCOL_BINARY_CMD_DECREMENT; acmd.message.body.delta = ntohll((lcb_uint64_t)(cmd->delta * -1)); } else { hdr->request.opcode = PROTOCOL_BINARY_CMD_INCREMENT; } memcpy(SPAN_BUFFER(&packet->kh_span), acmd.bytes, sizeof(acmd.bytes)); TRACE_ARITHMETIC_BEGIN(hdr, cmd); mcreq_sched_add(pipeline, packet); return LCB_SUCCESS; }
LIBCOUCHBASE_API lcb_error_t lcb_unlock3(lcb_t instance, const void *cookie, const lcb_CMDUNLOCK *cmd) { mc_CMDQUEUE *cq = &instance->cmdq; mc_PIPELINE *pl; mc_PACKET *pkt; mc_REQDATA *rd; lcb_error_t err; protocol_binary_request_header hdr; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } err = mcreq_basic_packet(cq, cmd, &hdr, 0, &pkt, &pl, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } rd = &pkt->u_rdata.reqdata; rd->cookie = cookie; rd->start = gethrtime(); hdr.request.magic = PROTOCOL_BINARY_REQ; hdr.request.opcode = PROTOCOL_BINARY_CMD_UNLOCK_KEY; hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr.request.bodylen = htonl((lcb_uint32_t)ntohs(hdr.request.keylen)); hdr.request.opaque = pkt->opaque; hdr.request.cas = cmd->cas; memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes)); TRACE_UNLOCK_BEGIN(&hdr, cmd); mcreq_sched_add(pl, pkt); return LCB_SUCCESS; }
LIBCOUCHBASE_API lcb_error_t lcb_rget3(lcb_t instance, const void *cookie, const lcb_CMDGETREPLICA *cmd) { /** * Because we need to direct these commands to specific servers, we can't * just use the 'basic_packet()' function. */ mc_CMDQUEUE *cq = &instance->cmdq; const void *hk; lcb_size_t nhk; int vbid; protocol_binary_request_header req; unsigned r0, r1; rget_cookie *rck = NULL; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } mcreq_extract_hashkey(&cmd->key, &cmd->hashkey, MCREQ_PKT_BASESIZE, &hk, &nhk); vbid = lcbvb_k2vb(cq->config, hk, nhk); /** Get the vbucket by index */ if (cmd->strategy == LCB_REPLICA_SELECT) { r0 = r1 = cmd->index; } else if (cmd->strategy == LCB_REPLICA_ALL) { r0 = 0; r1 = instance->nreplicas; } else { /* first */ r0 = r1 = 0; } if (r1 < r0 || r1 >= cq->npipelines) { return LCB_NO_MATCHING_SERVER; } /* Initialize the cookie */ rck = calloc(1, sizeof(*rck)); rck->base.cookie = cookie; rck->base.start = gethrtime(); rck->base.callback = rget_callback; rck->strategy = cmd->strategy; rck->r_cur = r0; rck->r_max = instance->nreplicas; rck->instance = instance; rck->vbucket = vbid; /* Initialize the packet */ req.request.magic = PROTOCOL_BINARY_REQ; req.request.opcode = PROTOCOL_BINARY_CMD_GET_REPLICA; req.request.datatype = PROTOCOL_BINARY_RAW_BYTES; req.request.vbucket = htons((lcb_uint16_t)vbid); req.request.cas = 0; req.request.extlen = 0; req.request.keylen = htons((lcb_uint16_t)cmd->key.contig.nbytes); req.request.bodylen = htonl((lcb_uint32_t)cmd->key.contig.nbytes); do { int curix; mc_PIPELINE *pl; mc_PACKET *pkt; curix = lcbvb_vbreplica(cq->config, vbid, r0); if (curix == -1) { return LCB_NO_MATCHING_SERVER; } pl = cq->pipelines[curix]; pkt = mcreq_allocate_packet(pl); if (!pkt) { return LCB_CLIENT_ENOMEM; } pkt->u_rdata.exdata = &rck->base; pkt->flags |= MCREQ_F_REQEXT; mcreq_reserve_key(pl, pkt, sizeof(req.bytes), &cmd->key); req.request.opaque = pkt->opaque; rck->remaining++; mcreq_write_hdr(pkt, &req); mcreq_sched_add(pl, pkt); } while (++r0 < r1); 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; }
static lcb_error_t do_store3(lcb_t instance, const void *cookie, const lcb_CMDBASE *cmd, int is_durstore) { mc_PIPELINE *pipeline; mc_PACKET *packet; mc_REQDATA *rdata; mc_CMDQUEUE *cq = &instance->cmdq; int hsize; int should_compress = 0; lcb_error_t err; lcb_storage_t operation; lcb_U32 flags; const lcb_VALBUF *vbuf; lcb_datatype_t datatype; protocol_binary_request_set scmd; protocol_binary_request_header *hdr = &scmd.message.header; if (!is_durstore) { const lcb_CMDSTORE *simple_cmd = (const lcb_CMDSTORE *)cmd; operation = simple_cmd->operation; flags = simple_cmd->flags; vbuf = &simple_cmd->value; datatype = simple_cmd->datatype; } else { const lcb_CMDSTOREDUR *durcmd = (const lcb_CMDSTOREDUR *)cmd; operation = durcmd->operation; flags = durcmd->flags; vbuf = &durcmd->value; datatype = durcmd->datatype; } if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } err = get_esize_and_opcode( operation, &hdr->request.opcode, &hdr->request.extlen); if (err != LCB_SUCCESS) { return err; } switch (operation) { case LCB_APPEND: case LCB_PREPEND: if (cmd->exptime || flags) { return LCB_OPTIONS_CONFLICT; } break; case LCB_ADD: if (cmd->cas) { return LCB_OPTIONS_CONFLICT; } break; default: break; } hsize = hdr->request.extlen + sizeof(*hdr); err = mcreq_basic_packet(cq, (const lcb_CMDBASE *)cmd, hdr, hdr->request.extlen, &packet, &pipeline, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } should_compress = can_compress(instance, pipeline, vbuf, datatype); if (should_compress) { int rv = mcreq_compress_value(pipeline, packet, &vbuf->u_buf.contig); if (rv != 0) { mcreq_release_packet(pipeline, packet); return LCB_CLIENT_ENOMEM; } } else { mcreq_reserve_value(pipeline, packet, vbuf); } if (is_durstore) { int duropts = 0; lcb_U16 persist_u , replicate_u; const lcb_CMDSTOREDUR *dcmd = (const lcb_CMDSTOREDUR *)cmd; DURSTORECTX *dctx = calloc(1, sizeof(*dctx)); persist_u = dcmd->persist_to; replicate_u = dcmd->replicate_to; if (dcmd->replicate_to == -1 || dcmd->persist_to == -1) { duropts = LCB_DURABILITY_VALIDATE_CAPMAX; } err = lcb_durability_validate(instance, &persist_u, &replicate_u, duropts); if (err != LCB_SUCCESS) { mcreq_wipe_packet(pipeline, packet); mcreq_release_packet(pipeline, packet); return err; } dctx->instance = instance; dctx->persist_to = persist_u; dctx->replicate_to = replicate_u; packet->u_rdata.exdata = &dctx->base; packet->flags |= MCREQ_F_REQEXT; dctx->base.cookie = cookie; dctx->base.procs = &storedur_procs; } rdata = MCREQ_PKT_RDATA(packet); rdata->cookie = cookie; rdata->start = gethrtime(); scmd.message.body.expiration = htonl(cmd->exptime); scmd.message.body.flags = htonl(flags); hdr->request.magic = PROTOCOL_BINARY_REQ; hdr->request.cas = cmd->cas; hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES; if (should_compress || (datatype & LCB_VALUE_F_SNAPPYCOMP)) { hdr->request.datatype |= PROTOCOL_BINARY_DATATYPE_COMPRESSED; } if (datatype & LCB_VALUE_F_JSON) { hdr->request.datatype |= PROTOCOL_BINARY_DATATYPE_JSON; } hdr->request.opaque = packet->opaque; hdr->request.bodylen = htonl( hdr->request.extlen + ntohs(hdr->request.keylen) + get_value_size(packet)); memcpy(SPAN_BUFFER(&packet->kh_span), scmd.bytes, hsize); mcreq_sched_add(pipeline, packet); TRACE_STORE_BEGIN(hdr, (lcb_CMDSTORE* )cmd); return LCB_SUCCESS; }
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; }
LIBCOUCHBASE_API lcb_error_t lcb_rget3(lcb_t instance, const void *cookie, const lcb_CMDGETREPLICA *cmd) { /** * Because we need to direct these commands to specific servers, we can't * just use the 'basic_packet()' function. */ mc_CMDQUEUE *cq = &instance->cmdq; int vbid, ixtmp; protocol_binary_request_header req; unsigned r0, r1 = 0; rget_cookie *rck = NULL; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } if (!cq->config) { return LCB_CLIENT_ETMPFAIL; } if (!LCBT_NREPLICAS(instance)) { return LCB_NO_MATCHING_SERVER; } mcreq_map_key(cq, &cmd->key, &cmd->_hashkey, MCREQ_PKT_BASESIZE, &vbid, &ixtmp); /* The following blocks will also validate that the entire index range is * valid. This is in order to ensure that we don't allocate the cookie * if there aren't enough replicas online to satisfy the requirements */ if (cmd->strategy == LCB_REPLICA_SELECT) { r0 = r1 = cmd->index; if ((ixtmp = lcbvb_vbreplica(cq->config, vbid, r0)) < 0) { return LCB_NO_MATCHING_SERVER; } } else if (cmd->strategy == LCB_REPLICA_ALL) { unsigned ii; r0 = 0; r1 = LCBT_NREPLICAS(instance); /* Make sure they're all online */ for (ii = 0; ii < LCBT_NREPLICAS(instance); ii++) { if ((ixtmp = lcbvb_vbreplica(cq->config, vbid, ii)) < 0) { return LCB_NO_MATCHING_SERVER; } } } else { for (r0 = 0; r0 < LCBT_NREPLICAS(instance); r0++) { if ((ixtmp = lcbvb_vbreplica(cq->config, vbid, r0)) > -1) { r1 = r0; break; } } if (r0 == LCBT_NREPLICAS(instance)) { return LCB_NO_MATCHING_SERVER; } } if (r1 < r0 || r1 >= cq->npipelines) { return LCB_NO_MATCHING_SERVER; } /* Initialize the cookie */ rck = calloc(1, sizeof(*rck)); rck->base.cookie = cookie; rck->base.start = gethrtime(); rck->base.procs = &rget_procs; rck->strategy = cmd->strategy; rck->r_cur = r0; rck->r_max = LCBT_NREPLICAS(instance); rck->instance = instance; rck->vbucket = vbid; /* Initialize the packet */ req.request.magic = PROTOCOL_BINARY_REQ; req.request.opcode = PROTOCOL_BINARY_CMD_GET_REPLICA; req.request.datatype = PROTOCOL_BINARY_RAW_BYTES; req.request.vbucket = htons((lcb_uint16_t)vbid); req.request.cas = 0; req.request.extlen = 0; req.request.keylen = htons((lcb_uint16_t)cmd->key.contig.nbytes); req.request.bodylen = htonl((lcb_uint32_t)cmd->key.contig.nbytes); do { int curix; mc_PIPELINE *pl; mc_PACKET *pkt; curix = lcbvb_vbreplica(cq->config, vbid, r0); /* XXX: this is always expected to be in range. For the FIRST mode * it will seek to the first valid index (checked above), and for the * ALL mode, it will fail if not all replicas are already online * (also checked above) */ pl = cq->pipelines[curix]; pkt = mcreq_allocate_packet(pl); if (!pkt) { return LCB_CLIENT_ENOMEM; } pkt->u_rdata.exdata = &rck->base; pkt->flags |= MCREQ_F_REQEXT; mcreq_reserve_key(pl, pkt, sizeof(req.bytes), &cmd->key); req.request.opaque = pkt->opaque; rck->remaining++; mcreq_write_hdr(pkt, &req); mcreq_sched_add(pl, pkt); } while (++r0 < r1); return LCB_SUCCESS; }
LIBCOUCHBASE_API lcb_error_t lcb_store3(lcb_t instance, const void *cookie, const lcb_CMDSTORE *cmd) { mc_PIPELINE *pipeline; mc_PACKET *packet; mc_REQDATA *rdata; mc_CMDQUEUE *cq = &instance->cmdq; int hsize; int should_compress = 0; lcb_error_t err; protocol_binary_request_set scmd; protocol_binary_request_header *hdr = &scmd.message.header; if (LCB_KEYBUF_IS_EMPTY(&cmd->key)) { return LCB_EMPTY_KEY; } err = get_esize_and_opcode( cmd->operation, &hdr->request.opcode, &hdr->request.extlen); if (err != LCB_SUCCESS) { return err; } hsize = hdr->request.extlen + sizeof(*hdr); err = mcreq_basic_packet(cq, (const lcb_CMDBASE *)cmd, hdr, hdr->request.extlen, &packet, &pipeline, MCREQ_BASICPACKET_F_FALLBACKOK); if (err != LCB_SUCCESS) { return err; } should_compress = can_compress(instance, pipeline, cmd); if (should_compress) { int rv = mcreq_compress_value(pipeline, packet, &cmd->value.u_buf.contig); if (rv != 0) { mcreq_release_packet(pipeline, packet); return LCB_CLIENT_ENOMEM; } } else { mcreq_reserve_value(pipeline, packet, &cmd->value); } rdata = &packet->u_rdata.reqdata; rdata->cookie = cookie; rdata->start = gethrtime(); scmd.message.body.expiration = htonl(cmd->exptime); scmd.message.body.flags = htonl(cmd->flags); hdr->request.magic = PROTOCOL_BINARY_REQ; hdr->request.cas = cmd->cas; hdr->request.datatype = PROTOCOL_BINARY_RAW_BYTES; if (should_compress || (cmd->datatype & LCB_VALUE_F_SNAPPYCOMP)) { hdr->request.datatype |= PROTOCOL_BINARY_DATATYPE_COMPRESSED; } if (cmd->datatype & LCB_VALUE_F_JSON) { hdr->request.datatype |= PROTOCOL_BINARY_DATATYPE_JSON; } hdr->request.opaque = packet->opaque; hdr->request.bodylen = htonl( hdr->request.extlen + ntohs(hdr->request.keylen) + get_value_size(packet)); memcpy(SPAN_BUFFER(&packet->kh_span), scmd.bytes, hsize); mcreq_sched_add(pipeline, packet); TRACE_STORE_BEGIN(hdr, cmd); return LCB_SUCCESS; }