mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-14 11:58:02 +00:00
refactor: Use DbContext
, OpArgs
and Transaction
to access DbSlice
(#3311)
This is a refactor that will put us closer to adding namespaces, see included `docs/namespaces.md`
This commit is contained in:
parent
bf2e5fd3f5
commit
d7351b315e
28 changed files with 355 additions and 233 deletions
docs
src/server
bitops_family.ccbloom_family.cccontainer_utils.ccdb_slice.ccdb_slice.h
detail
dflycmd.ccdragonfly_test.ccengine_shard_set.ccengine_shard_set.hgeneric_family.cchll_family.cchset_family.ccjson_family.cclist_family.ccmain_service.ccmemory_cmd.ccsearch
server_family.ccset_family.ccstream_family.ccstring_family.cctransaction.cctransaction.htx_base.cctx_base.hzset_family.cc
71
docs/namespaces.md
Normal file
71
docs/namespaces.md
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Namespaces in Dragonfly
|
||||||
|
|
||||||
|
Dragonfly will soon add an _experimental_ feature, allowing complete separation of data by different users.
|
||||||
|
We call this feature _namespaces_, and it allows using a single Dragonfly server with multiple
|
||||||
|
tenants, each using their own data, without being able to mix them together.
|
||||||
|
|
||||||
|
Note that this feature can alternatively be achieved by having each user `SELECT` a different
|
||||||
|
(numeric) database, or by asking that each user uses a unique prefix for their keys. This approach
|
||||||
|
has several disadvantages, like users forgetting to `SELECT` / use their prefix, accessing data
|
||||||
|
logically belonging to other users.
|
||||||
|
|
||||||
|
The advantage of using Namespaces is that data is completely isolated, and users cannot accidentally
|
||||||
|
use data they do not own. A user must authenticate in order to access the namespace it was assigned.
|
||||||
|
And as a bonus, each namespace can have multiple databases, switched via `SELECT` like any regular
|
||||||
|
data store.
|
||||||
|
|
||||||
|
However, before using this feature, please note that it is experimental. This means that:
|
||||||
|
|
||||||
|
* Some features are not supported for non-default namespaces, such as replication and save to RDB
|
||||||
|
* Some tools are missing, like breakdown of memory / load per namespace
|
||||||
|
* We do not yet consider this production ready, and it might still have some uncovered bugs
|
||||||
|
|
||||||
|
So kindly use it at your own risk.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This section describes how, as a Dragonfly user / administrator, you could use namespaces.
|
||||||
|
|
||||||
|
A namespace is identified by a unique string id, defined by the user / admin. Each Dragonfly user
|
||||||
|
is associated with a single namespace. If not set explicitly, then the default namespace is used,
|
||||||
|
which is the empty string id.
|
||||||
|
|
||||||
|
Multiple users can use the same namespace if they are all assigned the same namespace id. This can
|
||||||
|
allow, for example, creating a read-only user as well as a mutating user over the same data.
|
||||||
|
|
||||||
|
To associate user `user1` with the namespace `namespace1`, use the `ACL` command with the
|
||||||
|
`NAMESPACE:namespace1` flag:
|
||||||
|
|
||||||
|
```
|
||||||
|
ACL SETUSER user1 NAMESPACE:namespace1 ON >user_pass +@all ~*
|
||||||
|
```
|
||||||
|
|
||||||
|
This sets / creates user `user`, using password `user_pass`, using namespace `namespace1`.
|
||||||
|
|
||||||
|
For more examples check out `tests/dragonfly/acl_family_test.py` - specifically the
|
||||||
|
`test_namespaces` function.
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
This section describes how we _implemented_ namespaces in Dragonfly. It is meant to be used by those
|
||||||
|
who wish to contribute pull requests to Dragonfly.
|
||||||
|
|
||||||
|
Prior to adding namespaces to Dragonfly, each _shard_ had a single `DbSlice` that it owned. They
|
||||||
|
were thread-local, global-scope instances.
|
||||||
|
|
||||||
|
To support namespaces, we created a `Namespace` class (see `src/server/namespaces.h`) which contains
|
||||||
|
a `vector<DbSlice>`, with a `DbSlice` per shard. When first used, a `Namespace` calls the engine
|
||||||
|
shard set to initialize the array of `DbSlice`s.
|
||||||
|
|
||||||
|
To access all `Namespace`s, we also added a registry with the original name `Namespaces`. It is a
|
||||||
|
global, thread safe class that allows accessing all registered namespaces, and registering new ones
|
||||||
|
on the fly. Note that, while it is thread safe, it shouldn't be a bottle neck because it is supposed
|
||||||
|
to only be used during the authentication of a connection (or when adding new namespaces).
|
||||||
|
|
||||||
|
When a new connection is authenticated with Dragonfly, we look up (and create, if needed) the
|
||||||
|
namespace it is associated with. We then save a `Namespace* ns` inside the `dfly::ConnectionContext`
|
||||||
|
class to associate the user with the namespaces. Because we removed the global `DbSlice` objects,
|
||||||
|
this is now the only way to access namespaces, which protects users from accessing unowned data.
|
||||||
|
|
||||||
|
Currently, we do not have any support for removing namespaces, so they hang in memory until the
|
||||||
|
server exits.
|
|
@ -310,7 +310,7 @@ class ElementAccess {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<bool> ElementAccess::Exists(EngineShard* shard) {
|
std::optional<bool> ElementAccess::Exists(EngineShard* shard) {
|
||||||
auto res = shard->db_slice().FindReadOnly(context_, key_, OBJ_STRING);
|
auto res = context_.GetDbSlice(shard->shard_id()).FindReadOnly(context_, key_, OBJ_STRING);
|
||||||
if (res.status() == OpStatus::WRONG_TYPE) {
|
if (res.status() == OpStatus::WRONG_TYPE) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ std::optional<bool> ElementAccess::Exists(EngineShard* shard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus ElementAccess::Find(EngineShard* shard) {
|
OpStatus ElementAccess::Find(EngineShard* shard) {
|
||||||
auto op_res = shard->db_slice().AddOrFind(context_, key_);
|
auto op_res = context_.GetDbSlice(shard->shard_id()).AddOrFind(context_, key_);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
auto& add_res = *op_res;
|
auto& add_res = *op_res;
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ OpResult<bool> BitNewValue(const OpArgs& args, std::string_view key, uint32_t of
|
||||||
bool bit_value) {
|
bool bit_value) {
|
||||||
EngineShard* shard = args.shard;
|
EngineShard* shard = args.shard;
|
||||||
ElementAccess element_access{key, args};
|
ElementAccess element_access{key, args};
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = args.GetDbSlice();
|
||||||
DCHECK(db_slice.IsDbValid(element_access.Index()));
|
DCHECK(db_slice.IsDbValid(element_access.Index()));
|
||||||
bool old_value = false;
|
bool old_value = false;
|
||||||
|
|
||||||
|
@ -445,9 +445,9 @@ OpResult<std::string> CombineResultOp(ShardStringResults result, std::string_vie
|
||||||
|
|
||||||
// For bitop not - we cannot accumulate
|
// For bitop not - we cannot accumulate
|
||||||
OpResult<std::string> RunBitOpNot(const OpArgs& op_args, string_view key) {
|
OpResult<std::string> RunBitOpNot(const OpArgs& op_args, string_view key) {
|
||||||
EngineShard* es = op_args.shard;
|
|
||||||
// if we found the value, just return, if not found then skip, otherwise report an error
|
// if we found the value, just return, if not found then skip, otherwise report an error
|
||||||
auto find_res = es->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
DbSlice& db_slice = op_args.GetDbSlice();
|
||||||
|
auto find_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (find_res) {
|
if (find_res) {
|
||||||
return GetString(find_res.value()->second);
|
return GetString(find_res.value()->second);
|
||||||
} else {
|
} else {
|
||||||
|
@ -463,12 +463,13 @@ OpResult<std::string> RunBitOpOnShard(std::string_view op, const OpArgs& op_args
|
||||||
if (op == NOT_OP_NAME) {
|
if (op == NOT_OP_NAME) {
|
||||||
return RunBitOpNot(op_args, *start);
|
return RunBitOpNot(op_args, *start);
|
||||||
}
|
}
|
||||||
EngineShard* es = op_args.shard;
|
|
||||||
|
DbSlice& db_slice = op_args.GetDbSlice();
|
||||||
BitsStrVec values;
|
BitsStrVec values;
|
||||||
|
|
||||||
// collect all the value for this shard
|
// collect all the value for this shard
|
||||||
for (; start != end; ++start) {
|
for (; start != end; ++start) {
|
||||||
auto find_res = es->db_slice().FindReadOnly(op_args.db_cntx, *start, OBJ_STRING);
|
auto find_res = db_slice.FindReadOnly(op_args.db_cntx, *start, OBJ_STRING);
|
||||||
if (find_res) {
|
if (find_res) {
|
||||||
values.emplace_back(GetString(find_res.value()->second));
|
values.emplace_back(GetString(find_res.value()->second));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1244,7 +1245,8 @@ OpResult<bool> ReadValueBitsetAt(const OpArgs& op_args, std::string_view key, ui
|
||||||
|
|
||||||
OpResult<std::string> ReadValue(const DbContext& context, std::string_view key,
|
OpResult<std::string> ReadValue(const DbContext& context, std::string_view key,
|
||||||
EngineShard* shard) {
|
EngineShard* shard) {
|
||||||
auto it_res = shard->db_slice().FindReadOnly(context, key, OBJ_STRING);
|
DbSlice& db_slice = context.GetDbSlice(shard->shard_id());
|
||||||
|
auto it_res = db_slice.FindReadOnly(context, key, OBJ_STRING);
|
||||||
if (!it_res.ok()) {
|
if (!it_res.ok()) {
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ using AddResult = absl::InlinedVector<OpResult<bool>, 4>;
|
||||||
using ExistsResult = absl::InlinedVector<bool, 4>;
|
using ExistsResult = absl::InlinedVector<bool, 4>;
|
||||||
|
|
||||||
OpStatus OpReserve(const SbfParams& params, const OpArgs& op_args, string_view key) {
|
OpStatus OpReserve(const SbfParams& params, const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
OpResult op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
OpResult op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
if (!op_res)
|
if (!op_res)
|
||||||
return op_res.status();
|
return op_res.status();
|
||||||
|
@ -50,7 +50,7 @@ OpStatus OpReserve(const SbfParams& params, const OpArgs& op_args, string_view k
|
||||||
|
|
||||||
// Returns true, if item was added, false if it was already "present".
|
// Returns true, if item was added, false if it was already "present".
|
||||||
OpResult<AddResult> OpAdd(const OpArgs& op_args, string_view key, CmdArgList items) {
|
OpResult<AddResult> OpAdd(const OpArgs& op_args, string_view key, CmdArgList items) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
OpResult op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
OpResult op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
if (!op_res)
|
if (!op_res)
|
||||||
|
@ -73,7 +73,7 @@ OpResult<AddResult> OpAdd(const OpArgs& op_args, string_view key, CmdArgList ite
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<ExistsResult> OpExists(const OpArgs& op_args, string_view key, CmdArgList items) {
|
OpResult<ExistsResult> OpExists(const OpArgs& op_args, string_view key, CmdArgList items) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
OpResult op_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_SBF);
|
OpResult op_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_SBF);
|
||||||
if (!op_res)
|
if (!op_res)
|
||||||
return op_res.status();
|
return op_res.status();
|
||||||
|
|
|
@ -60,8 +60,9 @@ OpResult<string> FindFirstNonEmptySingleShard(Transaction* trans, int req_obj_ty
|
||||||
DCHECK_EQ(trans->GetUniqueShardCnt(), 1u);
|
DCHECK_EQ(trans->GetUniqueShardCnt(), 1u);
|
||||||
string key;
|
string key;
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) -> Transaction::RunnableResult {
|
auto cb = [&](Transaction* t, EngineShard* shard) -> Transaction::RunnableResult {
|
||||||
auto args = t->GetShardArgs(shard->shard_id());
|
ShardId sid = shard->shard_id();
|
||||||
auto ff_res = FindFirstReadOnly(shard->db_slice(), t->GetDbContext(), args, req_obj_type);
|
auto args = t->GetShardArgs(sid);
|
||||||
|
auto ff_res = FindFirstReadOnly(t->GetDbSlice(sid), t->GetDbContext(), args, req_obj_type);
|
||||||
|
|
||||||
if (ff_res == OpStatus::WRONG_TYPE)
|
if (ff_res == OpStatus::WRONG_TYPE)
|
||||||
return OpStatus::WRONG_TYPE;
|
return OpStatus::WRONG_TYPE;
|
||||||
|
@ -96,8 +97,9 @@ OpResult<ShardFFResult> FindFirstNonEmpty(Transaction* trans, int req_obj_type)
|
||||||
std::fill(find_res.begin(), find_res.end(), OpStatus::KEY_NOTFOUND);
|
std::fill(find_res.begin(), find_res.end(), OpStatus::KEY_NOTFOUND);
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||||
auto args = t->GetShardArgs(shard->shard_id());
|
ShardId sid = shard->shard_id();
|
||||||
auto ff_res = FindFirstReadOnly(shard->db_slice(), t->GetDbContext(), args, req_obj_type);
|
auto args = t->GetShardArgs(sid);
|
||||||
|
auto ff_res = FindFirstReadOnly(t->GetDbSlice(sid), t->GetDbContext(), args, req_obj_type);
|
||||||
if (ff_res) {
|
if (ff_res) {
|
||||||
find_res[shard->shard_id()] =
|
find_res[shard->shard_id()] =
|
||||||
FFResult{ff_res->first->first.AsRef(), ff_res->second, shard->shard_id()};
|
FFResult{ff_res->first->first.AsRef(), ff_res->second, shard->shard_id()};
|
||||||
|
@ -339,7 +341,7 @@ OpResult<string> RunCbOnFirstNonEmptyBlocking(Transaction* trans, int req_obj_ty
|
||||||
auto wcb = [](Transaction* t, EngineShard* shard) { return t->GetShardArgs(shard->shard_id()); };
|
auto wcb = [](Transaction* t, EngineShard* shard) { return t->GetShardArgs(shard->shard_id()); };
|
||||||
const auto key_checker = [req_obj_type](EngineShard* owner, const DbContext& context,
|
const auto key_checker = [req_obj_type](EngineShard* owner, const DbContext& context,
|
||||||
Transaction*, std::string_view key) -> bool {
|
Transaction*, std::string_view key) -> bool {
|
||||||
return owner->db_slice().FindReadOnly(context, key, req_obj_type).ok();
|
return context.GetDbSlice(owner->shard_id()).FindReadOnly(context, key, req_obj_type).ok();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto status = trans->WaitOnWatch(limit_tp, std::move(wcb), key_checker, block_flag, pause_flag);
|
auto status = trans->WaitOnWatch(limit_tp, std::move(wcb), key_checker, block_flag, pause_flag);
|
||||||
|
|
|
@ -618,18 +618,18 @@ void DbSlice::ActivateDb(DbIndex db_ind) {
|
||||||
CreateDb(db_ind);
|
CreateDb(db_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DbSlice::Del(DbIndex db_ind, Iterator it) {
|
bool DbSlice::Del(Context cntx, Iterator it) {
|
||||||
if (!IsValid(it)) {
|
if (!IsValid(it)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db = db_arr_[db_ind];
|
auto& db = db_arr_[cntx.db_index];
|
||||||
auto obj_type = it->second.ObjType();
|
auto obj_type = it->second.ObjType();
|
||||||
|
|
||||||
if (doc_del_cb_ && (obj_type == OBJ_JSON || obj_type == OBJ_HASH)) {
|
if (doc_del_cb_ && (obj_type == OBJ_JSON || obj_type == OBJ_HASH)) {
|
||||||
string tmp;
|
string tmp;
|
||||||
string_view key = it->first.GetSlice(&tmp);
|
string_view key = it->first.GetSlice(&tmp);
|
||||||
doc_del_cb_(key, DbContext{db_ind, GetCurrentTimeMs()}, it->second);
|
doc_del_cb_(key, cntx, it->second);
|
||||||
}
|
}
|
||||||
fetched_items_.erase(it->first.AsRef());
|
fetched_items_.erase(it->first.AsRef());
|
||||||
PerformDeletion(it, db.get());
|
PerformDeletion(it, db.get());
|
||||||
|
@ -842,7 +842,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.db_index, prime_it));
|
CHECK(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);
|
||||||
|
|
|
@ -329,7 +329,7 @@ class DbSlice {
|
||||||
// Creates a database with index `db_ind`. If such database exists does nothing.
|
// Creates a database with index `db_ind`. If such database exists does nothing.
|
||||||
void ActivateDb(DbIndex db_ind);
|
void ActivateDb(DbIndex db_ind);
|
||||||
|
|
||||||
bool Del(DbIndex db_ind, Iterator it);
|
bool Del(Context cntx, Iterator it);
|
||||||
|
|
||||||
constexpr static DbIndex kDbAll = 0xFFFF;
|
constexpr static DbIndex kDbAll = 0xFFFF;
|
||||||
|
|
||||||
|
|
|
@ -254,10 +254,11 @@ void SaveStagesController::SaveDfs() {
|
||||||
|
|
||||||
// Save shard files.
|
// Save shard files.
|
||||||
auto cb = [this](Transaction* t, EngineShard* shard) {
|
auto cb = [this](Transaction* t, EngineShard* shard) {
|
||||||
|
auto& db_slice = shard->db_slice();
|
||||||
// a hack to avoid deadlock in Transaction::RunCallback(...)
|
// a hack to avoid deadlock in Transaction::RunCallback(...)
|
||||||
shard->db_slice().UnlockChangeCb();
|
db_slice.UnlockChangeCb();
|
||||||
SaveDfsSingle(shard);
|
SaveDfsSingle(shard);
|
||||||
shard->db_slice().LockChangeCb();
|
db_slice.LockChangeCb();
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
};
|
};
|
||||||
trans_->ScheduleSingleHop(std::move(cb));
|
trans_->ScheduleSingleHop(std::move(cb));
|
||||||
|
@ -298,9 +299,10 @@ void SaveStagesController::SaveRdb() {
|
||||||
|
|
||||||
auto cb = [snapshot = snapshot.get()](Transaction* t, EngineShard* shard) {
|
auto cb = [snapshot = snapshot.get()](Transaction* t, EngineShard* shard) {
|
||||||
// a hack to avoid deadlock in Transaction::RunCallback(...)
|
// a hack to avoid deadlock in Transaction::RunCallback(...)
|
||||||
shard->db_slice().UnlockChangeCb();
|
auto& db_slice = shard->db_slice();
|
||||||
|
db_slice.UnlockChangeCb();
|
||||||
snapshot->StartInShard(shard);
|
snapshot->StartInShard(shard);
|
||||||
shard->db_slice().LockChangeCb();
|
db_slice.LockChangeCb();
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
};
|
};
|
||||||
trans_->ScheduleSingleHop(std::move(cb));
|
trans_->ScheduleSingleHop(std::move(cb));
|
||||||
|
|
|
@ -73,7 +73,7 @@ std::string_view SyncStateName(DflyCmd::SyncState sync_state) {
|
||||||
|
|
||||||
struct TransactionGuard {
|
struct TransactionGuard {
|
||||||
static OpStatus ExitGuardCb(Transaction* t, EngineShard* shard) {
|
static OpStatus ExitGuardCb(Transaction* t, EngineShard* shard) {
|
||||||
shard->db_slice().SetExpireAllowed(true);
|
t->GetDbSlice(shard->shard_id()).SetExpireAllowed(true);
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ struct TransactionGuard {
|
||||||
t->Execute(
|
t->Execute(
|
||||||
[disable_expirations](Transaction* t, EngineShard* shard) {
|
[disable_expirations](Transaction* t, EngineShard* shard) {
|
||||||
if (disable_expirations) {
|
if (disable_expirations) {
|
||||||
shard->db_slice().SetExpireAllowed(!disable_expirations);
|
t->GetDbSlice(shard->shard_id()).SetExpireAllowed(!disable_expirations);
|
||||||
}
|
}
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
},
|
},
|
||||||
|
@ -455,7 +455,7 @@ void DflyCmd::TakeOver(CmdArgList args, ConnectionContext* cntx) {
|
||||||
void DflyCmd::Expire(CmdArgList args, ConnectionContext* cntx) {
|
void DflyCmd::Expire(CmdArgList args, ConnectionContext* cntx) {
|
||||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||||
cntx->transaction->ScheduleSingleHop([](Transaction* t, EngineShard* shard) {
|
cntx->transaction->ScheduleSingleHop([](Transaction* t, EngineShard* shard) {
|
||||||
shard->db_slice().ExpireAllIfNeeded();
|
t->GetDbSlice(shard->shard_id()).ExpireAllIfNeeded();
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -570,12 +570,12 @@ TEST_F(DflyEngineTest, Bug468) {
|
||||||
resp = Run({"exec"});
|
resp = Run({"exec"});
|
||||||
ASSERT_THAT(resp, ErrArg("not an integer"));
|
ASSERT_THAT(resp, ErrArg("not an integer"));
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
ASSERT_FALSE(IsLocked(0, "foo"));
|
||||||
|
|
||||||
resp = Run({"eval", "return redis.call('set', 'foo', 'bar', 'EX', 'moo')", "1", "foo"});
|
resp = Run({"eval", "return redis.call('set', 'foo', 'bar', 'EX', 'moo')", "1", "foo"});
|
||||||
ASSERT_THAT(resp, ErrArg("not an integer"));
|
ASSERT_THAT(resp, ErrArg("not an integer"));
|
||||||
|
|
||||||
ASSERT_FALSE(service_->IsLocked(0, "foo"));
|
ASSERT_FALSE(IsLocked(0, "foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DflyEngineTest, Bug496) {
|
TEST_F(DflyEngineTest, Bug496) {
|
||||||
|
|
|
@ -286,7 +286,7 @@ void EngineShard::ForceDefrag() {
|
||||||
bool EngineShard::DoDefrag() {
|
bool EngineShard::DoDefrag() {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// NOTE: This task is running with exclusive access to the shard.
|
// NOTE: This task is running with exclusive access to the shard.
|
||||||
// i.e. - Since we are using shared noting access here, and all access
|
// i.e. - Since we are using shared nothing access here, and all access
|
||||||
// are done using fibers, This fiber is run only when no other fiber in the
|
// are done using fibers, This fiber is run only when no other fiber in the
|
||||||
// context of the controlling thread will access this shard!
|
// context of the controlling thread will access this shard!
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
@ -422,15 +422,6 @@ void EngineShard::InitThreadLocal(ProactorBase* pb, bool update_db_time, size_t
|
||||||
CompactObj::InitThreadLocal(shard_->memory_resource());
|
CompactObj::InitThreadLocal(shard_->memory_resource());
|
||||||
SmallString::InitThreadLocal(data_heap);
|
SmallString::InitThreadLocal(data_heap);
|
||||||
|
|
||||||
if (string backing_prefix = GetFlag(FLAGS_tiered_prefix); !backing_prefix.empty()) {
|
|
||||||
LOG_IF(FATAL, pb->GetKind() != ProactorBase::IOURING)
|
|
||||||
<< "Only ioring based backing storage is supported. Exiting...";
|
|
||||||
|
|
||||||
shard_->tiered_storage_ = make_unique<TieredStorage>(&shard_->db_slice_, max_file_size);
|
|
||||||
error_code ec = shard_->tiered_storage_->Open(backing_prefix);
|
|
||||||
CHECK(!ec) << ec.message();
|
|
||||||
}
|
|
||||||
|
|
||||||
RoundRobinSharder::Init();
|
RoundRobinSharder::Init();
|
||||||
|
|
||||||
shard_->shard_search_indices_.reset(new ShardDocIndices());
|
shard_->shard_search_indices_.reset(new ShardDocIndices());
|
||||||
|
@ -441,11 +432,23 @@ void EngineShard::InitThreadLocal(ProactorBase* pb, bool update_db_time, size_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EngineShard::InitTieredStorage(ProactorBase* pb, size_t max_file_size) {
|
||||||
|
if (string backing_prefix = GetFlag(FLAGS_tiered_prefix); !backing_prefix.empty()) {
|
||||||
|
LOG_IF(FATAL, pb->GetKind() != ProactorBase::IOURING)
|
||||||
|
<< "Only ioring based backing storage is supported. Exiting...";
|
||||||
|
|
||||||
|
auto* shard = EngineShard::tlocal();
|
||||||
|
shard->tiered_storage_ = make_unique<TieredStorage>(&db_slice_, max_file_size);
|
||||||
|
error_code ec = shard->tiered_storage_->Open(backing_prefix);
|
||||||
|
CHECK(!ec) << ec.message();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EngineShard::DestroyThreadLocal() {
|
void EngineShard::DestroyThreadLocal() {
|
||||||
if (!shard_)
|
if (!shard_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t index = shard_->db_slice_.shard_id();
|
uint32_t shard_id = shard_->shard_id();
|
||||||
mi_heap_t* tlh = shard_->mi_resource_.heap();
|
mi_heap_t* tlh = shard_->mi_resource_.heap();
|
||||||
|
|
||||||
shard_->Shutdown();
|
shard_->Shutdown();
|
||||||
|
@ -456,7 +459,7 @@ void EngineShard::DestroyThreadLocal() {
|
||||||
CompactObj::InitThreadLocal(nullptr);
|
CompactObj::InitThreadLocal(nullptr);
|
||||||
mi_heap_delete(tlh);
|
mi_heap_delete(tlh);
|
||||||
RoundRobinSharder::Destroy();
|
RoundRobinSharder::Destroy();
|
||||||
VLOG(1) << "Shard reset " << index;
|
VLOG(1) << "Shard reset " << shard_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is called by Transaction::ExecuteAsync in order to run transaction tasks.
|
// Is called by Transaction::ExecuteAsync in order to run transaction tasks.
|
||||||
|
@ -643,12 +646,13 @@ void EngineShard::RunPeriodic(std::chrono::milliseconds period_ms) {
|
||||||
int64_t last_stats_time = time(nullptr);
|
int64_t last_stats_time = time(nullptr);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Heartbeat();
|
|
||||||
if (fiber_periodic_done_.WaitFor(period_ms)) {
|
if (fiber_periodic_done_.WaitFor(period_ms)) {
|
||||||
VLOG(2) << "finished running engine shard periodic task";
|
VLOG(2) << "finished running engine shard periodic task";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Heartbeat();
|
||||||
|
|
||||||
if (runs_global_periodic) {
|
if (runs_global_periodic) {
|
||||||
++global_count;
|
++global_count;
|
||||||
|
|
||||||
|
@ -864,6 +868,12 @@ void EngineShardSet::Init(uint32_t sz, bool update_db_time) {
|
||||||
InitThreadLocal(pb, update_db_time, max_shard_file_size);
|
InitThreadLocal(pb, update_db_time, max_shard_file_size);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pp_->AwaitFiberOnAll([&](uint32_t index, ProactorBase* pb) {
|
||||||
|
if (index < shard_queue_.size()) {
|
||||||
|
EngineShard::tlocal()->InitTieredStorage(pb, max_shard_file_size);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EngineShardSet::Shutdown() {
|
void EngineShardSet::Shutdown() {
|
||||||
|
|
|
@ -50,6 +50,9 @@ class EngineShard {
|
||||||
// If update_db_time is true, initializes periodic time update for its db_slice.
|
// If update_db_time is true, initializes periodic time update for its db_slice.
|
||||||
static void InitThreadLocal(util::ProactorBase* pb, bool update_db_time, size_t max_file_size);
|
static void InitThreadLocal(util::ProactorBase* pb, bool update_db_time, size_t max_file_size);
|
||||||
|
|
||||||
|
// Must be called after all InitThreadLocal() have finished
|
||||||
|
void InitTieredStorage(util::ProactorBase* pb, size_t max_file_size);
|
||||||
|
|
||||||
static void DestroyThreadLocal();
|
static void DestroyThreadLocal();
|
||||||
|
|
||||||
static EngineShard* tlocal() {
|
static EngineShard* tlocal() {
|
||||||
|
|
|
@ -150,7 +150,7 @@ class RdbRestoreValue : protected RdbLoaderBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<DbSlice::ItAndUpdater> Add(std::string_view payload, std::string_view key,
|
std::optional<DbSlice::ItAndUpdater> Add(std::string_view payload, std::string_view key,
|
||||||
DbSlice& db_slice, DbIndex index,
|
DbSlice& db_slice, const DbContext& cntx,
|
||||||
const RestoreArgs& args);
|
const RestoreArgs& args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -177,7 +177,8 @@ std::optional<RdbLoaderBase::OpaqueObj> RdbRestoreValue::Parse(std::string_view
|
||||||
|
|
||||||
std::optional<DbSlice::ItAndUpdater> RdbRestoreValue::Add(std::string_view data,
|
std::optional<DbSlice::ItAndUpdater> RdbRestoreValue::Add(std::string_view data,
|
||||||
std::string_view key, DbSlice& db_slice,
|
std::string_view key, DbSlice& db_slice,
|
||||||
DbIndex index, const RestoreArgs& args) {
|
const DbContext& cntx,
|
||||||
|
const RestoreArgs& args) {
|
||||||
auto opaque_res = Parse(data);
|
auto opaque_res = Parse(data);
|
||||||
if (!opaque_res) {
|
if (!opaque_res) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -190,8 +191,7 @@ std::optional<DbSlice::ItAndUpdater> RdbRestoreValue::Add(std::string_view data,
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = db_slice.AddNew(DbContext{index, GetCurrentTimeMs()}, key, std::move(pv),
|
auto res = db_slice.AddNew(cntx, key, std::move(pv), args.ExpirationTime());
|
||||||
args.ExpirationTime());
|
|
||||||
res->it->first.SetSticky(args.Sticky());
|
res->it->first.SetSticky(args.Sticky());
|
||||||
if (res) {
|
if (res) {
|
||||||
return std::move(res.value());
|
return std::move(res.value());
|
||||||
|
@ -374,13 +374,13 @@ void Renamer::FinalizeRename() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renamer::KeyExists(Transaction* t, EngineShard* shard, std::string_view key) const {
|
bool Renamer::KeyExists(Transaction* t, EngineShard* shard, std::string_view key) const {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto it = db_slice.FindReadOnly(t->GetDbContext(), key).it;
|
auto it = db_slice.FindReadOnly(t->GetDbContext(), key).it;
|
||||||
return IsValid(it);
|
return IsValid(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renamer::SerializeSrc(Transaction* t, EngineShard* shard) {
|
void Renamer::SerializeSrc(Transaction* t, EngineShard* shard) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto [it, exp_it] = db_slice.FindReadOnly(t->GetDbContext(), src_key_);
|
auto [it, exp_it] = db_slice.FindReadOnly(t->GetDbContext(), src_key_);
|
||||||
|
|
||||||
src_found_ = IsValid(it);
|
src_found_ = IsValid(it);
|
||||||
|
@ -399,7 +399,8 @@ void Renamer::SerializeSrc(Transaction* t, EngineShard* shard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus Renamer::DelSrc(Transaction* t, EngineShard* shard) {
|
OpStatus Renamer::DelSrc(Transaction* t, EngineShard* shard) {
|
||||||
auto res = shard->db_slice().FindMutable(t->GetDbContext(), src_key_);
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
|
auto res = db_slice.FindMutable(t->GetDbContext(), src_key_);
|
||||||
auto& it = res.it;
|
auto& it = res.it;
|
||||||
|
|
||||||
CHECK(IsValid(it));
|
CHECK(IsValid(it));
|
||||||
|
@ -407,7 +408,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(shard->db_slice().Del(t->GetDbIndex(), it));
|
CHECK(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);
|
||||||
}
|
}
|
||||||
|
@ -423,13 +424,13 @@ OpStatus Renamer::DeserializeDest(Transaction* t, EngineShard* shard) {
|
||||||
return OpStatus::OUT_OF_RANGE;
|
return OpStatus::OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto dest_res = db_slice.FindMutable(op_args.db_cntx, dest_key_);
|
auto dest_res = db_slice.FindMutable(op_args.db_cntx, dest_key_);
|
||||||
|
|
||||||
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.db_index, dest_res.it));
|
CHECK(db_slice.Del(op_args.db_cntx, dest_res.it));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restore_args.Expired()) {
|
if (restore_args.Expired()) {
|
||||||
|
@ -443,8 +444,8 @@ OpStatus Renamer::DeserializeDest(Transaction* t, EngineShard* shard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RdbRestoreValue loader(serialized_value_.version.value());
|
RdbRestoreValue loader(serialized_value_.version.value());
|
||||||
auto restored_dest_it = loader.Add(serialized_value_.value, dest_key_, db_slice,
|
auto restored_dest_it =
|
||||||
op_args.db_cntx.db_index, restore_args);
|
loader.Add(serialized_value_.value, dest_key_, db_slice, op_args.db_cntx, restore_args);
|
||||||
|
|
||||||
if (restored_dest_it) {
|
if (restored_dest_it) {
|
||||||
auto& dest_it = restored_dest_it->it;
|
auto& dest_it = restored_dest_it->it;
|
||||||
|
@ -472,7 +473,7 @@ OpStatus Renamer::DeserializeDest(Transaction* t, EngineShard* shard) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus OpPersist(const OpArgs& op_args, string_view key) {
|
OpStatus OpPersist(const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res = db_slice.FindMutable(op_args.db_cntx, key);
|
auto res = db_slice.FindMutable(op_args.db_cntx, key);
|
||||||
|
|
||||||
if (!IsValid(res.it)) {
|
if (!IsValid(res.it)) {
|
||||||
|
@ -488,7 +489,7 @@ OpStatus OpPersist(const OpArgs& op_args, string_view key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<std::string> OpDump(const OpArgs& op_args, string_view key) {
|
OpResult<std::string> OpDump(const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto [it, expire_it] = db_slice.FindReadOnly(op_args.db_cntx, key);
|
auto [it, expire_it] = db_slice.FindReadOnly(op_args.db_cntx, key);
|
||||||
|
|
||||||
if (IsValid(it)) {
|
if (IsValid(it)) {
|
||||||
|
@ -508,7 +509,7 @@ OpResult<bool> OnRestore(const OpArgs& op_args, std::string_view key, std::strin
|
||||||
return OpStatus::OUT_OF_RANGE;
|
return OpStatus::OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
// The redis impl (see cluster.c function restoreCommand), remove the old key if
|
// The redis impl (see cluster.c function restoreCommand), remove the old key if
|
||||||
// the replace option is set, so lets do the same here
|
// the replace option is set, so lets do the same here
|
||||||
{
|
{
|
||||||
|
@ -518,7 +519,7 @@ OpResult<bool> OnRestore(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.db_index, res.it));
|
CHECK(db_slice.Del(op_args.db_cntx, res.it));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we are not allowed to replace it, so make sure it doesn't exist
|
// we are not allowed to replace it, so make sure it doesn't exist
|
||||||
|
@ -534,13 +535,13 @@ OpResult<bool> OnRestore(const OpArgs& op_args, std::string_view key, std::strin
|
||||||
}
|
}
|
||||||
|
|
||||||
RdbRestoreValue loader(rdb_version);
|
RdbRestoreValue loader(rdb_version);
|
||||||
auto res = loader.Add(payload, key, db_slice, op_args.db_cntx.db_index, restore_args);
|
auto res = loader.Add(payload, key, db_slice, op_args.db_cntx, restore_args);
|
||||||
return res.has_value();
|
return res.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScanCb(const OpArgs& op_args, PrimeIterator prime_it, const ScanOpts& opts, string* scratch,
|
bool ScanCb(const OpArgs& op_args, PrimeIterator prime_it, const ScanOpts& opts, string* scratch,
|
||||||
StringVec* res) {
|
StringVec* res) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
DbSlice::Iterator it = DbSlice::Iterator::FromPrime(prime_it);
|
DbSlice::Iterator it = DbSlice::Iterator::FromPrime(prime_it);
|
||||||
if (prime_it->second.HasExpire()) {
|
if (prime_it->second.HasExpire()) {
|
||||||
|
@ -569,7 +570,7 @@ bool ScanCb(const OpArgs& op_args, PrimeIterator prime_it, const ScanOpts& opts,
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpScan(const OpArgs& op_args, const ScanOpts& scan_opts, uint64_t* cursor, StringVec* vec) {
|
void OpScan(const OpArgs& op_args, const ScanOpts& scan_opts, uint64_t* cursor, StringVec* vec) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
DCHECK(db_slice.IsDbValid(op_args.db_cntx.db_index));
|
DCHECK(db_slice.IsDbValid(op_args.db_cntx.db_index));
|
||||||
|
|
||||||
unsigned cnt = 0;
|
unsigned cnt = 0;
|
||||||
|
@ -643,7 +644,7 @@ uint64_t ScanGeneric(uint64_t cursor, const ScanOpts& scan_opts, StringVec* keys
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus OpExpire(const OpArgs& op_args, string_view key, const DbSlice::ExpireParams& params) {
|
OpStatus OpExpire(const OpArgs& op_args, string_view key, const DbSlice::ExpireParams& params) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto find_res = db_slice.FindMutable(op_args.db_cntx, key);
|
auto find_res = db_slice.FindMutable(op_args.db_cntx, key);
|
||||||
if (!IsValid(find_res.it)) {
|
if (!IsValid(find_res.it)) {
|
||||||
return OpStatus::KEY_NOTFOUND;
|
return OpStatus::KEY_NOTFOUND;
|
||||||
|
@ -670,7 +671,7 @@ OpStatus OpExpire(const OpArgs& op_args, string_view key, const DbSlice::ExpireP
|
||||||
// returns -2 if the key was not found, -3 if the field was not found,
|
// returns -2 if the key was not found, -3 if the field was not found,
|
||||||
// -1 if ttl on the field was not found.
|
// -1 if ttl on the field was not found.
|
||||||
OpResult<long> OpFieldTtl(Transaction* t, EngineShard* shard, string_view key, string_view field) {
|
OpResult<long> OpFieldTtl(Transaction* t, EngineShard* shard, string_view key, string_view field) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
const DbContext& db_cntx = t->GetDbContext();
|
const DbContext& db_cntx = t->GetDbContext();
|
||||||
auto [it, expire_it] = db_slice.FindReadOnly(db_cntx, key);
|
auto [it, expire_it] = db_slice.FindReadOnly(db_cntx, key);
|
||||||
if (!IsValid(it))
|
if (!IsValid(it))
|
||||||
|
@ -691,7 +692,7 @@ OpResult<long> OpFieldTtl(Transaction* t, EngineShard* shard, string_view key, s
|
||||||
|
|
||||||
OpResult<uint32_t> OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
OpResult<uint32_t> OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
DVLOG(1) << "Del: " << keys.Front();
|
DVLOG(1) << "Del: " << keys.Front();
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
uint32_t res = 0;
|
uint32_t res = 0;
|
||||||
|
|
||||||
|
@ -700,7 +701,7 @@ OpResult<uint32_t> OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
if (!IsValid(fres.it))
|
if (!IsValid(fres.it))
|
||||||
continue;
|
continue;
|
||||||
fres.post_updater.Run();
|
fres.post_updater.Run();
|
||||||
res += int(db_slice.Del(op_args.db_cntx.db_index, fres.it));
|
res += int(db_slice.Del(op_args.db_cntx, fres.it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -709,7 +710,7 @@ OpResult<uint32_t> OpDel(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
OpResult<uint32_t> OpStick(const OpArgs& op_args, const ShardArgs& keys) {
|
OpResult<uint32_t> OpStick(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
DVLOG(1) << "Stick: " << keys.Front();
|
DVLOG(1) << "Stick: " << keys.Front();
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
uint32_t res = 0;
|
uint32_t res = 0;
|
||||||
for (string_view key : keys) {
|
for (string_view key : keys) {
|
||||||
|
@ -1094,7 +1095,7 @@ OpResultTyped<SortEntryList> OpFetchSortEntries(const OpArgs& op_args, std::stri
|
||||||
bool alpha) {
|
bool alpha) {
|
||||||
using namespace container_utils;
|
using namespace container_utils;
|
||||||
|
|
||||||
auto it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key).it;
|
auto it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key).it;
|
||||||
if (!IsValid(it) || !IsContainer(it->second)) {
|
if (!IsValid(it) || !IsContainer(it->second)) {
|
||||||
return OpStatus::KEY_NOTFOUND;
|
return OpStatus::KEY_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
@ -1469,7 +1470,7 @@ void GenericFamily::Scan(CmdArgList args, ConnectionContext* cntx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint64_t> GenericFamily::OpTtl(Transaction* t, EngineShard* shard, string_view key) {
|
OpResult<uint64_t> GenericFamily::OpTtl(Transaction* t, EngineShard* shard, string_view key) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto [it, expire_it] = db_slice.FindReadOnly(t->GetDbContext(), key);
|
auto [it, expire_it] = db_slice.FindReadOnly(t->GetDbContext(), key);
|
||||||
if (!IsValid(it))
|
if (!IsValid(it))
|
||||||
return OpStatus::KEY_NOTFOUND;
|
return OpStatus::KEY_NOTFOUND;
|
||||||
|
@ -1484,7 +1485,7 @@ OpResult<uint64_t> GenericFamily::OpTtl(Transaction* t, EngineShard* shard, stri
|
||||||
|
|
||||||
OpResult<uint32_t> GenericFamily::OpExists(const OpArgs& op_args, const ShardArgs& keys) {
|
OpResult<uint32_t> GenericFamily::OpExists(const OpArgs& op_args, const ShardArgs& keys) {
|
||||||
DVLOG(1) << "Exists: " << keys.Front();
|
DVLOG(1) << "Exists: " << keys.Front();
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
uint32_t res = 0;
|
uint32_t res = 0;
|
||||||
|
|
||||||
for (string_view key : keys) {
|
for (string_view key : keys) {
|
||||||
|
@ -1497,7 +1498,7 @@ OpResult<uint32_t> GenericFamily::OpExists(const OpArgs& op_args, const ShardArg
|
||||||
OpResult<void> GenericFamily::OpRen(const OpArgs& op_args, string_view from_key, string_view to_key,
|
OpResult<void> GenericFamily::OpRen(const OpArgs& op_args, string_view from_key, string_view to_key,
|
||||||
bool destination_should_not_exist) {
|
bool destination_should_not_exist) {
|
||||||
auto* es = op_args.shard;
|
auto* es = op_args.shard;
|
||||||
auto& db_slice = es->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto from_res = db_slice.FindMutable(op_args.db_cntx, from_key);
|
auto from_res = db_slice.FindMutable(op_args.db_cntx, from_key);
|
||||||
if (!IsValid(from_res.it))
|
if (!IsValid(from_res.it))
|
||||||
return OpStatus::KEY_NOTFOUND;
|
return OpStatus::KEY_NOTFOUND;
|
||||||
|
@ -1535,13 +1536,13 @@ OpResult<void> GenericFamily::OpRen(const OpArgs& op_args, string_view from_key,
|
||||||
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.db_index, from_res.it));
|
CHECK(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.db_index, from_res.it));
|
CHECK(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);
|
||||||
|
@ -1558,7 +1559,7 @@ OpResult<void> GenericFamily::OpRen(const OpArgs& op_args, string_view from_key,
|
||||||
// as a global transaction.
|
// as a global transaction.
|
||||||
// TODO: Allow running OpMove without a global transaction.
|
// TODO: Allow running OpMove without a global transaction.
|
||||||
OpStatus GenericFamily::OpMove(const OpArgs& op_args, string_view key, DbIndex target_db) {
|
OpStatus GenericFamily::OpMove(const OpArgs& op_args, string_view key, DbIndex target_db) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
// Fetch value at key in current db.
|
// Fetch value at key in current db.
|
||||||
auto from_res = db_slice.FindMutable(op_args.db_cntx, key);
|
auto from_res = db_slice.FindMutable(op_args.db_cntx, key);
|
||||||
|
@ -1583,7 +1584,7 @@ OpStatus GenericFamily::OpMove(const OpArgs& op_args, string_view key, DbIndex t
|
||||||
// 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.db_index, from_res.it));
|
CHECK(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;
|
||||||
|
|
|
@ -67,7 +67,7 @@ void ConvertToDenseIfNeeded(string* hll) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<int> AddToHll(const OpArgs& op_args, string_view key, CmdArgList values) {
|
OpResult<int> AddToHll(const OpArgs& op_args, string_view key, CmdArgList values) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
string hll;
|
string hll;
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ void PFAdd(CmdArgList args, ConnectionContext* cntx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<int64_t> CountHllsSingle(const OpArgs& op_args, string_view key) {
|
OpResult<int64_t> CountHllsSingle(const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
auto it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
auto it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (it.ok()) {
|
if (it.ok()) {
|
||||||
|
@ -173,7 +173,7 @@ OpResult<vector<string>> ReadValues(const OpArgs& op_args, const ShardArgs& keys
|
||||||
try {
|
try {
|
||||||
vector<string> values;
|
vector<string> values;
|
||||||
for (string_view key : keys) {
|
for (string_view key : keys) {
|
||||||
auto it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
auto it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (it.ok()) {
|
if (it.ok()) {
|
||||||
string hll;
|
string hll;
|
||||||
it.value()->second.GetString(&hll);
|
it.value()->second.GetString(&hll);
|
||||||
|
@ -280,7 +280,7 @@ OpResult<int> PFMergeInternal(CmdArgList args, ConnectionContext* cntx) {
|
||||||
auto set_cb = [&](Transaction* t, EngineShard* shard) {
|
auto set_cb = [&](Transaction* t, EngineShard* shard) {
|
||||||
string_view key = ArgS(args, 0);
|
string_view key = ArgS(args, 0);
|
||||||
const OpArgs& op_args = t->GetOpArgs(shard);
|
const OpArgs& op_args = t->GetOpArgs(shard);
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto op_res = db_slice.AddOrFind(t->GetDbContext(), key);
|
auto op_res = db_slice.AddOrFind(t->GetDbContext(), key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
auto& res = *op_res;
|
auto& res = *op_res;
|
||||||
|
|
|
@ -166,7 +166,7 @@ OpStatus IncrementValue(optional<string_view> prev_val, IncrByParam* param) {
|
||||||
};
|
};
|
||||||
|
|
||||||
OpStatus OpIncrBy(const OpArgs& op_args, string_view key, string_view field, IncrByParam* param) {
|
OpStatus OpIncrBy(const OpArgs& op_args, string_view key, string_view field, IncrByParam* param) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
if (!op_res) {
|
if (!op_res) {
|
||||||
|
@ -280,7 +280,7 @@ OpResult<StringVec> OpScan(const OpArgs& op_args, std::string_view key, uint64_t
|
||||||
* of returning no or very few elements. (taken from redis code at db.c line 904 */
|
* of returning no or very few elements. (taken from redis code at db.c line 904 */
|
||||||
constexpr size_t INTERATION_FACTOR = 10;
|
constexpr size_t INTERATION_FACTOR = 10;
|
||||||
|
|
||||||
auto find_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto find_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
DVLOG(1) << "ScanOp: find failed: " << find_res << ", baling out";
|
DVLOG(1) << "ScanOp: find failed: " << find_res << ", baling out";
|
||||||
|
@ -343,7 +343,7 @@ OpResult<StringVec> OpScan(const OpArgs& op_args, std::string_view key, uint64_t
|
||||||
OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, CmdArgList values) {
|
OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, CmdArgList values) {
|
||||||
DCHECK(!values.empty());
|
DCHECK(!values.empty());
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
|
@ -397,7 +397,7 @@ OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, CmdArgList valu
|
||||||
if (enc == kEncodingListPack) {
|
if (enc == kEncodingListPack) {
|
||||||
stats->listpack_blob_cnt--;
|
stats->listpack_blob_cnt--;
|
||||||
}
|
}
|
||||||
db_slice.Del(op_args.db_cntx.db_index, it_res->it);
|
db_slice.Del(op_args.db_cntx, it_res->it);
|
||||||
} else if (enc == kEncodingListPack) {
|
} else if (enc == kEncodingListPack) {
|
||||||
stats->listpack_bytes += lpBytes((uint8_t*)pv.RObjPtr());
|
stats->listpack_bytes += lpBytes((uint8_t*)pv.RObjPtr());
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, CmdArgList valu
|
||||||
OpResult<vector<OptStr>> OpHMGet(const OpArgs& op_args, std::string_view key, CmdArgList fields) {
|
OpResult<vector<OptStr>> OpHMGet(const OpArgs& op_args, std::string_view key, CmdArgList fields) {
|
||||||
DCHECK(!fields.empty());
|
DCHECK(!fields.empty());
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
|
@ -466,7 +466,7 @@ OpResult<vector<OptStr>> OpHMGet(const OpArgs& op_args, std::string_view key, Cm
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (it_res) {
|
if (it_res) {
|
||||||
|
@ -479,7 +479,7 @@ OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<int> OpExist(const OpArgs& op_args, string_view key, string_view field) {
|
OpResult<int> OpExist(const OpArgs& op_args, string_view key, string_view field) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (!it_res) {
|
if (!it_res) {
|
||||||
|
@ -503,7 +503,7 @@ OpResult<int> OpExist(const OpArgs& op_args, string_view key, string_view field)
|
||||||
};
|
};
|
||||||
|
|
||||||
OpResult<string> OpGet(const OpArgs& op_args, string_view key, string_view field) {
|
OpResult<string> OpGet(const OpArgs& op_args, string_view key, string_view field) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -531,7 +531,7 @@ OpResult<string> OpGet(const OpArgs& op_args, string_view key, string_view field
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<vector<string>> OpGetAll(const OpArgs& op_args, string_view key, uint8_t mask) {
|
OpResult<vector<string>> OpGetAll(const OpArgs& op_args, string_view key, uint8_t mask) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
if (!it_res) {
|
if (!it_res) {
|
||||||
if (it_res.status() == OpStatus::KEY_NOTFOUND)
|
if (it_res.status() == OpStatus::KEY_NOTFOUND)
|
||||||
|
@ -582,7 +582,7 @@ OpResult<vector<string>> OpGetAll(const OpArgs& op_args, string_view key, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<size_t> OpStrLen(const OpArgs& op_args, string_view key, string_view field) {
|
OpResult<size_t> OpStrLen(const OpArgs& op_args, string_view key, string_view field) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_HASH);
|
||||||
|
|
||||||
if (!it_res) {
|
if (!it_res) {
|
||||||
|
@ -617,7 +617,7 @@ OpResult<uint32_t> OpSet(const OpArgs& op_args, string_view key, CmdArgList valu
|
||||||
DCHECK(!values.empty() && 0 == values.size() % 2);
|
DCHECK(!values.empty() && 0 == values.size() % 2);
|
||||||
VLOG(2) << "OpSet(" << key << ")";
|
VLOG(2) << "OpSet(" << key << ")";
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
auto& add_res = *op_res;
|
auto& add_res = *op_res;
|
||||||
|
@ -1094,7 +1094,7 @@ void HSetFamily::HRandField(CmdArgList args, ConnectionContext* cntx) {
|
||||||
if (string_map->Empty()) {
|
if (string_map->Empty()) {
|
||||||
auto it_mutable = db_slice.FindMutable(db_context, key, OBJ_HASH);
|
auto it_mutable = db_slice.FindMutable(db_context, key, OBJ_HASH);
|
||||||
it_mutable->post_updater.Run();
|
it_mutable->post_updater.Run();
|
||||||
db_slice.Del(db_context.db_index, it_mutable->it);
|
db_slice.Del(db_context, it_mutable->it);
|
||||||
return facade::OpStatus::KEY_NOTFOUND;
|
return facade::OpStatus::KEY_NOTFOUND;
|
||||||
}
|
}
|
||||||
} else if (pv.Encoding() == kEncodingListPack) {
|
} else if (pv.Encoding() == kEncodingListPack) {
|
||||||
|
|
|
@ -131,7 +131,7 @@ inline JsonType Evaluate(const json::Path& expr, const JsonType& obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
facade::OpStatus SetJson(const OpArgs& op_args, string_view key, JsonType&& value) {
|
facade::OpStatus SetJson(const OpArgs& op_args, string_view key, JsonType&& value) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
|
@ -244,7 +244,7 @@ error_code JsonReplace(JsonType& instance, string_view path, json::MutateCallbac
|
||||||
// jsoncons version
|
// jsoncons version
|
||||||
OpStatus UpdateEntry(const OpArgs& op_args, std::string_view key, std::string_view path,
|
OpStatus UpdateEntry(const OpArgs& op_args, std::string_view key, std::string_view path,
|
||||||
json::MutateCallback callback, JsonReplaceVerify verify_op = {}) {
|
json::MutateCallback callback, JsonReplaceVerify verify_op = {}) {
|
||||||
auto it_res = op_args.shard->db_slice().FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
auto it_res = op_args.GetDbSlice().FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
||||||
if (!it_res.ok()) {
|
if (!it_res.ok()) {
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ OpStatus UpdateEntry(const OpArgs& op_args, std::string_view key, std::string_vi
|
||||||
// json::Path version.
|
// json::Path version.
|
||||||
OpStatus UpdateEntry(const OpArgs& op_args, string_view key, const json::Path& path,
|
OpStatus UpdateEntry(const OpArgs& op_args, string_view key, const json::Path& path,
|
||||||
json::MutateCallback cb) {
|
json::MutateCallback cb) {
|
||||||
auto it_res = op_args.shard->db_slice().FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
auto it_res = op_args.GetDbSlice().FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
||||||
if (!it_res.ok()) {
|
if (!it_res.ok()) {
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ OpStatus UpdateEntry(const OpArgs& op_args, string_view key, const json::Path& p
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<JsonType*> GetJson(const OpArgs& op_args, string_view key) {
|
OpResult<JsonType*> GetJson(const OpArgs& op_args, string_view key) {
|
||||||
auto it_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON);
|
auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
|
@ -753,9 +753,9 @@ OpResult<string> OpDoubleArithmetic(const OpArgs& op_args, string_view key, stri
|
||||||
OpResult<long> OpDel(const OpArgs& op_args, string_view key, string_view path,
|
OpResult<long> OpDel(const OpArgs& op_args, string_view key, string_view path,
|
||||||
optional<JsonPathV2> expression) {
|
optional<JsonPathV2> expression) {
|
||||||
if (!expression || path.empty()) {
|
if (!expression || path.empty()) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
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 long(db_slice.Del(op_args.db_cntx.db_index, it));
|
return long(db_slice.Del(op_args.db_cntx, it));
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<JsonType*> result = GetJson(op_args, key);
|
OpResult<JsonType*> result = GetJson(op_args, key);
|
||||||
|
@ -1200,7 +1200,7 @@ vector<OptString> OpJsonMGet(const JsonPathV2& expression, const Transaction* t,
|
||||||
DCHECK(!args.Empty());
|
DCHECK(!args.Empty());
|
||||||
vector<OptString> response(args.Size());
|
vector<OptString> response(args.Size());
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
for (string_view key : args) {
|
for (string_view key : args) {
|
||||||
auto it_res = db_slice.FindReadOnly(t->GetDbContext(), key, OBJ_JSON);
|
auto it_res = db_slice.FindReadOnly(t->GetDbContext(), key, OBJ_JSON);
|
||||||
|
@ -1288,7 +1288,7 @@ OpResult<bool> OpSet(const OpArgs& op_args, string_view key, string_view path,
|
||||||
// and its not JSON, it would return an error.
|
// and its not JSON, it would return an error.
|
||||||
if (path == "." || path == "$") {
|
if (path == "." || path == "$") {
|
||||||
if (is_nx_condition || is_xx_condition) {
|
if (is_nx_condition || is_xx_condition) {
|
||||||
auto it_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON);
|
auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON);
|
||||||
bool key_exists = (it_res.status() != OpStatus::KEY_NOTFOUND);
|
bool key_exists = (it_res.status() != OpStatus::KEY_NOTFOUND);
|
||||||
if (is_nx_condition && key_exists) {
|
if (is_nx_condition && key_exists) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1417,7 +1417,7 @@ OpStatus OpMerge(const OpArgs& op_args, string_view key, std::string_view json_s
|
||||||
return OpStatus::SYNTAX_ERR;
|
return OpStatus::SYNTAX_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_JSON);
|
||||||
if (it_res.ok()) {
|
if (it_res.ok()) {
|
||||||
op_args.shard->search_indices()->RemoveDoc(key, op_args.db_cntx, it_res->it->second);
|
op_args.shard->search_indices()->RemoveDoc(key, op_args.db_cntx, it_res->it->second);
|
||||||
|
|
|
@ -178,7 +178,7 @@ class BPopPusher {
|
||||||
std::string OpBPop(Transaction* t, EngineShard* shard, std::string_view key, ListDir dir) {
|
std::string OpBPop(Transaction* t, EngineShard* shard, std::string_view key, ListDir dir) {
|
||||||
DVLOG(2) << "popping from " << key << " " << t->DebugId();
|
DVLOG(2) << "popping from " << key << " " << t->DebugId();
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto it_res = db_slice.FindMutable(t->GetDbContext(), key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(t->GetDbContext(), key, OBJ_LIST);
|
||||||
|
|
||||||
if (!it_res) {
|
if (!it_res) {
|
||||||
|
@ -206,14 +206,15 @@ std::string OpBPop(Transaction* t, EngineShard* shard, std::string_view key, Lis
|
||||||
std::string value = ListPop(dir, ql);
|
std::string value = ListPop(dir, ql);
|
||||||
it_res->post_updater.Run();
|
it_res->post_updater.Run();
|
||||||
|
|
||||||
|
OpArgs op_args = t->GetOpArgs(shard);
|
||||||
if (quicklistCount(ql) == 0) {
|
if (quicklistCount(ql) == 0) {
|
||||||
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
DVLOG(1) << "deleting key " << key << " " << t->DebugId();
|
||||||
absl::StrAppend(debugMessages.Next(), "OpBPop Del: ", key, " by ", t->DebugId());
|
absl::StrAppend(debugMessages.Next(), "OpBPop Del: ", key, " by ", t->DebugId());
|
||||||
|
|
||||||
CHECK(shard->db_slice().Del(t->GetDbIndex(), it));
|
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, it));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpArgs op_args = t->GetOpArgs(shard); op_args.shard->journal()) {
|
if (op_args.shard->journal()) {
|
||||||
string command = dir == ListDir::LEFT ? "LPOP" : "RPOP";
|
string command = dir == ListDir::LEFT ? "LPOP" : "RPOP";
|
||||||
RecordJournal(op_args, command, ArgSlice{key}, 1);
|
RecordJournal(op_args, command, ArgSlice{key}, 1);
|
||||||
}
|
}
|
||||||
|
@ -223,7 +224,7 @@ std::string OpBPop(Transaction* t, EngineShard* shard, std::string_view key, Lis
|
||||||
|
|
||||||
OpResult<string> OpMoveSingleShard(const OpArgs& op_args, string_view src, string_view dest,
|
OpResult<string> OpMoveSingleShard(const OpArgs& op_args, string_view src, string_view dest,
|
||||||
ListDir src_dir, ListDir dest_dir) {
|
ListDir src_dir, ListDir dest_dir) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto src_res = db_slice.FindMutable(op_args.db_cntx, src, OBJ_LIST);
|
auto src_res = db_slice.FindMutable(op_args.db_cntx, src, OBJ_LIST);
|
||||||
if (!src_res)
|
if (!src_res)
|
||||||
return src_res.status();
|
return src_res.status();
|
||||||
|
@ -271,7 +272,7 @@ OpResult<string> OpMoveSingleShard(const OpArgs& op_args, string_view src, strin
|
||||||
dest_res.post_updater.Run();
|
dest_res.post_updater.Run();
|
||||||
|
|
||||||
if (quicklistCount(src_ql) == 0) {
|
if (quicklistCount(src_ql) == 0) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx.db_index, src_it));
|
CHECK(db_slice.Del(op_args.db_cntx, src_it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
@ -280,7 +281,7 @@ OpResult<string> OpMoveSingleShard(const OpArgs& op_args, string_view src, strin
|
||||||
// Read-only peek operation that determines whether the list exists and optionally
|
// Read-only peek operation that determines whether the list exists and optionally
|
||||||
// returns the first from left/right value without popping it from the list.
|
// returns the first from left/right value without popping it from the list.
|
||||||
OpResult<string> Peek(const OpArgs& op_args, string_view key, ListDir dir, bool fetch) {
|
OpResult<string> Peek(const OpArgs& op_args, string_view key, ListDir dir, bool fetch) {
|
||||||
auto it_res = op_args.shard->db_slice().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) {
|
if (!it_res) {
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
}
|
}
|
||||||
|
@ -307,12 +308,12 @@ OpResult<uint32_t> OpPush(const OpArgs& op_args, std::string_view key, ListDir d
|
||||||
DbSlice::AddOrFindResult res;
|
DbSlice::AddOrFindResult res;
|
||||||
|
|
||||||
if (skip_notexist) {
|
if (skip_notexist) {
|
||||||
auto tmp_res = es->db_slice().FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto tmp_res = op_args.GetDbSlice().FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!tmp_res)
|
if (!tmp_res)
|
||||||
return 0; // Redis returns 0 for nonexisting keys for the *PUSHX actions.
|
return 0; // Redis returns 0 for nonexisting keys for the *PUSHX actions.
|
||||||
res = std::move(*tmp_res);
|
res = std::move(*tmp_res);
|
||||||
} else {
|
} else {
|
||||||
auto op_res = es->db_slice().AddOrFind(op_args.db_cntx, key);
|
auto op_res = op_args.GetDbSlice().AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
res = std::move(*op_res);
|
res = std::move(*op_res);
|
||||||
}
|
}
|
||||||
|
@ -363,7 +364,7 @@ OpResult<uint32_t> OpPush(const OpArgs& op_args, std::string_view key, ListDir d
|
||||||
|
|
||||||
OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, ListDir dir, uint32_t count,
|
OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, ListDir dir, uint32_t count,
|
||||||
bool return_results, bool journal_rewrite) {
|
bool return_results, bool journal_rewrite) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -391,7 +392,7 @@ OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, ListDir dir, u
|
||||||
|
|
||||||
if (quicklistCount(ql) == 0) {
|
if (quicklistCount(ql) == 0) {
|
||||||
absl::StrAppend(debugMessages.Next(), "OpPop Del: ", key, " by ", op_args.tx->DebugId());
|
absl::StrAppend(debugMessages.Next(), "OpPop Del: ", key, " by ", op_args.tx->DebugId());
|
||||||
CHECK(db_slice.Del(op_args.db_cntx.db_index, it));
|
CHECK(db_slice.Del(op_args.db_cntx, it));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op_args.shard->journal() && journal_rewrite) {
|
if (op_args.shard->journal() && journal_rewrite) {
|
||||||
|
@ -464,7 +465,7 @@ OpResult<string> MoveTwoShards(Transaction* trans, string_view src, string_view
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint32_t> OpLen(const OpArgs& op_args, std::string_view key) {
|
OpResult<uint32_t> OpLen(const OpArgs& op_args, std::string_view key) {
|
||||||
auto res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
auto res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!res)
|
if (!res)
|
||||||
return res.status();
|
return res.status();
|
||||||
|
|
||||||
|
@ -474,7 +475,7 @@ OpResult<uint32_t> OpLen(const OpArgs& op_args, std::string_view key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<string> OpIndex(const OpArgs& op_args, std::string_view key, long index) {
|
OpResult<string> OpIndex(const OpArgs& op_args, std::string_view key, long index) {
|
||||||
auto res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
auto res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!res)
|
if (!res)
|
||||||
return res.status();
|
return res.status();
|
||||||
quicklist* ql = GetQL(res.value()->second);
|
quicklist* ql = GetQL(res.value()->second);
|
||||||
|
@ -498,7 +499,7 @@ OpResult<string> OpIndex(const OpArgs& op_args, std::string_view key, long index
|
||||||
|
|
||||||
OpResult<vector<uint32_t>> OpPos(const OpArgs& op_args, std::string_view key,
|
OpResult<vector<uint32_t>> OpPos(const OpArgs& op_args, std::string_view key,
|
||||||
std::string_view element, int rank, int count, int max_len) {
|
std::string_view element, int rank, int count, int max_len) {
|
||||||
auto it_res = op_args.shard->db_slice().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();
|
||||||
|
|
||||||
|
@ -541,7 +542,7 @@ OpResult<vector<uint32_t>> OpPos(const OpArgs& op_args, std::string_view key,
|
||||||
|
|
||||||
OpResult<int> OpInsert(const OpArgs& op_args, string_view key, string_view pivot, string_view elem,
|
OpResult<int> OpInsert(const OpArgs& op_args, string_view key, string_view pivot, string_view elem,
|
||||||
InsertParam insert_param) {
|
InsertParam insert_param) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -573,7 +574,7 @@ OpResult<int> OpInsert(const OpArgs& op_args, string_view key, string_view pivot
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, string_view elem, long count) {
|
OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, string_view elem, long count) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -608,14 +609,14 @@ OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, string_view ele
|
||||||
quicklistReleaseIterator(qiter);
|
quicklistReleaseIterator(qiter);
|
||||||
|
|
||||||
if (quicklistCount(ql) == 0) {
|
if (quicklistCount(ql) == 0) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx.db_index, it));
|
CHECK(db_slice.Del(op_args.db_cntx, it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus OpSet(const OpArgs& op_args, string_view key, string_view elem, long index) {
|
OpStatus OpSet(const OpArgs& op_args, string_view key, string_view elem, long index) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -632,7 +633,7 @@ OpStatus OpSet(const OpArgs& op_args, string_view key, string_view elem, long in
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -670,13 +671,13 @@ OpStatus OpTrim(const OpArgs& op_args, string_view key, long start, long end) {
|
||||||
it_res->post_updater.Run();
|
it_res->post_updater.Run();
|
||||||
|
|
||||||
if (quicklistCount(ql) == 0) {
|
if (quicklistCount(ql) == 0) {
|
||||||
CHECK(db_slice.Del(op_args.db_cntx.db_index, it));
|
CHECK(db_slice.Del(op_args.db_cntx, it));
|
||||||
}
|
}
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<StringVec> OpRange(const OpArgs& op_args, std::string_view key, long start, long end) {
|
OpResult<StringVec> OpRange(const OpArgs& op_args, std::string_view key, long start, long end) {
|
||||||
auto res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
auto res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_LIST);
|
||||||
if (!res)
|
if (!res)
|
||||||
return res.status();
|
return res.status();
|
||||||
|
|
||||||
|
@ -876,7 +877,7 @@ OpResult<string> BPopPusher::RunSingle(ConnectionContext* cntx, time_point tp) {
|
||||||
|
|
||||||
const auto key_checker = [](EngineShard* owner, const DbContext& context, Transaction*,
|
const auto key_checker = [](EngineShard* owner, const DbContext& context, Transaction*,
|
||||||
std::string_view key) -> bool {
|
std::string_view key) -> bool {
|
||||||
return owner->db_slice().FindReadOnly(context, key, OBJ_LIST).ok();
|
return context.GetDbSlice(owner->shard_id()).FindReadOnly(context, key, OBJ_LIST).ok();
|
||||||
};
|
};
|
||||||
// Block
|
// Block
|
||||||
auto status = t->WaitOnWatch(tp, std::move(wcb), key_checker, &(cntx->blocked), &(cntx->paused));
|
auto status = t->WaitOnWatch(tp, std::move(wcb), key_checker, &(cntx->blocked), &(cntx->paused));
|
||||||
|
@ -907,7 +908,7 @@ OpResult<string> BPopPusher::RunPair(ConnectionContext* cntx, time_point tp) {
|
||||||
|
|
||||||
const auto key_checker = [](EngineShard* owner, const DbContext& context, Transaction*,
|
const auto key_checker = [](EngineShard* owner, const DbContext& context, Transaction*,
|
||||||
std::string_view key) -> bool {
|
std::string_view key) -> bool {
|
||||||
return owner->db_slice().FindReadOnly(context, key, OBJ_LIST).ok();
|
return context.GetDbSlice(owner->shard_id()).FindReadOnly(context, key, OBJ_LIST).ok();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto status = t->WaitOnWatch(tp, std::move(wcb), key_checker, &cntx->blocked, &cntx->paused);
|
if (auto status = t->WaitOnWatch(tp, std::move(wcb), key_checker, &cntx->blocked, &cntx->paused);
|
||||||
|
|
|
@ -813,6 +813,7 @@ Service::Service(ProactorPool* pp)
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CHECK(shard_set == nullptr);
|
||||||
shard_set = new EngineShardSet(pp);
|
shard_set = new EngineShardSet(pp);
|
||||||
|
|
||||||
// We support less than 1024 threads and we support less than 1024 shards.
|
// We support less than 1024 threads and we support less than 1024 shards.
|
||||||
|
@ -1284,7 +1285,7 @@ OpResult<void> OpTrackKeys(const OpArgs slice_args, const facade::Connection::We
|
||||||
DVLOG(2) << "Start tracking keys for client ID: " << conn_ref.GetClientId()
|
DVLOG(2) << "Start tracking keys for client ID: " << conn_ref.GetClientId()
|
||||||
<< " with thread ID: " << conn_ref.Thread();
|
<< " with thread ID: " << conn_ref.Thread();
|
||||||
|
|
||||||
auto& db_slice = slice_args.shard->db_slice();
|
auto& db_slice = slice_args.GetDbSlice();
|
||||||
// TODO: There is a bug here that we track all arguments instead of tracking only keys.
|
// TODO: There is a bug here that we track all arguments instead of tracking only keys.
|
||||||
for (auto key : args) {
|
for (auto key : args) {
|
||||||
DVLOG(2) << "Inserting client ID " << conn_ref.GetClientId()
|
DVLOG(2) << "Inserting client ID " << conn_ref.GetClientId()
|
||||||
|
@ -1659,9 +1660,10 @@ void Service::Watch(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
|
||||||
atomic_uint32_t keys_existed = 0;
|
atomic_uint32_t keys_existed = 0;
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||||
ShardArgs largs = t->GetShardArgs(shard->shard_id());
|
ShardId shard_id = shard->shard_id();
|
||||||
|
ShardArgs largs = t->GetShardArgs(shard_id);
|
||||||
for (auto k : largs) {
|
for (auto k : largs) {
|
||||||
shard->db_slice().RegisterWatchedKey(cntx->db_index(), k, &exec_info);
|
t->GetDbSlice(shard_id).RegisterWatchedKey(cntx->db_index(), k, &exec_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = GenericFamily::OpExists(t->GetOpArgs(shard), largs);
|
auto res = GenericFamily::OpExists(t->GetOpArgs(shard), largs);
|
||||||
|
@ -2131,8 +2133,10 @@ CmdArgVec CollectAllKeys(ConnectionState::ExecInfo* exec_info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if transaction was scheduled, false if scheduling was not required.
|
// Return true if transaction was scheduled, false if scheduling was not required.
|
||||||
void StartMultiExec(DbIndex dbid, Transaction* trans, ConnectionState::ExecInfo* exec_info,
|
void StartMultiExec(ConnectionContext* cntx, ConnectionState::ExecInfo* exec_info,
|
||||||
Transaction::MultiMode multi_mode) {
|
Transaction::MultiMode multi_mode) {
|
||||||
|
auto trans = cntx->transaction;
|
||||||
|
auto dbid = cntx->db_index();
|
||||||
switch (multi_mode) {
|
switch (multi_mode) {
|
||||||
case Transaction::GLOBAL:
|
case Transaction::GLOBAL:
|
||||||
trans->StartMultiGlobal(dbid);
|
trans->StartMultiGlobal(dbid);
|
||||||
|
@ -2189,7 +2193,7 @@ void Service::Exec(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
|
||||||
bool scheduled = false;
|
bool scheduled = false;
|
||||||
if (multi_mode != Transaction::NOT_DETERMINED) {
|
if (multi_mode != Transaction::NOT_DETERMINED) {
|
||||||
StartMultiExec(cntx->db_index(), cntx->transaction, &exec_info, multi_mode);
|
StartMultiExec(cntx, &exec_info, multi_mode);
|
||||||
scheduled = true;
|
scheduled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "server/server_family.h"
|
#include "server/server_family.h"
|
||||||
#include "server/server_state.h"
|
#include "server/server_state.h"
|
||||||
#include "server/snapshot.h"
|
#include "server/snapshot.h"
|
||||||
|
#include "server/transaction.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace facade;
|
using namespace facade;
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace {
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void TraverseAllMatching(const DocIndex& index, const OpArgs& op_args, F&& f) {
|
void TraverseAllMatching(const DocIndex& index, const OpArgs& op_args, F&& f) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
DCHECK(db_slice.IsDbValid(op_args.db_cntx.db_index));
|
DCHECK(db_slice.IsDbValid(op_args.db_cntx.db_index));
|
||||||
auto [prime_table, _] = db_slice.GetTables(op_args.db_cntx.db_index);
|
auto [prime_table, _] = db_slice.GetTables(op_args.db_cntx.db_index);
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ bool ShardDocIndex::Matches(string_view key, unsigned obj_code) const {
|
||||||
|
|
||||||
SearchResult ShardDocIndex::Search(const OpArgs& op_args, const SearchParams& params,
|
SearchResult ShardDocIndex::Search(const OpArgs& op_args, const SearchParams& params,
|
||||||
search::SearchAlgorithm* search_algo) const {
|
search::SearchAlgorithm* search_algo) const {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto search_results = search_algo->Search(&indices_, params.limit_offset + params.limit_total);
|
auto search_results = search_algo->Search(&indices_, params.limit_offset + params.limit_total);
|
||||||
|
|
||||||
if (!search_results.error.empty())
|
if (!search_results.error.empty())
|
||||||
|
@ -235,7 +235,7 @@ SearchResult ShardDocIndex::Search(const OpArgs& op_args, const SearchParams& pa
|
||||||
|
|
||||||
vector<absl::flat_hash_map<string, search::SortableValue>> ShardDocIndex::SearchForAggregator(
|
vector<absl::flat_hash_map<string, search::SortableValue>> ShardDocIndex::SearchForAggregator(
|
||||||
const OpArgs& op_args, ArgSlice load_fields, search::SearchAlgorithm* search_algo) const {
|
const OpArgs& op_args, ArgSlice load_fields, search::SearchAlgorithm* search_algo) const {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto search_results = search_algo->Search(&indices_);
|
auto search_results = search_algo->Search(&indices_);
|
||||||
|
|
||||||
if (!search_results.error.empty())
|
if (!search_results.error.empty())
|
||||||
|
@ -287,7 +287,7 @@ void ShardDocIndices::InitIndex(const OpArgs& op_args, std::string_view name,
|
||||||
if (ServerState::tlocal()->gstate() == GlobalState::ACTIVE)
|
if (ServerState::tlocal()->gstate() == GlobalState::ACTIVE)
|
||||||
it->second->Rebuild(op_args, &local_mr_);
|
it->second->Rebuild(op_args, &local_mr_);
|
||||||
|
|
||||||
op_args.shard->db_slice().SetDocDeletionCallback(
|
op_args.GetDbSlice().SetDocDeletionCallback(
|
||||||
[this](string_view key, const DbContext& cntx, const PrimeValue& pv) {
|
[this](string_view key, const DbContext& cntx, const PrimeValue& pv) {
|
||||||
RemoveDoc(key, cntx, pv);
|
RemoveDoc(key, cntx, pv);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1533,7 +1533,7 @@ error_code ServerFamily::Drakarys(Transaction* transaction, DbIndex db_ind) {
|
||||||
|
|
||||||
transaction->Execute(
|
transaction->Execute(
|
||||||
[db_ind](Transaction* t, EngineShard* shard) {
|
[db_ind](Transaction* t, EngineShard* shard) {
|
||||||
shard->db_slice().FlushDb(db_ind);
|
t->GetDbSlice(shard->shard_id()).FlushDb(db_ind);
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
|
|
|
@ -469,8 +469,7 @@ SvArray ToSvArray(const absl::flat_hash_set<std::string_view>& set) {
|
||||||
// if overwrite is true then OpAdd writes vals into the key and discards its previous value.
|
// if overwrite is true then OpAdd writes vals into the key and discards its previous value.
|
||||||
OpResult<uint32_t> OpAdd(const OpArgs& op_args, std::string_view key, const NewEntries& vals,
|
OpResult<uint32_t> OpAdd(const OpArgs& op_args, std::string_view key, const NewEntries& vals,
|
||||||
bool overwrite, bool journal_update) {
|
bool overwrite, bool journal_update) {
|
||||||
auto* es = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = es->db_slice();
|
|
||||||
auto vals_it = EntriesRange(vals);
|
auto vals_it = EntriesRange(vals);
|
||||||
|
|
||||||
VLOG(2) << "OpAdd(" << key << ")";
|
VLOG(2) << "OpAdd(" << key << ")";
|
||||||
|
@ -480,7 +479,7 @@ 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
|
||||||
db_slice.Del(op_args.db_cntx.db_index, 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});
|
||||||
}
|
}
|
||||||
|
@ -555,8 +554,7 @@ OpResult<uint32_t> OpAdd(const OpArgs& op_args, std::string_view key, const NewE
|
||||||
|
|
||||||
OpResult<uint32_t> OpAddEx(const OpArgs& op_args, string_view key, uint32_t ttl_sec,
|
OpResult<uint32_t> OpAddEx(const OpArgs& op_args, string_view key, uint32_t ttl_sec,
|
||||||
const NewEntries& vals) {
|
const NewEntries& vals) {
|
||||||
auto* es = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = es->db_slice();
|
|
||||||
|
|
||||||
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
|
@ -591,8 +589,7 @@ OpResult<uint32_t> OpAddEx(const OpArgs& op_args, string_view key, uint32_t ttl_
|
||||||
|
|
||||||
OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, facade::ArgRange vals,
|
OpResult<uint32_t> OpRem(const OpArgs& op_args, string_view key, facade::ArgRange vals,
|
||||||
bool journal_rewrite) {
|
bool journal_rewrite) {
|
||||||
auto* es = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = es->db_slice();
|
|
||||||
auto find_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_SET);
|
auto find_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_SET);
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
@ -604,7 +601,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.db_index, find_res->it));
|
CHECK(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);
|
||||||
|
@ -638,6 +635,7 @@ class Mover {
|
||||||
};
|
};
|
||||||
|
|
||||||
OpStatus Mover::OpFind(Transaction* t, EngineShard* es) {
|
OpStatus Mover::OpFind(Transaction* t, EngineShard* es) {
|
||||||
|
auto& db_slice = t->GetDbSlice(es->shard_id());
|
||||||
ShardArgs largs = t->GetShardArgs(es->shard_id());
|
ShardArgs largs = t->GetShardArgs(es->shard_id());
|
||||||
|
|
||||||
// In case both src and dest are in the same shard, largs size will be 2.
|
// In case both src and dest are in the same shard, largs size will be 2.
|
||||||
|
@ -645,7 +643,7 @@ OpStatus Mover::OpFind(Transaction* t, EngineShard* es) {
|
||||||
|
|
||||||
for (auto k : largs) {
|
for (auto k : largs) {
|
||||||
unsigned index = (k == src_) ? 0 : 1;
|
unsigned index = (k == src_) ? 0 : 1;
|
||||||
auto res = es->db_slice().FindReadOnly(t->GetDbContext(), k, OBJ_SET);
|
auto res = db_slice.FindReadOnly(t->GetDbContext(), k, OBJ_SET);
|
||||||
if (res && index == 0) { // successful src find.
|
if (res && index == 0) { // successful src find.
|
||||||
DCHECK(!res->is_done());
|
DCHECK(!res->is_done());
|
||||||
const CompactObj& val = res.value()->second;
|
const CompactObj& val = res.value()->second;
|
||||||
|
@ -713,7 +711,7 @@ OpResult<StringVec> OpUnion(const OpArgs& op_args, ShardArgs::Iterator start,
|
||||||
absl::flat_hash_set<string> uniques;
|
absl::flat_hash_set<string> uniques;
|
||||||
|
|
||||||
for (; start != end; ++start) {
|
for (; start != end; ++start) {
|
||||||
auto find_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
auto find_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
||||||
if (find_res) {
|
if (find_res) {
|
||||||
const PrimeValue& pv = find_res.value()->second;
|
const PrimeValue& pv = find_res.value()->second;
|
||||||
if (IsDenseEncoding(pv)) {
|
if (IsDenseEncoding(pv)) {
|
||||||
|
@ -738,10 +736,10 @@ OpResult<StringVec> OpUnion(const OpArgs& op_args, ShardArgs::Iterator start,
|
||||||
// Read-only OpDiff op on sets.
|
// Read-only OpDiff op on sets.
|
||||||
OpResult<StringVec> OpDiff(const OpArgs& op_args, ShardArgs::Iterator start,
|
OpResult<StringVec> OpDiff(const OpArgs& op_args, ShardArgs::Iterator start,
|
||||||
ShardArgs::Iterator end) {
|
ShardArgs::Iterator end) {
|
||||||
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
DCHECK(start != end);
|
DCHECK(start != end);
|
||||||
DVLOG(1) << "OpDiff from " << *start;
|
DVLOG(1) << "OpDiff from " << *start;
|
||||||
EngineShard* es = op_args.shard;
|
auto find_res = db_slice.FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
||||||
auto find_res = es->db_slice().FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
|
||||||
|
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
@ -762,7 +760,7 @@ OpResult<StringVec> OpDiff(const OpArgs& op_args, ShardArgs::Iterator start,
|
||||||
DCHECK(!uniques.empty()); // otherwise the key would not exist.
|
DCHECK(!uniques.empty()); // otherwise the key would not exist.
|
||||||
|
|
||||||
for (++start; start != end; ++start) {
|
for (++start; start != end; ++start) {
|
||||||
auto diff_res = es->db_slice().FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
auto diff_res = db_slice.FindReadOnly(op_args.db_cntx, *start, OBJ_SET);
|
||||||
if (!diff_res) {
|
if (!diff_res) {
|
||||||
if (diff_res.status() == OpStatus::WRONG_TYPE) {
|
if (diff_res.status() == OpStatus::WRONG_TYPE) {
|
||||||
return OpStatus::WRONG_TYPE;
|
return OpStatus::WRONG_TYPE;
|
||||||
|
@ -791,6 +789,7 @@ OpResult<StringVec> OpDiff(const OpArgs& op_args, ShardArgs::Iterator start,
|
||||||
|
|
||||||
// Read-only OpInter op on sets.
|
// Read-only OpInter op on sets.
|
||||||
OpResult<StringVec> OpInter(const Transaction* t, EngineShard* es, bool remove_first) {
|
OpResult<StringVec> OpInter(const Transaction* t, EngineShard* es, bool remove_first) {
|
||||||
|
auto& db_slice = t->GetDbSlice(es->shard_id());
|
||||||
ShardArgs args = t->GetShardArgs(es->shard_id());
|
ShardArgs args = t->GetShardArgs(es->shard_id());
|
||||||
auto it = args.begin();
|
auto it = args.begin();
|
||||||
if (remove_first) {
|
if (remove_first) {
|
||||||
|
@ -800,7 +799,7 @@ OpResult<StringVec> OpInter(const Transaction* t, EngineShard* es, bool remove_f
|
||||||
|
|
||||||
StringVec result;
|
StringVec result;
|
||||||
if (args.Size() == 1 + unsigned(remove_first)) {
|
if (args.Size() == 1 + unsigned(remove_first)) {
|
||||||
auto find_res = es->db_slice().FindReadOnly(t->GetDbContext(), *it, OBJ_SET);
|
auto find_res = db_slice.FindReadOnly(t->GetDbContext(), *it, OBJ_SET);
|
||||||
if (!find_res)
|
if (!find_res)
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
|
||||||
|
@ -824,7 +823,7 @@ OpResult<StringVec> OpInter(const Transaction* t, EngineShard* es, bool remove_f
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
for (; it != args.end(); ++it) {
|
for (; it != args.end(); ++it) {
|
||||||
auto& dest = sets[index++];
|
auto& dest = sets[index++];
|
||||||
auto find_res = es->db_slice().FindReadOnly(t->GetDbContext(), *it, OBJ_SET);
|
auto find_res = db_slice.FindReadOnly(t->GetDbContext(), *it, OBJ_SET);
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
if (status == OpStatus::OK || status == OpStatus::KEY_NOTFOUND ||
|
if (status == OpStatus::OK || status == OpStatus::KEY_NOTFOUND ||
|
||||||
find_res.status() != OpStatus::KEY_NOTFOUND) {
|
find_res.status() != OpStatus::KEY_NOTFOUND) {
|
||||||
|
@ -872,7 +871,7 @@ OpResult<StringVec> OpInter(const Transaction* t, EngineShard* es, bool remove_f
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<StringVec> OpRandMember(const OpArgs& op_args, std::string_view key, int count) {
|
OpResult<StringVec> OpRandMember(const OpArgs& op_args, std::string_view key, int count) {
|
||||||
auto find_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_SET);
|
auto find_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_SET);
|
||||||
if (!find_res)
|
if (!find_res)
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
|
||||||
|
@ -897,7 +896,7 @@ OpResult<StringVec> OpRandMember(const OpArgs& op_args, std::string_view key, in
|
||||||
// count - how many elements to pop.
|
// count - how many elements to pop.
|
||||||
OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, unsigned count) {
|
OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, unsigned count) {
|
||||||
auto& db_cntx = op_args.db_cntx;
|
auto& db_cntx = op_args.db_cntx;
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto find_res = db_slice.FindMutable(db_cntx, key, OBJ_SET);
|
auto find_res = db_slice.FindMutable(db_cntx, key, OBJ_SET);
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
@ -927,7 +926,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.db_index, find_res->it));
|
CHECK(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()) {
|
||||||
|
@ -963,7 +962,7 @@ OpResult<StringVec> OpPop(const OpArgs& op_args, string_view key, unsigned count
|
||||||
|
|
||||||
OpResult<StringVec> OpScan(const OpArgs& op_args, string_view key, uint64_t* cursor,
|
OpResult<StringVec> OpScan(const OpArgs& op_args, string_view key, uint64_t* cursor,
|
||||||
const ScanOpts& scan_op) {
|
const ScanOpts& scan_op) {
|
||||||
auto find_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_SET);
|
auto find_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_SET);
|
||||||
|
|
||||||
if (!find_res)
|
if (!find_res)
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
@ -1010,7 +1009,7 @@ void SIsMember(CmdArgList args, ConnectionContext* cntx) {
|
||||||
string_view val = ArgS(args, 1);
|
string_view val = ArgS(args, 1);
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||||
auto find_res = shard->db_slice().FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
auto find_res = t->GetDbSlice(shard->shard_id()).FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
||||||
|
|
||||||
if (find_res) {
|
if (find_res) {
|
||||||
SetType st{find_res.value()->second.RObjPtr(), find_res.value()->second.Encoding()};
|
SetType st{find_res.value()->second.RObjPtr(), find_res.value()->second.Encoding()};
|
||||||
|
@ -1037,7 +1036,7 @@ void SMIsMember(CmdArgList args, ConnectionContext* cntx) {
|
||||||
memberships.reserve(vals.size());
|
memberships.reserve(vals.size());
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||||
auto find_res = shard->db_slice().FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
auto find_res = t->GetDbSlice(shard->shard_id()).FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
||||||
if (find_res) {
|
if (find_res) {
|
||||||
SetType st{find_res.value()->second.RObjPtr(), find_res.value()->second.Encoding()};
|
SetType st{find_res.value()->second.RObjPtr(), find_res.value()->second.Encoding()};
|
||||||
FindInSet(memberships, t->GetDbContext(), st, vals);
|
FindInSet(memberships, t->GetDbContext(), st, vals);
|
||||||
|
@ -1097,7 +1096,7 @@ void SCard(CmdArgList args, ConnectionContext* cntx) {
|
||||||
string_view key = ArgS(args, 0);
|
string_view key = ArgS(args, 0);
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
||||||
auto find_res = shard->db_slice().FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
auto find_res = t->GetDbSlice(shard->shard_id()).FindReadOnly(t->GetDbContext(), key, OBJ_SET);
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
}
|
}
|
||||||
|
|
|
@ -605,7 +605,7 @@ int StreamTrim(const AddTrimOpts& opts, stream* s) {
|
||||||
|
|
||||||
OpResult<streamID> OpAdd(const OpArgs& op_args, const AddTrimOpts& opts, CmdArgList args) {
|
OpResult<streamID> OpAdd(const OpArgs& op_args, const AddTrimOpts& opts, CmdArgList args) {
|
||||||
DCHECK(!args.empty() && args.size() % 2 == 0);
|
DCHECK(!args.empty() && args.size() % 2 == 0);
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
DbSlice::AddOrFindResult add_res;
|
DbSlice::AddOrFindResult add_res;
|
||||||
|
|
||||||
if (opts.no_mkstream) {
|
if (opts.no_mkstream) {
|
||||||
|
@ -657,7 +657,7 @@ OpResult<streamID> OpAdd(const OpArgs& op_args, const AddTrimOpts& opts, CmdArgL
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<RecordVec> OpRange(const OpArgs& op_args, string_view key, const RangeOpts& opts) {
|
OpResult<RecordVec> OpRange(const OpArgs& op_args, string_view key, const RangeOpts& opts) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -801,7 +801,7 @@ stream* GetReadOnlyStream(const CompactObj& cobj) {
|
||||||
OpResult<vector<pair<string, streamID>>> OpLastIDs(const OpArgs& op_args, const ShardArgs& args) {
|
OpResult<vector<pair<string, streamID>>> OpLastIDs(const OpArgs& op_args, const ShardArgs& args) {
|
||||||
DCHECK(!args.Empty());
|
DCHECK(!args.Empty());
|
||||||
|
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
vector<pair<string, streamID>> last_ids;
|
vector<pair<string, streamID>> last_ids;
|
||||||
for (string_view key : args) {
|
for (string_view key : args) {
|
||||||
|
@ -866,7 +866,7 @@ vector<RecordVec> OpRead(const OpArgs& op_args, const ShardArgs& shard_args, con
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -877,7 +877,7 @@ OpResult<uint32_t> OpLen(const OpArgs& op_args, string_view key) {
|
||||||
|
|
||||||
OpResult<vector<GroupInfo>> OpListGroups(const DbContext& db_cntx, string_view key,
|
OpResult<vector<GroupInfo>> OpListGroups(const DbContext& db_cntx, string_view key,
|
||||||
EngineShard* shard) {
|
EngineShard* shard) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = db_cntx.GetDbSlice(shard->shard_id());
|
||||||
auto res_it = db_slice.FindReadOnly(db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindReadOnly(db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1009,7 +1009,7 @@ void GetConsumers(stream* s, streamCG* cg, long long count, GroupInfo* ginfo) {
|
||||||
|
|
||||||
OpResult<StreamInfo> OpStreams(const DbContext& db_cntx, string_view key, EngineShard* shard,
|
OpResult<StreamInfo> OpStreams(const DbContext& db_cntx, string_view key, EngineShard* shard,
|
||||||
int full, size_t count) {
|
int full, size_t count) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = db_cntx.GetDbSlice(shard->shard_id());
|
||||||
auto res_it = db_slice.FindReadOnly(db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindReadOnly(db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1072,7 +1072,7 @@ OpResult<StreamInfo> OpStreams(const DbContext& db_cntx, string_view key, Engine
|
||||||
|
|
||||||
OpResult<vector<ConsumerInfo>> OpConsumers(const DbContext& db_cntx, EngineShard* shard,
|
OpResult<vector<ConsumerInfo>> OpConsumers(const DbContext& db_cntx, EngineShard* shard,
|
||||||
string_view stream_name, string_view group_name) {
|
string_view stream_name, string_view group_name) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = db_cntx.GetDbSlice(shard->shard_id());
|
||||||
auto res_it = db_slice.FindReadOnly(db_cntx, stream_name, OBJ_STREAM);
|
auto res_it = db_slice.FindReadOnly(db_cntx, stream_name, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1116,8 +1116,7 @@ struct CreateOpts {
|
||||||
};
|
};
|
||||||
|
|
||||||
OpStatus OpCreate(const OpArgs& op_args, string_view key, const CreateOpts& opts) {
|
OpStatus OpCreate(const OpArgs& op_args, string_view key, const CreateOpts& opts) {
|
||||||
auto* shard = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = shard->db_slice();
|
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
int64_t entries_read = SCG_INVALID_ENTRIES_READ;
|
int64_t entries_read = SCG_INVALID_ENTRIES_READ;
|
||||||
if (!res_it) {
|
if (!res_it) {
|
||||||
|
@ -1164,7 +1163,7 @@ struct FindGroupResult {
|
||||||
|
|
||||||
OpResult<FindGroupResult> FindGroup(const OpArgs& op_args, string_view key, string_view gname) {
|
OpResult<FindGroupResult> FindGroup(const OpArgs& op_args, string_view key, string_view gname) {
|
||||||
auto* shard = op_args.shard;
|
auto* shard = op_args.shard;
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1453,8 +1452,7 @@ OpStatus OpSetId(const OpArgs& op_args, string_view key, string_view gname, stri
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus OpSetId2(const OpArgs& op_args, string_view key, const streamID& sid) {
|
OpStatus OpSetId2(const OpArgs& op_args, string_view key, const streamID& sid) {
|
||||||
auto* shard = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = shard->db_slice();
|
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1492,8 +1490,7 @@ OpStatus OpSetId2(const OpArgs& op_args, string_view key, const streamID& sid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, absl::Span<streamID> ids) {
|
OpResult<uint32_t> OpDel(const OpArgs& op_args, string_view key, absl::Span<streamID> ids) {
|
||||||
auto* shard = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = shard->db_slice();
|
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STREAM);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1922,8 +1919,7 @@ void XGroupHelp(CmdArgList args, ConnectionContext* cntx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<int64_t> OpTrim(const OpArgs& op_args, const AddTrimOpts& opts) {
|
OpResult<int64_t> OpTrim(const OpArgs& op_args, const AddTrimOpts& opts) {
|
||||||
auto* shard = op_args.shard;
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto& db_slice = shard->db_slice();
|
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, opts.key, OBJ_STREAM);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, opts.key, OBJ_STREAM);
|
||||||
if (!res_it) {
|
if (!res_it) {
|
||||||
if (res_it.status() == OpStatus::KEY_NOTFOUND) {
|
if (res_it.status() == OpStatus::KEY_NOTFOUND) {
|
||||||
|
@ -2900,7 +2896,8 @@ void XReadBlock(ReadOpts* opts, ConnectionContext* cntx) {
|
||||||
|
|
||||||
const auto key_checker = [&opts](EngineShard* owner, const DbContext& context, Transaction* tx,
|
const auto key_checker = [&opts](EngineShard* owner, const DbContext& context, Transaction* tx,
|
||||||
std::string_view key) -> bool {
|
std::string_view key) -> bool {
|
||||||
auto res_it = owner->db_slice().FindReadOnly(context, key, OBJ_STREAM);
|
auto& db_slice = context.GetDbSlice(owner->shard_id());
|
||||||
|
auto res_it = db_slice.FindReadOnly(context, key, OBJ_STREAM);
|
||||||
if (!res_it.ok())
|
if (!res_it.ok())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ template <typename T> T GetResult(std::variant<T, util::fb2::Future<T>> v) {
|
||||||
OpResult<uint32_t> OpSetRange(const OpArgs& op_args, string_view key, size_t start,
|
OpResult<uint32_t> OpSetRange(const OpArgs& op_args, string_view key, size_t start,
|
||||||
string_view value) {
|
string_view value) {
|
||||||
VLOG(2) << "SetRange(" << key << ", " << start << ", " << value << ")";
|
VLOG(2) << "SetRange(" << key << ", " << start << ", " << value << ")";
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
size_t range_len = start + value.size();
|
size_t range_len = start + value.size();
|
||||||
|
|
||||||
if (range_len == 0) {
|
if (range_len == 0) {
|
||||||
|
@ -107,7 +107,7 @@ OpResult<uint32_t> OpSetRange(const OpArgs& op_args, string_view key, size_t sta
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<string> OpGetRange(const OpArgs& op_args, string_view key, int32_t start, int32_t end) {
|
OpResult<string> OpGetRange(const OpArgs& op_args, string_view key, int32_t start, int32_t end) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
auto it_res = db_slice.FindReadOnly(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
@ -153,7 +153,7 @@ size_t ExtendExisting(DbSlice::Iterator it, string_view key, string_view val, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<bool> ExtendOrSkip(const OpArgs& op_args, string_view key, string_view val, bool prepend) {
|
OpResult<bool> ExtendOrSkip(const OpArgs& op_args, string_view key, string_view val, bool prepend) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STRING);
|
auto it_res = db_slice.FindMutable(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (!it_res) {
|
if (!it_res) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -163,7 +163,7 @@ OpResult<bool> ExtendOrSkip(const OpArgs& op_args, string_view key, string_view
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<double> OpIncrFloat(const OpArgs& op_args, string_view key, double val) {
|
OpResult<double> OpIncrFloat(const OpArgs& op_args, string_view key, double val) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
auto op_res = db_slice.AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(op_res);
|
RETURN_ON_BAD_STATUS(op_res);
|
||||||
|
@ -208,7 +208,7 @@ OpResult<double> OpIncrFloat(const OpArgs& op_args, string_view key, double val)
|
||||||
// if skip_on_missing - returns KEY_NOTFOUND.
|
// if skip_on_missing - returns KEY_NOTFOUND.
|
||||||
OpResult<int64_t> OpIncrBy(const OpArgs& op_args, string_view key, int64_t incr,
|
OpResult<int64_t> OpIncrBy(const OpArgs& op_args, string_view key, int64_t incr,
|
||||||
bool skip_on_missing) {
|
bool skip_on_missing) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
// we avoid using AddOrFind because of skip_on_missing option for memcache.
|
// we avoid using AddOrFind because of skip_on_missing option for memcache.
|
||||||
auto res = db_slice.FindMutable(op_args.db_cntx, key);
|
auto res = db_slice.FindMutable(op_args.db_cntx, key);
|
||||||
|
@ -307,7 +307,7 @@ OpStatus OpMSet(const OpArgs& op_args, const ShardArgs& args) {
|
||||||
OpResult<array<int64_t, 5>> OpThrottle(const OpArgs& op_args, const string_view key,
|
OpResult<array<int64_t, 5>> OpThrottle(const OpArgs& op_args, const string_view key,
|
||||||
const int64_t limit, const int64_t emission_interval_ms,
|
const int64_t limit, const int64_t emission_interval_ms,
|
||||||
const uint64_t quantity) {
|
const uint64_t quantity) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
if (emission_interval_ms > INT64_MAX / limit) {
|
if (emission_interval_ms > INT64_MAX / limit) {
|
||||||
return OpStatus::INVALID_INT;
|
return OpStatus::INVALID_INT;
|
||||||
|
@ -413,7 +413,7 @@ SinkReplyBuilder::MGetResponse OpMGet(util::fb2::BlockingCounter wait_bc, bool f
|
||||||
ShardArgs keys = t->GetShardArgs(shard->shard_id());
|
ShardArgs keys = t->GetShardArgs(shard->shard_id());
|
||||||
DCHECK(!keys.Empty());
|
DCHECK(!keys.Empty());
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
|
|
||||||
SinkReplyBuilder::MGetResponse response(keys.Size());
|
SinkReplyBuilder::MGetResponse response(keys.Size());
|
||||||
absl::InlinedVector<DbSlice::ConstIterator, 32> iters(keys.Size());
|
absl::InlinedVector<DbSlice::ConstIterator, 32> iters(keys.Size());
|
||||||
|
@ -478,7 +478,7 @@ OpResult<variant<size_t, util::fb2::Future<size_t>>> OpExtend(const OpArgs& op_a
|
||||||
std::string_view value,
|
std::string_view value,
|
||||||
bool prepend) {
|
bool prepend) {
|
||||||
auto* shard = op_args.shard;
|
auto* shard = op_args.shard;
|
||||||
auto it_res = shard->db_slice().AddOrFind(op_args.db_cntx, key);
|
auto it_res = op_args.GetDbSlice().AddOrFind(op_args.db_cntx, key);
|
||||||
RETURN_ON_BAD_STATUS(it_res);
|
RETURN_ON_BAD_STATUS(it_res);
|
||||||
|
|
||||||
if (it_res->is_new) {
|
if (it_res->is_new) {
|
||||||
|
@ -551,7 +551,7 @@ bool StringValue::IsEmpty() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpStatus SetCmd::Set(const SetParams& params, string_view key, string_view value) {
|
OpStatus SetCmd::Set(const SetParams& params, string_view key, string_view value) {
|
||||||
auto& db_slice = op_args_.shard->db_slice();
|
auto& db_slice = op_args_.GetDbSlice();
|
||||||
|
|
||||||
DCHECK(db_slice.IsDbValid(op_args_.db_cntx.db_index));
|
DCHECK(db_slice.IsDbValid(op_args_.db_cntx.db_index));
|
||||||
VLOG(2) << "Set " << key << "(" << db_slice.shard_id() << ") ";
|
VLOG(2) << "Set " << key << "(" << db_slice.shard_id() << ") ";
|
||||||
|
@ -596,7 +596,7 @@ OpStatus SetCmd::SetExisting(const SetParams& params, DbSlice::Iterator it,
|
||||||
PrimeValue& prime_value = it->second;
|
PrimeValue& prime_value = it->second;
|
||||||
EngineShard* shard = op_args_.shard;
|
EngineShard* shard = op_args_.shard;
|
||||||
|
|
||||||
DbSlice& db_slice = shard->db_slice();
|
auto& db_slice = op_args_.GetDbSlice();
|
||||||
uint64_t at_ms =
|
uint64_t at_ms =
|
||||||
params.expire_after_ms ? params.expire_after_ms + op_args_.db_cntx.time_now_ms : 0;
|
params.expire_after_ms ? params.expire_after_ms + op_args_.db_cntx.time_now_ms : 0;
|
||||||
|
|
||||||
|
@ -636,8 +636,7 @@ OpStatus SetCmd::SetExisting(const SetParams& params, DbSlice::Iterator it,
|
||||||
|
|
||||||
void SetCmd::AddNew(const SetParams& params, DbSlice::Iterator it, DbSlice::ExpIterator e_it,
|
void SetCmd::AddNew(const SetParams& params, DbSlice::Iterator it, DbSlice::ExpIterator e_it,
|
||||||
std::string_view key, std::string_view value) {
|
std::string_view key, std::string_view value) {
|
||||||
EngineShard* shard = op_args_.shard;
|
auto& db_slice = op_args_.GetDbSlice();
|
||||||
auto& db_slice = shard->db_slice();
|
|
||||||
|
|
||||||
// Adding new value.
|
// Adding new value.
|
||||||
PrimeValue tvalue{value};
|
PrimeValue tvalue{value};
|
||||||
|
@ -858,7 +857,7 @@ void StringFamily::SetNx(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
|
||||||
void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
||||||
auto cb = [key = ArgS(args, 0)](Transaction* tx, EngineShard* es) -> OpResult<StringValue> {
|
auto cb = [key = ArgS(args, 0)](Transaction* tx, EngineShard* es) -> OpResult<StringValue> {
|
||||||
auto it_res = es->db_slice().FindReadOnly(tx->GetDbContext(), key, OBJ_STRING);
|
auto it_res = tx->GetDbSlice(es->shard_id()).FindReadOnly(tx->GetDbContext(), key, OBJ_STRING);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
|
@ -870,13 +869,14 @@ void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
|
||||||
void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) {
|
void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) {
|
||||||
auto cb = [key = ArgS(args, 0)](Transaction* tx, EngineShard* es) -> OpResult<StringValue> {
|
auto cb = [key = ArgS(args, 0)](Transaction* tx, EngineShard* es) -> OpResult<StringValue> {
|
||||||
auto it_res = es->db_slice().FindMutable(tx->GetDbContext(), key, OBJ_STRING);
|
auto& db_slice = tx->GetDbSlice(es->shard_id());
|
||||||
|
auto it_res = db_slice.FindMutable(tx->GetDbContext(), key, OBJ_STRING);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
auto value = StringValue::Read(tx->GetDbIndex(), key, it_res->it->second, es);
|
auto value = StringValue::Read(tx->GetDbIndex(), key, it_res->it->second, es);
|
||||||
it_res->post_updater.Run(); // Run manually before delete
|
it_res->post_updater.Run(); // Run manually before delete
|
||||||
es->db_slice().Del(tx->GetDbIndex(), it_res->it);
|
db_slice.Del(tx->GetDbContext(), it_res->it);
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -985,7 +985,7 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) {
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<StringValue> {
|
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<StringValue> {
|
||||||
auto op_args = t->GetOpArgs(shard);
|
auto op_args = t->GetOpArgs(shard);
|
||||||
|
|
||||||
auto it_res = op_args.shard->db_slice().FindMutable(op_args.db_cntx, key, OBJ_STRING);
|
auto it_res = op_args.GetDbSlice().FindMutable(op_args.db_cntx, key, OBJ_STRING);
|
||||||
if (!it_res)
|
if (!it_res)
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
|
@ -993,8 +993,8 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) {
|
||||||
|
|
||||||
if (exp_params.IsDefined()) {
|
if (exp_params.IsDefined()) {
|
||||||
it_res->post_updater.Run(); // Run manually before possible delete due to negative expire
|
it_res->post_updater.Run(); // Run manually before possible delete due to negative expire
|
||||||
RETURN_ON_BAD_STATUS(op_args.shard->db_slice().UpdateExpire(op_args.db_cntx, it_res->it,
|
RETURN_ON_BAD_STATUS(op_args.GetDbSlice().UpdateExpire(op_args.db_cntx, it_res->it,
|
||||||
it_res->exp_it, exp_params));
|
it_res->exp_it, exp_params));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replicate GETEX as PEXPIREAT or PERSIST
|
// Replicate GETEX as PEXPIREAT or PERSIST
|
||||||
|
@ -1261,7 +1261,7 @@ void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
|
||||||
string_view key = ArgS(args, 0);
|
string_view key = ArgS(args, 0);
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<size_t> {
|
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<size_t> {
|
||||||
auto it_res = shard->db_slice().FindReadOnly(t->GetDbContext(), key, OBJ_STRING);
|
auto it_res = t->GetDbSlice(shard->shard_id()).FindReadOnly(t->GetDbContext(), key, OBJ_STRING);
|
||||||
if (!it_res.ok())
|
if (!it_res.ok())
|
||||||
return it_res.status();
|
return it_res.status();
|
||||||
|
|
||||||
|
|
|
@ -585,7 +585,7 @@ bool Transaction::RunInShard(EngineShard* shard, bool txq_ooo) {
|
||||||
// touching those keys will be ordered via TxQueue. It's necessary because we preserve
|
// touching those keys will be ordered via TxQueue. It's necessary because we preserve
|
||||||
// the atomicity of awaked transactions by halting the TxQueue.
|
// the atomicity of awaked transactions by halting the TxQueue.
|
||||||
if (was_suspended || !became_suspended) {
|
if (was_suspended || !became_suspended) {
|
||||||
shard->db_slice().Release(mode, largs);
|
GetDbSlice(shard->shard_id()).Release(mode, largs);
|
||||||
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
||||||
}
|
}
|
||||||
sd.local_mask &= ~OUT_OF_ORDER;
|
sd.local_mask &= ~OUT_OF_ORDER;
|
||||||
|
@ -619,7 +619,8 @@ void Transaction::RunCallback(EngineShard* shard) {
|
||||||
DCHECK_EQ(shard, EngineShard::tlocal());
|
DCHECK_EQ(shard, EngineShard::tlocal());
|
||||||
|
|
||||||
RunnableResult result;
|
RunnableResult result;
|
||||||
shard->db_slice().LockChangeCb();
|
auto& db_slice = GetDbSlice(shard->shard_id());
|
||||||
|
db_slice.LockChangeCb();
|
||||||
try {
|
try {
|
||||||
result = (*cb_ptr_)(this, shard);
|
result = (*cb_ptr_)(this, shard);
|
||||||
|
|
||||||
|
@ -643,7 +644,7 @@ void Transaction::RunCallback(EngineShard* shard) {
|
||||||
LOG(FATAL) << "Unexpected exception " << e.what();
|
LOG(FATAL) << "Unexpected exception " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
shard->db_slice().OnCbFinish();
|
db_slice.OnCbFinish();
|
||||||
|
|
||||||
// Handle result flags to alter behaviour.
|
// Handle result flags to alter behaviour.
|
||||||
if (result.flags & RunnableResult::AVOID_CONCLUDING) {
|
if (result.flags & RunnableResult::AVOID_CONCLUDING) {
|
||||||
|
@ -657,10 +658,10 @@ void Transaction::RunCallback(EngineShard* shard) {
|
||||||
// Log to journal only once the command finished running
|
// Log to journal only once the command finished running
|
||||||
if ((coordinator_state_ & COORD_CONCLUDING) || (multi_ && multi_->concluding)) {
|
if ((coordinator_state_ & COORD_CONCLUDING) || (multi_ && multi_->concluding)) {
|
||||||
LogAutoJournalOnShard(shard, result);
|
LogAutoJournalOnShard(shard, result);
|
||||||
shard->db_slice().UnlockChangeCb();
|
db_slice.UnlockChangeCb();
|
||||||
MaybeInvokeTrackingCb();
|
MaybeInvokeTrackingCb();
|
||||||
} else {
|
} else {
|
||||||
shard->db_slice().UnlockChangeCb();
|
db_slice.UnlockChangeCb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,7 +1028,8 @@ bool Transaction::ScheduleInShard(EngineShard* shard, bool can_run_immediately)
|
||||||
bool shard_unlocked = shard->shard_lock()->Check(mode);
|
bool shard_unlocked = shard->shard_lock()->Check(mode);
|
||||||
|
|
||||||
// Check if we can run immediately
|
// Check if we can run immediately
|
||||||
if (shard_unlocked && can_run_immediately && CheckLocks(shard->db_slice(), mode, lock_args)) {
|
if (shard_unlocked && can_run_immediately &&
|
||||||
|
CheckLocks(GetDbSlice(shard->shard_id()), mode, lock_args)) {
|
||||||
sd.local_mask |= RAN_IMMEDIATELY;
|
sd.local_mask |= RAN_IMMEDIATELY;
|
||||||
shard->stats().tx_immediate_total++;
|
shard->stats().tx_immediate_total++;
|
||||||
|
|
||||||
|
@ -1038,7 +1040,7 @@ bool Transaction::ScheduleInShard(EngineShard* shard, bool can_run_immediately)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keys_unlocked = shard->db_slice().Acquire(mode, lock_args);
|
bool keys_unlocked = GetDbSlice(shard->shard_id()).Acquire(mode, lock_args);
|
||||||
lock_granted = shard_unlocked && keys_unlocked;
|
lock_granted = shard_unlocked && keys_unlocked;
|
||||||
|
|
||||||
sd.local_mask |= KEYLOCK_ACQUIRED;
|
sd.local_mask |= KEYLOCK_ACQUIRED;
|
||||||
|
@ -1062,7 +1064,7 @@ bool Transaction::ScheduleInShard(EngineShard* shard, bool can_run_immediately)
|
||||||
// fail this scheduling attempt for trans.
|
// fail this scheduling attempt for trans.
|
||||||
if (!txq->Empty() && txid_ < txq->TailScore() && !lock_granted) {
|
if (!txq->Empty() && txid_ < txq->TailScore() && !lock_granted) {
|
||||||
if (sd.local_mask & KEYLOCK_ACQUIRED) {
|
if (sd.local_mask & KEYLOCK_ACQUIRED) {
|
||||||
shard->db_slice().Release(mode, lock_args);
|
GetDbSlice(shard->shard_id()).Release(mode, lock_args);
|
||||||
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1106,7 +1108,7 @@ bool Transaction::CancelShardCb(EngineShard* shard) {
|
||||||
auto lock_args = GetLockArgs(shard->shard_id());
|
auto lock_args = GetLockArgs(shard->shard_id());
|
||||||
DCHECK(sd.local_mask & KEYLOCK_ACQUIRED);
|
DCHECK(sd.local_mask & KEYLOCK_ACQUIRED);
|
||||||
DCHECK(!lock_args.fps.empty());
|
DCHECK(!lock_args.fps.empty());
|
||||||
shard->db_slice().Release(LockMode(), lock_args);
|
GetDbSlice(shard->shard_id()).Release(LockMode(), lock_args);
|
||||||
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,7 +1198,7 @@ OpStatus Transaction::WatchInShard(BlockingController::Keys keys, EngineShard* s
|
||||||
void Transaction::ExpireShardCb(BlockingController::Keys keys, EngineShard* shard) {
|
void Transaction::ExpireShardCb(BlockingController::Keys keys, EngineShard* shard) {
|
||||||
// Blocking transactions don't release keys when suspending, release them now.
|
// Blocking transactions don't release keys when suspending, release them now.
|
||||||
auto lock_args = GetLockArgs(shard->shard_id());
|
auto lock_args = GetLockArgs(shard->shard_id());
|
||||||
shard->db_slice().Release(LockMode(), lock_args);
|
GetDbSlice(shard->shard_id()).Release(LockMode(), lock_args);
|
||||||
|
|
||||||
auto& sd = shard_data_[SidToId(shard->shard_id())];
|
auto& sd = shard_data_[SidToId(shard->shard_id())];
|
||||||
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
sd.local_mask &= ~KEYLOCK_ACQUIRED;
|
||||||
|
@ -1209,16 +1211,23 @@ void Transaction::ExpireShardCb(BlockingController::Keys keys, EngineShard* shar
|
||||||
FinishHop();
|
FinishHop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbSlice& Transaction::GetDbSlice(ShardId shard_id) const {
|
||||||
|
auto* shard = EngineShard::tlocal();
|
||||||
|
DCHECK_EQ(shard->shard_id(), shard_id);
|
||||||
|
return shard->db_slice();
|
||||||
|
}
|
||||||
|
|
||||||
OpStatus Transaction::RunSquashedMultiCb(RunnableType cb) {
|
OpStatus Transaction::RunSquashedMultiCb(RunnableType cb) {
|
||||||
DCHECK(multi_ && multi_->role == SQUASHED_STUB);
|
DCHECK(multi_ && multi_->role == SQUASHED_STUB);
|
||||||
DCHECK_EQ(unique_shard_cnt_, 1u);
|
DCHECK_EQ(unique_shard_cnt_, 1u);
|
||||||
|
|
||||||
auto* shard = EngineShard::tlocal();
|
auto* shard = EngineShard::tlocal();
|
||||||
shard->db_slice().LockChangeCb();
|
auto& db_slice = GetDbSlice(shard->shard_id());
|
||||||
|
db_slice.LockChangeCb();
|
||||||
auto result = cb(this, shard);
|
auto result = cb(this, shard);
|
||||||
shard->db_slice().OnCbFinish();
|
db_slice.OnCbFinish();
|
||||||
LogAutoJournalOnShard(shard, result);
|
LogAutoJournalOnShard(shard, result);
|
||||||
shard->db_slice().UnlockChangeCb();
|
db_slice.UnlockChangeCb();
|
||||||
MaybeInvokeTrackingCb();
|
MaybeInvokeTrackingCb();
|
||||||
|
|
||||||
DCHECK_EQ(result.flags, 0); // if it's sophisticated, we shouldn't squash it
|
DCHECK_EQ(result.flags, 0); // if it's sophisticated, we shouldn't squash it
|
||||||
|
@ -1231,7 +1240,7 @@ void Transaction::UnlockMultiShardCb(absl::Span<const LockFp> fps, EngineShard*
|
||||||
if (multi_->mode == GLOBAL) {
|
if (multi_->mode == GLOBAL) {
|
||||||
shard->shard_lock()->Release(IntentLock::EXCLUSIVE);
|
shard->shard_lock()->Release(IntentLock::EXCLUSIVE);
|
||||||
} else {
|
} else {
|
||||||
shard->db_slice().Release(*multi_->lock_mode, KeyLockArgs{db_index_, fps});
|
GetDbSlice(shard->shard_id()).Release(*multi_->lock_mode, KeyLockArgs{db_index_, fps});
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardId sid = shard->shard_id();
|
ShardId sid = shard->shard_id();
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace dfly {
|
||||||
|
|
||||||
class EngineShard;
|
class EngineShard;
|
||||||
class BlockingController;
|
class BlockingController;
|
||||||
|
class DbSlice;
|
||||||
|
|
||||||
using facade::OpResult;
|
using facade::OpResult;
|
||||||
using facade::OpStatus;
|
using facade::OpStatus;
|
||||||
|
@ -305,6 +306,8 @@ class Transaction {
|
||||||
return DbContext{db_index_, time_now_ms_};
|
return DbContext{db_index_, time_now_ms_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbSlice& GetDbSlice(ShardId sid) const;
|
||||||
|
|
||||||
DbIndex GetDbIndex() const {
|
DbIndex GetDbIndex() const {
|
||||||
return db_index_;
|
return db_index_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,17 @@ namespace dfly {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using Payload = journal::Entry::Payload;
|
using Payload = journal::Entry::Payload;
|
||||||
|
|
||||||
|
DbSlice& DbContext::GetDbSlice(ShardId shard_id) const {
|
||||||
|
// TODO: Update this when adding namespaces
|
||||||
|
DCHECK_EQ(shard_id, EngineShard::tlocal()->shard_id());
|
||||||
|
return EngineShard::tlocal()->db_slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
DbSlice& OpArgs::GetDbSlice() const {
|
||||||
|
// TODO: Update this when adding namespaces
|
||||||
|
return shard->db_slice();
|
||||||
|
}
|
||||||
|
|
||||||
size_t ShardArgs::Size() const {
|
size_t ShardArgs::Size() const {
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
for (const auto& s : slice_.second)
|
for (const auto& s : slice_.second)
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace dfly {
|
||||||
|
|
||||||
class EngineShard;
|
class EngineShard;
|
||||||
class Transaction;
|
class Transaction;
|
||||||
|
class DbSlice;
|
||||||
|
|
||||||
using DbIndex = uint16_t;
|
using DbIndex = uint16_t;
|
||||||
using ShardId = uint16_t;
|
using ShardId = uint16_t;
|
||||||
|
@ -59,19 +60,24 @@ struct KeyIndex {
|
||||||
struct DbContext {
|
struct DbContext {
|
||||||
DbIndex db_index = 0;
|
DbIndex db_index = 0;
|
||||||
uint64_t time_now_ms = 0;
|
uint64_t time_now_ms = 0;
|
||||||
|
|
||||||
|
// Convenience method.
|
||||||
|
DbSlice& GetDbSlice(ShardId shard_id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OpArgs {
|
struct OpArgs {
|
||||||
EngineShard* shard;
|
EngineShard* shard = nullptr;
|
||||||
const Transaction* tx;
|
const Transaction* tx = nullptr;
|
||||||
DbContext db_cntx;
|
DbContext db_cntx;
|
||||||
|
|
||||||
OpArgs() : shard(nullptr), tx(nullptr) {
|
OpArgs() = default;
|
||||||
}
|
|
||||||
|
|
||||||
OpArgs(EngineShard* s, const Transaction* tx, const DbContext& cntx)
|
OpArgs(EngineShard* s, const Transaction* tx, const DbContext& cntx)
|
||||||
: shard(s), tx(tx), db_cntx(cntx) {
|
: shard(s), tx(tx), db_cntx(cntx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenience method.
|
||||||
|
DbSlice& GetDbSlice() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A strong type for a lock tag. Helps to disambiguate between keys and the parts of the
|
// A strong type for a lock tag. Helps to disambiguate between keys and the parts of the
|
||||||
|
|
|
@ -188,7 +188,7 @@ void OutputScoredArrayResult(const OpResult<ScoredArray>& result,
|
||||||
|
|
||||||
OpResult<DbSlice::ItAndUpdater> FindZEntry(const ZParams& zparams, const OpArgs& op_args,
|
OpResult<DbSlice::ItAndUpdater> FindZEntry(const ZParams& zparams, const OpArgs& op_args,
|
||||||
string_view key, size_t member_len) {
|
string_view key, size_t member_len) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
if (zparams.flags & ZADD_IN_XX) {
|
if (zparams.flags & ZADD_IN_XX) {
|
||||||
return db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
return db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
}
|
}
|
||||||
|
@ -847,7 +847,7 @@ OpResult<ScoredMap> OpUnion(EngineShard* shard, Transaction* t, string_view dest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
KeyIterWeightVec key_weight_vec(keys.Size() - removed_keys);
|
KeyIterWeightVec key_weight_vec(keys.Size() - removed_keys);
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
for (; start != end; ++start) {
|
for (; start != end; ++start) {
|
||||||
|
@ -900,7 +900,7 @@ OpResult<ScoredMap> OpInter(EngineShard* shard, Transaction* t, string_view dest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
vector<pair<DbSlice::ItAndUpdater, double>> it_arr(keys.Size() - removed_keys);
|
vector<pair<DbSlice::ItAndUpdater, double>> it_arr(keys.Size() - removed_keys);
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
|
@ -966,11 +966,11 @@ size_t EstimateListpackMinBytes(ScoredMemberSpan members) {
|
||||||
OpResult<AddResult> OpAdd(const OpArgs& op_args, const ZParams& zparams, string_view key,
|
OpResult<AddResult> OpAdd(const OpArgs& op_args, const ZParams& zparams, string_view key,
|
||||||
ScoredMemberSpan members) {
|
ScoredMemberSpan members) {
|
||||||
DCHECK(!members.empty() || zparams.override);
|
DCHECK(!members.empty() || zparams.override);
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
|
|
||||||
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
|
||||||
db_slice.Del(op_args.db_cntx.db_index, it);
|
db_slice.Del(op_args.db_cntx, it);
|
||||||
return OpStatus::OK;
|
return OpStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,7 +1268,7 @@ bool ParseLimit(string_view offset_str, string_view limit_str, ZSetFamily::Range
|
||||||
}
|
}
|
||||||
|
|
||||||
ScoredArray OpBZPop(Transaction* t, EngineShard* shard, std::string_view key, bool is_max) {
|
ScoredArray OpBZPop(Transaction* t, EngineShard* shard, std::string_view key, bool is_max) {
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
auto it_res = db_slice.FindMutable(t->GetDbContext(), key, OBJ_ZSET);
|
auto it_res = db_slice.FindMutable(t->GetDbContext(), key, OBJ_ZSET);
|
||||||
CHECK(it_res) << t->DebugId() << " " << key; // must exist and must be ok.
|
CHECK(it_res) << t->DebugId() << " " << key; // must exist and must be ok.
|
||||||
auto it = it_res->it;
|
auto it = it_res->it;
|
||||||
|
@ -1299,7 +1299,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->GetDbIndex(), it_res->it));
|
CHECK(db_slice.Del(t->GetDbContext(), it_res->it));
|
||||||
}
|
}
|
||||||
|
|
||||||
OpArgs op_args = t->GetOpArgs(shard);
|
OpArgs op_args = t->GetOpArgs(shard);
|
||||||
|
@ -1376,7 +1376,7 @@ vector<ScoredMap> OpFetch(EngineShard* shard, Transaction* t) {
|
||||||
vector<ScoredMap> results;
|
vector<ScoredMap> results;
|
||||||
results.reserve(keys.Size());
|
results.reserve(keys.Size());
|
||||||
|
|
||||||
auto& db_slice = shard->db_slice();
|
auto& db_slice = t->GetDbSlice(shard->shard_id());
|
||||||
for (string_view key : keys) {
|
for (string_view key : keys) {
|
||||||
auto it = db_slice.FindReadOnly(t->GetDbContext(), key, OBJ_ZSET);
|
auto it = db_slice.FindReadOnly(t->GetDbContext(), key, OBJ_ZSET);
|
||||||
if (!it) {
|
if (!it) {
|
||||||
|
@ -1393,7 +1393,7 @@ vector<ScoredMap> OpFetch(EngineShard* shard, Transaction* t) {
|
||||||
|
|
||||||
auto OpPopCount(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args, string_view key)
|
auto OpPopCount(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args, string_view key)
|
||||||
-> OpResult<ScoredArray> {
|
-> OpResult<ScoredArray> {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1407,7 +1407,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.shard->db_slice().Del(op_args.db_cntx.db_index, res_it->it));
|
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return iv.PopResult();
|
return iv.PopResult();
|
||||||
|
@ -1415,7 +1415,7 @@ auto OpPopCount(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args,
|
||||||
|
|
||||||
auto OpRange(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args, string_view key)
|
auto OpRange(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args, string_view key)
|
||||||
-> OpResult<ScoredArray> {
|
-> OpResult<ScoredArray> {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1430,7 +1430,7 @@ auto OpRange(const ZSetFamily::ZRangeSpec& range_spec, const OpArgs& op_args, st
|
||||||
|
|
||||||
auto OpRanges(const std::vector<ZSetFamily::ZRangeSpec>& range_specs, const OpArgs& op_args,
|
auto OpRanges(const std::vector<ZSetFamily::ZRangeSpec>& range_specs, const OpArgs& op_args,
|
||||||
string_view key) -> OpResult<vector<ScoredArray>> {
|
string_view key) -> OpResult<vector<ScoredArray>> {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1448,7 +1448,7 @@ auto OpRanges(const std::vector<ZSetFamily::ZRangeSpec>& range_specs, const OpAr
|
||||||
|
|
||||||
OpResult<unsigned> OpRemRange(const OpArgs& op_args, string_view key,
|
OpResult<unsigned> OpRemRange(const OpArgs& op_args, string_view key,
|
||||||
const ZSetFamily::ZRangeSpec& range_spec) {
|
const ZSetFamily::ZRangeSpec& range_spec) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1461,7 +1461,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.shard->db_slice().Del(op_args.db_cntx.db_index, res_it->it));
|
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return iv.removed();
|
return iv.removed();
|
||||||
|
@ -1469,7 +1469,7 @@ OpResult<unsigned> OpRemRange(const OpArgs& op_args, string_view key,
|
||||||
|
|
||||||
OpResult<unsigned> OpRank(const OpArgs& op_args, string_view key, string_view member,
|
OpResult<unsigned> OpRank(const OpArgs& op_args, string_view key, string_view member,
|
||||||
bool reverse) {
|
bool reverse) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1515,7 +1515,7 @@ OpResult<unsigned> OpRank(const OpArgs& op_args, string_view key, string_view me
|
||||||
|
|
||||||
OpResult<unsigned> OpCount(const OpArgs& op_args, std::string_view key,
|
OpResult<unsigned> OpCount(const OpArgs& op_args, std::string_view key,
|
||||||
const ZSetFamily::ScoreInterval& interval) {
|
const ZSetFamily::ScoreInterval& interval) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1565,7 +1565,7 @@ OpResult<unsigned> OpCount(const OpArgs& op_args, std::string_view key,
|
||||||
|
|
||||||
OpResult<unsigned> OpLexCount(const OpArgs& op_args, string_view key,
|
OpResult<unsigned> OpLexCount(const OpArgs& op_args, string_view key,
|
||||||
const ZSetFamily::LexInterval& interval) {
|
const ZSetFamily::LexInterval& interval) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1607,7 +1607,7 @@ OpResult<unsigned> OpLexCount(const OpArgs& op_args, string_view key,
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<unsigned> OpRem(const OpArgs& op_args, string_view key, facade::ArgRange members) {
|
OpResult<unsigned> OpRem(const OpArgs& op_args, string_view key, facade::ArgRange members) {
|
||||||
auto& db_slice = op_args.shard->db_slice();
|
auto& db_slice = op_args.GetDbSlice();
|
||||||
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = db_slice.FindMutable(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
@ -1623,19 +1623,19 @@ 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.shard->db_slice().Del(op_args.db_cntx.db_index, res_it->it));
|
CHECK(op_args.GetDbSlice().Del(op_args.db_cntx, res_it->it));
|
||||||
}
|
}
|
||||||
|
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<void> OpKeyExisted(const OpArgs& op_args, string_view key) {
|
OpResult<void> OpKeyExisted(const OpArgs& op_args, string_view key) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpResult<double> OpScore(const OpArgs& op_args, string_view key, string_view member) {
|
OpResult<double> OpScore(const OpArgs& op_args, string_view key, string_view member) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1653,7 +1653,7 @@ OpResult<double> OpScore(const OpArgs& op_args, string_view key, string_view mem
|
||||||
|
|
||||||
OpResult<MScoreResponse> OpMScore(const OpArgs& op_args, string_view key,
|
OpResult<MScoreResponse> OpMScore(const OpArgs& op_args, string_view key,
|
||||||
facade::ArgRange members) {
|
facade::ArgRange members) {
|
||||||
auto res_it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto res_it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!res_it)
|
if (!res_it)
|
||||||
return res_it.status();
|
return res_it.status();
|
||||||
|
|
||||||
|
@ -1673,7 +1673,7 @@ OpResult<MScoreResponse> OpMScore(const OpArgs& op_args, string_view key,
|
||||||
|
|
||||||
OpResult<StringVec> OpScan(const OpArgs& op_args, std::string_view key, uint64_t* cursor,
|
OpResult<StringVec> OpScan(const OpArgs& op_args, std::string_view key, uint64_t* cursor,
|
||||||
const ScanOpts& scan_op) {
|
const ScanOpts& scan_op) {
|
||||||
auto find_res = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto find_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
|
|
||||||
if (!find_res)
|
if (!find_res)
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
|
@ -1725,7 +1725,7 @@ OpResult<StringVec> OpScan(const OpArgs& op_args, std::string_view key, uint64_t
|
||||||
|
|
||||||
OpResult<ScoredArray> OpRandMember(int count, const ZSetFamily::RangeParams& params,
|
OpResult<ScoredArray> OpRandMember(int count, const ZSetFamily::RangeParams& params,
|
||||||
const OpArgs& op_args, string_view key) {
|
const OpArgs& op_args, string_view key) {
|
||||||
auto it = op_args.shard->db_slice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
auto it = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_ZSET);
|
||||||
if (!it)
|
if (!it)
|
||||||
return it.status();
|
return it.status();
|
||||||
|
|
||||||
|
@ -1923,7 +1923,7 @@ void ZSetFamily::ZCard(CmdArgList args, ConnectionContext* cntx) {
|
||||||
string_view key = ArgS(args, 0);
|
string_view key = ArgS(args, 0);
|
||||||
|
|
||||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
||||||
auto find_res = shard->db_slice().FindReadOnly(t->GetDbContext(), key, OBJ_ZSET);
|
auto find_res = t->GetDbSlice(shard->shard_id()).FindReadOnly(t->GetDbContext(), key, OBJ_ZSET);
|
||||||
if (!find_res) {
|
if (!find_res) {
|
||||||
return find_res.status();
|
return find_res.status();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue