Loading...
Searching...
No Matches
consensus_manager_pbft.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include <glog/logging.h>
23#include <unistd.h>
24
26
27namespace resdb {
28
30 const ResDBConfig& config, std::unique_ptr<TransactionManager> executor,
31 std::unique_ptr<CustomQuery> query_executor)
32 : ConsensusManager(config),
33 system_info_(std::make_unique<SystemInfo>(config)),
34 checkpoint_manager_(std::make_unique<CheckPointManager>(
35 config, GetBroadCastClient(), GetSignatureVerifier())),
36 message_manager_(std::make_unique<MessageManager>(
37 config, std::move(executor), checkpoint_manager_.get(),
38 system_info_.get())),
39 commitment_(std::make_unique<Commitment>(config_, message_manager_.get(),
40 GetBroadCastClient(),
41 GetSignatureVerifier())),
42 query_(std::make_unique<Query>(config_, message_manager_.get(),
43 std::move(query_executor))),
44 response_manager_(config_.IsPerformanceRunning()
45 ? nullptr
46 : std::make_unique<ResponseManager>(
47 config_, GetBroadCastClient(),
48 system_info_.get(), GetSignatureVerifier())),
49 performance_manager_(config_.IsPerformanceRunning()
50 ? std::make_unique<PerformanceManager>(
51 config_, GetBroadCastClient(),
52 system_info_.get(), GetSignatureVerifier())
53 : nullptr),
54 view_change_manager_(std::make_unique<ViewChangeManager>(
56 system_info_.get(), GetBroadCastClient(), GetSignatureVerifier())),
57 recovery_(std::make_unique<Recovery>(config_, checkpoint_manager_.get(),
58 system_info_.get(),
59 message_manager_->GetStorage())) {
60 LOG(INFO) << "is running is performance mode:"
63
64 view_change_manager_->SetDuplicateManager(commitment_->GetDuplicateManager());
65
66 recovery_->ReadLogs(
67 [&](const SystemInfoData& data) {
68 system_info_->SetCurrentView(data.view());
69 system_info_->SetPrimary(data.primary_id());
70 },
71 [&](std::unique_ptr<Context> context, std::unique_ptr<Request> request) {
72 return InternalConsensusCommit(std::move(context), std::move(request));
73 });
74}
75
77 commitment_->SetNeedCommitQC(need_qc);
78}
79
81
82std::vector<ReplicaInfo> ConsensusManagerPBFT::GetReplicas() {
83 return message_manager_->GetReplicas();
84}
85
87 return system_info_->GetPrimaryId();
88}
89
91 return system_info_->GetCurrentView();
92}
93
94void ConsensusManagerPBFT::SetPrimary(uint32_t primary, uint64_t version) {
95 if (version > system_info_->GetCurrentView()) {
96 system_info_->SetCurrentView(version);
97 system_info_->SetPrimary(primary);
98 }
99}
100
101void ConsensusManagerPBFT::AddPendingRequest(std::unique_ptr<Context> context,
102 std::unique_ptr<Request> request) {
103 std::lock_guard<std::mutex> lk(mutex_);
104 request_pending_.push(std::make_pair(std::move(context), std::move(request)));
105}
106
108 std::unique_ptr<Context> context, std::unique_ptr<Request> request) {
109 std::lock_guard<std::mutex> lk(mutex_);
111 std::make_pair(std::move(context), std::move(request)));
112}
113
114absl::StatusOr<std::pair<std::unique_ptr<Context>, std::unique_ptr<Request>>>
116 std::lock_guard<std::mutex> lk(mutex_);
117 if (request_pending_.empty()) {
118 // LOG(ERROR) << "empty:";
119 return absl::InternalError("No Data.");
120 }
121 auto new_request = std::move(request_pending_.front());
122 request_pending_.pop();
123 return new_request;
124}
125
126absl::StatusOr<std::pair<std::unique_ptr<Context>, std::unique_ptr<Request>>>
128 std::lock_guard<std::mutex> lk(mutex_);
129 if (request_complained_.empty()) {
130 // LOG(ERROR) << "empty:";
131 return absl::InternalError("No Data.");
132 }
133 auto new_request = std::move(request_complained_.front());
135 return new_request;
136}
137
138// The implementation of PBFT.
139int ConsensusManagerPBFT::ConsensusCommit(std::unique_ptr<Context> context,
140 std::unique_ptr<Request> request) {
141 // LOG(INFO) << "recv impl type:" << request->type() << " "
142 // << "sender id:" << request->sender_id();
143 // If it is in viewchange, push the request to the queue
144 // for the requests from the new view which come before
145 // the local new view done.
146 recovery_->AddRequest(context.get(), request.get());
147 if (config_.GetConfigData().enable_viewchange()) {
148 view_change_manager_->MayStart();
149 if (view_change_manager_->IsInViewChange()) {
150 switch (request->type()) {
151 case Request::TYPE_NEW_TXNS:
152 case Request::TYPE_PRE_PREPARE:
153 case Request::TYPE_PREPARE:
154 case Request::TYPE_COMMIT:
155 AddPendingRequest(std::move(context), std::move(request));
156 return 0;
157 }
158 } else {
159 while (true) {
160 auto new_request = PopPendingRequest();
161 if (!new_request.ok()) {
162 break;
163 }
164 InternalConsensusCommit(std::move((*new_request).first),
165 std::move((*new_request).second));
166 }
167 }
168 }
169 int ret = InternalConsensusCommit(std::move(context), std::move(request));
170 if (config_.GetConfigData().enable_viewchange()) {
171 if (ret == -4) {
172 while (true) {
173 auto new_request = PopComplainedRequest();
174 if (!new_request.ok()) {
175 break;
176 }
177 // LOG(ERROR) << "[POP COMPLAINED REQUEST]";
178 InternalConsensusCommit(std::move((*new_request).first),
179 std::move((*new_request).second));
180 }
181 }
182 }
183 return ret;
184}
185
187 std::unique_ptr<Context> context, std::unique_ptr<Request> request) {
188 // LOG(INFO) << "recv impl type:" << request->type() << " "
189 // << "sender id:" << request->sender_id()<<" seq:"<<request->seq();
190
191 switch (request->type()) {
192 case Request::TYPE_CLIENT_REQUEST:
194 return performance_manager_->StartEval();
195 }
196 return response_manager_->NewUserRequest(std::move(context),
197 std::move(request));
198 case Request::TYPE_RESPONSE:
200 return performance_manager_->ProcessResponseMsg(std::move(context),
201 std::move(request));
202 }
203 return response_manager_->ProcessResponseMsg(std::move(context),
204 std::move(request));
205 case Request::TYPE_NEW_TXNS: {
206 uint64_t proxy_id = request->proxy_id();
207 std::string hash = request->hash();
208 int ret = commitment_->ProcessNewRequest(std::move(context),
209 std::move(request));
210 if (ret == -3) {
211 std::pair<std::unique_ptr<Context>, std::unique_ptr<Request>>
212 request_complained;
213 {
214 std::lock_guard<std::mutex> lk(commitment_->rc_mutex_);
215
216 request_complained =
217 std::move(commitment_->request_complained_.front());
218 commitment_->request_complained_.pop();
219 }
220 AddComplainedRequest(std::move(request_complained.first),
221 std::move(request_complained.second));
222 view_change_manager_->AddComplaintTimer(proxy_id, hash);
223 }
224 return ret;
225 }
226 case Request::TYPE_PRE_PREPARE:
227 return commitment_->ProcessProposeMsg(std::move(context),
228 std::move(request));
229 case Request::TYPE_PREPARE:
230 return commitment_->ProcessPrepareMsg(std::move(context),
231 std::move(request));
232 case Request::TYPE_COMMIT:
233 return commitment_->ProcessCommitMsg(std::move(context),
234 std::move(request));
235 case Request::TYPE_CHECKPOINT:
236 return checkpoint_manager_->ProcessCheckPoint(std::move(context),
237 std::move(request));
238 case Request::TYPE_VIEWCHANGE:
239 return view_change_manager_->ProcessViewChange(std::move(context),
240 std::move(request));
241 case Request::TYPE_NEWVIEW:
242 return view_change_manager_->ProcessNewView(std::move(context),
243 std::move(request));
244 case Request::TYPE_QUERY:
245 return query_->ProcessQuery(std::move(context), std::move(request));
246 case Request::TYPE_REPLICA_STATE:
247 return query_->ProcessGetReplicaState(std::move(context),
248 std::move(request));
249 case Request::TYPE_CUSTOM_QUERY:
250 return query_->ProcessCustomQuery(std::move(context), std::move(request));
251 }
252 return 0;
253}
254
256 std::function<std::string()> func) {
257 performance_manager_->SetDataFunc(func);
258}
259
261 std::function<bool(const Request&)> func) {
262 commitment_->SetPreVerifyFunc(func);
263}
264
265} // namespace resdb
std::string data
std::unique_ptr< Commitment > commitment_
std::queue< std::pair< std::unique_ptr< Context >, std::unique_ptr< Request > > > request_complained_
std::unique_ptr< PerformanceManager > performance_manager_
std::vector< ReplicaInfo > GetReplicas() override
ConsensusManagerPBFT(const ResDBConfig &config, std::unique_ptr< TransactionManager > executor, std::unique_ptr< CustomQuery > query_executor=nullptr)
void AddPendingRequest(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
std::unique_ptr< CheckPointManager > checkpoint_manager_
std::unique_ptr< ResponseManager > response_manager_
void AddComplainedRequest(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
std::unique_ptr< MessageManager > message_manager_
int InternalConsensusCommit(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
int ConsensusCommit(std::unique_ptr< Context > context, std::unique_ptr< Request > request) override
std::unique_ptr< SystemInfo > system_info_
void SetupPerformanceDataFunc(std::function< std::string()> func)
std::unique_ptr< ViewChangeManager > view_change_manager_
void SetPrimary(uint32_t primary, uint64_t version) override
absl::StatusOr< std::pair< std::unique_ptr< Context >, std::unique_ptr< Request > > > PopComplainedRequest()
std::unique_ptr< Recovery > recovery_
std::queue< std::pair< std::unique_ptr< Context >, std::unique_ptr< Request > > > request_pending_
std::unique_ptr< Query > query_
void SetPreVerifyFunc(std::function< bool(const Request &)>)
absl::StatusOr< std::pair< std::unique_ptr< Context >, std::unique_ptr< Request > > > PopPendingRequest()
ResConfigData GetConfigData() const
static Stats * GetGlobalStats(int sleep_seconds=5)
Definition stats.cpp:29
std::unique_ptr< Commitment > commitment_
CheckPointManager checkpoint_manager_
SystemInfo system_info_
std::unique_ptr< MessageManager > message_manager_
Query query_
std::unique_ptr< ResDBConfig > config_