Example #1
0
static lcb_error_t get_refresh(clconfig_provider *provider)
{
    http_provider *http = (http_provider *)provider;

    /**
     * We want a grace interval here because we might already be fetching a
     * connection. HOWEVER we don't want to indefinitely wait on a socket
     * so we issue a timer indicating how long we expect to wait for a
     * streaming update until we get something.
     */

    /** If we need a new socket, we do connect_next. */
    if (http->connection.state == LCB_CONNSTATE_UNINIT) {
        lcb_error_t rc = connect_next(http);
        if (rc != LCB_SUCCESS) {
            http->as_errcode = rc;
            lcb_async_signal(http->as_schederr);
        }
        return rc;
    }

    lcb_timer_disarm(http->disconn_timer);
    if (http->connection.state == LCB_CONNSTATE_CONNECTED) {
        lcb_timer_rearm(http->io_timer,
                        PROVIDER_SETTING(provider, config_node_timeout));
    }
    return LCB_SUCCESS;
}
Example #2
0
static void request_config(cccp_provider *cccp)
{
    protocol_binary_request_set_cluster_config req;
    lcb_connection_t conn = &cccp->connection;
    ringbuffer_t *buf = conn->output;

    memset(&req, 0, sizeof(req));
    req.message.header.request.magic = PROTOCOL_BINARY_REQ;
    req.message.header.request.opcode = CMD_GET_CLUSTER_CONFIG;
    req.message.header.request.opaque = 0xF00D;

    if (!buf) {
        if ((buf = calloc(1, sizeof(*buf))) == NULL) {
            mcio_error(cccp, LCB_CLIENT_ENOMEM);
            return;
        }
        conn->output = buf;
    }

    if (!ringbuffer_ensure_capacity(buf, sizeof(req.bytes))) {
        mcio_error(cccp, LCB_CLIENT_ENOMEM);
    }

    ringbuffer_write(buf, req.bytes, sizeof(req.bytes));
    lcb_sockrw_set_want(conn, LCB_WRITE_EVENT, 1);
    lcb_sockrw_apply_want(conn);
    lcb_timer_rearm(cccp->timer, PROVIDER_SETTING(&cccp->base,
                                                  config_node_timeout));
}
Example #3
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);
}
Example #4
0
static void connect_done_handler(lcb_connection_t conn, lcb_error_t err)
{
    http_provider *http = (http_provider *)conn->data;
    const lcb_host_t *host = lcb_connection_get_host(conn);

    if (err != LCB_SUCCESS) {
        lcb_log(LOGARGS(http, ERR),
                "Connection to REST API @%s:%s failed with code=0x%x",
                host->host, host->port, err);

        io_error(http, err);
        return;
    }

    lcb_log(LOGARGS(http, DEBUG),
            "Successfuly connected to REST API %s:%s",
            host->host, host->port);

    lcb_connection_reset_buffers(conn);
    ringbuffer_strcat(conn->output, http->request_buf);
    lcb_assert(conn->output->nbytes > 0);

    lcb_sockrw_set_want(conn, LCB_RW_EVENT, 0);
    lcb_sockrw_apply_want(conn);
    lcb_timer_rearm(http->io_timer,
                    PROVIDER_SETTING(&http->base, config_node_timeout));
}
Example #5
0
/**
 * Common function to handle parsing the HTTP stream for both v0 and v1 io
 * implementations.
 */
