1
0
Fork 0
mirror of https://github.com/dragonflydb/dragonfly.git synced 2024-12-14 11:58:02 +00:00

fix: circular dependency in qlist (#4302)

* fix: circular dependency in qlist

fixes #4294

Signed-off-by: Roman Gershman <roman@dragonflydb.io>

* chore: fixes

Signed-off-by: Roman Gershman <roman@dragonflydb.io>

---------

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2024-12-13 11:04:14 +02:00 committed by GitHub
parent f564513235
commit 53637790e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 7 deletions

View file

@ -371,6 +371,7 @@ string QList::Pop(Where where) {
/* The head and tail should never be compressed */ /* The head and tail should never be compressed */
DCHECK(node->encoding != QUICKLIST_NODE_ENCODING_LZF); DCHECK(node->encoding != QUICKLIST_NODE_ENCODING_LZF);
DCHECK(head_->prev->next == nullptr);
string res; string res;
if (ABSL_PREDICT_FALSE(QL_NODE_IS_PLAIN(node))) { if (ABSL_PREDICT_FALSE(QL_NODE_IS_PLAIN(node))) {
@ -390,6 +391,7 @@ string QList::Pop(Where where) {
} }
DelPackedIndex(node, pos); DelPackedIndex(node, pos);
} }
DCHECK(head_ == nullptr || head_->prev->next == nullptr);
return res; return res;
} }
@ -479,11 +481,13 @@ bool QList::PushSentinel(string_view value, Where where) {
if (len_ == 1) { // sanity check if (len_ == 1) { // sanity check
DCHECK_EQ(malloc_size_, orig->sz); DCHECK_EQ(malloc_size_, orig->sz);
} }
DCHECK(head_->prev->next == nullptr);
return false; return false;
} }
quicklistNode* node = CreateFromSV(QUICKLIST_NODE_CONTAINER_PACKED, value); quicklistNode* node = CreateFromSV(QUICKLIST_NODE_CONTAINER_PACKED, value);
InsertNode(orig, node, opt); InsertNode(orig, node, opt);
DCHECK(head_->prev->next == nullptr);
return true; return true;
} }
@ -837,12 +841,14 @@ quicklistNode* QList::ListpackMerge(quicklistNode* a, quicklistNode* b) {
void QList::DelNode(quicklistNode* node) { void QList::DelNode(quicklistNode* node) {
if (node->next) if (node->next)
node->next->prev = node->prev; node->next->prev = node->prev;
if (node->prev)
node->prev->next = node->next;
if (node == head_) { if (node == head_) {
head_ = node->next; head_ = node->next;
} else if (node == head_->prev) { // tail } else {
// for non-head nodes, update prev->next to point to node->next
// (If node==head, prev is tail and should always point to NULL).
node->prev->next = node->next;
if (node == head_->prev) // tail
head_->prev = node->prev; head_->prev = node->prev;
} }

View file

@ -282,6 +282,15 @@ TEST_F(QListTest, CompressionPlain) {
EXPECT_EQ(500, i); EXPECT_EQ(500, i);
} }
TEST_F(QListTest, LargeValues) {
string val(100000, 'a');
ql_.Push(val, QList::HEAD);
ql_.Push(val, QList::HEAD);
ql_.Pop(QList::HEAD);
auto items = ToItems();
EXPECT_THAT(items, ElementsAre(val));
}
using FillCompress = tuple<int, unsigned>; using FillCompress = tuple<int, unsigned>;
class PrintToFillCompress { class PrintToFillCompress {

View file

@ -56,9 +56,7 @@ end
function LG_funcs.add_list(key, keys) function LG_funcs.add_list(key, keys)
local is_huge = keys[key] local is_huge = keys[key]
--- TODO -- investigate why second case of replication_test_all fails redis.apcall('LPUSH', key, unpack(randstr_sequence(is_huge)))
--- we somehow create a quicklist that is circular and we deadlock
redis.apcall('LPUSH', key, unpack(randstr_sequence(false)))
end end
function LG_funcs.mod_list(key, keys) function LG_funcs.mod_list(key, keys)