-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add brpop cmd #48
Changes from all commits
d525c40
80a5fec
c5d9c3f
ea7da1b
60c7bf8
561f034
0ae4aa2
fec46cd
3ad6f20
30830a4
9bb4f81
5b0332f
94b9a33
8161ea9
617782f
3bf80ee
13ef6a5
14f302c
ccf2fa0
f1aae55
a69489c
e5e1ba6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -106,6 +106,84 @@ BaseCmd* BaseCmdGroup::GetSubCmd(const std::string& cmdName) { | |||||||||||||
return subCmd->second.get(); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
void BaseCmd::BlockThisClientToWaitLRPush(std::vector<std::string>& keys, int64_t expire_time, | ||||||||||||||
std::shared_ptr<PClient> client, BlockedConnNode::Type type) { | ||||||||||||||
std::lock_guard<std::shared_mutex> map_lock(g_kiwi->GetBlockMtx()); | ||||||||||||||
auto& key_to_conns = g_kiwi->GetMapFromKeyToConns(); | ||||||||||||||
for (auto key : keys) { | ||||||||||||||
kiwi::BlockKey blpop_key{client->GetCurrentDB(), key}; | ||||||||||||||
|
||||||||||||||
auto it = key_to_conns.find(blpop_key); | ||||||||||||||
if (it == key_to_conns.end()) { | ||||||||||||||
key_to_conns.emplace(blpop_key, std::make_unique<std::list<BlockedConnNode>>()); | ||||||||||||||
it = key_to_conns.find(blpop_key); | ||||||||||||||
} | ||||||||||||||
it->second->emplace_back(expire_time, client, type); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
void BaseCmd::ServeAndUnblockConns(PClient* client) { | ||||||||||||||
kiwi::BlockKey key{client->GetCurrentDB(), client->Key()}; | ||||||||||||||
|
||||||||||||||
std::lock_guard<std::shared_mutex> map_lock(g_kiwi->GetBlockMtx()); | ||||||||||||||
auto& key_to_conns = g_kiwi->GetMapFromKeyToConns(); | ||||||||||||||
auto it = key_to_conns.find(key); | ||||||||||||||
if (it == key_to_conns.end()) { | ||||||||||||||
// no client is waitting for this key | ||||||||||||||
return; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
auto& waitting_list = it->second; | ||||||||||||||
yeyeye2333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
std::vector<std::string> elements; | ||||||||||||||
storage::Status s; | ||||||||||||||
|
||||||||||||||
// traverse this list from head to tail(in the order of adding sequence) ,means "first blocked, first get served“ | ||||||||||||||
for (auto conn_blocked = waitting_list->begin(); conn_blocked != waitting_list->end();) { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里的迭代器 在哪里 ++ 的, 不在 for()的最后 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for循环中包含迭代器的erase操作,返回值赋值等同于++ |
||||||||||||||
auto BlockedClient = conn_blocked->GetBlockedClient(); | ||||||||||||||
|
||||||||||||||
Comment on lines
+142
to
+143
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null check for BlockedClient pointer. The function should validate that the BlockedClient pointer is not null before dereferencing it. Apply this diff to add null check: auto BlockedClient = conn_blocked->GetBlockedClient();
+ if (!BlockedClient) {
+ conn_blocked = waitting_list->erase(conn_blocked);
+ continue;
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||
if (BlockedClient->State() == ClientState::kClosed) { | ||||||||||||||
conn_blocked = waitting_list->erase(conn_blocked); | ||||||||||||||
g_kiwi->CleanBlockedNodes(BlockedClient); | ||||||||||||||
continue; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
switch (conn_blocked->GetCmdType()) { | ||||||||||||||
case BlockedConnNode::Type::BLPop: | ||||||||||||||
s = STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->LPop(client->Key(), 1, &elements); | ||||||||||||||
break; | ||||||||||||||
case BlockedConnNode::Type::BRPop: | ||||||||||||||
s = STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->RPop(client->Key(), 1, &elements); | ||||||||||||||
break; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
if (s.ok()) { | ||||||||||||||
BlockedClient->AppendArrayLen(2); | ||||||||||||||
BlockedClient->AppendString(client->Key()); | ||||||||||||||
BlockedClient->AppendString(elements[0]); | ||||||||||||||
} else if (s.IsNotFound()) { | ||||||||||||||
// this key has no more elements to serve more blocked conn. | ||||||||||||||
break; | ||||||||||||||
} else { | ||||||||||||||
BlockedClient->SetRes(CmdRes::kErrOther, s.ToString()); | ||||||||||||||
yeyeye2333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
} | ||||||||||||||
BlockedClient->SendPacket(); | ||||||||||||||
// remove this conn from current waiting list | ||||||||||||||
conn_blocked = waitting_list->erase(conn_blocked); | ||||||||||||||
g_kiwi->CleanBlockedNodes(BlockedClient); | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
bool BlockedConnNode::IsExpired(std::chrono::system_clock::time_point now) { | ||||||||||||||
if (expire_time_ == 0) { | ||||||||||||||
return false; | ||||||||||||||
} | ||||||||||||||
int64_t now_in_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count(); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 判断是否过期, 从调用 |
||||||||||||||
if (expire_time_ <= now_in_ms) { | ||||||||||||||
return true; | ||||||||||||||
} | ||||||||||||||
return false; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
bool BaseCmdGroup::DoInitial(PClient* client) { | ||||||||||||||
client->SetSubCmdName(client->argv_[1]); | ||||||||||||||
if (!subCmds_.contains(client->SubCmdName())) { | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
*/ | ||
|
||
#include "cmd_list.h" | ||
#include "src/scope_record_lock.h" | ||
#include "std_string.h" | ||
#include "store.h" | ||
|
||
|
@@ -27,6 +28,7 @@ void LPushCmd::DoCmd(PClient* client) { | |
STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->LPush(client->Key(), list_values, &reply_num); | ||
if (s.ok()) { | ||
client->AppendInteger(reply_num); | ||
ServeAndUnblockConns(client); | ||
} else if (s.IsInvalidArgument()) { | ||
client->SetRes(CmdRes::kMultiKey); | ||
} else { | ||
|
@@ -60,10 +62,6 @@ RPoplpushCmd::RPoplpushCmd(const std::string& name, int16_t arity) | |
: BaseCmd(name, arity, kCmdFlagsWrite, kAclCategoryWrite | kAclCategoryList) {} | ||
|
||
bool RPoplpushCmd::DoInitial(PClient* client) { | ||
if (((arity_ > 0 && client->argv_.size() != arity_) || (arity_ < 0 && client->argv_.size() < -arity_))) { | ||
client->SetRes(CmdRes::kWrongNum, kCmdNameRPoplpush); | ||
return false; | ||
} | ||
source_ = client->argv_[1]; | ||
receiver_ = client->argv_[2]; | ||
return true; | ||
|
@@ -75,6 +73,8 @@ void RPoplpushCmd::DoCmd(PClient* client) { | |
STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->RPoplpush(source_, receiver_, &value); | ||
if (s.ok()) { | ||
client->AppendString(value); | ||
client->SetKey(receiver_); | ||
ServeAndUnblockConns(client); | ||
} else if (s.IsNotFound()) { | ||
client->AppendString(""); | ||
} else if (s.IsInvalidArgument()) { | ||
|
@@ -99,6 +99,7 @@ void RPushCmd::DoCmd(PClient* client) { | |
STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->RPush(client->Key(), list_values, &reply_num); | ||
if (s.ok()) { | ||
client->AppendInteger(reply_num); | ||
ServeAndUnblockConns(client); | ||
} else if (s.IsInvalidArgument()) { | ||
client->SetRes(CmdRes::kMultiKey); | ||
} else { | ||
|
@@ -172,6 +173,59 @@ void RPopCmd::DoCmd(PClient* client) { | |
} | ||
} | ||
|
||
BLPopCmd::BLPopCmd(const std::string& name, int16_t arity) | ||
: BaseCmd(name, arity, kCmdFlagsWrite, kAclCategoryWrite | kAclCategoryList) {} | ||
|
||
bool BLPopCmd::DoInitial(PClient* client) { return true; } | ||
|
||
void BLPopCmd::DoCmd(PClient* client) {} | ||
Comment on lines
+176
to
+181
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement BLPopCmd functionality. The BLPopCmd has an empty implementation. It should mirror BRPopCmd's functionality but for the left side of the list. Would you like me to generate the implementation for BLPopCmd? |
||
|
||
BRPopCmd::BRPopCmd(const std::string& name, int16_t arity) | ||
: BaseCmd(name, arity, kCmdFlagsWrite, kAclCategoryWrite | kAclCategoryList) {} | ||
|
||
bool BRPopCmd::DoInitial(PClient* client) { | ||
std::vector<std::string> keys(client->argv_.begin() + 1, client->argv_.end() - 1); | ||
client->SetKey(keys); | ||
|
||
int64_t timeout = 0; | ||
if (!kstd::String2int(client->argv_.back(), &timeout)) { | ||
client->SetRes(CmdRes::kInvalidInt); | ||
return false; | ||
} | ||
if (timeout < 0) { | ||
client->SetRes(CmdRes::kErrOther, "timeout can't be a negative value"); | ||
return false; | ||
} | ||
if (timeout > 0) { | ||
auto now = std::chrono::system_clock::now(); | ||
expire_time_ = | ||
std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count() + timeout * 1000; | ||
} | ||
return true; | ||
} | ||
|
||
void BRPopCmd::DoCmd(PClient* client) { | ||
std::vector<std::string> elements; | ||
std::vector<std::string> list_keys(client->Keys().begin(), client->Keys().end()); | ||
storage::MultiScopeRecordLock(STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->GetLockMgr(), list_keys); | ||
for (auto& list_key : list_keys) { | ||
storage::Status s = | ||
STORE_INST.GetBackend(client->GetCurrentDB())->GetStorage()->RPopWithoutLock(list_key, 1, &elements); | ||
if (s.ok()) { | ||
client->AppendArrayLen(2); | ||
client->AppendString(list_key); | ||
client->AppendString(elements[0]); | ||
return; | ||
} else if (s.IsNotFound()) { | ||
continue; | ||
} else { | ||
client->SetRes(CmdRes::kErrOther, s.ToString()); | ||
return; | ||
} | ||
} | ||
BlockThisClientToWaitLRPush(list_keys, expire_time_, client->shared_from_this(), BlockedConnNode::Type::BRPop); | ||
} | ||
|
||
LRangeCmd::LRangeCmd(const std::string& name, int16_t arity) | ||
: BaseCmd(name, arity, kCmdFlagsReadonly, kAclCategoryRead | kAclCategoryList) {} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -168,6 +168,57 @@ void KiwiDB::OnNewConnection(uint64_t connId, std::shared_ptr<kiwi::PClient>& cl | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ClientMap::getInstance().AddClient(client->GetUniqueID(), client); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void KiwiDB::ScanEvictedBlockedConnsOfBlrpop() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
std::vector<kiwi::BlockKey> keys_need_remove; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
std::lock_guard<std::shared_mutex> map_lock(block_mtx_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto& key_to_blocked_conns = g_kiwi->GetMapFromKeyToConns(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto& it : key_to_blocked_conns) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto& conns_list = it.second; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto conn_node = conns_list->begin(); conn_node != conns_list->end();) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yeyeye2333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto conn_ptr = conn_node->GetBlockedClient(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (conn_node->GetBlockedClient()->State() == ClientState::kClosed) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
conn_node = conns_list->erase(conn_node); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CleanBlockedNodes(conn_ptr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (conn_node->IsExpired()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
conn_ptr->AppendString(""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
conn_ptr->SendPacket(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
conn_node = conns_list->erase(conn_node); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CleanBlockedNodes(conn_ptr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
++conn_node; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (conns_list->empty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
keys_need_remove.push_back(it.first); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto& remove_key : keys_need_remove) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
key_to_blocked_conns.erase(remove_key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+171
to
+200
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for SendPacket in ScanEvictedBlockedConnsOfBlrpop. The method should handle potential exceptions from void KiwiDB::ScanEvictedBlockedConnsOfBlrpop() {
std::vector<kiwi::BlockKey> keys_need_remove;
std::lock_guard<std::shared_mutex> map_lock(block_mtx_);
auto& key_to_blocked_conns = g_kiwi->GetMapFromKeyToConns();
for (auto& it : key_to_blocked_conns) {
auto& conns_list = it.second;
for (auto conn_node = conns_list->begin(); conn_node != conns_list->end();) {
auto conn_ptr = conn_node->GetBlockedClient();
+ try {
if (conn_node->GetBlockedClient()->State() == ClientState::kClosed) {
conn_node = conns_list->erase(conn_node);
CleanBlockedNodes(conn_ptr);
} else if (conn_node->IsExpired()) {
conn_ptr->AppendString("");
conn_ptr->SendPacket();
conn_node = conns_list->erase(conn_node);
CleanBlockedNodes(conn_ptr);
} else {
++conn_node;
}
+ } catch (...) {
+ conn_node = conns_list->erase(conn_node);
+ CleanBlockedNodes(conn_ptr);
+ }
}
if (conns_list->empty()) {
keys_need_remove.push_back(it.first);
}
}
for (auto& remove_key : keys_need_remove) {
key_to_blocked_conns.erase(remove_key);
}
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void KiwiDB::CleanBlockedNodes(const std::shared_ptr<kiwi::PClient>& client) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
std::vector<kiwi::BlockKey> blocked_keys; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto key : client->Keys()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
blocked_keys.emplace_back(client->GetCurrentDB(), key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto& key_to_blocked_conns = g_kiwi->GetMapFromKeyToConns(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto& blocked_key : blocked_keys) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const auto& it = key_to_blocked_conns.find(blocked_key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (it != key_to_blocked_conns.end()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto& conns_list = it->second; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto conn_node = conns_list->begin(); conn_node != conns_list->end(); ++conn_node) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yeyeye2333 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (conn_node->GetBlockedClient()->GetConnId() == client->GetConnId()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
conns_list->erase(conn_node); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+202
to
+220
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix potential iterator invalidation in CleanBlockedNodes. The method modifies the list while iterating, which could lead to iterator invalidation. void KiwiDB::CleanBlockedNodes(const std::shared_ptr<kiwi::PClient>& client) {
std::vector<kiwi::BlockKey> blocked_keys;
for (auto key : client->Keys()) {
blocked_keys.emplace_back(client->GetCurrentDB(), key);
}
auto& key_to_blocked_conns = g_kiwi->GetMapFromKeyToConns();
for (auto& blocked_key : blocked_keys) {
const auto& it = key_to_blocked_conns.find(blocked_key);
if (it != key_to_blocked_conns.end()) {
auto& conns_list = it->second;
- for (auto conn_node = conns_list->begin(); conn_node != conns_list->end(); ++conn_node) {
+ for (auto conn_node = conns_list->begin(); conn_node != conns_list->end();) {
if (conn_node->GetBlockedClient()->GetConnId() == client->GetConnId()) {
- conns_list->erase(conn_node);
+ conn_node = conns_list->erase(conn_node);
break;
+ } else {
+ ++conn_node;
}
}
}
}
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bool KiwiDB::Init() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
char runid[kRunidSize + 1] = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
getRandomHexChars(runid, kRunidSize); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -241,6 +292,10 @@ bool KiwiDB::Init() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timerTask->SetCallback([]() { PREPL.Cron(); }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
event_server_->AddTimerTask(timerTask); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto BLRPopTimerTask = std::make_shared<net::CommonTimerTask>(250); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BLRPopTimerTask->SetCallback(std::bind(&KiwiDB::ScanEvictedBlockedConnsOfBlrpop, this)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
event_server_->AddTimerTask(BLRPopTimerTask); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
time(&start_time_s_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add input validation for empty keys.
The function should validate that the keys vector is not empty before proceeding with the blocking operation.
Apply this diff to add input validation:
📝 Committable suggestion