static void Cr_handler(lcb_sockdata_t *sd, lcb_ssize_t nr, void *arg) { lcbio_CTX *ctx = arg; sd->is_reading = 0; ctx->npending--; if (ctx->state == ES_ACTIVE) { if (nr > 0) { unsigned total; rdb_rdend(&ctx->ior, nr); total = rdb_get_nused(&ctx->ior); if (total >= ctx->rdwant) { invoke_read_cb(ctx, total); } lcbio_ctx_schedule(ctx); } else { lcb_error_t err = convert_lcberr(ctx, nr ? LCBIO_SHUTDOWN : LCBIO_IOERR); ctx->rdwant = 0; invoke_entered_errcb(ctx, err); } } if (ctx->state != ES_ACTIVE && ctx->npending == 0) { free_ctx(ctx); } }
int lcb_pktinfo_ior_get(packet_info *info, rdb_IOROPE *ior, unsigned *required) { unsigned total = rdb_get_nused(ior); unsigned wanted = sizeof(info->res.bytes); if (total < wanted) { *required = wanted; return 0; } rdb_copyread(ior, info->res.bytes, sizeof(info->res.bytes)); if (!PACKET_NBODY(info)) { rdb_consumed(ior, sizeof(info->res.bytes)); return 1; } wanted += PACKET_NBODY(info); if (total < wanted) { *required = wanted; return 0; } rdb_consumed(ior, sizeof(info->res.bytes)); info->payload = rdb_get_consolidated(ior, PACKET_NBODY(info)); return 1; }
static void E_handler(lcb_socket_t sock, short which, void *arg) { lcbio_CTX *ctx = arg; lcbio_IOSTATUS status; (void)sock; if (which & LCB_READ_EVENT) { unsigned nb; status = lcbio_E_rdb_slurp(ctx, &ctx->ior); nb = rdb_get_nused(&ctx->ior); if (nb >= ctx->rdwant) { invoke_read_cb(ctx, nb); if (E_free_detached(ctx)) { return; } } if (!LCBIO_IS_OK(status)) { lcb_error_t err = convert_lcberr(ctx, status); lcbio_ctx_senderr(ctx, err); return; } } if (which & LCB_WRITE_EVENT) { if (ctx->wwant) { ctx->wwant = 0; ctx->procs.cb_flush_ready(ctx); if (ctx->err) { return; } } else if (ctx->output) { status = lcbio_E_rb_write(ctx, &ctx->output->rb); if (!LCBIO_IS_OK(status)) { deactivate_watcher(ctx); ctx->err = convert_lcberr(ctx, status); err_handler(ctx); return; } } } lcbio_ctx_schedule(ctx); }
/* This function is called within a loop to process a single packet. * * If a full packet is available, it will process the packet and return * PKT_READ_COMPLETE, resulting in the `on_read()` function calling this * function in a loop. * * When a complete packet is not available, PKT_READ_PARTIAL will be returned * and the `on_read()` loop will exit, scheduling any required pending I/O. */ static int try_read(lcbio_CTX *ctx, mc_SERVER *server, rdb_IOROPE *ior) { packet_info info_s, *info = &info_s; mc_PACKET *request; mc_PIPELINE *pl = &server->pipeline; unsigned pktsize = 24, is_last = 1; #define RETURN_NEED_MORE(n) \ if (mcserver_has_pending(server)) { \ lcbio_ctx_rwant(ctx, n); \ } \ return PKT_READ_PARTIAL; \ #define DO_ASSIGN_PAYLOAD() \ rdb_consumed(ior, sizeof(info->res.bytes)); \ if (PACKET_NBODY(info)) { \ info->payload = rdb_get_consolidated(ior, PACKET_NBODY(info)); \ } { #define DO_SWALLOW_PAYLOAD() \ } if (PACKET_NBODY(info)) { \ rdb_consumed(ior, PACKET_NBODY(info)); \ } if (rdb_get_nused(ior) < pktsize) { RETURN_NEED_MORE(pktsize) } /* copy bytes into the info structure */ rdb_copyread(ior, info->res.bytes, sizeof info->res.bytes); pktsize += PACKET_NBODY(info); if (rdb_get_nused(ior) < pktsize) { RETURN_NEED_MORE(pktsize); } /* Find the packet */ if (PACKET_OPCODE(info) == PROTOCOL_BINARY_CMD_STAT && PACKET_NKEY(info) != 0) { is_last = 0; request = mcreq_pipeline_find(pl, PACKET_OPAQUE(info)); } else { is_last = 1; request = mcreq_pipeline_remove(pl, PACKET_OPAQUE(info)); } if (!request) { lcb_log(LOGARGS(server, WARN), LOGFMT "Found stale packet (OP=0x%x, RC=0x%x, SEQ=%u)", LOGID(server), PACKET_OPCODE(info), PACKET_STATUS(info), PACKET_OPAQUE(info)); rdb_consumed(ior, pktsize); return PKT_READ_COMPLETE; } if (PACKET_STATUS(info) == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) { /* consume the header */ DO_ASSIGN_PAYLOAD() if (!handle_nmv(server, info, request)) { mcreq_dispatch_response(pl, request, info, LCB_NOT_MY_VBUCKET); } DO_SWALLOW_PAYLOAD() return PKT_READ_COMPLETE; }