mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
chore: minor refactorings around dense_set deletions (#4390)
chore: refactorings around deletions Done as a preparation to introduce asynchronous deletions for sets/zsets/hmaps. 1. Restrict the interface around DbSlice::Del. Now it requires for the iterator to be valid and the checks should be explicit before the call. Most callers already provides a valid iterator. 2. Some minor refactoring in compact_object_test. 3. Expose DenseSet::ClearStep to allow iterative deletions of elements. Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
3b082e42b8
commit
7a68528022
14 changed files with 116 additions and 93 deletions
|
@ -791,8 +791,8 @@ uint64_t CompactObj::HashCode() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoded) {
|
if (encoded) {
|
||||||
GetString(&tl.tmp_str);
|
string_view sv = GetSlice(&tl.tmp_str);
|
||||||
return XXH3_64bits_withSeed(tl.tmp_str.data(), tl.tmp_str.size(), kHashSeed);
|
return XXH3_64bits_withSeed(sv.data(), sv.size(), kHashSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (taglen_) {
|
switch (taglen_) {
|
||||||
|
|
|
@ -76,18 +76,15 @@ void DeallocateAtRandom(size_t steps, std::vector<void*>* ptrs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompactObjectTest : public ::testing::Test {
|
static void InitThreadStructs() {
|
||||||
protected:
|
|
||||||
static void SetUpTestSuite() {
|
|
||||||
InitRedisTables(); // to initialize server struct.
|
|
||||||
|
|
||||||
auto* tlh = mi_heap_get_backing();
|
auto* tlh = mi_heap_get_backing();
|
||||||
init_zmalloc_threadlocal(tlh);
|
init_zmalloc_threadlocal(tlh);
|
||||||
SmallString::InitThreadLocal(tlh);
|
SmallString::InitThreadLocal(tlh);
|
||||||
CompactObj::InitThreadLocal(PMR_NS::get_default_resource());
|
thread_local MiMemoryResource mi_resource(tlh);
|
||||||
}
|
CompactObj::InitThreadLocal(&mi_resource);
|
||||||
|
};
|
||||||
|
|
||||||
static void TearDownTestSuite() {
|
static void CheckEverythingDeallocated() {
|
||||||
mi_heap_collect(mi_heap_get_backing(), true);
|
mi_heap_collect(mi_heap_get_backing(), true);
|
||||||
|
|
||||||
auto cb_visit = [](const mi_heap_t* heap, const mi_heap_area_t* area, void* block,
|
auto cb_visit = [](const mi_heap_t* heap, const mi_heap_area_t* area, void* block,
|
||||||
|
@ -99,6 +96,18 @@ class CompactObjectTest : public ::testing::Test {
|
||||||
|
|
||||||
mi_heap_visit_blocks(mi_heap_get_backing(), false /* do not visit all blocks*/, cb_visit,
|
mi_heap_visit_blocks(mi_heap_get_backing(), false /* do not visit all blocks*/, cb_visit,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompactObjectTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
static void SetUpTestSuite() {
|
||||||
|
InitRedisTables(); // to initialize server struct.
|
||||||
|
|
||||||
|
InitThreadStructs();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TearDownTestSuite() {
|
||||||
|
CheckEverythingDeallocated();
|
||||||
}
|
}
|
||||||
|
|
||||||
CompactObj cobj_;
|
CompactObj cobj_;
|
||||||
|
|
|
@ -168,14 +168,14 @@ auto DenseSet::PopPtrFront(DenseSet::ChainVectorIterator it) -> DensePtr {
|
||||||
return front;
|
return front;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DenseSet::ClearInternal(uint32_t start, uint32_t count) {
|
uint32_t DenseSet::ClearStep(uint32_t start, uint32_t count) {
|
||||||
constexpr unsigned kArrLen = 32;
|
constexpr unsigned kArrLen = 32;
|
||||||
ClearItem arr[kArrLen];
|
ClearItem arr[kArrLen];
|
||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
|
|
||||||
size_t end = min<size_t>(entries_.size(), start + count);
|
size_t end = min<size_t>(entries_.size(), start + count);
|
||||||
for (size_t i = start; i < end; ++i) {
|
for (size_t i = start; i < end; ++i) {
|
||||||
DensePtr ptr = entries_[i];
|
DensePtr& ptr = entries_[i];
|
||||||
if (ptr.IsEmpty())
|
if (ptr.IsEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -190,6 +190,7 @@ uint32_t DenseSet::ClearInternal(uint32_t start, uint32_t count) {
|
||||||
dest.ptr = ptr;
|
dest.ptr = ptr;
|
||||||
dest.obj = nullptr;
|
dest.obj = nullptr;
|
||||||
}
|
}
|
||||||
|
ptr.Reset();
|
||||||
if (len == kArrLen) {
|
if (len == kArrLen) {
|
||||||
ClearBatch(kArrLen, arr);
|
ClearBatch(kArrLen, arr);
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
|
@ -215,9 +215,13 @@ class DenseSet {
|
||||||
virtual ~DenseSet();
|
virtual ~DenseSet();
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
ClearInternal(0, entries_.size());
|
ClearStep(0, entries_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the next bucket index that should be cleared.
|
||||||
|
// Returns BucketCount when all objects are erased.
|
||||||
|
uint32_t ClearStep(uint32_t start, uint32_t count);
|
||||||
|
|
||||||
// Returns the number of elements in the map. Note that it might be that some of these elements
|
// Returns the number of elements in the map. Note that it might be that some of these elements
|
||||||
// have expired and can't be accessed.
|
// have expired and can't be accessed.
|
||||||
size_t UpperBoundSize() const {
|
size_t UpperBoundSize() const {
|
||||||
|
@ -303,11 +307,6 @@ class DenseSet {
|
||||||
|
|
||||||
void* PopInternal();
|
void* PopInternal();
|
||||||
|
|
||||||
// Note this does not free any dynamic allocations done by derived classes, that a DensePtr
|
|
||||||
// in the set may point to. This function only frees the allocated DenseLinkKeys created by
|
|
||||||
// DenseSet. All data allocated by a derived class should be freed before calling this
|
|
||||||
uint32_t ClearInternal(uint32_t start, uint32_t count);
|
|
||||||
|
|
||||||
void IncreaseMallocUsed(size_t delta) {
|
void IncreaseMallocUsed(size_t delta) {
|
||||||
obj_malloc_used_ += delta;
|
obj_malloc_used_ += delta;
|
||||||
}
|
}
|
||||||
|
|
|
@ -669,10 +669,8 @@ void DbSlice::ActivateDb(DbIndex db_ind) {
|
||||||
CreateDb(db_ind);
|
CreateDb(db_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DbSlice::Del(Context cntx, Iterator it) {
|
void DbSlice::Del(Context cntx, Iterator it) {
|
||||||
if (!IsValid(it)) {
|
CHECK(IsValid(it));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& db = db_arr_[cntx.db_index];
|
auto& db = db_arr_[cntx.db_index];
|
||||||
auto obj_type = it->second.ObjType();
|
auto obj_type = it->second.ObjType();
|
||||||
|
@ -683,8 +681,6 @@ bool DbSlice::Del(Context cntx, Iterator it) {
|
||||||
doc_del_cb_(key, cntx, it->second);
|
doc_del_cb_(key, cntx, it->second);
|
||||||
}
|
}
|
||||||
PerformDeletion(it, db.get());
|
PerformDeletion(it, db.get());
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbSlice::FlushSlotsFb(const cluster::SlotSet& slot_ids) {
|
void DbSlice::FlushSlotsFb(const cluster::SlotSet& slot_ids) {
|
||||||
|
@ -917,7 +913,7 @@ OpResult<int64_t> DbSlice::UpdateExpire(const Context& cntx, Iterator prime_it,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rel_msec <= 0) { // implicit - don't persist
|
if (rel_msec <= 0) { // implicit - don't persist
|
||||||
CHECK(Del(cntx, prime_it));
|
Del(cntx, prime_it);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (IsValid(expire_it) && !params.persist) {
|
} else if (IsValid(expire_it) && !params.persist) {
|
||||||
auto current = ExpireTime(expire_it);
|
auto current = ExpireTime(expire_it);
|
||||||
|
|
|
@ -346,7 +346,8 @@ class DbSlice {
|
||||||
// Delete a key referred by its iterator.
|
// Delete a key referred by its iterator.
|
||||||
void PerformDeletion(Iterator del_it, DbTable* table);
|
void PerformDeletion(Iterator del_it, DbTable* table);
|
||||||
|
|
||||||
bool Del(Context cntx, Iterator it);
|
// Deletes the iterator. The iterator must be valid.
|
||||||
|
void Del(Context cntx, Iterator it);
|
||||||
|
|
||||||
constexpr static DbIndex kDbAll = 0xFFFF;
|
constexpr static DbIndex kDbAll = 0xFFFF;
|
||||||
|
|
||||||
|
|
|
@ -426,11 +426,10 @@ bool EngineShard::DoDefrag() {
|
||||||
// priority.
|
// priority.
|
||||||
// otherwise lower the task priority so that it would not use the CPU when not required
|
// otherwise lower the task priority so that it would not use the CPU when not required
|
||||||
uint32_t EngineShard::DefragTask() {
|
uint32_t EngineShard::DefragTask() {
|
||||||
if (!namespaces) {
|
|
||||||
return util::ProactorBase::kOnIdleMaxLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr uint32_t kRunAtLowPriority = 0u;
|
constexpr uint32_t kRunAtLowPriority = 0u;
|
||||||
|
if (!namespaces) {
|
||||||
|
return kRunAtLowPriority;
|
||||||
|
}
|
||||||
|
|
||||||
if (defrag_state_.CheckRequired()) {
|
if (defrag_state_.CheckRequired()) {
|
||||||
VLOG(2) << shard_id_ << ": need to run defrag memory cursor state: " << defrag_state_.cursor;
|
VLOG(2) << shard_id_ << ": need to run defrag memory cursor state: " << defrag_state_.cursor;
|
||||||
|
|
|
@ -440,7 +440,7 @@ OpStatus Renamer::DelSrc(Transaction* t, EngineShard* shard) {
|
||||||
DVLOG(1) << "Rename: removing the key '" << src_key_;
|
DVLOG(1) << "Rename: removing the key '" << src_key_;
|
||||||
|
|
||||||
res.post_updater.Run();
|
res.post_updater.Run();
|
||||||
CHECK(db_slice.Del(t->GetDbContext(), it));
|
db_slice.Del(t->GetDbContext(), it);
|
||||||
if (shard->journal()) {
|
if (shard->journal()) {
|
||||||
RecordJournal(t->GetOpArgs(shard), "DEL"sv, ArgSlice{src_key_}, 2);
|
RecordJournal(t->GetOpArgs(shard), "DEL"sv, ArgSlice{src_key_}, 2);
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ OpStatus Renamer::DeserializeDest(Transaction* t, EngineShard* shard) {
|
||||||
if (dest_found_) {
|
if (dest_found_) {
|
||||||
DVLOG(1) << "Rename: deleting the destiny key '" << dest_key_;
|
DVLOG(1) << "Rename: deleting the destiny key '" << dest_key_;
|
||||||
dest_res.post_updater.Run();
|
dest_res.post_updater.Run();
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, dest_res.it));
|
db_slice.Del(op_args.db_cntx, dest_res.it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restore_args.Expired()) {
|
if (restore_args.Expired()) {
|
||||||
|
@ -554,7 +554,7 @@ OpResult<bool> OpRestore(const OpArgs& op_args, std::string_view key, std::strin
|
||||||
VLOG(1) << "restore command is running with replace, found old key '" << key
|
VLOG(1) << "restore command is running with replace, found old key '" << key
|
||||||
<< "' and removing it";
|
<< "' and removing it";
|
||||||
res.post_updater.Run();
|
res.post_updater.Run();
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, res.it));
|
db_slice.Del(op_args.db_cntx, res.it);
|
||||||
} else {
|
} else {
|
||||||
// we are not allowed to replace it.
|
// we are not allowed to replace it.
|
||||||
return OpStatus::KEY_EXISTS;
|
return OpStatus::KEY_EXISTS;
|
||||||
|
@ -812,7 +812,7 @@ OpStatus OpMove(const OpArgs& op_args, string_view key, DbIndex target_db) {
|
||||||
// Restore expire flag after std::move.
|
// Restore expire flag after std::move.
|
||||||
from_res.it->second.SetExpire(IsValid(from_res.exp_it));
|
from_res.it->second.SetExpire(IsValid(from_res.exp_it));
|
||||||
|
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, from_res.it));
|
db_slice.Del(op_args.db_cntx, from_res.it);
|
||||||
auto op_result = db_slice.AddNew(target_cntx, key, std::move(from_obj), exp_ts);
|
auto op_result = db_slice.AddNew(target_cntx, key, std::move(from_obj), exp_ts);
|
||||||
RETURN_ON_BAD_STATUS(op_result);
|
RETURN_ON_BAD_STATUS(op_result);
|
||||||
auto& add_res = *op_result;
|
auto& add_res = *op_result;
|
||||||
|
@ -868,13 +868,13 @@ OpResult<void> OpRen(const OpArgs& op_args, string_view from_key, string_view to
|
||||||
to_res.post_updater.Run();
|
to_res.post_updater.Run();
|
||||||
|
|
||||||
from_res.post_updater.Run();
|
from_res.post_updater.Run();
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, from_res.it));
|
db_slice.Del(op_args.db_cntx, from_res.it);
|
||||||
} else {
|
} else {
|
||||||
// Here we first delete from_it because AddNew below could invalidate from_it.
|
// Here we first delete from_it because AddNew below could invalidate from_it.
|
||||||
// On the other hand, AddNew does not rely on the iterators - this is why we keep
|
// On the other hand, AddNew does not rely on the iterators - this is why we keep
|
||||||
// the value in `from_obj`.
|
// the value in `from_obj`.
|
||||||
from_res.post_updater.Run();
|
from_res.post_updater.Run();
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, from_res.it));
|
db_slice.Del(op_args.db_cntx, from_res.it);
|
||||||
auto op_result = db_slice.AddNew(op_args.db_cntx, to_key, std::move(from_obj), exp_ts);
|
auto op_result = db_slice.AddNew(op_args.db_cntx, to_key, std::move(from_obj), exp_ts);
|
||||||
RETURN_ON_BAD_STATUS(op_result);
|
RETURN_ON_BAD_STATUS(op_result);
|
||||||
to_res = std::move(*op_result);
|
to_res = std::move(*op_result);
|
||||||
|
@ -995,35 +995,14 @@ std::optional<int32_t> ParseExpireOptionsOrReply(const CmdArgList args, SinkRepl
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
void DeleteGeneric(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
|
|
||||||
OpResult<uint32_t> GenericFamily::OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
|
||||||
DVLOG(1) << "Del: " << keys.Front();
|
|
||||||
auto& db_slice = op_args.GetDbSlice();
|
|
||||||
|
|
||||||
uint32_t res = 0;
|
|
||||||
|
|
||||||
for (string_view key : keys) {
|
|
||||||
auto fres = db_slice.FindMutable(op_args.db_cntx, key);
|
|
||||||
if (!IsValid(fres.it))
|
|
||||||
continue;
|
|
||||||
fres.post_updater.Run();
|
|
||||||
res += int(db_slice.Del(op_args.db_cntx, fres.it));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenericFamily::Del(CmdArgList args, const CommandContext& cmd_cntx) {
|
|
||||||
VLOG(1) << "Del " << ArgS(args, 0);
|
|
||||||
|
|
||||||
atomic_uint32_t result{0};
|
atomic_uint32_t result{0};
|
||||||
auto* builder = cmd_cntx.rb;
|
auto* builder = cmd_cntx.rb;
|
||||||
bool is_mc = (builder->GetProtocol() == Protocol::MEMCACHE);
|
bool is_mc = (builder->GetProtocol() == Protocol::MEMCACHE);
|
||||||
|
|
||||||
auto cb = [&result](const Transaction* t, EngineShard* shard) {
|
auto cb = [&result](const Transaction* t, EngineShard* shard) {
|
||||||
ShardArgs args = t->GetShardArgs(shard->shard_id());
|
ShardArgs args = t->GetShardArgs(shard->shard_id());
|
||||||
auto res = OpDel(t->GetOpArgs(shard), args);
|
auto res = GenericFamily::OpDel(t->GetOpArgs(shard), args);
|
||||||
result.fetch_add(res.value_or(0), memory_order_relaxed);
|
result.fetch_add(res.value_or(0), memory_order_relaxed);
|
||||||
|
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
|
@ -1049,6 +1028,36 @@ void GenericFamily::Del(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
OpResult<uint32_t> GenericFamily::OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
|
DVLOG(1) << "Del: " << keys.Front();
|
||||||
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
|
uint32_t res = 0;
|
||||||
|
|
||||||
|
for (string_view key : keys) {
|
||||||
|
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
||||||
|
if (!IsValid(it))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
|
++res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericFamily::Del(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
|
VLOG(1) << "Del " << ArgS(args, 0);
|
||||||
|
|
||||||
|
DeleteGeneric(args, cmd_cntx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericFamily::Unlink(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
|
DeleteGeneric(args, cmd_cntx);
|
||||||
|
}
|
||||||
|
|
||||||
void GenericFamily::Ping(CmdArgList args, const CommandContext& cmd_cntx) {
|
void GenericFamily::Ping(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
auto* rb = static_cast<RedisReplyBuilder*>(cmd_cntx.rb);
|
auto* rb = static_cast<RedisReplyBuilder*>(cmd_cntx.rb);
|
||||||
if (args.size() > 1) {
|
if (args.size() > 1) {
|
||||||
|
@ -1886,7 +1895,7 @@ void GenericFamily::Register(CommandRegistry* registry) {
|
||||||
<< CI{"TIME", CO::LOADING | CO::FAST, 1, 0, 0, acl::kTime}.HFUNC(Time)
|
<< CI{"TIME", CO::LOADING | CO::FAST, 1, 0, 0, acl::kTime}.HFUNC(Time)
|
||||||
<< CI{"TYPE", CO::READONLY | CO::FAST | CO::LOADING, 2, 1, 1, acl::kType}.HFUNC(Type)
|
<< CI{"TYPE", CO::READONLY | CO::FAST | CO::LOADING, 2, 1, 1, acl::kType}.HFUNC(Type)
|
||||||
<< CI{"DUMP", CO::READONLY, 2, 1, 1, acl::kDump}.HFUNC(Dump)
|
<< CI{"DUMP", CO::READONLY, 2, 1, 1, acl::kDump}.HFUNC(Dump)
|
||||||
<< CI{"UNLINK", CO::WRITE, -2, 1, -1, acl::kUnlink}.HFUNC(Del)
|
<< CI{"UNLINK", CO::WRITE, -2, 1, -1, acl::kUnlink}.HFUNC(Unlink)
|
||||||
<< CI{"STICK", CO::WRITE, -2, 1, -1, acl::kStick}.HFUNC(Stick)
|
<< CI{"STICK", CO::WRITE, -2, 1, -1, acl::kStick}.HFUNC(Stick)
|
||||||
<< CI{"SORT", CO::READONLY, -2, 1, 1, acl::kSort}.HFUNC(Sort)
|
<< CI{"SORT", CO::READONLY, -2, 1, 1, acl::kSort}.HFUNC(Sort)
|
||||||
<< CI{"MOVE", CO::WRITE | CO::GLOBAL_TRANS | CO::NO_AUTOJOURNAL, 3, 1, 1, acl::kMove}.HFUNC(
|
<< CI{"MOVE", CO::WRITE | CO::GLOBAL_TRANS | CO::NO_AUTOJOURNAL, 3, 1, 1, acl::kMove}.HFUNC(
|
||||||
|
|
|
@ -35,6 +35,7 @@ class GenericFamily {
|
||||||
using SinkReplyBuilder = facade::SinkReplyBuilder;
|
using SinkReplyBuilder = facade::SinkReplyBuilder;
|
||||||
|
|
||||||
static void Del(CmdArgList args, const CommandContext& cmd_cntx);
|
static void Del(CmdArgList args, const CommandContext& cmd_cntx);
|
||||||
|
static void Unlink(CmdArgList args, const CommandContext& cmd_cntx);
|
||||||
static void Ping(CmdArgList args, const CommandContext& cmd_cntx);
|
static void Ping(CmdArgList args, const CommandContext& cmd_cntx);
|
||||||
static void Exists(CmdArgList args, const CommandContext& cmd_cntx);
|
static void Exists(CmdArgList args, const CommandContext& cmd_cntx);
|
||||||
static void Expire(CmdArgList args, const CommandContext& cmd_cntx);
|
static void Expire(CmdArgList args, const CommandContext& cmd_cntx);
|
||||||
|
|
|
@ -585,10 +585,10 @@ OpResult<vector<string>> OpGetAll(const OpArgs& op_args, string_view key, uint8_
|
||||||
// and the enconding is guaranteed to be a DenseSet since we only support expiring
|
// and the enconding is guaranteed to be a DenseSet since we only support expiring
|
||||||
// value with that enconding.
|
// value with that enconding.
|
||||||
if (res.empty()) {
|
if (res.empty()) {
|
||||||
auto mutable_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_HASH);
|
// post_updater will run immediately
|
||||||
// Run postupdater, it means that we deleted the keys
|
auto it = db_slice.FindMutable(op_args.db_cntx, key).it;
|
||||||
mutable_res->post_updater.Run();
|
|
||||||
db_slice.Del(op_args.db_cntx, mutable_res->it);
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1169,10 +1169,10 @@ void HSetFamily::HRandField(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string_map->Empty()) {
|
if (string_map->Empty()) { // Can happen if we use a TTL on hash members.
|
||||||
auto it_mutable = db_slice.FindMutable(db_context, key, OBJ_HASH);
|
// post_updater will run immediately
|
||||||
it_mutable->post_updater.Run();
|
auto it = db_slice.FindMutable(db_context, key).it;
|
||||||
db_slice.Del(db_context, it_mutable->it);
|
db_slice.Del(db_context, it);
|
||||||
return facade::OpStatus::KEY_NOTFOUND;
|
return facade::OpStatus::KEY_NOTFOUND;
|
||||||
}
|
}
|
||||||
} else if (pv.Encoding() == kEncodingListPack) {
|
} else if (pv.Encoding() == kEncodingListPack) {
|
||||||
|
@ -1207,8 +1207,7 @@ void HSetFamily::HRandField(CmdArgList args, const CommandContext& cmd_cntx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Invalid encoding " << pv.Encoding();
|
LOG(FATAL) << "Invalid encoding " << pv.Encoding();
|
||||||
return OpStatus::INVALID_VALUE;
|
|
||||||
}
|
}
|
||||||
return str_vec;
|
return str_vec;
|
||||||
};
|
};
|
||||||
|
|
|
@ -913,8 +913,13 @@ OpResult<long> OpDel(const OpArgs& op_args, string_view key, string_view path,
|
||||||
if (json_path.RefersToRootElement()) {
|
if (json_path.RefersToRootElement()) {
|
||||||
auto& db_slice = op_args.GetDbSlice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
||||||
return static_cast<long>(db_slice.Del(op_args.db_cntx, it));
|
if (IsValid(it)) {
|
||||||
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
JsonMemTracker tracker;
|
JsonMemTracker tracker;
|
||||||
// FindMutable because we need to run the AutoUpdater at the end which will account
|
// FindMutable because we need to run the AutoUpdater at the end which will account
|
||||||
// the deltas calculated from the MemoryTracker
|
// the deltas calculated from the MemoryTracker
|
||||||
|
|
|
@ -180,7 +180,7 @@ std::string OpBPop(Transaction* t, EngineShard* shard, std::string_view key, Lis
|
||||||
OpArgs op_args = t->GetOpArgs(shard);
|
OpArgs op_args = t->GetOpArgs(shard);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
||||||
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, it));
|
op_args.GetDbSlice().Del(op_args.db_cntx, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op_args.shard->journal()) {
|
if (op_args.shard->journal()) {
|
||||||
|
@ -276,7 +276,7 @@ OpResult<string> OpMoveSingleShard(const OpArgs& op_args, string_view src, strin
|
||||||
dest_res.post_updater.Run();
|
dest_res.post_updater.Run();
|
||||||
|
|
||||||
if (prev_len == 1) {
|
if (prev_len == 1) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, src_it));
|
db_slice.Del(op_args.db_cntx, src_it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
@ -452,7 +452,7 @@ OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, ListDir dir, u
|
||||||
it_res->post_updater.Run();
|
it_res->post_updater.Run();
|
||||||
|
|
||||||
if (count == prev_len) {
|
if (count == prev_len) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, it));
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op_args.shard->journal() && journal_rewrite) {
|
if (op_args.shard->journal() && journal_rewrite) {
|
||||||
|
@ -765,7 +765,7 @@ OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, string_view ele
|
||||||
it_res->post_updater.Run();
|
it_res->post_updater.Run();
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, it));
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
|
@ -840,7 +840,7 @@ OpStatus OpTrim(const OpArgs& op_args, string_view key, long start, long end) {
|
||||||
it_res->post_updater.Run();
|
it_res->post_updater.Run();
|
||||||
|
|
||||||
if (it->second.Size() == 0) {
|
if (it->second.Size() == 0) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, it));
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
}
|
}
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,10 +443,12 @@ OpResult<uint32_t> OpAdd(const OpArgs& op_args, std::string_view key, const NewE
|
||||||
// key if it exists.
|
// key if it exists.
|
||||||
if (overwrite && (vals_it.begin() == vals_it.end())) {
|
if (overwrite && (vals_it.begin() == vals_it.end())) {
|
||||||
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
||||||
|
if (IsValid(it)) {
|
||||||
db_slice.Del(op_args.db_cntx, it);
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
if (journal_update && op_args.shard->journal()) {
|
if (journal_update && op_args.shard->journal()) {
|
||||||
RecordJournal(op_args, "DEL"sv, ArgSlice{key});
|
RecordJournal(op_args, "DEL"sv, ArgSlice{key});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +563,7 @@ OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, facade::ArgRang
|
||||||
find_res->post_updater.Run();
|
find_res->post_updater.Run();
|
||||||
|
|
||||||
if (isempty) {
|
if (isempty) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, find_res->it));
|
db_slice.Del(op_args.db_cntx, find_res->it);
|
||||||
}
|
}
|
||||||
if (journal_rewrite && op_args.shard->journal()) {
|
if (journal_rewrite && op_args.shard->journal()) {
|
||||||
vector<string_view> mapped(vals.Size() + 1);
|
vector<string_view> mapped(vals.Size() + 1);
|
||||||
|
@ -886,7 +888,7 @@ OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, unsigned count
|
||||||
|
|
||||||
// Delete the set as it is now empty
|
// Delete the set as it is now empty
|
||||||
find_res->post_updater.Run();
|
find_res->post_updater.Run();
|
||||||
CHECK(db_slice.Del(op_args.db_cntx, find_res->it));
|
db_slice.Del(op_args.db_cntx, find_res->it);
|
||||||
|
|
||||||
// Replicate as DEL.
|
// Replicate as DEL.
|
||||||
if (op_args.shard->journal()) {
|
if (op_args.shard->journal()) {
|
||||||
|
|
|
@ -964,7 +964,9 @@ OpResult<AddResult> OpAdd(const OpArgs& op_args, const ZParams& zparams, string_
|
||||||
|
|
||||||
if (zparams.override && members.empty()) {
|
if (zparams.override && members.empty()) {
|
||||||
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
auto it = db_slice.FindMutable(op_args.db_cntx, key).it; // post_updater will run immediately
|
||||||
|
if (IsValid(it)) {
|
||||||
db_slice.Del(op_args.db_cntx, it);
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
|
}
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,7 +1221,7 @@ ScoredArray OpBZPop(Transaction* t, EngineShard* shard, std::string_view key, bo
|
||||||
auto zlen = pv.Size();
|
auto zlen = pv.Size();
|
||||||
if (zlen == 0) {
|
if (zlen == 0) {
|
||||||
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
||||||
CHECK(db_slice.Del(t->GetDbContext(), it_res->it));
|
db_slice.Del(t->GetDbContext(), it_res->it);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpArgs op_args = t->GetOpArgs(shard);
|
OpArgs op_args = t->GetOpArgs(shard);
|
||||||
|
@ -1330,7 +1332,7 @@ auto OpPopCount(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args,
|
||||||
|
|
||||||
auto zlen = pv.Size();
|
auto zlen = pv.Size();
|
||||||
if (zlen == 0) {
|
if (zlen == 0) {
|
||||||
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return iv.PopResult();
|
return iv.PopResult();
|
||||||
|
@ -1384,7 +1386,7 @@ OpResult<unsigned> OpRemRange(const OpArgs& op_args, string_view key,
|
||||||
|
|
||||||
auto zlen = pv.Size();
|
auto zlen = pv.Size();
|
||||||
if (zlen == 0) {
|
if (zlen == 0) {
|
||||||
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return iv.removed();
|
return iv.removed();
|
||||||
|
@ -1563,7 +1565,7 @@ OpResult<unsigned> OpRem(const OpArgs& op_args, string_view key, facade::ArgRang
|
||||||
res_it->post_updater.Run();
|
res_it->post_updater.Run();
|
||||||
|
|
||||||
if (zlen == 0) {
|
if (zlen == 0) {
|
||||||
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return deleted;
|
return deleted;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue