Skip to content

Commit 6a1bce4

Browse files
committed
CCBC-1610: fix collection id encoding
* use packet flags only to decide whether to decode collection id * fix header length calculation when overriding collection id * prefer standalone network buffer when overriding collection id Change-Id: Ib1c94d1dcca1ea6bf9b51eb8437c1f718abf8741 Reviewed-on: https://review.couchbase.org/c/libcouchbase/+/196764 Reviewed-by: Brett Lawson <brett19@gmail.com> Tested-by: Build Bot <build@couchbase.com>
1 parent 3e21d89 commit 6a1bce4

7 files changed

Lines changed: 24 additions & 20 deletions

File tree

src/handler.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ void init_resp(lcb_INSTANCE *instance, mc_PIPELINE *pipeline, const MemcachedRes
271271
resp->cookie = const_cast<void *>(MCREQ_PKT_COOKIE(req));
272272
const char *key = nullptr;
273273
size_t key_len = 0;
274-
mcreq_get_key(instance, req, &key, &key_len);
274+
mcreq_get_key(req, &key, &key_len);
275275
if (key != nullptr) {
276276
resp->ctx.key.assign(key, key_len);
277277
}

src/mc/mcreq.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ void mcreq_wipe_packet(mc_PIPELINE *pipeline, mc_PACKET *packet)
376376
return;
377377
}
378378

