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; } }
LIBCOUCHBASE_API lcb_error_t lcb_remove3(lcb_t instance, const void *cookie, const lcb_CMDREMOVE * cmd) { mc_CMDQUEUE *cq = &instance->cmdq; mc_PIPELINE *pl; mc_PACKET *pkt; lcb_error_t err; protocol_binary_request_header hdr; err = mcreq_basic_packet(cq, cmd, &hdr, 0, &pkt, &pl); if (err != LCB_SUCCESS) { return err; } hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; hdr.request.magic = PROTOCOL_BINARY_REQ; hdr.request.opcode = PROTOCOL_BINARY_CMD_DELETE; hdr.request.cas = cmd->options.cas; hdr.request.opaque = pkt->opaque; hdr.request.bodylen = htonl((lcb_uint32_t)ntohs(hdr.request.keylen)); pkt->u_rdata.reqdata.cookie = cookie; pkt->u_rdata.reqdata.start = gethrtime(); memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof(hdr.bytes)); mcreq_sched_add(pl, pkt); return LCB_SUCCESS; }
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; }
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; }
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; }
/** * This callback is invoked for packet relocation twice. It tries to relocate * commands to their destination server. Some commands may not be relocated * either because they have no explicit "Relocation Information" (i.e. no * specific vbucket) or because the command is tied to a specific server (i.e. * CMD_STAT) */ static int iterwipe_cb(mc_CMDQUEUE *cq, mc_PIPELINE *oldpl, mc_PACKET *oldpkt, void *arg) { protocol_binary_request_header hdr; mc_SERVER *srv = (mc_SERVER *)oldpl; mc_PIPELINE *newpl; mc_PACKET *newpkt; int newix; uint8_t op; (void)arg; memcpy(&hdr, SPAN_BUFFER(&oldpkt->kh_span), sizeof(hdr.bytes)); op = hdr.request.opcode; if (op == PROTOCOL_BINARY_CMD_OBSERVE || op == PROTOCOL_BINARY_CMD_STAT || op == PROTOCOL_BINARY_CMD_GET_CLUSTER_CONFIG) { return MCREQ_KEEP_PACKET; } newix = vbucket_get_master(cq->config, ntohs(hdr.request.vbucket)); if (newix < 0 || newix > (int)cq->npipelines) { return MCREQ_KEEP_PACKET; } if (!lcb_should_retry(srv->settings, oldpkt, LCB_MAX_ERROR)) { return MCREQ_KEEP_PACKET; } newpl = cq->pipelines[newix]; if (newpl == oldpl || newpl == NULL) { return MCREQ_KEEP_PACKET; } lcb_log(LOGARGS(cq->instance, DEBUG), "Remapped packet %p (SEQ=%u) from "SERVER_FMT " to " SERVER_FMT, (void*)oldpkt, oldpkt->opaque, SERVER_ARGS((mc_SERVER*)oldpl), SERVER_ARGS((mc_SERVER*)newpl)); /** Otherwise, copy over the packet and find the new vBucket to map to */ newpkt = mcreq_dup_packet(oldpkt); newpkt->flags &= ~MCREQ_STATE_FLAGS; mcreq_reenqueue_packet(newpl, newpkt); mcreq_packet_handled(oldpl, oldpkt); return MCREQ_REMOVE_PACKET; }
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; }
static void handle_observe_callback(mc_PIPELINE *pl, mc_PACKET *pkt, lcb_error_t err, const void *arg) { OBSERVECTX *oc = (void *)pkt->u_rdata.exdata; lcb_RESPOBSERVE *resp = (void *)arg; lcb_t instance = oc->instance; (void)pl; if (resp == NULL) { int nfailed = 0; /** We need to fail the request manually.. */ const char *ptr = SPAN_BUFFER(&pkt->u_value.single); const char *end = ptr + pkt->u_value.single.size; while (ptr < end) { lcb_uint16_t nkey; lcb_RESPOBSERVE cur = { 0 }; cur.rflags = LCB_RESP_F_CLIENTGEN; ptr += 2; memcpy(&nkey, ptr, sizeof(nkey)); nkey = ntohs(nkey); ptr += 2; memset(&cur, 0, sizeof(cur)); cur.key = ptr; cur.nkey = nkey; cur.cookie = (void *)oc->base.cookie; cur.rc = err; handle_observe_callback(NULL, pkt, err, &cur); ptr += nkey; nfailed++; } lcb_assert(nfailed); return; } resp->cookie = (void *)oc->base.cookie; resp->rc = err; if (oc->oflags & F_DURABILITY) { lcb_durability_dset_update( instance, (lcb_DURSET *)MCREQ_PKT_COOKIE(pkt), err, resp); } else if ((oc->oflags & F_SCHEDFAILED) == 0) { lcb_RESPCALLBACK callback = lcb_find_callback(instance, LCB_CALLBACK_OBSERVE); callback(instance, LCB_CALLBACK_OBSERVE, (lcb_RESPBASE *)resp); } if (oc->oflags & F_DESTROY) { return; } if (--oc->remaining) { return; } else { lcb_RESPOBSERVE resp2 = { 0 }; resp2.rc = err; resp2.rflags = LCB_RESP_F_CLIENTGEN|LCB_RESP_F_FINAL; oc->oflags |= F_DESTROY; handle_observe_callback(NULL, pkt, err, &resp2); free(oc); } }
lcb_STATUS mc_forward_packet(mc_CMDQUEUE *cq, mc_IOVINFO *info, mc_PACKET **pkt_p, mc_PIPELINE **pl_p, int options) { /* stack based header with our modifications. this is copied into the * packet's actual header */ protocol_binary_request_header hdr; int vbid, srvix; mc_IOVCURSOR *mincur = &info->c; unsigned n_packet; /* total packet size */ unsigned n_header; /* extras + key + memcached header */ unsigned n_body_total; /* size of everything following the memcached header */ unsigned n_body_key; /* length of the key */ unsigned n_body_value; /* packetsize - hdrsize */ unsigned offset; /* stack buffer and key pointer. stack buffer is used if the key is not * contiguous */ char kbuf_s[256]; const char *kptr; /* pipeline and packet for command */ mc_PIPELINE *pl; mc_PACKET *pkt; info->wanted = 0; /* not enough bytes */ if (info->total < 24) { info->wanted = 24; return LCB_INCOMPLETE_PACKET; } iovcursor_peek(mincur, (char *)hdr.bytes, sizeof hdr.bytes, 0); /* Initialize our size variables */ n_body_total = ntohl(hdr.request.bodylen); n_body_key = ntohs(hdr.request.keylen); n_header = sizeof hdr.bytes + n_body_key + hdr.request.extlen; n_packet = n_body_total + sizeof hdr.bytes; n_body_value = n_packet - n_header; if (n_packet > info->total) { info->wanted = n_packet; return LCB_INCOMPLETE_PACKET; } info->total -= n_packet; /* seek ahead to read the item's key into the header */ offset = sizeof hdr.bytes + hdr.request.extlen; iovcursor_peek_ex(mincur, kbuf_s, &kptr, n_body_key, offset); if (kptr == NULL) { /* key is not contiguous? that's ok. use the static buffer */ kptr = kbuf_s; } if ((options & MC_FWD_OPT_NOMAP) == 0) { lcbvb_map_key(cq->config, kptr, n_body_key, &vbid, &srvix); if (srvix < 0 || (unsigned)srvix >= cq->npipelines) { return LCB_NO_MATCHING_SERVER; } pl = cq->pipelines[srvix]; hdr.request.vbucket = htons(vbid); } else { pl = *pl_p; if (!pl) { return LCB_EINVAL; } srvix = pl->index; } pkt = mcreq_allocate_packet(pl); if (pkt == NULL) { return LCB_CLIENT_ENOMEM; } hdr.request.opaque = pkt->opaque; pkt->extlen = hdr.request.extlen; info->consumed = n_packet; if (options & MC_FWD_OPT_COPY) { /* reserve bytes for the entire packet */ mcreq_reserve_header(pl, pkt, n_header); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->kh_span), n_header); if (n_body_value) { mcreq_reserve_value2(pl, pkt, n_body_value); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->u_value.single), n_body_value); pkt->flags |= MCREQ_F_HASVALUE; } } else { if (IOVCURSOR_HAS_CONTIG(mincur, n_header)) { span_from_first(mincur, n_header, &pkt->kh_span); pkt->flags |= MCREQ_F_KEY_NOCOPY; } else { /* header is fragmented into multiple IOVs */ mcreq_reserve_header(pl, pkt, n_header); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->kh_span), n_header); } /* do we have a value payload still? */ if (n_body_value) { pkt->flags |= MCREQ_F_HASVALUE | MCREQ_F_VALUE_NOCOPY; if (IOVCURSOR_HAS_CONTIG(mincur, n_body_value)) { span_from_first(mincur, n_body_value, &pkt->u_value.single); } else { /* body is fragmented */ iovcursor_adv_iovalloc(mincur, n_body_value, (nb_IOV **)&pkt->u_value.multi.iov, &pkt->u_value.multi.niov); pkt->u_value.multi.total_length = n_body_value; pkt->flags |= MCREQ_F_VALUE_IOV; } } } /* Copy the first 24 bytes into the header span */ memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof hdr.bytes); *pkt_p = pkt; *pl_p = pl; /* Set the UFWD flag. This causes the rest of the system to invoke the * handler for the raw response, rather than the "Contiguous" structures*/ pkt->flags |= MCREQ_F_UFWD; mcreq_sched_add(pl, pkt); 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; }
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; }