static void read_common(http_provider *http)
{
    lcb_error_t err;
    lcb_connection_t conn = &http->connection;
    int old_generation = http->stream.generation;

    lcb_log(LOGARGS(http, TRACE),
            "Received %d bytes on HTTP stream", conn->input->nbytes);

    lcb_timer_rearm(http->io_timer,
                    PROVIDER_SETTING(&http->base, config_node_timeout));

    lcb_string_rbappend(&http->stream.chunk, conn->input, 1);

    err = htvb_parse(&http->stream, http->base.parent->settings->conntype);

    if (http->stream.generation != old_generation) {
        lcb_log(LOGARGS(http, DEBUG),
                "Generation %d -> %d", old_generation, http->stream.generation);

        set_new_config(http);
    } else {
        lcb_log(LOGARGS(http, TRACE), "HTTP not yet done. Err=0x%x", err);
    }

    if (err != LCB_BUSY && err != LCB_SUCCESS) {
        io_error(http, err);
        return;
    }

    lcb_sockrw_set_want(conn, LCB_READ_EVENT, 1);
    lcb_sockrw_apply_want(conn);
}
Example #6
0
static void timer_callback(lcb_socket_t sock, short which, void *arg)
{
    lcb_timer_t timer = arg;
    lcb_t instance = timer->instance;

    lcb_assert(TMR_IS_ARMED(timer));
    lcb_assert(!TMR_IS_DESTROYED(timer));

    timer->state |= LCB_TIMER_S_ENTERED;

    lcb_timer_disarm(timer);
    timer->callback(timer, instance, timer->cookie);

    if (TMR_IS_DESTROYED(timer) == 0 && TMR_IS_PERIODIC(timer) != 0) {
        lcb_timer_rearm(timer, timer->usec_);
        return;
    }

    if (! TMR_IS_STANDALONE(timer)) {
        lcb_aspend_del(&instance->pendops, LCB_PENDTYPE_TIMER, timer);
        lcb_maybe_breakout(instance);
    }

    if (TMR_IS_DESTROYED(timer)) {
        destroy_timer(timer);
    } else {
        timer->state &= ~LCB_TIMER_S_ENTERED;
    }

    (void)sock;
    (void)which;
}
Example #7
0
static lcb_error_t schedule_next_request(cccp_provider *cccp,
        lcb_error_t err,
        int can_rollover)
{
    lcb_server_t *server = NULL;
    lcb_size_t ii;

    lcb_host_t *next_host = hostlist_shift_next(cccp->nodes, can_rollover);

    if (!next_host) {
        lcb_timer_disarm(cccp->timer);
        lcb_confmon_provider_failed(&cccp->base, err);
        cccp->server_active = 0;
        return err;
    }

    /** See if we can find a server */
    for (ii = 0; ii < cccp->instance->nservers; ii++) {
        lcb_server_t *cur = cccp->instance->servers + ii;
        if (lcb_host_equals(&cur->curhost, next_host)) {
            server = cur;
            break;
        }
    }

    if (server) {
        protocol_binary_request_get_cluster_config req;
        cccp_cookie *cookie = calloc(1, sizeof(*cookie));

        lcb_log(LOGARGS(cccp, INFO),
                "Re-Issuing CCCP Command on server struct %p", server);

        cookie->parent = cccp;
        memset(&req, 0, sizeof(req));
        req.message.header.request.magic = PROTOCOL_BINARY_REQ;
        req.message.header.request.opcode = CMD_GET_CLUSTER_CONFIG;
        req.message.header.request.opaque = ++cccp->instance->seqno;
        lcb_server_start_packet(server, cookie, &req, sizeof(req.bytes));
        lcb_server_end_packet(server);
        lcb_server_send_packets(server);
        lcb_timer_rearm(cccp->timer, PROVIDER_SETTING(&cccp->base,
                        config_node_timeout));
    } else {
        cccp->cur_connreq = calloc(1, sizeof(*cccp->cur_connreq));
        connmgr_req_init(cccp->cur_connreq, next_host->host, next_host->port,
                         socket_connected);
        cccp->cur_connreq->data = cccp;
        connmgr_get(cccp->instance->memd_sockpool, cccp->cur_connreq,
                    PROVIDER_SETTING(&cccp->base, config_node_timeout));
    }

    cccp->server_active = 1;
    return LCB_SUCCESS;
}
Example #8
0
static lcb_error_t pause_http(clconfig_provider *pb)
{
    http_provider *http = (http_provider *)pb;
    if (is_v220_compat(http)) {
        return LCB_SUCCESS;
    }

    if (!lcb_timer_armed(http->disconn_timer)) {
        lcb_timer_rearm(http->disconn_timer,
                        PROVIDER_SETTING(pb, bc_http_stream_time));
    }
    return LCB_SUCCESS;
}
Example #9
0
static lcb_error_t pause_http(clconfig_provider *pb)
{
    http_provider *http = (http_provider *)pb;
    if (http->always_on) {
        lcb_timer_disarm(http->io_timer);
        return LCB_SUCCESS;
    }

    if (!lcb_timer_armed(http->disconn_timer)) {
        lcb_timer_rearm(http->disconn_timer,
                        PROVIDER_SETTING(pb, bc_http_stream_time));
    }
    return LCB_SUCCESS;
}
Example #10
0
LCB_INTERNAL_API
lcb_timer_t lcb_timer_create2(lcbio_TABLE *io,
                              const void *cookie,
                              lcb_uint32_t usec,
                              lcb_timer_options options,
                              lcb_timer_callback callback,
                              lcb_t instance,
                              lcb_error_t *error)
{
    lcb_timer_t tmr = calloc(1, sizeof(struct lcb_timer_st));
    tmr->io = io;

    if (!tmr) {
        *error = LCB_CLIENT_ENOMEM;
        return NULL;
    }
    if (!callback) {
        *error = LCB_EINVAL;
        return NULL;
    }

    if (! (options & LCB_TIMER_STANDALONE)) {
        lcb_assert(instance);
    }

    lcbio_table_ref(tmr->io);
    tmr->instance = instance;
    tmr->callback = callback;
    tmr->cookie = cookie;
    tmr->options = options;
    tmr->event = io->timer.create(io->p);

    if (tmr->event == NULL) {
        free(tmr);
        *error = LCB_CLIENT_ENOMEM;
        return NULL;
    }

    if ( (options & LCB_TIMER_STANDALONE) == 0) {
        lcb_aspend_add(&instance->pendops, LCB_PENDTYPE_TIMER, tmr);
    }

    lcb_timer_rearm(tmr, usec);

    *error = LCB_SUCCESS;
    return tmr;
}
Example #11
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);
        }
    }
}