379-
if ((packet->flags & MCREQ_F_DETACHED) || IS_STANDALONE_SPAN(&packet->kh_span)) {
379+
if (packet->flags & MCREQ_F_DETACHED) {
380380
free(SPAN_BUFFER(&packet->u_value.single));
381381
} else {
382382
netbuf_mblock_release(&pipeline->nbmgr, &packet->u_value.single);
@@ -651,34 +651,37 @@ void mcreq_set_cid(mc_PIPELINE *pipeline, mc_PACKET *packet, uint32_t cid)
651651
char *key = header_and_key + header_size;
652652

653653
// parse old collection id and determine its length
654-
uint32_t old_collection_id;
655-
int old_collection_id_length = leb128_decode((uint8_t *)key, key_length, &old_collection_id);
654+
uint32_t old_collection_id = 0;
655+
int old_collection_id_length = 0;
656+
if ((packet->flags & MCREQ_F_HASCID) != 0) {
657+
old_collection_id_length = leb128_decode((uint8_t *)key, key_length, &old_collection_id);
658+
}
656659

657660
// encode new collection id
658661
uint8_t collection_id[5] = {0};
659662
int collection_id_length = leb128_encode(cid, collection_id);
660663

661664
// fix field lengths in the packet
662665
int diff = collection_id_length - old_collection_id_length;
663-
size_t new_header_and_key_size = old_span.size + diff;
664666
req.request.bodylen = htonl(ntohl(req.request.bodylen) + diff);
665-
size_t new_klen = key_length + diff;
667+
size_t new_key_length = key_length + diff;
666668
if (req.request.magic == PROTOCOL_BINARY_AREQ) {
667-
req.request.keylen = (new_klen << 8) | (flexible_extras_length & 0xff);
669+
req.request.keylen = (new_key_length << 8) | (flexible_extras_length & 0xff);
668670
} else {
669-
req.request.keylen = htons(new_klen);
671+
req.request.keylen = htons(new_key_length);
670672
}
671673

672674
// copy old header fields, with only collection id updated
673-
netbuf_mblock_reserve(&pipeline->nbmgr, &packet->kh_span);
674-
char *new_header_and_key = SPAN_BUFFER(&packet->kh_span);
675+
char *new_header_and_key = malloc(old_span.size + diff);
676+
CREATE_STANDALONE_SPAN(&packet->kh_span, new_header_and_key, old_span.size + diff);
677+
675678
const char *ptr = header_and_key;
676679
memcpy(new_header_and_key, ptr, header_size);
680+
// update header with new length values
677681
memcpy(new_header_and_key, req.bytes, sizeof(req.bytes));
678-
ptr += header_size + old_collection_id_length;
679682
memcpy(new_header_and_key + header_size, collection_id, collection_id_length);
680-
memcpy(new_header_and_key + header_size + collection_id_length, ptr,
681-
new_header_and_key_size - collection_id_length - header_size);
683+
ptr += header_size + old_collection_id_length;
684+
memcpy(new_header_and_key + header_size + collection_id_length, ptr, key_length - old_collection_id_length);
682685

683686
// deallocate the old span
684687
if (IS_STANDALONE_SPAN(&old_span)) {
@@ -689,6 +692,7 @@ void mcreq_set_cid(mc_PIPELINE *pipeline, mc_PACKET *packet, uint32_t cid)
689692
}
690693

691694
packet->flags |= MCREQ_F_HASCID;
695+
packet->flags &= ~MCREQ_F_KEY_NOCOPY;
692696
}
693697

694698
uint32_t mcreq_get_cid(lcb_INSTANCE *instance, const mc_PACKET *packet, int *cid_set)
@@ -725,7 +729,7 @@ uint32_t mcreq_get_cid(lcb_INSTANCE *instance, const mc_PACKET *packet, int *cid
725729
return 0;
726730
}
727731

728-
void mcreq_get_key(lcb_INSTANCE *instance, const mc_PACKET *packet, const char **key, size_t *nkey)
732+
void mcreq_get_key(const mc_PACKET *packet, const char **key, size_t *nkey)
729733
{
730734
uint8_t ffext = 0;
731735
uint16_t nk = 0;
@@ -743,7 +747,7 @@ void mcreq_get_key(lcb_INSTANCE *instance, const mc_PACKET *packet, const char *
743747
nk = ntohs(req.request.keylen);
744748
}
745749
k = kh + sizeof(req) + req.request.extlen + ffext;
746-
if ((packet->flags & MCREQ_F_NOCID) == 0 && instance && LCBT_SETTING(instance, use_collections)) {
750+
if ((packet->flags & MCREQ_F_HASCID) != 0) {
747751
ncid = leb128_decode((uint8_t *)k, nk, &cid);
748752
(void)cid;
749753
}

src/mc/mcreq.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ lcb_STATUS mcreq_basic_packet(mc_CMDQUEUE *queue, const lcb_KEYBUF *key, uint32_
688688
* @param[out] key
689689
* @param[out] nkey
690690
*/
691-
void mcreq_get_key(lcb_INSTANCE *instance, const mc_PACKET *packet, const char **key, size_t *nkey);
691+
void mcreq_get_key(const mc_PACKET *packet, const char **key, size_t *nkey);
692692

693693
/** @brief Returns the size of the key, in bytes */
694694
uint16_t mcreq_get_key_size(protocol_binary_request_header *hdr);

src/mcserver/mcserver.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ bool Server::handle_unknown_collection(MemcachedResponse &resp, mc_PACKET *oldpk
290290
std::string name = instance->collcache->id_to_name(cid);
291291

292292
packet_wrapper wrapper;
293-
mcreq_get_key(instance, oldpkt, (const char **)&wrapper.key.contig.bytes, &wrapper.key.contig.nbytes);
293+
mcreq_get_key(oldpkt, (const char **)&wrapper.key.contig.bytes, &wrapper.key.contig.nbytes);
294294

295295
lcb_log(LOGARGS_T(WARN), LOGFMT "UNKNOWN_COLLECTION. Packet=%p (M=0x%x, S=%u, OP=0x%x), CID=%u, CNAME=%s",
296296
LOGID_T(), (void *)oldpkt, (int)req.request.magic, oldpkt->opaque, (int)req.request.opcode, (unsigned)cid,

src/newconfig.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static int iterwipe_cb(mc_CMDQUEUE *cq, mc_PIPELINE *oldpl, mc_PACKET *oldpkt, v
214214

215215
/* XXX: We ignore hashkey. This is going away soon, and is probably
216216
* better than simply failing the items. */
217-
mcreq_get_key(instance, oldpkt, &key, &nkey);
217+
mcreq_get_key(oldpkt, &key, &nkey);
218218
lcbvb_map_key(cq->config, key, nkey, &tmpid, &newix);
219219
}
220220

tests/mc/t_alloc.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ TEST_F(McAlloc, testKeyAlloc)
144144
const char *key;
145145
size_t nkey;
146146
// Get back the key we just placed inside the header
147-
mcreq_get_key(nullptr, packet, &key, &nkey);
147+
mcreq_get_key(packet, &key, &nkey);
148148
ASSERT_EQ(5, nkey);
149149
ASSERT_EQ(0, memcmp(key, "Hello", 5));
150150

tests/mc/t_forward.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ TEST_F(McFwd, testNoMap)
250250
// Get the key
251251
const char *key;
252252
size_t nkey;
253-
mcreq_get_key(NULL, pkt_tmp, &key, &nkey);
253+
mcreq_get_key(pkt_tmp, &key, &nkey);
254254
ASSERT_EQ(0, nkey);
255255

256256
// Ensure we have no vBucket stamping

0 commit comments

Comments
 (0)