summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryoav-steinberg <yoav@monfort.co.il>2021-04-01 00:07:19 +0300
committerGitHub <noreply@github.com>2021-04-01 00:07:19 +0300
commit636aa8de76f07dd0f9b3c6d6e72f334a881a50f2 (patch)
treefa2f539971566874d3ea1515b76368209a689c35
parent68ba4d43ace055596909c082d436795e81630ee7 (diff)
downloadredis-636aa8de76f07dd0f9b3c6d6e72f334a881a50f2.tar.gz
Always use prev node if there's some room in it setDeferredReply (#8729)
this is a followup PR for #8699 instead of copying the deferred reply data to the previous node only if it has room for the entire thing, we can now split the new payload, put part of it into the spare space in the prev node, and the rest may fit into the next node.
-rw-r--r--src/networking.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/networking.c b/src/networking.c
index 9bee8910f..850717b5a 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -582,13 +582,22 @@ void setDeferredReply(client *c, void *node, const char *s, size_t length) {
* - It has enough room already allocated
* - And not too large (avoid large memmove) */
if (ln->prev != NULL && (prev = listNodeValue(ln->prev)) &&
- prev->size - prev->used >= length)
+ prev->size - prev->used > 0)
{
- memcpy(prev->buf + prev->used, s, length);
- prev->used += length;
- listDelNode(c->reply, ln);
+ size_t len_to_copy = prev->size - prev->used;
+ if (len_to_copy > length)
+ len_to_copy = length;
+ memcpy(prev->buf + prev->used, s, len_to_copy);
+ prev->used += len_to_copy;
+ length -= len_to_copy;
+ if (length == 0) {
+ listDelNode(c->reply, ln);
+ return;
+ }
+ s += len_to_copy;
}
- else if (ln->next != NULL && (next = listNodeValue(ln->next)) &&
+
+ if (ln->next != NULL && (next = listNodeValue(ln->next)) &&
next->size - next->used >= length &&
next->used < PROTO_REPLY_CHUNK_BYTES * 4)
{