コード例 #1
0
ファイル: handler.c プロジェクト: NewtrendDesign/libcouchbase
/**
 * Handles the propagation and population of the 'synctoken' information.
 * @param mc_resp The response packet
 * @param req The request packet (used to get the vBucket)
 * @param tgt Pointer to synctoken which should be populated.
 */
static void
handle_synctoken(lcb_t instance, const packet_info *mc_resp,
    const mc_PACKET *req, lcb_SYNCTOKEN *stok)
{
    const char *sbuf;
    uint16_t vbid;

    if (PACKET_EXTLEN(mc_resp) == 0) {
        return; /* No extras */
    }

    if (!instance->dcpinfo && LCBT_SETTING(instance, dur_synctokens)) {
        size_t nvb = LCBT_VBCONFIG(instance)->nvb;
        if (nvb) {
            instance->dcpinfo = calloc(nvb, sizeof(*instance->dcpinfo));
        }
    }

    sbuf = PACKET_BODY(mc_resp);
    vbid = mcreq_get_vbucket(req);
    stok->vbid_ = vbid;
    memcpy(&stok->uuid_, sbuf, 8);
    memcpy(&stok->seqno_, sbuf + 8, 8);

    stok->uuid_ = lcb_ntohll(stok->uuid_);
    stok->seqno_ = lcb_ntohll(stok->seqno_);

    if (instance->dcpinfo) {
        instance->dcpinfo[vbid] = *stok;
    }
}
コード例 #2
0
ファイル: durability.c プロジェクト: Akshayvs/Solr-Search
void
lcbdur_prepare_item(lcb_DURITEM *ent, lcb_U16 *ixarray, size_t *nitems)
{
    size_t ii, oix = 0, maxix = 0;
    lcb_DURSET *dset = ent->parent;
    lcb_t instance = dset->instance;
    lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance);

    RESFLD(ent, persisted_master) = 0;
    RESFLD(ent, exists_master) = 0;
    RESFLD(ent, npersisted) = 0;
    RESFLD(ent, nreplicated) = 0;
    RESFLD(ent, cas) = 0;
    RESFLD(ent, rc) = LCB_SUCCESS;

    if (DSET_OPTFLD(dset, persist_to) == 1 &&
            DSET_OPTFLD(dset, replicate_to) == 0) {
        maxix = 1; /* Only master! */
    } else {
        maxix = LCBT_NREPLICAS(instance) + 1;
    }

    for (ii = 0; ii < maxix; ii++) {
        int cur_ix;
        lcbdur_SERVINFO *info = &ent->sinfo[ii];
        const mc_SERVER *s_exp;

        cur_ix = lcbvb_vbserver(vbc, ent->vbid, ii);
        if (cur_ix < 0) {
            memset(info, 0, sizeof(*info));
            continue;
        }

        s_exp = LCBT_GET_SERVER(instance, cur_ix);
        if (s_exp != info->server) {
            memset(info, 0, sizeof(*info));

        } else if (server_criteria_satisfied(ent, info, ii==0)) {
            /* Update counters as required */
            if (ii == 0) {
                RESFLD(ent, exists_master) = 1;
            } else {
                RESFLD(ent, nreplicated)++;
            }

            if (info->persisted) {
                RESFLD(ent, npersisted)++;
                if (ii == 0) {
                    RESFLD(ent, persisted_master) = 1;
                }
            }
            continue;
        }

        /* Otherwise, write the expected server out */
        ixarray[oix++] = s_exp->pipeline.index;
    }
    *nitems = oix;
}
コード例 #3
0
ファイル: nodeinfo.c プロジェクト: 00christian00/couchnode
LIBCOUCHBASE_API
lcb_int32_t lcb_get_num_nodes(lcb_t instance)
{
    if (LCBT_VBCONFIG(instance)) {
        return LCBT_NSERVERS(instance);
    } else {
        return -1;
    }
}
コード例 #4
0
ファイル: nodeinfo.c プロジェクト: 00christian00/couchnode
LIBCOUCHBASE_API
lcb_int32_t lcb_get_num_replicas(lcb_t instance)
{
    if (LCBT_VBCONFIG(instance)) {
        return LCBT_NREPLICAS(instance);
    } else {
        return -1;
    }
}
コード例 #5
0
ファイル: durability.c プロジェクト: Demotix/couchnode
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;
}
コード例 #6
0
ファイル: durability.c プロジェクト: Akshayvs/Solr-Search
lcbdur_SERVINFO *
lcbdur_ent_getinfo(lcb_DURITEM *item, int srvix)
{
    size_t ii;
    lcb_t instance = item->parent->instance;

    for (ii = 0; ii < LCBT_NREPLICAS(instance)+1; ii++) {
        int ix = lcbvb_vbserver(LCBT_VBCONFIG(instance), item->vbid, ii);
        if (ix > -1 && ix == srvix) {
            return &item->sinfo[ii];
        }
    }
    return NULL;
}
コード例 #7
0
/**
 * Invoked when get a NOT_MY_VBUCKET response. If the response contains a JSON
 * payload then we refresh the configuration with it.
 *
 * This function returns 1 if the operation was successfully rescheduled;
 * otherwise it returns 0. If it returns 0 then we give the error back to the
 * user.
 */
