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; }
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; }
/** * This function is where the configuration actually takes place. We ensure * in other functions that this is only ever called directly from an event * loop stack frame (or one of the small mini functions here) so that we * don't accidentally end up destroying resources underneath us. */ static void config_callback(clconfig_listener *listener, clconfig_event_t event, clconfig_info *info) { struct lcb_BOOTSTRAP *bs = (struct lcb_BOOTSTRAP *)listener; lcb_t instance = bs->parent; if (event != CLCONFIG_EVENT_GOT_NEW_CONFIG) { if (event == CLCONFIG_EVENT_PROVIDERS_CYCLED) { if (!LCBT_VBCONFIG(instance)) { initial_bootstrap_error( instance, LCB_ERROR, "No more bootstrap providers remain"); } } return; } instance->last_error = LCB_SUCCESS; /** Ensure we're not called directly twice again */ listener->callback = async_step_callback; lcbio_timer_disarm(bs->tm); lcb_log(LOGARGS(instance, DEBUG), "Instance configured!"); if (info->origin != LCB_CLCONFIG_FILE) { /* Set the timestamp for the current config to control throttling, * but only if it's not an initial file-based config. See CCBC-482 */ bs->last_refresh = gethrtime(); bs->errcounter = 0; } if (info->origin == LCB_CLCONFIG_CCCP) { /* Disable HTTP provider if we've received something via CCCP */ if (instance->cur_configinfo == NULL || instance->cur_configinfo->origin != LCB_CLCONFIG_HTTP) { /* Never disable HTTP if it's still being used */ lcb_confmon_set_provider_active( instance->confmon, LCB_CLCONFIG_HTTP, 0); } } if (instance->type != LCB_TYPE_CLUSTER) { lcb_update_vbconfig(instance, info); } if (!bs->bootstrapped) { bs->bootstrapped = 1; lcb_aspend_del(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL); if (instance->type == LCB_TYPE_BUCKET && LCBVB_DISTTYPE(LCBT_VBCONFIG(instance)) == LCBVB_DIST_KETAMA && instance->cur_configinfo->origin != LCB_CLCONFIG_MCRAW) { lcb_log(LOGARGS(instance, INFO), "Reverting to HTTP Config for memcached buckets"); instance->settings->bc_http_stream_time = -1; lcb_confmon_set_provider_active( instance->confmon, LCB_CLCONFIG_HTTP, 1); lcb_confmon_set_provider_active( instance->confmon, LCB_CLCONFIG_CCCP, 0); } instance->callbacks.bootstrap(instance, LCB_SUCCESS); } lcb_maybe_breakout(instance); }