|
12 | 12 | #include "include/pika_cache.h" |
13 | 13 | #include "include/pika_conf.h" |
14 | 14 | #include "include/pika_slot_command.h" |
| 15 | +#include "include/pika_server.h" |
| 16 | +#include "praft/praft.h" |
15 | 17 |
|
16 | 18 | extern std::unique_ptr<PikaConf> g_pika_conf; |
| 19 | +extern PikaServer* g_pika_server; |
17 | 20 | /* SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>] */ |
18 | 21 | void SetCmd::DoInitial() { |
19 | 22 | if (!CheckArg(argv_.size())) { |
@@ -67,24 +70,74 @@ void SetCmd::DoInitial() { |
67 | 70 | void SetCmd::Do() { |
68 | 71 | int32_t res = 1; |
69 | 72 | STAGE_TIMER_GUARD(storage_duration_ms, true); |
| 73 | + |
| 74 | + bool is_raft_leader = false; |
| 75 | + if (g_pika_server && g_pika_server->GetRaftManager()) { |
| 76 | + auto node = g_pika_server->GetRaftManager()->GetRaftNode(db_->GetDBName()); |
| 77 | + is_raft_leader = (node && node->IsLeader()); |
| 78 | + } |
| 79 | + |
| 80 | + storage::CommitCallback callback = nullptr; |
| 81 | + |
| 82 | + if (is_raft_leader && db_->storage() && db_->storage()->IsRaftEnabled()) { |
| 83 | + auto self = std::static_pointer_cast<SetCmd>(shared_from_this()); |
| 84 | + auto resp_ptr = std::make_shared<std::string>(); |
| 85 | + |
| 86 | + auto pika_conn = std::dynamic_pointer_cast<PikaClientConn>(GetConn()); |
| 87 | + if (!pika_conn) { |
| 88 | + res_.SetRes(CmdRes::kErrOther, "Invalid connection"); |
| 89 | + return; |
| 90 | + } |
| 91 | + |
| 92 | + callback = [self, resp_ptr, pika_conn](rocksdb::Status status) { |
| 93 | + int32_t result = (status.ok() || status.IsNotFound()) ? 1 : 0; |
| 94 | + |
| 95 | + if (status.ok() || status.IsNotFound()) { |
| 96 | + if (self->condition_ == SetCmd::kVX) { |
| 97 | + self->res_.AppendInteger(self->success_); |
| 98 | + } else { |
| 99 | + if (result == 1) { |
| 100 | + self->res_.SetRes(CmdRes::kOk); |
| 101 | + AddSlotKey("k", self->key_, self->db_); |
| 102 | + } else { |
| 103 | + self->res_.AppendStringLen(-1); |
| 104 | + } |
| 105 | + } |
| 106 | + } else { |
| 107 | + self->res_.SetRes(CmdRes::kErrOther, status.ToString()); |
| 108 | + } |
| 109 | + |
| 110 | + *resp_ptr = std::move(self->res_.message()); |
| 111 | + pika_conn->WriteResp(*resp_ptr); |
| 112 | + pika_conn->NotifyEpoll(true); |
| 113 | + }; |
| 114 | + } |
| 115 | + |
| 116 | + // Call storage layer with optional callback |
70 | 117 | switch (condition_) { |
71 | 118 | case SetCmd::kXX: |
72 | | - s_ = db_->storage()->Setxx(key_, value_, &res, static_cast<int32_t>(sec_)); |
| 119 | + s_ = db_->storage()->Setxx(key_, value_, &res, static_cast<int32_t>(sec_), callback); |
73 | 120 | break; |
74 | 121 | case SetCmd::kNX: |
75 | | - s_ = db_->storage()->Setnx(key_, value_, &res, static_cast<int32_t>(sec_)); |
| 122 | + s_ = db_->storage()->Setnx(key_, value_, &res, static_cast<int32_t>(sec_), callback); |
76 | 123 | break; |
77 | 124 | case SetCmd::kVX: |
78 | 125 | s_ = db_->storage()->Setvx(key_, target_, value_, &success_, static_cast<int32_t>(sec_)); |
79 | 126 | break; |
80 | 127 | case SetCmd::kEXORPX: |
81 | | - s_ = db_->storage()->Setex(key_, value_, static_cast<int32_t>(sec_)); |
| 128 | + s_ = db_->storage()->Setex(key_, value_, static_cast<int32_t>(sec_), callback); |
82 | 129 | break; |
83 | 130 | default: |
84 | | - s_ = db_->storage()->Set(key_, value_); |
| 131 | + s_ = db_->storage()->Set(key_, value_, callback); |
85 | 132 | break; |
86 | 133 | } |
87 | 134 |
|
| 135 | + // For async mode (Leader), response is handled by callback |
| 136 | + if (is_raft_leader && db_->storage() && db_->storage()->IsRaftEnabled()) { |
| 137 | + return; |
| 138 | + } |
| 139 | + |
| 140 | + // For sync mode (non-Leader or non-Raft), set response immediately |
88 | 141 | if (s_.ok() || s_.IsNotFound()) { |
89 | 142 | if (condition_ == SetCmd::kVX) { |
90 | 143 | res_.AppendInteger(success_); |
|
0 commit comments