void lcb_failout_observe_request(lcb_server_t *server, struct lcb_command_data_st *command_data, const char *packet, lcb_size_t npacket, lcb_error_t err) { lcb_t instance = server->instance; protocol_binary_request_header *req = (void *)packet; const char *ptr = packet + sizeof(req->bytes); const char *end = packet + npacket; lcb_observe_resp_t resp; memset(&resp, 0, sizeof(resp)); resp.v.v0.status = LCB_OBSERVE_MAX; while (ptr < end) { lcb_uint16_t nkey; /* ignore vbucket */ ptr += sizeof(lcb_uint16_t); memcpy(&nkey, ptr, sizeof(nkey)); nkey = ntohs(nkey); ptr += sizeof(lcb_uint16_t); resp.v.v0.key = ptr; resp.v.v0.nkey = nkey; TRACE_OBSERVE_PROGRESS(req->request.opaque, ntohs(req->request.vbucket), req->request.opcode, err, &resp); lcb_observe_invoke_callback(instance, command_data, err, &resp); ptr += nkey; } if ((command_data->flags & LCB_CMD_F_OBS_BCAST) && lcb_lookup_server_with_command(instance, CMD_OBSERVE, req->request.opaque, server) < 0) { TRACE_OBSERVE_END(req->request.opaque, ntohs(req->request.vbucket), req->request.opcode, err); resp.v.v0.key = NULL; resp.v.v0.nkey = 0; lcb_observe_invoke_callback(instance, command_data, err, &resp); } }
static void H_observe(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_t root = pipeline->parent->cqdata; uint32_t ttp; uint32_t ttr; lcb_size_t pos; lcbvb_CONFIG* config; const char *end, *ptr; mc_REQDATAEX *rd = request->u_rdata.exdata; lcb_RESPOBSERVE resp = { 0 }; MK_ERROR(root, &resp, response, immerr); if (resp.rc != LCB_SUCCESS) { if (! (request->flags & MCREQ_F_INVOKED)) { rd->procs->handler(pipeline, request, resp.rc, NULL); } return; } /** The CAS field is split into TTP/TTR values */ ptr = (char *)&response->res.response.cas; memcpy(&ttp, ptr, sizeof(ttp)); memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttp)); ttp = ntohl(ttp); ttr = ntohl(ttr); /** Actual payload sequence of (vb, nkey, key). Repeats multiple times */ ptr = response->payload; end = (char *)ptr + PACKET_NBODY(response); config = pipeline->parent->config; for (pos = 0; ptr < end; pos++) { lcb_cas_t cas; lcb_uint8_t obs; lcb_uint16_t nkey, vb; const char *key; memcpy(&vb, ptr, sizeof(vb)); vb = ntohs(vb); ptr += sizeof(vb); memcpy(&nkey, ptr, sizeof(nkey)); nkey = ntohs(nkey); ptr += sizeof(nkey); key = (const char *)ptr; ptr += nkey; obs = *((lcb_uint8_t *)ptr); ptr += sizeof(obs); memcpy(&cas, ptr, sizeof(cas)); ptr += sizeof(cas); resp.key = key; resp.nkey = nkey; resp.cas = cas; resp.status = obs; resp.ismaster = pipeline->index == lcbvb_vbmaster(config, vb); resp.ttp = 0; resp.ttr = 0; TRACE_OBSERVE_PROGRESS(response, &resp); if (! (request->flags & MCREQ_F_INVOKED)) { rd->procs->handler(pipeline, request, resp.rc, &resp); } } TRACE_OBSERVE_END(response); }
static void observe_response_handler(lcb_server_t *server, struct lcb_command_data_st *command_data, protocol_binary_response_header *res) { lcb_t root = server->instance; lcb_uint16_t status = ntohs(res->response.status); lcb_error_t rc = map_error(root, status); lcb_uint32_t ttp; lcb_uint32_t ttr; lcb_size_t pos; VBUCKET_CONFIG_HANDLE config; const char *end, *ptr = (const char *)&res->response.cas; /** * If we have an error we must decode the request instead */ if (rc != LCB_SUCCESS) { protocol_binary_request_header req; lcb_size_t nr; nr = ringbuffer_peek(&server->cmd_log, req.bytes, sizeof(req.bytes)); if (nr != sizeof(req.bytes)) { lcb_error_handler(server->instance, LCB_EINTERNAL, NULL); abort(); } if (req.request.bodylen) { lcb_size_t npacket = sizeof(req.bytes) + ntohl(req.request.bodylen); char *packet = server->cmd_log.read_head; int allocated = 0; if (!ringbuffer_is_continous(&server->cmd_log, RINGBUFFER_READ, npacket)) { packet = malloc(npacket); if (packet == NULL) { lcb_error_handler(root, LCB_CLIENT_ENOMEM, NULL); abort(); } nr = ringbuffer_peek(&server->cmd_log, packet, npacket); if (nr != npacket) { lcb_error_handler(root, LCB_EINTERNAL, NULL); free(packet); abort(); } allocated = 1; } lcb_failout_observe_request(server, command_data, packet, npacket, rc); if (allocated) { free(packet); } } return; } memcpy(&ttp, ptr, sizeof(ttp)); ttp = ntohl(ttp); memcpy(&ttr, ptr + sizeof(ttp), sizeof(ttr)); ttr = ntohl(ttr); ptr = (const char *)res + sizeof(res->bytes); end = ptr + ntohl(res->response.bodylen); config = root->vbucket_config; for (pos = 0; ptr < end; pos++) { lcb_cas_t cas; lcb_uint8_t obs; lcb_uint16_t nkey, vb; const char *key; lcb_observe_resp_t resp; memcpy(&vb, ptr, sizeof(vb)); vb = ntohs(vb); ptr += sizeof(vb); memcpy(&nkey, ptr, sizeof(nkey)); nkey = ntohs(nkey); ptr += sizeof(nkey); key = (const char *)ptr; ptr += nkey; obs = *((lcb_uint8_t *)ptr); ptr += sizeof(obs); memcpy(&cas, ptr, sizeof(cas)); ptr += sizeof(cas); setup_lcb_observe_resp_t(&resp, key, nkey, cas, obs, server->index == vbucket_get_master(config, vb), ttp, ttr); TRACE_OBSERVE_PROGRESS(res->response.opaque, command_data->vbucket, res->response.opcode, rc, &resp); lcb_observe_invoke_callback(root, command_data, rc, &resp); } /* run callback with null-null-null to signal the end of transfer */ if ((command_data->flags & LCB_CMD_F_OBS_BCAST) && lcb_lookup_server_with_command(root, CMD_OBSERVE, res->response.opaque, server) < 0) { lcb_observe_resp_t resp; memset(&resp, 0, sizeof(resp)); TRACE_OBSERVE_END(res->response.opaque, command_data->vbucket, res->response.opcode, rc); lcb_observe_invoke_callback(root, command_data, LCB_SUCCESS, &resp); } }