Loading...
Searching...
No Matches
replica_communicator.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 <thread>
25
26#include "platform/proto/broadcast.pb.h"
27
28namespace resdb {
29
31 const std::vector<ReplicaInfo>& replicas, SignatureVerifier* verifier,
32 bool is_use_long_conn, int epoll_num, int tcp_batch)
33 : replicas_(replicas),
34 verifier_(verifier),
35 is_running_(false),
36 batch_queue_("bc_batch", tcp_batch),
37 is_use_long_conn_(is_use_long_conn) {
38 global_stats_ = Stats::GetGlobalStats();
39 if (is_use_long_conn_) {
40 worker_ = std::make_unique<boost::asio::io_service::work>(io_service_);
41 for (int i = 0; i < epoll_num; ++i) {
42 worker_threads_.push_back(std::thread([&]() { io_service_.run(); }));
43 }
44 }
45
46 /*
47 for (const ReplicaInfo& info : replicas) {
48 std::string ip = info.ip();
49 int port = info.port();
50 auto client = std::make_unique<AsyncReplicaClient>(
51 &io_service_, ip, port + (is_use_long_conn_ ? 10000 : 0), true);
52 client_pools_[std::make_pair(ip, port)] = std::move(client);
53 }
54 */
55
57}
58
60 is_running_ = false;
61 if (broadcast_thread_.joinable()) {
62 broadcast_thread_.join();
63 }
64 if (is_use_long_conn_) {
65 for (auto& cli : client_pools_) {
66 cli.second.reset();
67 }
68 worker_.reset();
69 worker_ = nullptr;
70 io_service_.stop();
71 for (auto& worker_th : worker_threads_) {
72 if (worker_th.joinable()) {
73 worker_th.join();
74 }
75 }
76 }
77}
78
79bool ReplicaCommunicator::IsInPool(const ReplicaInfo& replica_info) {
80 for (auto& replica : replicas_) {
81 if (replica_info.ip() == replica.ip() &&
82 replica_info.port() == replica.port()) {
83 return true;
84 }
85 }
86 return false;
87}
88
89bool ReplicaCommunicator::IsRunning() const { return is_running_; }
90
92 const std::vector<ReplicaInfo>& replicas) {
93 clients_ = replicas;
94}
95
96std::vector<ReplicaInfo> ReplicaCommunicator::GetClientReplicas() {
97 return clients_;
98}
99
100int ReplicaCommunicator::SendHeartBeat(const Request& hb_info) {
101 int ret = 0;
102 for (const auto& replica : replicas_) {
103 NetChannel client(replica.ip(), replica.port());
104 if (client.SendRawMessage(hb_info) == 0) {
105 ret++;
106 }
107 }
108 return ret;
109}
110
112 is_running_ = true;
113 broadcast_thread_ = std::thread([&]() {
114 while (IsRunning()) {
115 std::vector<std::unique_ptr<QueueItem>> batch_req =
116 batch_queue_.Pop(10000);
117 if (batch_req.empty()) {
118 continue;
119 }
120 BroadcastData broadcast_data;
121 for (auto& queue_item : batch_req) {
122 broadcast_data.add_data()->swap(queue_item->data);
123 }
124
125 global_stats_->SendBroadCastMsg(broadcast_data.data_size());
126 int ret = SendMessageFromPool(broadcast_data, replicas_);
127 if (ret < 0) {
128 LOG(ERROR) << "broadcast request fail:";
129 }
130 }
131 });
132}
133
134int ReplicaCommunicator::SendMessage(const google::protobuf::Message& message) {
135 global_stats_->BroadCastMsg();
136 if (is_use_long_conn_) {
137 auto item = std::make_unique<QueueItem>();
138 item->data = NetChannel::GetRawMessageString(message, verifier_);
139 batch_queue_.Push(std::move(item));
140 return 0;
141 } else {
142 LOG(ERROR) << "send internal";
143 return SendMessageInternal(message, replicas_);
144 }
145}
146
147int ReplicaCommunicator::SendMessage(const google::protobuf::Message& message,
148 const ReplicaInfo& replica_info) {
149 if (is_use_long_conn_) {
150 std::string data = NetChannel::GetRawMessageString(message, verifier_);
151 BroadcastData broadcast_data;
152 broadcast_data.add_data()->swap(data);
153 return SendMessageFromPool(broadcast_data, {replica_info});
154 } else {
155 return SendMessageInternal(message, {replica_info});
156 }
157}
158
160 const std::vector<std::unique_ptr<Request>>& messages,
161 const ReplicaInfo& replica_info) {
162 if (is_use_long_conn_) {
163 BroadcastData broadcast_data;
164 for (const auto& message : messages) {
165 std::string data = NetChannel::GetRawMessageString(*message, verifier_);
166 broadcast_data.add_data()->swap(data);
167 }
168 return SendMessageFromPool(broadcast_data, {replica_info});
169 } else {
170 int ret = 0;
171 for (const auto& message : messages) {
172 ret += SendMessageInternal(*message, {replica_info});
173 }
174 return ret;
175 }
176}
177
179 const google::protobuf::Message& message,
180 const std::vector<ReplicaInfo>& replicas) {
181 int ret = 0;
182 std::string data;
183 message.SerializeToString(&data);
184 global_stats_->SendBroadCastMsgPerRep();
185 std::lock_guard<std::mutex> lk(mutex_);
186 for (const auto& replica : replicas) {
187 auto client = GetClientFromPool(replica.ip(), replica.port());
188 if (client == nullptr) {
189 continue;
190 }
191 if (client->SendMessage(data) == 0) {
192 ret++;
193 } else {
194 LOG(ERROR) << "send to:" << replica.ip() << " fail";
195 }
196 }
197 return ret;
198}
199
201 const google::protobuf::Message& message,
202 const std::vector<ReplicaInfo>& replicas) {
203 int ret = 0;
204 for (const auto& replica : replicas) {
205 auto client = GetClient(replica.ip(), replica.port());
206 if (client == nullptr) {
207 continue;
208 }
209 if (verifier_ != nullptr) {
210 client->SetSignatureVerifier(verifier_);
211 }
212 if (client->SendRawMessage(message) == 0) {
213 ret++;
214 }
215 }
216 return ret;
217}
218
220 const std::string& ip, int port) {
221 if (client_pools_.find(std::make_pair(ip, port)) == client_pools_.end()) {
222 auto client = std::make_unique<AsyncReplicaClient>(
223 &io_service_, ip, port + (is_use_long_conn_ ? 10000 : 0), true);
224 client_pools_[std::make_pair(ip, port)] = std::move(client);
225 }
226 return client_pools_[std::make_pair(ip, port)].get();
227}
228
229std::unique_ptr<NetChannel> ReplicaCommunicator::GetClient(
230 const std::string& ip, int port) {
231 return std::make_unique<NetChannel>(ip, port);
232}
233
234void ReplicaCommunicator::BroadCast(const google::protobuf::Message& message) {
235 int ret = SendMessage(message);
236 if (ret < 0) {
237 LOG(ERROR) << "broadcast request fail:";
238 }
239}
240
241void ReplicaCommunicator::SendMessage(const google::protobuf::Message& message,
242 int64_t node_id) {
243 ReplicaInfo target_replica;
244 for (const auto& replica : replicas_) {
245 if (replica.id() == node_id) {
246 target_replica = replica;
247 break;
248 }
249 }
250 if (target_replica.ip().empty()) {
251 for (const auto& replica : GetClientReplicas()) {
252 if (replica.id() == node_id) {
253 target_replica = replica;
254 break;
255 }
256 }
257 }
258
259 if (target_replica.ip().empty()) {
260 LOG(ERROR) << "no replica info";
261 return;
262 }
263
264 int ret = SendMessage(message, target_replica);
265 if (ret < 0) {
266 LOG(ERROR) << "broadcast request fail:";
267 }
268}
269
270} // namespace resdb
std::string data
std::vector< T > Pop(int timeout_ms)
Definition batch_queue.h:52
void Push(T &&data)
Definition batch_queue.h:40
virtual int SendRawMessage(const google::protobuf::Message &message)
static std::string GetRawMessageString(const google::protobuf::Message &message, SignatureVerifier *verifier=nullptr)
ReplicaCommunicator(const std::vector< ReplicaInfo > &replicas, SignatureVerifier *verifier=nullptr, bool is_use_long_conn=false, int epoll_num=1, int tcp_batch=100)
virtual void BroadCast(const google::protobuf::Message &message)
int SendMessageFromPool(const google::protobuf::Message &message, const std::vector< ReplicaInfo > &replicas)
int SendMessageInternal(const google::protobuf::Message &message, const std::vector< ReplicaInfo > &replicas)
virtual std::unique_ptr< NetChannel > GetClient(const std::string &ip, int port)
virtual int SendBatchMessage(const std::vector< std::unique_ptr< Request > > &messages, const ReplicaInfo &replica_info)
virtual int SendHeartBeat(const Request &hb_info)
std::vector< ReplicaInfo > GetClientReplicas()
bool IsInPool(const ReplicaInfo &replica_info)
virtual int SendMessage(const google::protobuf::Message &message)
virtual AsyncReplicaClient * GetClientFromPool(const std::string &ip, int port)
void UpdateClientReplicas(const std::vector< ReplicaInfo > &replicas)
void BroadCastMsg()
Definition stats.cpp:261
static Stats * GetGlobalStats(int sleep_seconds=5)
Definition stats.cpp:29
void SendBroadCastMsg(uint32_t num)
Definition stats.cpp:268
void SendBroadCastMsgPerRep()
Definition stats.cpp:270
MockSignatureVerifier verifier_
std::vector< ReplicaInfo > replicas_