22#include <glog/logging.h>
29 std::unique_ptr<TransactionManager> transaction_manager)
31 post_exec_func_(post_exec_func),
33 transaction_manager_(std::move(transaction_manager)),
34 commit_queue_(
"order"),
35 execute_queue_(
"execute"),
37 duplicate_manager_(nullptr) {
39 ordering_thread_ = std::thread(&TransactionExecutor::OrderMessage,
this);
40 execute_thread_ = std::thread(&TransactionExecutor::ExecuteMessage,
this);
42 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
44 std::thread(&TransactionExecutor::ExecuteMessageOutOfOrder,
this);
45 LOG(ERROR) <<
" is out of order:" << transaction_manager_->IsOutOfOrder();
53 if (ordering_thread_.joinable()) {
54 ordering_thread_.join();
56 if (execute_thread_.joinable()) {
57 execute_thread_.join();
59 if (execute_OOO_thread_.joinable()) {
60 execute_OOO_thread_.join();
65 return transaction_manager_ ? transaction_manager_->GetStorage() :
nullptr;
69 pre_exec_func_ = pre_exec_func;
73 seq_update_notify_func_ = func;
76bool TransactionExecutor::IsStop() {
return stop_; }
79 return next_execute_seq_ - 1;
83 return transaction_manager_ ==
nullptr ||
84 transaction_manager_->NeedResponse();
89 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
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));
96 commit_queue_.
Push(std::move(message));
101void TransactionExecutor::AddNewData(std::unique_ptr<Request> message) {
102 candidates_.insert(std::make_pair(message->seq(), std::move(message)));
105std::unique_ptr<Request> TransactionExecutor::GetNextData() {
106 if (candidates_.empty() || candidates_.begin()->first != next_execute_seq_) {
109 auto res = std::move(candidates_.begin()->second);
110 if (pre_exec_func_) {
111 pre_exec_func_(
res.get());
113 candidates_.erase(candidates_.begin());
117void TransactionExecutor::OrderMessage() {
119 auto message = commit_queue_.
Pop();
120 if (message !=
nullptr) {
122 uint64_t seq = message->seq();
123 if (next_execute_seq_ > seq) {
129 AddNewData(std::move(message));
133 std::unique_ptr<Request> message = GetNextData();
134 if (message ==
nullptr) {
137 execute_queue_.
Push(std::move(message));
139 if (seq_update_notify_func_) {
140 seq_update_notify_func_(next_execute_seq_);
147void TransactionExecutor::ExecuteMessage() {
149 auto message = execute_queue_.
Pop();
150 if (message ==
nullptr) {
153 bool need_execute =
true;
154 if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
155 need_execute =
false;
157 Execute(std::move(message), need_execute);
161void TransactionExecutor::ExecuteMessageOutOfOrder() {
163 auto message = execute_OOO_queue_.
Pop();
164 if (message ==
nullptr) {
167 OnlyExecute(std::move(message));
171void TransactionExecutor::OnlyExecute(std::unique_ptr<Request> request) {
173 BatchUserRequest batch_request;
174 if (!batch_request.ParseFromString(request->data())) {
175 LOG(ERROR) <<
"parse data fail";
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();
190 std::unique_ptr<BatchUserResponse> response;
191 if (transaction_manager_) {
192 response = transaction_manager_->ExecuteBatch(batch_request);
199void TransactionExecutor::Execute(std::unique_ptr<Request> request,
202 BatchUserRequest batch_request;
203 if (!batch_request.ParseFromString(request->data())) {
204 LOG(ERROR) <<
"parse data fail";
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();
219 std::unique_ptr<BatchUserResponse> response;
220 if (transaction_manager_ && need_execute) {
221 response = transaction_manager_->ExecuteBatch(batch_request);
224 if (duplicate_manager_) {
225 duplicate_manager_->
AddExecuted(batch_request.hash(), batch_request.seq());
229 if (response ==
nullptr) {
230 response = std::make_unique<BatchUserResponse>();
233 response->set_createtime(batch_request.createtime());
234 response->set_local_id(batch_request.local_id());
235 response->set_hash(batch_request.hash());
237 post_exec_func_(std::move(request), std::move(response));
243 duplicate_manager_ = manager;
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)
static Stats * GetGlobalStats(int sleep_seconds=5)
void IncTotalRequest(uint32_t num)
uint64_t GetMaxPendingExecutedSeq()
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
std::unique_ptr< ResDBConfig > config_