/** * Optionally decompress an incoming payload. * @param o The instance * @param resp The response received * @param[out] bytes pointer to the final payload * @param[out] nbytes pointer to the size of the final payload * @param[out] freeptr pointer to free. This should be initialized to `NULL`. * If temporary dynamic storage is required this will be set to the allocated * pointer upon return. Otherwise it will be set to NULL. In any case it must */ static void maybe_decompress(lcb_t o, const packet_info *respkt, lcb_RESPGET *rescmd, void **freeptr) { lcb_U8 dtype = 0; if (!PACKET_NVALUE(respkt)) { return; } if (PACKET_DATATYPE(respkt) & PROTOCOL_BINARY_DATATYPE_JSON) { dtype = LCB_VALUE_F_JSON; } if (PACKET_DATATYPE(respkt) & PROTOCOL_BINARY_DATATYPE_COMPRESSED) { if (LCBT_SETTING(o, compressopts) & LCB_COMPRESS_IN) { /* if we inflate, we don't set the flag */ mcreq_inflate_value( PACKET_VALUE(respkt), PACKET_NVALUE(respkt), &rescmd->value, &rescmd->nvalue, freeptr); } else { /* user doesn't want inflation. signal it's compressed */ dtype |= LCB_VALUE_F_SNAPPYCOMP; } } rescmd->datatype = dtype; }
static void getq_response_handler(lcb_server_t *server, packet_info *info) { lcb_t root = server->instance; char *packet; lcb_uint16_t nkey; const char *key = get_key(server, &nkey, &packet); lcb_error_t rc; lcb_get_resp_t resp; fprintf(stderr, "\n The datatype is ...%d", PACKET_DATATYPE(info)); if (key == NULL) { lcb_error_handler(server->instance, LCB_EINTERNAL, NULL); return; } else if (PACKET_STATUS(info) == PROTOCOL_BINARY_RESPONSE_SUCCESS) { const protocol_binary_response_getq *getq = PACKET_EPHEMERAL_START(info); rc = LCB_SUCCESS; setup_lcb_get_resp_t(&resp, key, nkey, PACKET_VALUE(info), PACKET_NVALUE(info), ntohl(getq->message.body.flags), PACKET_CAS(info), PACKET_DATATYPE(info)); } else { rc = map_error(root, PACKET_STATUS(info)); setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0); } root->callbacks.get(root, info->ct.cookie, rc, &resp); release_key(server, packet); }
static void H_get(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_t o; lcb_RESPGET resp = { 0 }; void *freeptr = NULL; o = pipeline->parent->cqdata; init_resp3(o, response, request, immerr, (lcb_RESPBASE *)&resp); if (resp.rc == LCB_SUCCESS) { const protocol_binary_response_getq *getq = PACKET_EPHEMERAL_START(response); resp.datatype = PACKET_DATATYPE(response); resp.itmflags = ntohl(getq->message.body.flags); resp.value = PACKET_VALUE(response); resp.nvalue = PACKET_NVALUE(response); resp.bufh = response->bufh; } maybe_decompress(o, response, &resp, &freeptr); TRACE_GET_END(response, &resp); INVOKE_CALLBACK3(request, &resp, o, LCB_CALLBACK_GET); free(freeptr); }
static void H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_error_t rc; lcb_get_resp_t resp; lcb_t instance = pipeline->parent->instance; void *freeptr = NULL; MK_RESPKEY(&resp, 0, request); MK_ERROR(instance, rc, response, immerr); resp.version = 0; if (rc == LCB_SUCCESS) { const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(response); resp.v.v0.cas = PACKET_CAS(response); resp.v.v0.datatype = PACKET_DATATYPE(response); resp.v.v0.flags = ntohl(get->message.body.flags); resp.v.v0.bytes = PACKET_VALUE(response); resp.v.v0.nbytes = PACKET_NVALUE(response); } maybe_decompress(instance, response, &resp, &freeptr); request->u_rdata.exdata->callback(pipeline, request, rc, &resp); free(freeptr); }
static void H_getreplica(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_RESPGET resp = { 0 }; lcb_t instance = pipeline->parent->cqdata; void *freeptr = NULL; mc_REQDATAEX *rd = request->u_rdata.exdata; init_resp3(instance, response, request, immerr, (lcb_RESPBASE *)&resp); if (resp.rc == LCB_SUCCESS) { const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(response); resp.itmflags = ntohl(get->message.body.flags); resp.datatype = PACKET_DATATYPE(response); resp.value = PACKET_VALUE(response); resp.nvalue = PACKET_NVALUE(response); resp.bufh = response->bufh; } maybe_decompress(instance, response, &resp, &freeptr); rd->procs->handler(pipeline, request, resp.rc, &resp); free(freeptr); }
static void H_get(mc_PIPELINE *pipeline, mc_PACKET *request, packet_info *response, lcb_error_t immerr) { lcb_error_t rc; lcb_t o; lcb_get_resp_t resp; void *freeptr = NULL; o = pipeline->parent->instance; MK_RESPKEY(&resp, 0, request); MK_ERROR(o, rc, response, immerr); resp.version = 0; if (rc == LCB_SUCCESS) { const protocol_binary_response_getq *getq = PACKET_EPHEMERAL_START(response); resp.v.v0.cas = PACKET_CAS(response); resp.v.v0.datatype = PACKET_DATATYPE(response); resp.v.v0.flags = ntohl(getq->message.body.flags); resp.v.v0.bytes = PACKET_VALUE(response); resp.v.v0.nbytes = PACKET_NVALUE(response); rc = LCB_SUCCESS; } else { resp.v.v0.cas = 0; resp.v.v0.nbytes = 0; resp.v.v0.bytes = NULL; resp.v.v0.flags = 0; } maybe_decompress(o, response, &resp, &freeptr); INVOKE_CALLBACK(request, o->callbacks.get, (o, MCREQ_PKT_COOKIE(request), rc, &resp)); free(freeptr); }
static void get_replica_response_handler(lcb_server_t *server, packet_info *info) { lcb_t root = server->instance; lcb_uint16_t nkey; const char *key; char *packet; lcb_uint16_t status = PACKET_STATUS(info); lcb_error_t rc = map_error(root, status); /** * Success? always perform the callback */ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) { const protocol_binary_response_get *get = PACKET_EPHEMERAL_START(info); lcb_get_resp_t resp; setup_lcb_get_resp_t(&resp, PACKET_KEY(info), PACKET_NKEY(info), PACKET_VALUE(info), PACKET_NVALUE(info), ntohl(get->message.body.flags), PACKET_CAS(info), PACKET_DATATYPE(info)); root->callbacks.get(root, info->ct.cookie, rc, &resp); return; } key = get_key(server, &nkey, &packet); /** * Following code handles errors. */ if (info->ct.replica == -1) { /* Perform the callback. Either SELECT or ALL */ lcb_get_resp_t resp; setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0); PACKET_TRACE(TRACE_GET_END, info, rc, &resp); root->callbacks.get(root, info->ct.cookie, rc, &resp); release_key(server, packet); return; } /** LCB_REPLICA_FIRST */ if (status == PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET) { /** * the config was updated, start from first replica. * Reset the iteration count */ info->ct.replica = 0; } else { info->ct.replica++; } if (info->ct.replica < root->nreplicas) { /* try next replica */ protocol_binary_request_get req; lcb_server_t *new_server; int idx = vbucket_get_replica(root->vbucket_config, info->ct.vbucket, info->ct.replica); if (idx < 0 || idx > (int)root->nservers) { lcb_error_handler(root, LCB_NETWORK_ERROR, "GET_REPLICA: missing server"); release_key(server, packet); return; } new_server = root->servers + idx; memset(&req, 0, sizeof(req)); req.message.header.request.magic = PROTOCOL_BINARY_REQ; req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES; req.message.header.request.opcode = CMD_GET_REPLICA; req.message.header.request.keylen = ntohs((lcb_uint16_t)nkey); req.message.header.request.vbucket = ntohs(info->ct.vbucket); req.message.header.request.bodylen = ntohl((lcb_uint32_t)nkey); req.message.header.request.opaque = ++root->seqno; TRACE_GET_BEGIN(&req, key, nkey, 0); lcb_server_retry_packet(new_server, &info->ct, req.bytes, sizeof(req.bytes)); lcb_server_write_packet(new_server, key, nkey); lcb_server_end_packet(new_server); lcb_server_send_packets(new_server); } else { /* give up and report the error */ lcb_get_resp_t resp; setup_lcb_get_resp_t(&resp, key, nkey, NULL, 0, 0, 0, 0); PACKET_TRACE(TRACE_GET_END, info, rc, &resp) root->callbacks.get(root, info->ct.cookie, rc, &resp); } release_key(server, packet); }