Skip to content

Commit e017b69

Browse files
committed
chore: move single shard lua to new interface
Signed-off-by: Vladislav Oleshko <[email protected]>
1 parent a72a150 commit e017b69

File tree

5 files changed

+32
-61
lines changed

5 files changed

+32
-61
lines changed

src/server/command_registry.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class CommandId : public facade::CommandId {
9393

9494
bool IsTransactional() const;
9595

96+
bool IsMultiTransactional() const {
97+
return CO::IsTransKind(name()) || CO::IsEvalKind(name());
98+
}
99+
96100
bool IsReadOnly() const {
97101
return opt_mask_ & CO::READONLY;
98102
}

src/server/main_service.cc

Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ optional<bool> StartMultiEval(DbIndex dbid, CmdArgList keys, ScriptMgr::ScriptPa
17211721
trans->StartMultiGlobal(dbid);
17221722
return true;
17231723
case Transaction::LOCK_AHEAD:
1724-
trans->StartMultiLockedAhead(dbid, keys);
1724+
trans->StartMultiLockedAhead(dbid, keys, true);
17251725
return true;
17261726
case Transaction::NON_ATOMIC:
17271727
trans->StartMultiNonAtomic();
@@ -1762,26 +1762,6 @@ std::pair<const CommandId*, CmdArgList> Service::FindCmd(CmdArgList args) const
17621762
return {res, args.subspan(1)};
17631763
}
17641764

1765-
static bool CanRunSingleShardMulti(optional<ShardId> sid, const ScriptMgr::ScriptParams& params,
1766-
const Transaction& tx) {
1767-
if (!sid.has_value()) {
1768-
return false;
1769-
}
1770-
1771-
if (DetermineMultiMode(params) != Transaction::LOCK_AHEAD) {
1772-
return false;
1773-
}
1774-
1775-
if (tx.GetMultiMode() != Transaction::NOT_DETERMINED) {
1776-
// We may be running EVAL under MULTI. Currently RunSingleShardMulti() will attempt to lock
1777-
// keys, in which case will be already locked by MULTI. We could optimize this path as well
1778-
// though.
1779-
return false;
1780-
}
1781-
1782-
return true;
1783-
}
1784-
17851765
void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpreter* interpreter,
17861766
ConnectionContext* cntx) {
17871767
DCHECK(!eval_args.sha.empty());
@@ -1806,20 +1786,6 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret
18061786
sinfo = make_unique<ConnectionState::ScriptInfo>();
18071787
sinfo->keys.reserve(eval_args.keys.size());
18081788

1809-
optional<ShardId> sid;
1810-
for (size_t i = 0; i < eval_args.keys.size(); ++i) {
1811-
string_view key = ArgS(eval_args.keys, i);
1812-
sinfo->keys.insert(KeyLockArgs::GetLockKey(key));
1813-
1814-
ShardId cur_sid = Shard(key, shard_count());
1815-
if (i == 0) {
1816-
sid = cur_sid;
1817-
}
1818-
if (sid.has_value() && *sid != cur_sid) {
1819-
sid = nullopt;
1820-
}
1821-
}
1822-
18231789
sinfo->async_cmds_heap_limit = absl::GetFlag(FLAGS_multi_eval_squash_buffer);
18241790
Transaction* tx = cntx->transaction;
18251791
CHECK(tx != nullptr);
@@ -1834,19 +1800,29 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret
18341800

18351801
Interpreter::RunResult result;
18361802

1837-
if (CanRunSingleShardMulti(sid, *params, *tx)) {
1838-
// If script runs on a single shard, we run it remotely to save hops.
1803+
optional<bool> scheduled = StartMultiEval(cntx->db_index(), eval_args.keys, *params, cntx);
1804+
if (!scheduled) {
1805+
return;
1806+
}
1807+
1808+
// If script runs on a single shard, we run it remotely to save hops
1809+
if (!tx->IsScheduled() && tx->GetMultiMode() == Transaction::LOCK_AHEAD &&
1810+
tx->GetUniqueShardCnt() == 1) {
1811+
DCHECK(*scheduled); // because tx multi mode is lock ahead
1812+
CHECK(!tx->IsScheduled()); // skip_scheduling = true in StartMultiEval
1813+
18391814
interpreter->SetRedisFunc([cntx, tx, this](Interpreter::CallArgs args) {
18401815
// Disable squashing, as we're using the squashing mechanism to run remotely.
18411816
args.async = false;
18421817
CallFromScript(cntx, args);
18431818
});
18441819

18451820
++ServerState::tlocal()->stats.eval_shardlocal_coordination_cnt;
1846-
// TODO: remove doubule key iteration
1847-
tx->PrepareMultiForScheduleSingleHop(*sid, tx->GetDbIndex(), args);
1821+
1822+
auto sid = tx->GetUniqueShard();
1823+
tx->MultiBecomeSquasher();
18481824
tx->ScheduleSingleHop([&](Transaction*, EngineShard*) {
1849-
boost::intrusive_ptr<Transaction> stub_tx = new Transaction{tx, *sid};
1825+
boost::intrusive_ptr<Transaction> stub_tx = new Transaction{tx, sid};
18501826
stub_tx->MultiUpdateWithParent(tx);
18511827
cntx->transaction = stub_tx.get();
18521828

@@ -1856,16 +1832,14 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret
18561832
return OpStatus::OK;
18571833
});
18581834

1859-
if (*sid != ServerState::tlocal()->thread_index()) {
1835+
if (sid != ServerState::tlocal()->thread_index()) {
18601836
VLOG(1) << "Migrating connection " << cntx->conn() << " from "
1861-
<< ProactorBase::me()->GetPoolIndex() << " to " << *sid;
1862-
cntx->conn()->RequestAsyncMigration(shard_set->pool()->at(*sid));
1837+
<< ProactorBase::me()->GetPoolIndex() << " to " << sid;
1838+
cntx->conn()->RequestAsyncMigration(shard_set->pool()->at(sid));
18631839
}
18641840
} else {
1865-
optional<bool> scheduled = StartMultiEval(cntx->db_index(), eval_args.keys, *params, cntx);
1866-
if (!scheduled) {
1867-
return;
1868-
}
1841+
if (*scheduled && !tx->IsScheduled())
1842+
tx->Schedule();
18691843

18701844
++ServerState::tlocal()->stats.eval_io_coordination_cnt;
18711845
interpreter->SetRedisFunc(
@@ -2080,6 +2054,7 @@ void Service::Exec(CmdArgList args, ConnectionContext* cntx) {
20802054
if (scheduled && allow_squashing) {
20812055
MultiCommandSquasher::Execute(absl::MakeSpan(exec_info.body), cntx, this);
20822056
} else {
2057+
DCHECK(!scheduled || !delay_scheduling);
20832058
for (auto& scmd : exec_info.body) {
20842059
VLOG(2) << "TX CMD " << scmd.Cid()->name() << " " << scmd.NumArgs();
20852060

src/server/multi_command_squasher.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void MultiCommandSquasher::PerformHop() {
8686
// Doesn't work with replication, so disallow if inline scheduling is not allowed.
8787
bool singlehop_possible = IsAtomic() && !tx->IsScheduled() && cmds_.empty();
8888
if (singlehop_possible) {
89-
tx->MultiSwitchToNonAtomic();
89+
tx->MultiBecomeSquasher();
9090
DCHECK_GT(tx->GetUniqueShardCnt(), 0u); // it was initialized and determined active shards
9191
tx->ScheduleSingleHop(run_cb);
9292
return;

src/server/transaction.cc

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,10 @@ void Transaction::PrepareSquashedMultiHop(const CommandId* cid,
347347
}
348348
}
349349

350-
void Transaction::MultiSwitchToNonAtomic() {
350+
void Transaction::MultiBecomeSquasher() {
351351
DCHECK_EQ(multi_->mode, LOCK_AHEAD);
352352
CHECK_EQ(coordinator_state_, 0); // not scheduled and certainly not executing
353353
multi_->role = SQUASHER;
354-
multi_->locks.clear();
355354
}
356355

357356
void Transaction::StartMultiGlobal(DbIndex dbid) {
@@ -440,15 +439,6 @@ string Transaction::DebugId() const {
440439
return res;
441440
}
442441

443-
void Transaction::PrepareMultiForScheduleSingleHop(ShardId sid, DbIndex db, CmdArgList args) {
444-
multi_.reset();
445-
InitBase(db, args);
446-
EnableShard(sid);
447-
OpResult<KeyIndex> key_index = DetermineKeys(cid_, args);
448-
CHECK(key_index);
449-
StoreKeysInArgs(*key_index, false);
450-
}
451-
452442
// Runs in the dbslice thread. Returns true if the transaction continues running in the thread.
453443
bool Transaction::RunInShard(EngineShard* shard, bool txq_ooo) {
454444
DCHECK_GT(run_count_.load(memory_order_relaxed), 0u);
@@ -588,6 +578,7 @@ void Transaction::ScheduleInternal() {
588578
DCHECK(!shard_data_.empty());
589579
DCHECK_EQ(0u, txid_);
590580
DCHECK_EQ(0, coordinator_state_ & (COORD_SCHED | COORD_OOO));
581+
DCHECK(!multi_ || cid_->IsMultiTransactional());
591582

592583
bool span_all = IsGlobal();
593584

@@ -706,6 +697,7 @@ OpStatus Transaction::ScheduleSingleHop(RunnableType cb) {
706697
bool scheduled = (coordinator_state_ & COORD_SCHED) > 0;
707698
DCHECK(!scheduled || IsAtomicMulti()); // if we don't need to schedule, we're an atomic multi
708699
DCHECK(scheduled || !IsAtomicMulti() || multi_->role == SQUASHER); // only useful for squashing
700+
DCHECK(scheduled || !multi_ || cid_->IsMultiTransactional()); // don't schedule on normal cmd
709701

710702
if (!scheduled) // Conclude only if we schedule, otherwise we're part of multi-hop multi
711703
coordinator_state_ |= COORD_EXEC_CONCLUDING;

src/server/transaction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ class Transaction {
320320
// to it must not block.
321321
void PrepareMultiForScheduleSingleHop(ShardId sid, DbIndex db, CmdArgList args);
322322

323-
// Switch lock-ahead transaction to non-atomic. Can only be called *before* it was scheduled.
324-
void MultiSwitchToNonAtomic();
323+
// Mark as squasher.
324+
void MultiBecomeSquasher();
325325

326326
// Write a journal entry to a shard journal with the given payload. When logging a non-automatic
327327
// journal command, multiple journal entries may be necessary. In this case, call with set

0 commit comments

Comments
 (0)