MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / setDeferredReply

Function setDeferredReply

src/networking.cpp:712–768  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

710}
711
712void setDeferredReply(client *c, void *node, const char *s, size_t length) {
713 listNode *ln = (listNode*)node;
714 clientReplyBlock *next, *prev;
715
716 /* Abort when *node is NULL: when the client should not accept writes
717 * we return NULL in addReplyDeferredLen() */
718 if (node == NULL) return;
719 serverAssert(!listNodeValue(ln));
720
721 /* Normally we fill this dummy NULL node, added by addReplyDeferredLen(),
722 * with a new buffer structure containing the protocol needed to specify
723 * the length of the array following. However sometimes there might be room
724 * in the previous/next node so we can instead remove this NULL node, and
725 * suffix/prefix our data in the node immediately before/after it, in order
726 * to save a write(2) syscall later. Conditions needed to do it:
727 *
728 * - The prev node is non-NULL and has space in it or
729 * - The next node is non-NULL,
730 * - It has enough room already allocated
731 * - And not too large (avoid large memmove) */
732 if (ln->prev != NULL && (prev = (clientReplyBlock*)listNodeValue(ln->prev)) &&
733 prev->size - prev->used > 0)
734 {
735 size_t len_to_copy = prev->size - prev->used;
736 if (len_to_copy > length)
737 len_to_copy = length;
738 memcpy(prev->buf() + prev->used, s, len_to_copy);
739 prev->used += len_to_copy;
740 length -= len_to_copy;
741 if (length == 0) {
742 listDelNode(c->reply, ln);
743 return;
744 }
745 s += len_to_copy;
746 }
747
748 if (ln->next != NULL && (next = (clientReplyBlock*)listNodeValue(ln->next)) &&
749 next->size - next->used >= length &&
750 next->used < PROTO_REPLY_CHUNK_BYTES * 4)
751 {
752 memmove(next->buf() + length, next->buf(), next->used);
753 memcpy(next->buf(), s, length);
754 next->used += length;
755 listDelNode(c->reply,ln);
756 } else {
757 /* Create a new node */
758 clientReplyBlock *buf = (clientReplyBlock*)zmalloc(length + sizeof(clientReplyBlock));
759 /* Take over the allocation's internal fragmentation */
760 buf->size = zmalloc_usable_size(buf) - sizeof(clientReplyBlock);
761 buf->used = length;
762 memcpy(buf->buf(), s, length);
763 listNodeValue(ln) = buf;
764 c->reply_bytes += buf->size;
765
766 closeClientOnOutputBufferLimitReached(c, 1);
767 }
768}
769

Callers 2

setDeferredAggregateLenFunction · 0.85
setDeferredReplyBulkSdsFunction · 0.85

Calls 5

listDelNodeFunction · 0.85
zmallocFunction · 0.85
zmalloc_usable_sizeFunction · 0.85
bufMethod · 0.45

Tested by

no test coverage detected