LIBCOUCHBASE_API int vbucket_map(lcbvb_CONFIG *cfg, const void *k, lcb_SIZE nk, int *pvb, int *pix) { return lcbvb_map_key(cfg, k, nk, pvb, pix); }
lcb_STATUS mc_forward_packet(mc_CMDQUEUE *cq, mc_IOVINFO *info, mc_PACKET **pkt_p, mc_PIPELINE **pl_p, int options) { /* stack based header with our modifications. this is copied into the * packet's actual header */ protocol_binary_request_header hdr; int vbid, srvix; mc_IOVCURSOR *mincur = &info->c; unsigned n_packet; /* total packet size */ unsigned n_header; /* extras + key + memcached header */ unsigned n_body_total; /* size of everything following the memcached header */ unsigned n_body_key; /* length of the key */ unsigned n_body_value; /* packetsize - hdrsize */ unsigned offset; /* stack buffer and key pointer. stack buffer is used if the key is not * contiguous */ char kbuf_s[256]; const char *kptr; /* pipeline and packet for command */ mc_PIPELINE *pl; mc_PACKET *pkt; info->wanted = 0; /* not enough bytes */ if (info->total < 24) { info->wanted = 24; return LCB_INCOMPLETE_PACKET; } iovcursor_peek(mincur, (char *)hdr.bytes, sizeof hdr.bytes, 0); /* Initialize our size variables */ n_body_total = ntohl(hdr.request.bodylen); n_body_key = ntohs(hdr.request.keylen); n_header = sizeof hdr.bytes + n_body_key + hdr.request.extlen; n_packet = n_body_total + sizeof hdr.bytes; n_body_value = n_packet - n_header; if (n_packet > info->total) { info->wanted = n_packet; return LCB_INCOMPLETE_PACKET; } info->total -= n_packet; /* seek ahead to read the item's key into the header */ offset = sizeof hdr.bytes + hdr.request.extlen; iovcursor_peek_ex(mincur, kbuf_s, &kptr, n_body_key, offset); if (kptr == NULL) { /* key is not contiguous? that's ok. use the static buffer */ kptr = kbuf_s; } if ((options & MC_FWD_OPT_NOMAP) == 0) { lcbvb_map_key(cq->config, kptr, n_body_key, &vbid, &srvix); if (srvix < 0 || (unsigned)srvix >= cq->npipelines) { return LCB_NO_MATCHING_SERVER; } pl = cq->pipelines[srvix]; hdr.request.vbucket = htons(vbid); } else { pl = *pl_p; if (!pl) { return LCB_EINVAL; } srvix = pl->index; } pkt = mcreq_allocate_packet(pl); if (pkt == NULL) { return LCB_CLIENT_ENOMEM; } hdr.request.opaque = pkt->opaque; pkt->extlen = hdr.request.extlen; info->consumed = n_packet; if (options & MC_FWD_OPT_COPY) { /* reserve bytes for the entire packet */ mcreq_reserve_header(pl, pkt, n_header); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->kh_span), n_header); if (n_body_value) { mcreq_reserve_value2(pl, pkt, n_body_value); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->u_value.single), n_body_value); pkt->flags |= MCREQ_F_HASVALUE; } } else { if (IOVCURSOR_HAS_CONTIG(mincur, n_header)) { span_from_first(mincur, n_header, &pkt->kh_span); pkt->flags |= MCREQ_F_KEY_NOCOPY; } else { /* header is fragmented into multiple IOVs */ mcreq_reserve_header(pl, pkt, n_header); iovcursor_adv_copy(mincur, SPAN_BUFFER(&pkt->kh_span), n_header); } /* do we have a value payload still? */ if (n_body_value) { pkt->flags |= MCREQ_F_HASVALUE | MCREQ_F_VALUE_NOCOPY; if (IOVCURSOR_HAS_CONTIG(mincur, n_body_value)) { span_from_first(mincur, n_body_value, &pkt->u_value.single); } else { /* body is fragmented */ iovcursor_adv_iovalloc(mincur, n_body_value, (nb_IOV **)&pkt->u_value.multi.iov, &pkt->u_value.multi.niov); pkt->u_value.multi.total_length = n_body_value; pkt->flags |= MCREQ_F_VALUE_IOV; } } } /* Copy the first 24 bytes into the header span */ memcpy(SPAN_BUFFER(&pkt->kh_span), hdr.bytes, sizeof hdr.bytes); *pkt_p = pkt; *pl_p = pl; /* Set the UFWD flag. This causes the rest of the system to invoke the * handler for the raw response, rather than the "Contiguous" structures*/ pkt->flags |= MCREQ_F_UFWD; mcreq_sched_add(pl, pkt); return LCB_SUCCESS; }