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; hrtime_t now; lcbio_pTABLE io = instance->iotable; if (!errp) { errp = &err_s; } if (!LCBT_VBCONFIG(instance)) { *errp = LCB_CLIENT_ETMPFAIL; return NULL; } now = gethrtime(); dset = calloc(1, sizeof(*dset)); if (!dset) { *errp = LCB_CLIENT_ENOMEM; return NULL; } dset->opts = *options; 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) = LCB_DEFAULT_DURABILITY_INTERVAL; } if (-1 == verify_critera(instance, dset)) { free(dset); *errp = LCB_DURABILITY_ETOOMANY; return NULL; } dset->us_timeout = (lcb_U32)(now / 1000) + DSET_OPTFLD(dset, timeout); dset->timer = io->timer.create(io->p); lcb_string_init(&dset->kvbufs); return &dset->mctx; }
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) { hrtime_t now = gethrtime(); lcb_durability_set_t *dset; lcb_size_t ii; lcb_io_opt_t io = instance->settings.io; if (!ncmds) { return LCB_EINVAL; } dset = calloc(1, sizeof(*dset)); if (!dset) { return LCB_CLIENT_ENOMEM; } dset->opts = *options; dset->instance = instance; if (!DSET_OPTFLD(dset, timeout)) { DSET_OPTFLD(dset, timeout) = instance->settings.durability_timeout; } if (-1 == verify_critera(instance, dset)) { free(dset); return LCB_DURABILITY_ETOOMANY; } /* set our timeouts now */ dset->us_timeout = (lcb_uint32_t)(now / 1000) + DSET_OPTFLD(dset, timeout); dset->timer = io->v.v0.create_timer(io); dset->cookie = cookie; dset->nentries = ncmds; dset->nremaining = ncmds; /** Get the timings */ if (!DSET_OPTFLD(dset, interval)) { DSET_OPTFLD(dset, interval) = LCB_DEFAULT_DURABILITY_INTERVAL; } /* list of observe commands to schedule */ if (dset->nentries == 1) { dset->entries = &dset->single.ent; dset->valid_entries = &dset->single.entp; } else { dset->ht = lcb_hashtable_nc_new(dset->nentries); dset->entries = calloc(dset->nentries, sizeof(*dset->entries)); dset->valid_entries = malloc(dset->nentries * sizeof(*dset->valid_entries)); if (dset->entries == NULL || dset->valid_entries == NULL) { lcb_durability_dset_destroy(dset); return LCB_CLIENT_ENOMEM; } } /* set up the observe commands */ for (ii = 0; ii < dset->nentries; ii++) { lcb_durability_entry_t *ent = dset->entries + ii; ent_init(cmds[ii], ent); ent->parent = dset; if (dset->nentries > 1) { int mt = genhash_update(dset->ht, REQFLD(ent, key), REQFLD(ent, nkey), ent, 0); if (mt != NEW) { lcb_durability_dset_destroy(dset); return LCB_DUPLICATE_COMMANDS; } } } /** * Increase the refcount by one. This will be decremented * when the remaining_total count hits 0 */ dset_ref(dset); hashset_add(instance->durability_polls, dset); timer_schedule(dset, 0, STATE_OBSPOLL); return lcb_synchandler_return(instance, LCB_SUCCESS); }