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; }
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)); }
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); }
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)); }
/** * 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); }
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; }
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; }
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; }
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; }
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; }
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); } } }