/** * Release all allocated resources for this server instance * @param server the server to destroy */ void lcb_server_destroy(lcb_server_t *server) { lcb_server_release_connection(server, LCB_SUCCESS); /* Cancel all pending commands */ if (server->cmd_log.nbytes) { lcb_server_purge_implicit_responses(server, server->instance->seqno, gethrtime(), 1); } if (server->io_timer) { lcb_timer_destroy(NULL, server->io_timer); } lcb_connection_cleanup(&server->connection); free(server->rest_api_server); free(server->couch_api_base); free(server->authority); ringbuffer_destruct(&server->output_cookies); ringbuffer_destruct(&server->cmd_log); ringbuffer_destruct(&server->pending); ringbuffer_destruct(&server->pending_cookies); memset(server, 0xff, sizeof(*server)); }
static void Cw_handler(lcb_sockdata_t *sd, int status, void *arg) { lcbio__EASYRB *erb = arg; lcbio_CTX *ctx = erb->parent; (void)sd; ctx->npending--; if (!ctx->output) { ctx->output = erb; ringbuffer_reset(&erb->rb); } else { ringbuffer_destruct(&erb->rb); free(erb); } if (ctx->state == ES_ACTIVE && status) { invoke_entered_errcb(ctx, convert_lcberr(ctx, LCBIO_IOERR)); } if (ctx->state != ES_ACTIVE && ctx->npending == 0) { free_ctx(ctx); } }
static void destroy_request(struct observe_st *req) { if (req->allocated) { ringbuffer_destruct(&req->body); req->allocated = 0; } }
void lcbio_ctx_close_ex(lcbio_CTX *ctx, lcbio_CTXCLOSE_cb cb, void *arg, lcbio_CTXDTOR_cb dtor, void *dtor_arg) { unsigned oldrc; ctx->state = ES_DETACHED; assert(ctx->sock); if (ctx->event) { deactivate_watcher(ctx); IOT_V0EV(CTX_IOT(ctx)).destroy(IOT_ARG(CTX_IOT(ctx)), ctx->event); ctx->event = NULL; } if (ctx->as_err) { lcbio_timer_destroy(ctx->as_err); ctx->as_err = NULL; } oldrc = ctx->sock->refcount; lcb_log(LOGARGS(ctx, DEBUG), CTX_LOGFMT "Destroying. PND=%d,ENT=%d,SORC=%d", CTX_LOGID(ctx), (int)ctx->npending, (int)ctx->entered, oldrc); if (cb) { int reusable = ctx->npending == 0 && /* no pending events */ ctx->err == LCB_SUCCESS && /* no socket errors */ ctx->rdwant == 0 && /* no expected input */ ctx->wwant == 0 && /* no expected output */ (ctx->output == NULL || ctx->output->rb.nbytes == 0); cb(ctx->sock, reusable, arg); } if (oldrc == ctx->sock->refcount) { lcbio_shutdown(ctx->sock); } if (ctx->output) { ringbuffer_destruct(&ctx->output->rb); free(ctx->output); ctx->output = NULL; } ctx->fd = INVALID_SOCKET; ctx->sd = NULL; if (dtor) { ctx->data = dtor_arg; ctx->procs.cb_flush_ready = dtor; } else { ctx->procs.cb_flush_ready = NULL; } if (ctx->npending == 0 && ctx->entered == 0) { free_ctx(ctx); } }
static void destroy_requests(OBSERVECTX *reqs) { lcb_size_t ii; for (ii = 0; ii < reqs->nrequests; ii++) { struct observe_st *rr = reqs->requests + ii; if (!rr->allocated) { continue; } ringbuffer_destruct(&rr->body); rr->allocated = 0; } }
void lcb_connection_cleanup(lcb_connection_t conn) { if (conn->ai) { freeaddrinfo(conn->ai); conn->ai = NULL; } if (conn->input) { ringbuffer_destruct(conn->input); free(conn->input); conn->input = NULL; } if (conn->output) { ringbuffer_destruct(conn->output); free(conn->output); conn->output = NULL; } lcb_connection_close(conn); if (conn->evinfo.ptr) { conn->instance->io->v.v0.destroy_event(conn->instance->io, conn->evinfo.ptr); conn->evinfo.ptr = NULL; } lcb_connection_cancel_timer(conn); if (conn->timeout.timer) { conn->instance->io->v.v0.destroy_timer(conn->instance->io, conn->timeout.timer); } memset(conn, 0, sizeof(*conn)); }
static void free_ctx(lcbio_CTX *ctx) { rdb_cleanup(&ctx->ior); lcbio_unref(ctx->sock); if (ctx->output) { ringbuffer_destruct(&ctx->output->rb); free(ctx->output); } if (ctx->procs.cb_flush_ready) { /* dtor */ ctx->procs.cb_flush_ready(ctx); } free(ctx); }
int ringbuffer_ensure_alignment(ringbuffer_t *c) { #if defined(__hpux__) || defined(__hpux) || defined(__sparc__) || defined(__sparc) intptr_t addr = (intptr_t)c->read_head; if (addr % 8 != 0) { ringbuffer_t copy; if (ringbuffer_initialize(©, c->size) == 0 || ringbuffer_memcpy(©, c, ringbuffer_get_nbytes(c)) == -1) { return -1; } ringbuffer_destruct(c); *c = copy; } #else (void)c; #endif return 0; }
LIBCOUCHBASE_API void lcb_destroy(lcb_t instance) { lcb_size_t ii; lcb_settings *settings = &instance->settings; if (instance->cur_configinfo) { lcb_clconfig_decref(instance->cur_configinfo); instance->cur_configinfo = NULL; } instance->vbucket_config = NULL; lcb_bootstrap_destroy(instance); lcb_confmon_destroy(instance->confmon); hostlist_destroy(instance->usernodes); if (instance->timers != NULL) { for (ii = 0; ii < instance->timers->capacity; ++ii) { if (instance->timers->items[ii] > 1) { lcb_timer_destroy(instance, (lcb_timer_t)instance->timers->items[ii]); } } hashset_destroy(instance->timers); } if (instance->durability_polls) { struct lcb_durability_set_st **dset_list; lcb_size_t nitems = hashset_num_items(instance->durability_polls); dset_list = (struct lcb_durability_set_st **) hashset_get_items(instance->durability_polls, NULL); if (dset_list) { for (ii = 0; ii < nitems; ii++) { lcb_durability_dset_destroy(dset_list[ii]); } free(dset_list); } hashset_destroy(instance->durability_polls); } for (ii = 0; ii < instance->nservers; ++ii) { lcb_server_destroy(instance->servers + ii); } if (instance->http_requests) { for (ii = 0; ii < instance->http_requests->capacity; ++ii) { if (instance->http_requests->items[ii] > 1) { lcb_http_request_t htreq = (lcb_http_request_t)instance->http_requests->items[ii]; /** * We don't want to invoke callbacks *or* remove it from our * hash table */ htreq->status |= LCB_HTREQ_S_CBINVOKED | LCB_HTREQ_S_HTREMOVED; /* we should figure out a better error code for this.. */ lcb_http_request_finish(instance, htreq, LCB_ERROR); } } } hashset_destroy(instance->http_requests); free(instance->servers); connmgr_destroy(instance->memd_sockpool); if (settings->io && settings->io->v.v0.need_cleanup) { lcb_destroy_io_ops(settings->io); } ringbuffer_destruct(&instance->purged_buf); ringbuffer_destruct(&instance->purged_cookies); free(instance->histogram); free(instance->scratch); free(settings->username); free(settings->password); free(settings->bucket); free(settings->sasl_mech_force); if (instance->cmdht) { genhash_free(instance->cmdht); instance->cmdht = NULL; } memset(instance, 0xff, sizeof(*instance)); free(instance); }
static void purge_single_server(lcb_server_t *server, lcb_error_t error, hrtime_t min_nonstale, hrtime_t *tmo_next) { protocol_binary_request_header req; struct lcb_command_data_st ct; lcb_size_t nr; char *packet; lcb_size_t packetsize; char *keyptr; ringbuffer_t rest; ringbuffer_t *stream = &server->cmd_log; ringbuffer_t *cookies; ringbuffer_t *mirror = NULL; /* mirror buffer should be purged with main stream */ lcb_connection_t conn = &server->connection; lcb_size_t send_size = 0; lcb_size_t stream_size = ringbuffer_get_nbytes(stream); hrtime_t now = gethrtime(); if (server->connection_ready) { cookies = &server->output_cookies; } else { cookies = &server->pending_cookies; mirror = &server->pending; } if (conn->output) { /* This will usually be false for v1 */ send_size = ringbuffer_get_nbytes(conn->output); } lcb_assert(ringbuffer_initialize(&rest, 1024)); do { int allocated = 0; lcb_uint32_t headersize; lcb_uint16_t nkey; nr = ringbuffer_peek(cookies, &ct, sizeof(ct)); if (nr != sizeof(ct)) { break; } nr = ringbuffer_peek(stream, req.bytes, sizeof(req)); if (nr != sizeof(req)) { break; } packetsize = (lcb_uint32_t)sizeof(req) + ntohl(req.request.bodylen); if (stream->nbytes < packetsize) { break; } if (min_nonstale && ct.start >= min_nonstale) { lcb_log(LOGARGS(server, INFO), "Still have %d ms remaining for command", (ct.start - min_nonstale) / 1000000); if (tmo_next) { *tmo_next = (ct.start - min_nonstale) + 1; } break; } lcb_log(LOGARGS(server, INFO), "Command with cookie=%p timed out from server %s:%s", ct.cookie, server->curhost.host, server->curhost.port); ringbuffer_consumed(cookies, sizeof(ct)); lcb_assert(nr == sizeof(req)); packet = stream->read_head; if (server->instance->histogram) { lcb_record_metrics(server->instance, now - ct.start, req.request.opcode); } if (server->connection_ready && stream_size > send_size && (stream_size - packetsize) < send_size) { /* Copy the rest of the current packet into the temporary stream */ /* I do believe I have some IOV functions to do that? */ lcb_size_t nbytes = packetsize - (stream_size - send_size); lcb_assert(ringbuffer_memcpy(&rest, conn->output, nbytes) == 0); ringbuffer_consumed(conn->output, nbytes); send_size -= nbytes; } stream_size -= packetsize; headersize = (lcb_uint32_t)sizeof(req) + req.request.extlen + htons(req.request.keylen); if (!ringbuffer_is_continous(stream, RINGBUFFER_READ, headersize)) { packet = malloc(headersize); if (packet == NULL) { lcb_error_handler(server->instance, LCB_CLIENT_ENOMEM, NULL); abort(); } nr = ringbuffer_peek(stream, packet, headersize); if (nr != headersize) { lcb_error_handler(server->instance, LCB_EINTERNAL, NULL); free(packet); abort(); } allocated = 1; } keyptr = packet + sizeof(req) + req.request.extlen; nkey = ntohs(req.request.keylen); failout_single_request(server, &req, &ct, error, keyptr, nkey, packet); if (allocated) { free(packet); } ringbuffer_consumed(stream, packetsize); if (mirror) { ringbuffer_consumed(mirror, packetsize); } } while (1); /* CONSTCOND */ if (server->connection_ready && conn->output) { /* Preserve the rest of the stream */ lcb_size_t nbytes = ringbuffer_get_nbytes(stream); send_size = ringbuffer_get_nbytes(conn->output); if (send_size >= nbytes) { ringbuffer_consumed(conn->output, send_size - nbytes); lcb_assert(ringbuffer_memcpy(&rest, conn->output, nbytes) == 0); } ringbuffer_reset(conn->output); ringbuffer_append(&rest, conn->output); } ringbuffer_destruct(&rest); lcb_maybe_breakout(server->instance); }
static libcouchbase_error_t create_memcached(const struct libcouchbase_memcached_st *user, VBUCKET_CONFIG_HANDLE vbconfig) { ringbuffer_t buffer; char *copy = strdup(user->serverlist); char head[1024]; int first; char *ptr = copy; int fail; libcouchbase_ssize_t offset = 0; if (copy == NULL) { return LIBCOUCHBASE_CLIENT_ENOMEM; } if (ringbuffer_initialize(&buffer, 1024) == -1) { free(copy); return LIBCOUCHBASE_CLIENT_ENOMEM; } head[0] = '\0'; offset += snprintf(head + offset, sizeof(head) - offset, "%s", "{"); offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"bucketType\":\"memcached\","); offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"nodeLocator\":\"ketama\","); if (user->username != NULL) { offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"authType\":\"sasl\","); offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"name\":\""); offset += snprintf(head + offset, sizeof(head) - offset, "%s", user->username); offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\","); if (user->password != NULL) { offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"saslPassword\":\""); offset += snprintf(head + offset, sizeof(head) - offset, "%s", user->password); offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\","); } } offset += snprintf(head + offset, sizeof(head) - offset, "%s", "\"nodes\": ["); ringbuffer_write(&buffer, head, strlen(head)); /* Let's add the hosts... */ first = 1; do { char *tok; char *next = strchr(ptr, ';'); const char *port = "11211"; libcouchbase_ssize_t length; if (next != NULL) { *next = '\0'; } tok = strchr(ptr, ':'); if (tok != NULL) { *tok = '\0'; port = tok + 1; if ((tok = strchr(ptr, ':')) != NULL) { *tok = '\0'; /* Remove weight for now */ } } length = snprintf(head, sizeof(head), "%c{\"hostname\":\"%s\",\"ports\":{\"direct\":%s}}", first ? ' ' : ',', ptr, port); first = 0; if (ringbuffer_ensure_capacity(&buffer, length) == -1) { free(copy); return LIBCOUCHBASE_CLIENT_ENOMEM; } ringbuffer_write(&buffer, head, length); if (next != NULL) { ptr = next + 1; } else { ptr = NULL; } } while (ptr != NULL); if (ringbuffer_ensure_capacity(&buffer, 3) == -1) { free(copy); return LIBCOUCHBASE_CLIENT_ENOMEM; } ringbuffer_write(&buffer, "]}", 3); /* Include '\0' */ /* Now let's parse the config! */ fail = vbucket_config_parse(vbconfig, LIBVBUCKET_SOURCE_MEMORY, (char *)ringbuffer_get_read_head(&buffer)); free(copy); ringbuffer_destruct(&buffer); if (fail) { /* Hmm... internal error! */ return LIBCOUCHBASE_EINTERNAL; } return LIBCOUCHBASE_SUCCESS; }