-
Notifications
You must be signed in to change notification settings - Fork 998
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This class will consolidate list functionality across multiple layers, and eventually replace the original quicklist code. Right now we added the skeleton files and defined most of the interface. The implementation is not done yet. Signed-off-by: Roman Gershman <[email protected]>
- Loading branch information
Showing
6 changed files
with
217 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2024, DragonflyDB authors. All rights reserved. | ||
// See LICENSE for licensing terms. | ||
// | ||
|
||
#include "core/qlist.h" | ||
|
||
extern "C" { | ||
#include "redis/zmalloc.h" | ||
} | ||
|
||
#include "base/logging.h" | ||
|
||
using namespace std; | ||
|
||
namespace dfly { | ||
|
||
QList::QList() : fill_(-2), compress_(0), bookmark_count_(0) { | ||
} | ||
|
||
QList::QList(int fill, int compress) : fill_(fill), compress_(compress), bookmark_count_(0) { | ||
} | ||
|
||
QList::~QList() { | ||
unsigned long len; | ||
quicklistNode *current, *next; | ||
|
||
current = head_; | ||
len = len_; | ||
while (len--) { | ||
next = current->next; | ||
|
||
zfree(current->entry); | ||
count_ -= current->count; | ||
|
||
zfree(current); | ||
|
||
len_--; | ||
current = next; | ||
} | ||
} | ||
|
||
void QList::Push(string_view value, Where where) { | ||
/* The head and tail should never be compressed (we don't attempt to decompress them) */ | ||
if (head_) | ||
DCHECK(head_->encoding != QUICKLIST_NODE_ENCODING_LZF); | ||
if (tail_) | ||
DCHECK(tail_->encoding != QUICKLIST_NODE_ENCODING_LZF); | ||
|
||
if (where == HEAD) { | ||
PushHead(value); | ||
} else { | ||
DCHECK_EQ(TAIL, where); | ||
PushTail(value); | ||
} | ||
} | ||
|
||
void QList::AppendListpack(unsigned char* zl) { | ||
} | ||
|
||
void QList::AppendPlain(unsigned char* zl) { | ||
} | ||
|
||
void QList::Insert(std::string_view pivot, std::string_view elem, InsertOpt opt) { | ||
} | ||
|
||
size_t QList::MallocUsed() const { | ||
// Approximation since does not account for listpacks. | ||
size_t res = len_ * sizeof(quicklistNode) + znallocx(sizeof(quicklist)); | ||
return res + count_ * 16; // we account for each member 16 bytes. | ||
} | ||
|
||
string QList::Peek(Where where) const { | ||
return {}; | ||
} | ||
|
||
optional<string> QList::Get(long index) const { | ||
return nullopt; | ||
} | ||
|
||
void QList::Iterate(IterateFunc cb, long start, long end) const { | ||
} | ||
|
||
bool QList::PushHead(string_view value) { | ||
return false; | ||
} | ||
|
||
// Returns false if used existing head, true if new head created. | ||
bool QList::PushTail(string_view value) { | ||
return false; | ||
} | ||
|
||
void InsertPlainNode(quicklistNode* old_node, string_view, bool after) { | ||
} | ||
|
||
void InsertNode(quicklist* quicklist, quicklistNode* old_node, quicklistNode* new_node, | ||
bool after) { | ||
} | ||
|
||
} // namespace dfly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2024, DragonflyDB authors. All rights reserved. | ||
// See LICENSE for licensing terms. | ||
// | ||
|
||
#pragma once | ||
|
||
extern "C" { | ||
#include "redis/quicklist.h" | ||
} | ||
|
||
#include <functional> | ||
#include <optional> | ||
#include <string> | ||
|
||
namespace dfly { | ||
|
||
class QList { | ||
public: | ||
enum Where { TAIL, HEAD }; | ||
|
||
struct Entry { | ||
Entry(const char* value, size_t length) : value{value}, length{length} { | ||
} | ||
Entry(long long longval) : value{nullptr}, longval{longval} { | ||
} | ||
|
||
const char* value; | ||
union { | ||
size_t length; | ||
long long longval; | ||
}; | ||
}; | ||
|
||
using IterateFunc = std::function<bool(Entry)>; | ||
enum InsertOpt { BEFORE, AFTER }; | ||
|
||
QList(); | ||
QList(int fill, int compress); | ||
~QList(); | ||
|
||
size_t Size() const { | ||
return count_; | ||
} | ||
|
||
void Push(std::string_view value, Where where); | ||
void AppendListpack(unsigned char* zl); | ||
void AppendPlain(unsigned char* zl); | ||
void Insert(std::string_view pivot, std::string_view elem, InsertOpt opt); | ||
|
||
size_t MallocUsed() const; | ||
|
||
std::string Peek(Where where) const; | ||
std::optional<std::string> Get(long index) const; | ||
|
||
void Iterate(IterateFunc cb, long start, long end) const; | ||
|
||
private: | ||
// Returns false if used existing head, true if new head created. | ||
bool PushHead(std::string_view value); | ||
|
||
// Returns false if used existing head, true if new head created. | ||
bool PushTail(std::string_view value); | ||
void InsertPlainNode(quicklistNode* old_node, std::string_view, bool after); | ||
void InsertNode(quicklist* quicklist, quicklistNode* old_node, quicklistNode* new_node, | ||
bool after); | ||
|
||
quicklistNode* head_ = nullptr; | ||
quicklistNode* tail_ = nullptr; | ||
uint32_t count_ = 0; /* total count of all entries in all listpacks */ | ||
uint32_t len_ = 0; /* number of quicklistNodes */ | ||
signed int fill_ : QL_FILL_BITS; /* fill factor for individual nodes */ | ||
unsigned int compress_ : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */ | ||
unsigned int bookmark_count_ : QL_BM_BITS; | ||
}; | ||
|
||
} // namespace dfly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2024, DragonflyDB authors. All rights reserved. | ||
// See LICENSE for licensing terms. | ||
// | ||
|
||
#include "core/qlist.h" | ||
|
||
#include "base/gtest.h" | ||
#include "core/mi_memory_resource.h" | ||
|
||
extern "C" { | ||
#include "redis/zmalloc.h" | ||
} | ||
|
||
namespace dfly { | ||
|
||
class QListTest : public ::testing::Test { | ||
protected: | ||
QListTest() : mr_(mi_heap_get_backing()) { | ||
} | ||
|
||
static void SetUpTestSuite() { | ||
// configure redis lib zmalloc which requires mimalloc heap to work. | ||
auto* tlh = mi_heap_get_backing(); | ||
init_zmalloc_threadlocal(tlh); | ||
} | ||
|
||
MiMemoryResource mr_; | ||
QList ql_; | ||
}; | ||
|
||
TEST_F(QListTest, Basic) { | ||
EXPECT_EQ(0, ql_.Size()); | ||
} | ||
|
||
}; // namespace dfly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters