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

chore: fully support qlist in all list_family commands (#4201)

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2024-11-27 13:56:56 +02:00 committed by GitHub
parent 66e0fd0908
commit a87d6aecef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 105 additions and 58 deletions

View file

@ -133,7 +133,8 @@ jobs:
run: |
cd ${GITHUB_WORKSPACE}/build
echo Run ctest -V -L DFLY
GLOG_alsologtostderr=1 GLOG_vmodule=rdb_load=1,rdb_save=1,snapshot=1 timeout 20m ctest -V -L DFLY
GLOG_alsologtostderr=1 GLOG_vmodule=rdb_load=1,rdb_save=1,snapshot=1 \
FLAGS_list_experimental_v2=true timeout 20m ctest -V -L DFLY
echo "Running tests with --force_epoll"

View file

@ -571,47 +571,75 @@ OpResult<string> OpIndex(const OpArgs& op_args, std::string_view key, long index
}
OpResult<vector<uint32_t>> OpPos(const OpArgs& op_args, string_view key, string_view element,
int rank, int count, int max_len) {
int rank, uint32_t count, uint32_t max_len) {
DCHECK(key.data() && element.data());
DCHECK_NE(rank, 0);
auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
if (!it_res.ok())
return it_res.status();
int direction = AL_START_HEAD;
if (rank < 0) {
rank = -rank;
direction = AL_START_TAIL;
}
quicklist* ql = GetQL(it_res.value()->second);
quicklistIter* ql_iter = quicklistGetIterator(ql, direction);
quicklistEntry entry;
int index = 0;
int matched = 0;
const PrimeValue& pv = (*it_res)->second;
vector<uint32_t> matches;
string str;
while (quicklistNext(ql_iter, &entry) && (max_len == 0 || index < max_len)) {
if (entry.value) {
str.assign(reinterpret_cast<char*>(entry.value), entry.sz);
} else {
str = absl::StrCat(entry.longval);
if (pv.Encoding() == kEncodingQL2) {
QList* ql = GetQLV2(pv);
QList::Where where = QList::HEAD;
if (rank < 0) {
rank = -rank;
where = QList::TAIL;
}
if (str == element) {
matched++;
auto k = (direction == AL_START_TAIL) ? ql->count - index - 1 : index;
if (matched >= rank) {
matches.push_back(k);
if (count && matched - rank + 1 >= count) {
break;
auto it = ql->GetIterator(where);
unsigned index = 0;
while (it.Next() && (max_len == 0 || index < max_len)) {
if (it.Get() == element) {
if (rank == 1) {
auto k = (where == QList::HEAD) ? index : ql->Size() - index - 1;
matches.push_back(k);
if (count && matches.size() >= count)
break;
} else {
rank--;
}
}
index++;
}
index++;
} else {
int direction = AL_START_HEAD;
if (rank < 0) {
rank = -rank;
direction = AL_START_TAIL;
}
quicklist* ql = GetQL(it_res.value()->second);
quicklistIter* ql_iter = quicklistGetIterator(ql, direction);
quicklistEntry entry;
unsigned index = 0;
int matched = 0;
string str;
while (quicklistNext(ql_iter, &entry) && (max_len == 0 || index < max_len)) {
if (entry.value) {
str.assign(reinterpret_cast<char*>(entry.value), entry.sz);
} else {
str = absl::StrCat(entry.longval);
}
if (str == element) {
matched++;
auto k = (direction == AL_START_TAIL) ? ql->count - index - 1 : index;
if (matched >= rank) {
matches.push_back(k);
if (count && unsigned(matched - rank + 1) >= count) {
break;
}
}
}
index++;
}
quicklistReleaseIterator(ql_iter);
}
quicklistReleaseIterator(ql_iter);
return matches;
}
@ -624,29 +652,41 @@ OpResult<int> OpInsert(const OpArgs& op_args, string_view key, string_view pivot
if (!it_res)
return it_res.status();
quicklist* ql = GetQL(it_res->it->second);
quicklistEntry entry = container_utils::QLEntry();
quicklistIter* qiter = quicklistGetIterator(ql, AL_START_HEAD);
bool found = false;
while (quicklistNext(qiter, &entry)) {
if (ElemCompare(entry, pivot)) {
found = true;
break;
}
}
PrimeValue& pv = it_res->it->second;
int res = -1;
if (found) {
if (insert_param == INSERT_AFTER) {
quicklistInsertAfter(qiter, &entry, elem.data(), elem.size());
} else {
DCHECK_EQ(INSERT_BEFORE, insert_param);
quicklistInsertBefore(qiter, &entry, elem.data(), elem.size());
if (pv.Encoding() == kEncodingQL2) {
QList* ql = GetQLV2(pv);
QList::InsertOpt insert_opt = (insert_param == INSERT_BEFORE) ? QList::BEFORE : QList::AFTER;
if (ql->Insert(pivot, elem, insert_opt)) {
res = ql->Size();
}
res = quicklistCount(ql);
} else {
quicklist* ql = GetQL(pv);
quicklistEntry entry = container_utils::QLEntry();
quicklistIter* qiter = quicklistGetIterator(ql, AL_START_HEAD);
bool found = false;
while (quicklistNext(qiter, &entry)) {
if (ElemCompare(entry, pivot)) {
found = true;
break;
}
}
if (found) {
if (insert_param == INSERT_AFTER) {
quicklistInsertAfter(qiter, &entry, elem.data(), elem.size());
} else {
DCHECK_EQ(INSERT_BEFORE, insert_param);
quicklistInsertBefore(qiter, &entry, elem.data(), elem.size());
}
res = quicklistCount(ql);
}
quicklistReleaseIterator(qiter);
}
quicklistReleaseIterator(qiter);
return res;
}
@ -738,14 +778,21 @@ OpStatus OpSet(const OpArgs& op_args, string_view key, string_view elem, long in
return it_res.status();
auto it = it_res->it;
quicklist* ql = GetQL(it->second);
OpStatus status = OpStatus::OUT_OF_RANGE;
if (it->second.Encoding() == kEncodingQL2) {
QList* ql = GetQLV2(it->second);
if (ql->Replace(index, elem))
status = OpStatus::OK;
} else {
DCHECK_EQ(it->second.Encoding(), OBJ_ENCODING_QUICKLIST);
quicklist* ql = GetQL(it->second);
int replaced = quicklistReplaceAtIndex(ql, index, elem.data(), elem.size());
if (!replaced) {
return OpStatus::OUT_OF_RANGE;
int replaced = quicklistReplaceAtIndex(ql, index, elem.data(), elem.size());
if (replaced) {
status = OpStatus::OK;
}
}
return OpStatus::OK;
return status;
}
OpStatus OpTrim(const OpArgs& op_args, string_view key, long start, long end) {
@ -803,8 +850,8 @@ OpResult<StringVec> OpRange(const OpArgs& op_args, std::string_view key, long st
if (!res)
return res.status();
quicklist* ql = GetQL(res.value()->second);
long llen = quicklistCount(ql);
const PrimeValue& pv = (*res)->second;
long llen = pv.Size();
/* convert negative indexes */
if (start < 0)
@ -823,13 +870,12 @@ OpResult<StringVec> OpRange(const OpArgs& op_args, std::string_view key, long st
StringVec str_vec;
container_utils::IterateList(
res.value()->second,
pv,
[&str_vec](container_utils::ContainerEntry ce) {
str_vec.emplace_back(ce.ToString());
return true;
},
start, end);
return str_vec;
}