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:
parent
66e0fd0908
commit
a87d6aecef
2 changed files with 105 additions and 58 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -133,7 +133,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd ${GITHUB_WORKSPACE}/build
|
cd ${GITHUB_WORKSPACE}/build
|
||||||
echo Run ctest -V -L DFLY
|
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"
|
echo "Running tests with --force_epoll"
|
||||||
|
|
||||||
|
|
|
@ -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,
|
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(key.data() && element.data());
|
||||||
|
DCHECK_NE(rank, 0);
|
||||||
|
|
||||||
auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
int direction = AL_START_HEAD;
|
const PrimeValue& pv = (*it_res)->second;
|
||||||
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;
|
|
||||||
vector<uint32_t> matches;
|
vector<uint32_t> matches;
|
||||||
string str;
|
|
||||||
|
|
||||||
while (quicklistNext(ql_iter, &entry) && (max_len == 0 || index < max_len)) {
|
if (pv.Encoding() == kEncodingQL2) {
|
||||||
if (entry.value) {
|
QList* ql = GetQLV2(pv);
|
||||||
str.assign(reinterpret_cast<char*>(entry.value), entry.sz);
|
QList::Where where = QList::HEAD;
|
||||||
} else {
|
if (rank < 0) {
|
||||||
str = absl::StrCat(entry.longval);
|
rank = -rank;
|
||||||
|
where = QList::TAIL;
|
||||||
}
|
}
|
||||||
if (str == element) {
|
|
||||||
matched++;
|
auto it = ql->GetIterator(where);
|
||||||
auto k = (direction == AL_START_TAIL) ? ql->count - index - 1 : index;
|
unsigned index = 0;
|
||||||
if (matched >= rank) {
|
while (it.Next() && (max_len == 0 || index < max_len)) {
|
||||||
matches.push_back(k);
|
if (it.Get() == element) {
|
||||||
if (count && matched - rank + 1 >= count) {
|
if (rank == 1) {
|
||||||
break;
|
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;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,29 +652,41 @@ OpResult<int> OpInsert(const OpArgs& op_args, string_view key, string_view pivot
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
quicklist* ql = GetQL(it_res->it->second);
|
PrimeValue& pv = 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
if (found) {
|
|
||||||
if (insert_param == INSERT_AFTER) {
|
if (pv.Encoding() == kEncodingQL2) {
|
||||||
quicklistInsertAfter(qiter, &entry, elem.data(), elem.size());
|
QList* ql = GetQLV2(pv);
|
||||||
} else {
|
QList::InsertOpt insert_opt = (insert_param == INSERT_BEFORE) ? QList::BEFORE : QList::AFTER;
|
||||||
DCHECK_EQ(INSERT_BEFORE, insert_param);
|
if (ql->Insert(pivot, elem, insert_opt)) {
|
||||||
quicklistInsertBefore(qiter, &entry, elem.data(), elem.size());
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,14 +778,21 @@ OpStatus OpSet(const OpArgs& op_args, string_view key, string_view elem, long in
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
auto it = it_res->it;
|
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());
|
int replaced = quicklistReplaceAtIndex(ql, index, elem.data(), elem.size());
|
||||||
|
if (replaced) {
|
||||||
if (!replaced) {
|
status = OpStatus::OK;
|
||||||
return OpStatus::OUT_OF_RANGE;
|
}
|
||||||
}
|
}
|
||||||
return OpStatus::OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus OpTrim(const OpArgs& op_args, string_view key, long start, long end) {
|
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)
|
if (!res)
|
||||||
return res.status();
|
return res.status();
|
||||||
|
|
||||||
quicklist* ql = GetQL(res.value()->second);
|
const PrimeValue& pv = (*res)->second;
|
||||||
long llen = quicklistCount(ql);
|
long llen = pv.Size();
|
||||||
|
|
||||||
/* convert negative indexes */
|
/* convert negative indexes */
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
|
@ -823,13 +870,12 @@ OpResult<StringVec> OpRange(const OpArgs& op_args, std::string_view key, long st
|
||||||
|
|
||||||
StringVec str_vec;
|
StringVec str_vec;
|
||||||
container_utils::IterateList(
|
container_utils::IterateList(
|
||||||
res.value()->second,
|
pv,
|
||||||
[&str_vec](container_utils::ContainerEntry ce) {
|
[&str_vec](container_utils::ContainerEntry ce) {
|
||||||
str_vec.emplace_back(ce.ToString());
|
str_vec.emplace_back(ce.ToString());
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
start, end);
|
start, end);
|
||||||
|
|
||||||
return str_vec;
|
return str_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue