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); }
/** * Decrement the refcount for the 'dset'. When it hits zero then the dset is * freed. */ static void dset_unref(lcb_durability_set_t *dset) { if (--dset->refcnt == 0) { lcb_durability_dset_destroy(dset); } }
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); }
LIBCOUCHBASE_API void lcb_destroy(lcb_t instance) { lcb_size_t ii; lcb_settings *settings = &instance->settings; if (instance->cur_configinfo) { lcb_clconfig_decref(instance->cur_configinfo); instance->cur_configinfo = NULL; } instance->vbucket_config = NULL; lcb_bootstrap_destroy(instance); lcb_confmon_destroy(instance->confmon); hostlist_destroy(instance->usernodes); if (instance->timers != NULL) { for (ii = 0; ii < instance->timers->capacity; ++ii) { if (instance->timers->items[ii] > 1) { lcb_timer_destroy(instance, (lcb_timer_t)instance->timers->items[ii]); } } hashset_destroy(instance->timers); } if (instance->durability_polls) { struct lcb_durability_set_st **dset_list; lcb_size_t nitems = hashset_num_items(instance->durability_polls); dset_list = (struct lcb_durability_set_st **) hashset_get_items(instance->durability_polls, NULL); if (dset_list) { for (ii = 0; ii < nitems; ii++) { lcb_durability_dset_destroy(dset_list[ii]); } free(dset_list); } hashset_destroy(instance->durability_polls); } for (ii = 0; ii < instance->nservers; ++ii) { lcb_server_destroy(instance->servers + ii); } if (instance->http_requests) { for (ii = 0; ii < instance->http_requests->capacity; ++ii) { if (instance->http_requests->items[ii] > 1) { lcb_http_request_t htreq = (lcb_http_request_t)instance->http_requests->items[ii]; /** * We don't want to invoke callbacks *or* remove it from our * hash table */ htreq->status |= LCB_HTREQ_S_CBINVOKED | LCB_HTREQ_S_HTREMOVED; /* we should figure out a better error code for this.. */ lcb_http_request_finish(instance, htreq, LCB_ERROR); } } } hashset_destroy(instance->http_requests); free(instance->servers); connmgr_destroy(instance->memd_sockpool); if (settings->io && settings->io->v.v0.need_cleanup) { lcb_destroy_io_ops(settings->io); } ringbuffer_destruct(&instance->purged_buf); ringbuffer_destruct(&instance->purged_cookies); free(instance->histogram); free(instance->scratch); free(settings->username); free(settings->password); free(settings->bucket); free(settings->sasl_mech_force); if (instance->cmdht) { genhash_free(instance->cmdht); instance->cmdht = NULL; } memset(instance, 0xff, sizeof(*instance)); free(instance); }
static void dset_ctx_fail(lcb_MULTICMD_CTX *mctx) { lcb_DURSET *dset = CTX_FROM_MULTI(mctx); lcb_durability_dset_destroy(dset); }