Loading...
Searching...
No Matches
transaction_executor.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
24namespace resdb {
25
27 const ResDBConfig& config, PostExecuteFunc post_exec_func,
28 SystemInfo* system_info,
29 std::unique_ptr<TransactionManager> transaction_manager)
30 : config_(config),
31 post_exec_func_(post_exec_func),
32 system_info_(system_info),
33 transaction_manager_(std::move(transaction_manager)),
34 commit_queue_("order"),
35 execute_queue_("execute"),
36 stop_(false),
37 duplicate_manager_(nullptr) {
38 global_stats_ = Stats::GetGlobalStats();
39 ordering_thread_ = std::thread(&TransactionExecutor::OrderMessage, this);
40 execute_thread_ = std::thread(&TransactionExecutor::ExecuteMessage, this);
41
42 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
43 execute_OOO_thread_ =
44 std::thread(&TransactionExecutor::ExecuteMessageOutOfOrder, this);
45 LOG(ERROR) << " is out of order:" << transaction_manager_->IsOutOfOrder();
46 }
47}
48
50
52 stop_ = true;
53 if (ordering_thread_.joinable()) {
54 ordering_thread_.join();
55 }
56 if (execute_thread_.joinable()) {
57 execute_thread_.join();
58 }
59 if (execute_OOO_thread_.joinable()) {
60 execute_OOO_thread_.join();
61 }
62}
63
65 return transaction_manager_ ? transaction_manager_->GetStorage() : nullptr;
66}
67
69 pre_exec_func_ = pre_exec_func;
70}
71
73 seq_update_notify_func_ = func;
74}
75
76bool TransactionExecutor::IsStop() { return stop_; }
77
79 return next_execute_seq_ - 1;
80}
81
83 return transaction_manager_ == nullptr ||
84 transaction_manager_->NeedResponse();
85}
86
87int TransactionExecutor::Commit(std::unique_ptr<Request> message) {
88 global_stats_->IncPendingExecute();
89 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
90 // LOG(ERROR)<<"add out of order exe:"<<message->seq()<<" from
91 // proxy:"<<message->proxy_id();
92 std::unique_ptr<Request> msg = std::make_unique<Request>(*message);
93 execute_OOO_queue_.Push(std::move(message));
94 commit_queue_.Push(std::move(msg));
95 } else {
96 commit_queue_.Push(std::move(message));
97 }
98 return 0;
99}
100
101void TransactionExecutor::AddNewData(std::unique_ptr<Request> message) {
102 candidates_.insert(std::make_pair(message->seq(), std::move(message)));
103}
104
105std::unique_ptr<Request> TransactionExecutor::GetNextData() {
106 if (candidates_.empty() || candidates_.begin()->first != next_execute_seq_) {
107 return nullptr;
108 }
109 auto res = std::move(candidates_.begin()->second);
110 if (pre_exec_func_) {
111 pre_exec_func_(res.get());
112 }
113 candidates_.erase(candidates_.begin());
114 return res;
115}
116
117void TransactionExecutor::OrderMessage() {
118 while (!IsStop()) {
119 auto message = commit_queue_.Pop();
120 if (message != nullptr) {
121 global_stats_->IncExecute();
122 uint64_t seq = message->seq();
123 if (next_execute_seq_ > seq) {
124 // LOG(INFO) << "request seq:" << seq << " has been executed"
125 // << " next seq:" << next_execute_seq_;
126 continue;
127 }
128
129 AddNewData(std::move(message));
130 }
131
132 while (!IsStop()) {
133 std::unique_ptr<Request> message = GetNextData();
134 if (message == nullptr) {
135 break;
136 }
137 execute_queue_.Push(std::move(message));
138 next_execute_seq_++;
139 if (seq_update_notify_func_) {
140 seq_update_notify_func_(next_execute_seq_);
141 }
142 }
143 }
144 return;
145}
146
147void TransactionExecutor::ExecuteMessage() {
148 while (!IsStop()) {
149 auto message = execute_queue_.Pop();
150 if (message == nullptr) {
151 continue;
152 }
153 bool need_execute = true;
154 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
155 need_execute = false;
156 }
157 Execute(std::move(message), need_execute);
158 }
159}
160
161void TransactionExecutor::ExecuteMessageOutOfOrder() {
162 while (!IsStop()) {
163 auto message = execute_OOO_queue_.Pop();
164 if (message == nullptr) {
165 continue;
166 }
167 OnlyExecute(std::move(message));
168 }
169}
170
171void TransactionExecutor::OnlyExecute(std::unique_ptr<Request> request) {
172 // Only Execute the request.
173 BatchUserRequest batch_request;
174 if (!batch_request.ParseFromString(request->data())) {
175 LOG(ERROR) << "parse data fail";
176 }
177 batch_request.set_seq(request->seq());
178 batch_request.set_hash(request->hash());
179 batch_request.set_proxy_id(request->proxy_id());
180 if (request->has_committed_certs()) {
181 *batch_request.mutable_committed_certs() = request->committed_certs();
182 }
183
184 // LOG(INFO) << " get request batch size:"
185 // << batch_request.user_requests_size()<<" proxy
186 // id:"<<request->proxy_id();
187 // std::unique_ptr<BatchUserResponse> batch_response =
188 // std::make_unique<BatchUserResponse>();
189
190 std::unique_ptr<BatchUserResponse> response;
191 if (transaction_manager_) {
192 response = transaction_manager_->ExecuteBatch(batch_request);
193 }
194
195 // global_stats_->IncTotalRequest(batch_request.user_requests_size());
196 // global_stats_->IncExecuteDone();
197}
198
199void TransactionExecutor::Execute(std::unique_ptr<Request> request,
200 bool need_execute) {
201 // Execute the request, then send the response back to the user.
202 BatchUserRequest batch_request;
203 if (!batch_request.ParseFromString(request->data())) {
204 LOG(ERROR) << "parse data fail";
205 }
206 batch_request.set_seq(request->seq());
207 batch_request.set_hash(request->hash());
208 batch_request.set_proxy_id(request->proxy_id());
209 if (request->has_committed_certs()) {
210 *batch_request.mutable_committed_certs() = request->committed_certs();
211 }
212
213 // LOG(INFO) << " get request batch size:"
214 // << batch_request.user_requests_size()<<" proxy
215 // id:"<<request->proxy_id()<<" need execute:"<<need_execute;
216 // std::unique_ptr<BatchUserResponse> batch_response =
217 // std::make_unique<BatchUserResponse>();
218
219 std::unique_ptr<BatchUserResponse> response;
220 if (transaction_manager_ && need_execute) {
221 response = transaction_manager_->ExecuteBatch(batch_request);
222 }
223
224 if (duplicate_manager_) {
225 duplicate_manager_->AddExecuted(batch_request.hash(), batch_request.seq());
226 }
227
228 global_stats_->IncTotalRequest(batch_request.user_requests_size());
229 if (response == nullptr) {
230 response = std::make_unique<BatchUserResponse>();
231 }
232
233 response->set_createtime(batch_request.createtime());
234 response->set_local_id(batch_request.local_id());
235 response->set_hash(batch_request.hash());
236
237 post_exec_func_(std::move(request), std::move(response));
238
239 global_stats_->IncExecuteDone();
240}
241
243 duplicate_manager_ = manager;
244}
245
246} // namespace resdb
void AddExecuted(const std::string &hash, uint64_t seq)
void Push(std::unique_ptr< T > data)
std::unique_ptr< T > Pop(int timeout_ms=100)
void IncExecuteDone()
Definition stats.cpp:254
static Stats * GetGlobalStats(int sleep_seconds=5)
Definition stats.cpp:29
void IncTotalRequest(uint32_t num)
Definition stats.cpp:274
void IncExecute()
Definition stats.cpp:252
void IncPendingExecute()
Definition stats.cpp:250
TransactionExecutor(const ResDBConfig &config, PostExecuteFunc post_exec_func, SystemInfo *system_info, std::unique_ptr< TransactionManager > transaction_manager)
void SetDuplicateManager(DuplicateManager *manager)
std::function< void(uint64_t seq)> SeqUpdateNotifyFunc
void SetPreExecuteFunc(PreExecuteFunc func)
std::function< void(Request *)> PreExecuteFunc
void SetSeqUpdateNotifyFunc(SeqUpdateNotifyFunc func)
int Commit(std::unique_ptr< Request > request)
std::function< void(std::unique_ptr< Request >, std::unique_ptr< BatchUserResponse > resp)> PostExecuteFunc
SystemInfo system_info_
res
Definition addr.py:25
std::unique_ptr< ResDBConfig > config_