LIBCOUCHBASE_API lcb_MULTICMD_CTX * lcb_endure3_ctxnew(lcb_t instance, const lcb_durability_opts_t *options, lcb_error_t *errp) { lcb_DURSET *dset; lcb_error_t err_s; lcbio_pTABLE io = instance->iotable; const lcb_DURABILITYOPTSv0 *opts_in = &options->v.v0; if (!errp) { errp = &err_s; } *errp = LCB_SUCCESS; if (!LCBT_VBCONFIG(instance)) { *errp = LCB_CLIENT_ETMPFAIL; return NULL; } dset = calloc(1, sizeof(*dset)); if (!dset) { *errp = LCB_CLIENT_ENOMEM; return NULL; } /* Ensure we don't clobber options from older versions */ dset->opts.cap_max = opts_in->cap_max; dset->opts.check_delete = opts_in->check_delete; dset->opts.interval = opts_in->interval; dset->opts.persist_to = opts_in->persist_to; dset->opts.replicate_to = opts_in->replicate_to; dset->opts.timeout = opts_in->timeout; if (options->version > 0) { dset->opts.pollopts = opts_in->pollopts; } dset->opts.pollopts = get_poll_meth(instance, &dset->opts); dset->instance = instance; dset->mctx.addcmd = dset_ctx_add; dset->mctx.done = dset_ctx_schedule; dset->mctx.fail = dset_ctx_fail; if (!DSET_OPTFLD(dset, timeout)) { DSET_OPTFLD(dset, timeout) = LCBT_SETTING(instance, durability_timeout); } if (!DSET_OPTFLD(dset, interval)) { DSET_OPTFLD(dset, interval) = LCBT_SETTING(instance, durability_interval); } *errp = lcb_durability_validate(instance, &dset->opts.persist_to, &dset->opts.replicate_to, dset->opts.cap_max ? LCB_DURABILITY_VALIDATE_CAPMAX : 0); if (*errp != LCB_SUCCESS) { free(dset); return NULL; } dset->timer = io->timer.create(io->p); lcb_string_init(&dset->kvbufs); return &dset->mctx; }
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; }