From 8a349962bedea797db67a452ba342deeeccfe344 Mon Sep 17 00:00:00 2001 From: Mingyi Kang Date: Mon, 25 Sep 2023 20:19:05 +0800 Subject: [PATCH 1/3] Add new function lpTrim to optimize lptrimCommand --- src/listpack.c | 38 ++++++++++++++++++++++++++++++++++++++ src/listpack.h | 1 + src/t_list.c | 3 +-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/listpack.c b/src/listpack.c index ecc7e9f6f..df34fb459 100644 --- a/src/listpack.c +++ b/src/listpack.c @@ -1112,6 +1112,44 @@ unsigned char *lpBatchDelete(unsigned char *lp, unsigned char **ps, unsigned lon return lpShrinkToFit(lp); } +/* Trim a listpack, remove 'ltrim' elements from left and 'rtrim' elements from right. */ +unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtrim) { + if (ltrim == 0 && rtrim == 0) return lp; + size_t bytes = lpBytes(lp); + unsigned long llen = lpLength(lp); + if (ltrim + rtrim >= llen) { + /* Remove all elements */ + lp[LP_HDR_SIZE] = LP_EOF; + lpSetTotalBytes(lp, LP_HDR_SIZE + 1); + lpSetNumElements(lp, 0); + return lpShrinkToFit(lp); + } + unsigned long rangelen = llen - ltrim - rtrim; + unsigned char *first, *tail; /* first points to the first byte we want to save, + and tail points to the byte after the last byte we want to save */ + first = lpSeek(lp, ltrim); + tail = lp + bytes - 1; /* When rtrim is zero, tail points to the EOF char */ + if (rtrim) { + if (rangelen < rtrim) { + tail = first; + unsigned long num = rangelen; + while (num--) { + tail = lpSkip(tail); + } + assert(tail[0] != LP_EOF); + lpAssertValidEntry(lp, bytes, tail); + } else { + tail = lpSeek(lp, llen - (int)rtrim); + } + } + size_t rangebytes = tail - first; + memmove(lp + LP_HDR_SIZE, first, rangebytes); + lp[LP_HDR_SIZE + rangebytes] = LP_EOF; + lpSetTotalBytes(lp, LP_HDR_SIZE + rangebytes + 1); + lpSetNumElements(lp, rangelen); + return lpShrinkToFit(lp); +} + /* Merge listpacks 'first' and 'second' by appending 'second' to 'first'. * * NOTE: The larger listpack is reallocated to contain the new merged listpack. diff --git a/src/listpack.h b/src/listpack.h index a60f089f9..fc947ac83 100644 --- a/src/listpack.h +++ b/src/listpack.h @@ -71,6 +71,7 @@ unsigned char *lpDelete(unsigned char *lp, unsigned char *p, unsigned char **new unsigned char *lpDeleteRangeWithEntry(unsigned char *lp, unsigned char **p, unsigned long num); unsigned char *lpDeleteRange(unsigned char *lp, long index, unsigned long num); unsigned char *lpBatchDelete(unsigned char *lp, unsigned char **ps, unsigned long count); +unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtrim); unsigned char *lpMerge(unsigned char **first, unsigned char **second); unsigned char *lpDup(unsigned char *lp); unsigned long lpLength(unsigned char *lp); diff --git a/src/t_list.c b/src/t_list.c index 8da0a21c4..6d1f43ffe 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -923,8 +923,7 @@ void ltrimCommand(client *c) { quicklistDelRange(o->ptr,0,ltrim); quicklistDelRange(o->ptr,-rtrim,rtrim); } else if (o->encoding == OBJ_ENCODING_LISTPACK) { - o->ptr = lpDeleteRange(o->ptr,0,ltrim); - o->ptr = lpDeleteRange(o->ptr,-rtrim,rtrim); + o->ptr = lpTrim(o->ptr, ltrim, rtrim); } else { serverPanic("Unknown list encoding"); } From f60bb2176a7ace987b62a23d3e364c7fa85b35ff Mon Sep 17 00:00:00 2001 From: Mingyi Kang Date: Thu, 19 Oct 2023 20:13:41 +0800 Subject: [PATCH 2/3] Return lp when lpSeek returns NULL --- src/listpack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/listpack.c b/src/listpack.c index df34fb459..5042392cd 100644 --- a/src/listpack.c +++ b/src/listpack.c @@ -1127,7 +1127,7 @@ unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtri unsigned long rangelen = llen - ltrim - rtrim; unsigned char *first, *tail; /* first points to the first byte we want to save, and tail points to the byte after the last byte we want to save */ - first = lpSeek(lp, ltrim); + if ((first = lpSeek(lp, ltrim)) == NULL) return lp; tail = lp + bytes - 1; /* When rtrim is zero, tail points to the EOF char */ if (rtrim) { if (rangelen < rtrim) { From 6d08c6a678b921086ab9f1855bb571048628fce0 Mon Sep 17 00:00:00 2001 From: Mingyi Kang Date: Sun, 22 Oct 2023 00:02:32 +0800 Subject: [PATCH 3/3] Update lpTrim: assert lpSeek returns a not-null value Co-authored-by: sundb --- src/listpack.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/listpack.c b/src/listpack.c index 5042392cd..812cc51a1 100644 --- a/src/listpack.c +++ b/src/listpack.c @@ -1127,7 +1127,8 @@ unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtri unsigned long rangelen = llen - ltrim - rtrim; unsigned char *first, *tail; /* first points to the first byte we want to save, and tail points to the byte after the last byte we want to save */ - if ((first = lpSeek(lp, ltrim)) == NULL) return lp; + first = lpSeek(lp, ltrim); + assert(first != NULL); tail = lp + bytes - 1; /* When rtrim is zero, tail points to the EOF char */ if (rtrim) { if (rangelen < rtrim) {