Loading...
Searching...
No Matches
transaction_collector.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
25
26namespace resdb {
27
28uint64_t TransactionCollector::Seq() { return seq_; }
29
30bool TransactionCollector::IsPrepared() { return is_prepared_; }
31
33
35 uint64_t seq, std::vector<std::unique_ptr<Context>> context) {
36 if (seq != seq_) {
37 return -2;
38 }
39 context_list_ = std::move(context);
40 return 0;
41}
42
44 if (seq != seq_) {
45 return false;
46 }
47 return !context_list_.empty();
48}
49
50std::vector<std::unique_ptr<Context>> TransactionCollector::FetchContextList(
51 uint64_t seq) {
52 if (seq != seq_) {
53 return std::vector<std::unique_ptr<Context>>();
54 }
55 return std::move(context_list_);
56}
57
58std::vector<RequestInfo> TransactionCollector::GetPreparedProof() {
59 std::vector<RequestInfo> prepared_info;
60 for (const auto& proof : prepared_proof_) {
61 RequestInfo info;
62 info.signature = proof->signature;
63 info.request = std::make_unique<Request>(*proof->request);
64 prepared_info.push_back(std::move(info));
65 }
66 return prepared_info;
67}
68
70 std::unique_ptr<Request> request, const SignatureInfo& signature,
71 bool is_main_request,
72 std::function<void(const Request&, int received_count, CollectorDataType*,
73 std::atomic<TransactionStatue>* status, bool force)>
74 call_back) {
75 if (request == nullptr) {
76 LOG(ERROR) << "request empty";
77 return -2;
78 }
79
80 int32_t sender_id = request->sender_id();
81 std::string hash = request->hash();
82 int type = request->type();
83 uint64_t seq = request->seq();
84 uint64_t view = request->current_view();
85 if (is_committed_) {
86 return -2;
87 }
88 if (status_.load() == EXECUTED) {
89 return -2;
90 }
91
92 if (seq_ != static_cast<uint64_t>(request->seq())) {
93 // LOG(ERROR) << "data invalid, seq not the same:" << seq
94 // << " collect seq:" << seq_;
95 return -2;
96 }
97
98 if (is_main_request) {
99 auto request_info = std::make_unique<RequestInfo>();
100 request_info->signature = signature;
101 request_info->request = std::move(request);
102 bool force = false;
103 if (view_ && view_ < view && !is_prepared_) {
104 force = true;
105 atomic_mian_request_.Clear();
106 }
107 int ret = atomic_mian_request_.Set(request_info);
108 if (!ret) {
109 other_main_request_.insert(std::move(request_info));
110 LOG(ERROR) << "set main request fail: data existed:" << seq
111 << " ret:" << ret;
112 return -2;
113 }
114 auto main_request = atomic_mian_request_.Reference();
115 if (main_request->request == nullptr) {
116 LOG(ERROR) << "set main request data fail";
117 return -2;
118 }
119 view_ = view;
120 call_back(*main_request->request.get(), 1, nullptr, &status_, force);
121 return 0;
122 } else {
123 if (enable_viewchange_) {
124 if (type == Request::TYPE_PREPARE) {
125 if (status_.load() <= TransactionStatue::READY_PREPARE) {
126 auto request_info = std::make_unique<RequestInfo>();
127 request_info->signature = signature;
128 request_info->request = std::make_unique<Request>(*request);
129 std::lock_guard<std::mutex> lk(mutex_);
130 if (is_prepared_) {
131 return 0;
132 }
133 prepared_proof_.push_back(std::move(request_info));
134 if (senders_[type].count(hash) == 0) {
135 senders_[type].insert(std::make_pair(hash, std::bitset<128>()));
136 }
137 senders_[type][hash][sender_id] = 1;
138 call_back(*request, senders_[type][hash].count(), nullptr, &status_,
139 false);
140 if (status_.load() == TransactionStatue::READY_COMMIT) {
141 is_prepared_ = true;
142 if (atomic_mian_request_.Reference() != nullptr &&
143 atomic_mian_request_.Reference()->request->hash() != hash) {
144 atomic_mian_request_.Clear();
145 for (auto it = other_main_request_.begin();
146 it != other_main_request_.end(); it++) {
147 if ((*it)->request->hash() == hash) {
148 auto request_info = std::make_unique<RequestInfo>();
149 request_info->signature = (*it)->signature;
150 request_info->request = std::move((*it)->request);
151 atomic_mian_request_.Set(request_info);
152 break;
153 }
154 }
155 other_main_request_.clear();
156 }
157 int pos = 0;
158 for (size_t i = 0; i < prepared_proof_.size(); i++) {
159 if (prepared_proof_[i]->request->hash() == hash) {
160 prepared_proof_[pos++] = std::move(prepared_proof_[i]);
161 }
162 }
163 prepared_proof_.erase(prepared_proof_.begin() + pos,
164 prepared_proof_.end());
165 }
166 }
167 return 0;
168 }
169 }
170 if (request->type() == Request::TYPE_COMMIT) {
171 if (request->has_data_signature() &&
172 request->data_signature().node_id() > 0) {
173 std::lock_guard<std::mutex> lk(mutex_);
174 LOG(ERROR) << "add qc signature";
175 commit_certs_.push_back(request->data_signature());
176 }
177 }
178
179 {
180 std::lock_guard<std::mutex> lk(mutex_);
181 if (senders_[type].count(hash) == 0) {
182 senders_[type].insert(std::make_pair(hash, std::bitset<128>()));
183 }
184 senders_[type][hash][sender_id] = 1;
185 call_back(*request, senders_[type][hash].count(), nullptr, &status_,
186 false);
187 }
188
189 if (status_.load() == TransactionStatue::READY_EXECUTE) {
190 Commit();
191 return 1;
192 }
193 }
194 return 0;
195}
196
197int TransactionCollector::Commit() {
199 bool res = status_.compare_exchange_strong(
200 old_status, TransactionStatue::EXECUTED, std::memory_order_acq_rel,
201 std::memory_order_acq_rel);
202 if (!res) {
203 return -2;
204 }
205
206 auto main_request = atomic_mian_request_.Reference();
207 if (main_request == nullptr) {
208 LOG(ERROR) << "no main";
209 return -2;
210 }
211
212 is_committed_ = true;
213 if (executor_ && main_request->request) {
214 if (!commit_certs_.empty()) {
215 for (const auto& sig : commit_certs_) {
216 *main_request->request->mutable_committed_certs()
217 ->add_committed_certs() = sig;
218 // LOG(ERROR) << "add sig:" << sig.DebugString();
219 }
220 }
221 executor_->Commit(std::move(main_request->request));
222 }
223 return 0;
224}
225
226std::vector<std::string> TransactionCollector::GetAllStoredHash() {
227 std::vector<std::string> v;
228 auto main_request = atomic_mian_request_.Reference();
229 if (main_request) {
230 v.push_back(main_request->request->hash());
231 }
232 for (auto& info : other_main_request_) {
233 v.push_back(info->request->hash());
234 }
235 return v;
236}
237
238} // namespace resdb
std::vector< RequestInfo > GetPreparedProof()
int SetContextList(uint64_t seq, std::vector< std::unique_ptr< Context > > context)
std::vector< std::unique_ptr< Context > > FetchContextList(uint64_t seq)
int AddRequest(std::unique_ptr< Request > request, const SignatureInfo &signature, bool is_main_request, std::function< void(const Request &, int received_count, CollectorDataType *data, std::atomic< TransactionStatue > *status, bool force)> call_back)
std::list< std::unique_ptr< RequestInfo > > CollectorDataType
bool HasClientContextList(uint64_t seq) const
std::vector< std::string > GetAllStoredHash()
TransactionStatue GetStatus() const
int Commit(std::unique_ptr< Request > request)
std::unique_ptr< Request > request