示例#1
0
void lcb_timeout_server(lcb_server_t *server)
{
    hrtime_t now, min_valid, next_ns = 0;
    lcb_uint32_t next_us;

    LOG(server, ERR, "Server timed out");
    lcb_bootstrap_errcount_incr(server->instance);

    if (!server->connection_ready) {
        lcb_failout_server(server, LCB_ETIMEDOUT);
        return;
    }

    now = gethrtime();

    /** The oldest valid command timestamp */
    min_valid = now - ((hrtime_t)MCSERVER_TIMEOUT(server)) * 1000;

    purge_single_server(server, LCB_ETIMEDOUT, min_valid, &next_ns);
    if (next_ns) {
        next_us = (lcb_uint32_t) (next_ns / 1000);

    } else {
        next_us = MCSERVER_TIMEOUT(server);
    }

    lcb_log(LOGARGS(server, INFO),
            "%p, Scheduling next timeout for %d ms",
            server,
            next_us / 1000);

    lcb_timer_rearm(server->io_timer, next_us);
    lcb_maybe_breakout(server->instance);
}
示例#2
0
void lcb_server_send_packets(lcb_server_t *server)
{
    if (server->pending.nbytes > 0 || server->connection.output->nbytes > 0) {
        if (server->connection_ready) {
            lcb_sockrw_set_want(&server->connection, LCB_WRITE_EVENT, 0);
            if (!server->inside_handler) {
                lcb_sockrw_apply_want(&server->connection);
                if (!lcb_timer_armed(server->io_timer)) {
                    lcb_timer_rearm(server->io_timer, MCSERVER_TIMEOUT(server));
                }
            }

        } else if (server->connection.state == LCB_CONNSTATE_UNINIT) {
            lcb_server_connect(server);
        }
    }
}
示例#3
0
void
mcserver_flush(mc_SERVER *server)
{
    /** Call into the wwant stuff.. */
    if (!server->connctx->rdwant) {
        lcbio_ctx_rwant(server->connctx, 24);
    }

    lcbio_ctx_wwant(server->connctx);
    lcbio_ctx_schedule(server->connctx);

    if (!lcbio_timer_armed(server->io_timer)) {
        /**
         * XXX: Maybe use get_next_timeout(), although here we can assume
         * that a command was just scheduled
         */
        lcbio_timer_rearm(server->io_timer, MCSERVER_TIMEOUT(server));
    }
}
示例#4
0
lcb_error_t lcb_server_initialize(lcb_server_t *server, int servernum)
{
    /* Initialize all members */
    lcb_error_t err;
    char *p;
    const char *n = vbucket_config_get_server(server->instance->vbucket_config,
                                              servernum);

    err = lcb_connection_init(&server->connection,
                              server->instance->settings.io,
                              &server->instance->settings);
    if (err != LCB_SUCCESS) {
        return err;
    }

    server->connection.data = server;
    server->index = servernum;
    server->authority = strdup(n);
    strcpy(server->curhost.host, n);
    p = strchr(server->curhost.host, ':');
    *p = '\0';
    strcpy(server->curhost.port, p + 1);

    n = vbucket_config_get_couch_api_base(server->instance->vbucket_config,
                                          servernum);
    server->couch_api_base = (n != NULL) ? strdup(n) : NULL;
    n = vbucket_config_get_rest_api_server(server->instance->vbucket_config,
                                           servernum);
    server->rest_api_server = strdup(n);
    server->io_timer = lcb_timer_create_simple(server->instance->settings.io,
                                               server, MCSERVER_TIMEOUT(server),
                                               tmo_thunk);
    lcb_timer_disarm(server->io_timer);

    return LCB_SUCCESS;
}
示例#5
0
/**
 * Returns 1 if retried, 0 if the command should fail, -1 for an internal
 * error
 */
static int handle_not_my_vbucket(lcb_server_t *c,
                                 packet_info *resinfo,
                                 protocol_binary_request_header *oldreq,
                                 struct lcb_command_data_st *oldct)
{
    int idx;
    char *body;
    lcb_size_t nbody, nr;
    lcb_server_t *new_srv;
    struct lcb_command_data_st ct;
    protocol_binary_request_header req;
    hrtime_t now;
    lcb_string config_string;
    lcb_error_t err = LCB_ERROR;

    lcb_log(LOGARGS(c, WARN),
            "NOT_MY_VBUCKET; Server=%p,ix=%d,real_start=%lu,vb=%d",
            (void *)c, c->index,
            (unsigned long)oldct->real_start,
            (int)ntohs(oldreq->request.vbucket));

    lcb_string_init(&config_string);
    if (PACKET_NBODY(resinfo)) {
        lcb_string_append(&config_string,
                          PACKET_VALUE(resinfo),
                          PACKET_NVALUE(resinfo));

        err = lcb_cccp_update(lcb_confmon_get_provider(c->instance->confmon,
                              LCB_CLCONFIG_CCCP),
                              c->curhost.host,
                              &config_string);
    }

    lcb_string_release(&config_string);

    if (err != LCB_SUCCESS) {
        lcb_bootstrap_refresh(c->instance);
    }

    /* re-schedule command to new server */
    if (!c->instance->settings.vb_noguess) {
        idx = vbucket_found_incorrect_master(c->instance->vbucket_config,
                                             ntohs(oldreq->request.vbucket),
                                             (int)c->index);
    } else {
        idx = c->index;
    }

    if (idx == -1) {
        lcb_log(LOGARGS(c, ERR), "no alternate server");
        return 0;
    }
    lcb_log(LOGARGS(c, INFO), "Mapped key to new server %d -> %d",
            c->index, idx);

    now = gethrtime();

    if (oldct->real_start) {
        hrtime_t min_ok = now - MCSERVER_TIMEOUT(c) * 1000;
        if (oldct->real_start < min_ok) {
            /** Timed out in a 'natural' manner */
            return 0;
        }
    }

    req = *oldreq;

    lcb_assert((lcb_size_t)idx < c->instance->nservers);
    new_srv = c->instance->servers + idx;

    nr = ringbuffer_read(&c->cmd_log, req.bytes, sizeof(req));
    lcb_assert(nr == sizeof(req));

    req.request.opaque = ++c->instance->seqno;
    nbody = ntohl(req.request.bodylen);
    body = malloc(nbody);
    if (body == NULL) {
        lcb_error_handler(c->instance, LCB_CLIENT_ENOMEM, NULL);
        return -1;
    }
    nr = ringbuffer_read(&c->cmd_log, body, nbody);
    lcb_assert(nr == nbody);
    nr = ringbuffer_read(&c->output_cookies, &ct, sizeof(ct));
    lcb_assert(nr == sizeof(ct));

    /* Preserve the cookie and reset timestamp for the command. This
     * means that the library will retry the command until it will
     * get code different from LCB_NOT_MY_VBUCKET */
    if (!ct.real_start) {
        ct.real_start = ct.start;
    }
    ct.start = now;

    lcb_server_retry_packet(new_srv, &ct, &req, sizeof(req));
    /* FIXME dtrace instrumentation */
    lcb_server_write_packet(new_srv, body, nbody);
    lcb_server_end_packet(new_srv);
    lcb_server_send_packets(new_srv);
    free(body);

    return 1;
}