static int
handle_nmv(mc_SERVER *oldsrv, packet_info *resinfo, mc_PACKET *oldpkt)
{
    mc_PACKET *newpkt;
    protocol_binary_request_header hdr;
    lcb_error_t err = LCB_ERROR;
    lcb_t instance = oldsrv->instance;
    lcb_U16 vbid;
    int tmpix;
    clconfig_provider *cccp = lcb_confmon_get_provider(instance->confmon,
        LCB_CLCONFIG_CCCP);

    mcreq_read_hdr(oldpkt, &hdr);
    vbid = ntohs(hdr.request.vbucket);
    lcb_log(LOGARGS(oldsrv, WARN), LOGFMT "NOT_MY_VBUCKET. Packet=%p (S=%u). VBID=%u", LOGID(oldsrv), (void*)oldpkt, oldpkt->opaque, vbid);

    /* Notify of new map */
    tmpix = lcb_vbguess_remap(LCBT_VBCONFIG(instance),
        instance->vbguess, vbid, oldsrv->pipeline.index);
    if (tmpix > -1 && tmpix != oldsrv->pipeline.index) {
        lcb_log(LOGARGS(oldsrv, TRACE), LOGFMT "Heuristically set IX=%d as master for VBID=%u", LOGID(oldsrv), tmpix, vbid);
    }

    if (PACKET_NBODY(resinfo) && cccp->enabled) {
        lcb_string s;

        lcb_string_init(&s);
        lcb_string_append(&s, PACKET_VALUE(resinfo), PACKET_NVALUE(resinfo));
        err = lcb_cccp_update(cccp, mcserver_get_host(oldsrv), &s);
        lcb_string_release(&s);
    }

    if (err != LCB_SUCCESS) {
        lcb_bootstrap_common(instance, LCB_BS_REFRESH_ALWAYS);
    }

    if (!lcb_should_retry(oldsrv->settings, oldpkt, LCB_NOT_MY_VBUCKET)) {
        return 0;
    }

    /** Reschedule the packet again .. */
    newpkt = mcreq_renew_packet(oldpkt);
    newpkt->flags &= ~MCREQ_STATE_FLAGS;
    lcb_retryq_add(instance->retryq, (mc_EXPACKET*)newpkt, LCB_NOT_MY_VBUCKET);
    return 1;
}
コード例 #8
0
ファイル: durability.c プロジェクト: Akshayvs/Solr-Search
void
lcbdur_update_item(lcb_DURITEM *item, int flags, int srvix)
{
    lcbdur_SERVINFO *info;
    lcb_t instance;
    int is_master;
    const mc_SERVER *server;

    if (!flags || item->done) {
        return;
    }

    info = lcbdur_ent_getinfo(item, srvix);
    if (!info) {
        lcb_log(LOGARGS(item->parent, DEBUG), "Ignoring response from server %d. Not a master or replica for vBucket %d", srvix, item->vbid);
        return;
    }

    instance = item->parent->instance;
    is_master = lcbvb_vbmaster(LCBT_VBCONFIG(instance), item->vbid) == srvix;
    server = LCBT_GET_SERVER(instance, srvix);

    memset(info, 0, sizeof(*info));
    info->server = server;

    if (flags & LCBDUR_UPDATE_PERSISTED) {
        info->persisted = 1;
        RESFLD(item, npersisted)++;
        if (is_master) {
            RESFLD(item, persisted_master) = 1;
        }
    }
    if (flags & LCBDUR_UPDATE_REPLICATED) {
        info->exists = 1;
        if (is_master) {
            RESFLD(item, exists_master) = 1;
        } else {
            RESFLD(item, nreplicated)++;
        }
    }
    if (lcbdur_ent_check_done(item)) {
        RESFLD(item, rc) = LCB_SUCCESS;
        lcbdur_ent_finish(item);
    }
}
コード例 #9
0
ファイル: wait.c プロジェクト: Akshayvs/Solr-Search
/**
 * Run the event loop until we've got a response for all of our spooled
 * commands. You should not call this function from within your callbacks.
 *
 * @param instance the instance to run the event loop for.
 *
 * @author Trond Norbye
 */
