Loading...
Searching...
No Matches
resdb_txn_accessor.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
24#include <future>
25#include <thread>
26
27namespace resdb {
28
30 : config_(config),
31 replicas_(config.GetReplicaInfos()),
32 recv_timeout_(1) /*1s*/ {}
33
34std::unique_ptr<NetChannel> ResDBTxnAccessor::GetNetChannel(
35 const std::string& ip, int port) {
36 return std::make_unique<NetChannel>(ip, port);
37}
38
39// Obtain ReplicaState of each replica.
40absl::StatusOr<std::vector<std::pair<uint64_t, std::string>>>
41ResDBTxnAccessor::GetTxn(uint64_t min_seq, uint64_t max_seq) {
42 QueryRequest request;
43 request.set_min_seq(min_seq);
44 request.set_max_seq(max_seq);
45
46 std::vector<std::unique_ptr<NetChannel>> clients;
47 std::vector<std::thread> ths;
48 std::string final_str;
49 std::mutex mtx;
50 std::condition_variable resp_cv;
51 bool success = false;
52 std::map<std::string, int> recv_count;
53 for (const auto& replica : replicas_) {
54 std::unique_ptr<NetChannel> client =
55 GetNetChannel(replica.ip(), replica.port());
56 NetChannel* client_ptr = client.get();
57 clients.push_back(std::move(client));
58
59 ths.push_back(std::thread(
60 [&](NetChannel* client) {
61 std::string response_str;
62 int ret = client->SendRequest(request, Request::TYPE_QUERY);
63 if (ret) {
64 return;
65 }
66 client->SetRecvTimeout(1000);
67 ret = client->RecvRawMessageStr(&response_str);
68 if (ret == 0) {
69 std::unique_lock<std::mutex> lck(mtx);
70 recv_count[response_str]++;
71 // receive f+1 count.
72 if (recv_count[response_str] == config_.GetMinClientReceiveNum()) {
73 final_str = response_str;
74 success = true;
75 // notify the main thread.
76 resp_cv.notify_all();
77 }
78 }
79 return;
80 },
81 client_ptr));
82 }
83
84 {
85 std::unique_lock<std::mutex> lck(mtx);
86 resp_cv.wait_for(lck, std::chrono::seconds(recv_timeout_));
87 // Time out or done, close all the client.
88 for (auto& client : clients) {
89 client->Close();
90 }
91 }
92
93 // wait for all theads done.
94 for (auto& th : ths) {
95 if (th.joinable()) {
96 th.join();
97 }
98 }
99
100 std::vector<std::pair<uint64_t, std::string>> txn_resp;
101 QueryResponse resp;
102 if (success && final_str.empty()) {
103 return txn_resp;
104 }
105
106 if (final_str.empty() || !resp.ParseFromString(final_str)) {
107 LOG(ERROR) << "parse fail len:" << final_str.size();
108 return absl::InternalError("recv data fail.");
109 }
110 for (auto& transaction : resp.transactions()) {
111 txn_resp.push_back(std::make_pair(transaction.seq(), transaction.data()));
112 }
113 return txn_resp;
114}
115
116absl::StatusOr<std::vector<Request>> ResDBTxnAccessor::GetRequestFromReplica(
117 uint64_t min_seq, uint64_t max_seq, const ReplicaInfo& replica) {
118 QueryRequest request;
119 request.set_min_seq(min_seq);
120 request.set_max_seq(max_seq);
121
122 std::unique_ptr<NetChannel> client =
123 GetNetChannel(replica.ip(), replica.port());
124
125 std::string response_str;
126 int ret = client->SendRequest(request, Request::TYPE_QUERY);
127 if (ret) {
128 return absl::InternalError("send data fail.");
129 }
130 client->SetRecvTimeout(1000);
131 ret = client->RecvRawMessageStr(&response_str);
132 if (ret) {
133 return absl::InternalError("recv data fail.");
134 }
135
136 QueryResponse resp;
137
138 if (!resp.ParseFromString(response_str)) {
139 LOG(ERROR) << "parse fail len:" << response_str.size();
140 return absl::InternalError("recv data fail.");
141 }
142
143 std::vector<Request> txn_resp;
144 for (auto& transaction : resp.transactions()) {
145 txn_resp.push_back(transaction);
146 }
147 return txn_resp;
148}
149
150} // namespace resdb
int GetMinClientReceiveNum() const
virtual std::unique_ptr< NetChannel > GetNetChannel(const std::string &ip, int port)
virtual absl::StatusOr< std::vector< Request > > GetRequestFromReplica(uint64_t min_seq, uint64_t max_seq, const ReplicaInfo &replica)
ResDBTxnAccessor(const ResDBConfig &config)
virtual absl::StatusOr< std::vector< std::pair< uint64_t, std::string > > > GetTxn(uint64_t min_seq, uint64_t max_seq)
std::vector< ReplicaInfo > replicas_
std::unique_ptr< ResDBConfig > config_