LIBCOUCHBASE_API
lcb_error_t lcb_wait(lcb_t instance)
{
    if (instance->wait != 0) {
        return instance->last_error;
    }

    if (!has_pending(instance)) {
        return LCB_SUCCESS;
    }

    maybe_reset_timeouts(instance);
    instance->last_error = LCB_SUCCESS;
    instance->wait = 1;
    IOT_START(instance->iotable);
    instance->wait = 0;

    if (LCBT_VBCONFIG(instance)) {
        return LCB_SUCCESS;
    }

    return instance->last_error;
}
コード例 #10
0
ファイル: observe.c プロジェクト: Ramzi-Alqrainy/libcouchbase
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;
}
コード例 #11
0
ファイル: durability.c プロジェクト: Akshayvs/Solr-Search
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;
}
コード例 #12
0
ファイル: nodeinfo.c プロジェクト: 00christian00/couchnode
LIBCOUCHBASE_API
const char *
lcb_get_node(lcb_t instance, lcb_GETNODETYPE type, unsigned ix)
{
    if (type & LCB_NODE_HTCONFIG) {
        if (type & LCB_NODE_CONNECTED) {
            const lcb_host_t *host = lcb_confmon_get_rest_host(instance->confmon);
            if (host) {
                return mk_scratch_host(instance, host);
            } else {
                return return_badhost(type);
            }

        } else {
            /* Retrieve one from the vbucket configuration */
            lcbvb_CONFIG *vbc = LCBT_VBCONFIG(instance);
            lcbvb_SVCMODE mode;
            const char *hp = NULL;
            if (LCBT_SETTING(instance, sslopts) & LCB_SSL_ENABLED) {
                mode = LCBVB_SVCMODE_SSL;
            } else {
                mode = LCBVB_SVCMODE_PLAIN;
            }

            if (instance->type == LCB_TYPE_BUCKET) {
                if (vbc) {
                    ix %= LCBVB_NSERVERS(vbc);
                    hp = lcbvb_get_hostport(vbc, ix, LCBVB_SVCTYPE_MGMT, mode);

                } else if ((type & LCB_NODE_NEVERNULL) == 0) {
                    return NULL;
                }
            }
            if (hp == NULL && instance->ht_nodes && instance->ht_nodes->nentries) {
                ix %= instance->ht_nodes->nentries;
                hostlist_ensure_strlist(instance->ht_nodes);
                hp = instance->ht_nodes->slentries[ix];
            }
            if (!hp) {
                if ((hp = return_badhost(type)) == NULL) {
                    return NULL;
                }
            }
            if (!ensure_scratch(instance, strlen(hp)+1)) {
                return NULL;
            }
            lcb_string_appendz(instance->scratch, hp);
            return instance->scratch->base;
        }
    } else if (type & (LCB_NODE_DATA|LCB_NODE_VIEWS)) {
        const mc_SERVER *server;
        ix %= LCBT_NSERVERS(instance);
        server = LCBT_GET_SERVER(instance, ix);

        if ((type & LCB_NODE_CONNECTED) && server->connctx == NULL) {
            return return_badhost(type);
        }
        if (server->curhost == NULL) {
            return return_badhost(type);
        }

        /* otherwise, return the actual host:port of the server */
        if (type & LCB_NODE_DATA) {
            return mk_scratch_host(instance, server->curhost);
        } else {
            return server->viewshost;
        }
    } else {
        return NULL; /* don't know the type */
    }
}
コード例 #13
0
ファイル: observe.c プロジェクト: NewtrendDesign/libcouchbase
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;
}
コード例 #14
0
ファイル: bootstrap.c プロジェクト: 00christian00/couchnode
/**
 * 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);
}