Loading...
Searching...
No Matches
async_replica_client.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 <boost/bind/bind.hpp>
23
25#include "platform/proto/replica_info.pb.h"
26
27namespace resdb {
28
29AsyncReplicaClient::AsyncReplicaClient(boost::asio::io_service* io_service,
30 const std::string& ip, int port,
31 bool is_use_long_conn)
32 : socket_(*io_service),
33 endpoint_(boost::asio::ip::address::from_string(ip), port),
34 in_process_(false) {}
35
37
38int AsyncReplicaClient::SendMessage(const std::string& data) {
39 queue_.Push(std::make_unique<std::string>(data));
40 if (!in_process_.load()) {
41 bool old_value = false;
42 if (in_process_.compare_exchange_strong(old_value, true,
43 std::memory_order_acq_rel,
44 std::memory_order_acq_rel)) {
45 OnSendNewMessage();
46 }
47 }
48 return 0;
49}
50
51void AsyncReplicaClient::OnSendNewMessage() {
52 std::unique_ptr<std::string> data = queue_.Pop(0);
53 if (data == nullptr || data->empty()) {
54 in_process_ = false;
55 return;
56 }
57 pending_data_ = std::move(data);
58 status_ = 0;
59 OnSendMessage();
60}
61
62void AsyncReplicaClient::OnSendMessage() {
63 if (status_ == 0) {
64 data_size_ = pending_data_->size();
65 sending_data_size_ = sizeof(data_size_);
66 sending_data_ptr_ = reinterpret_cast<char*>(&data_size_);
67 sending_data_idx_ = 0;
68 status_ = 1;
69 OnSend();
70 } else if (status_ == 1) {
71 sending_data_size_ = data_size_;
72 sending_data_ptr_ = pending_data_->c_str();
73 sending_data_idx_ = 0;
74 status_ = 2;
75 OnSend();
76 } else {
77 status_ = 0;
78 OnSendNewMessage();
79 }
80}
81
82void AsyncReplicaClient::OnSend() {
83 socket_.async_write_some(
84 boost::asio::buffer(sending_data_ptr_ + sending_data_idx_,
85 sending_data_size_ - sending_data_idx_),
86 [&](const boost::system::error_code& error, size_t send_size) {
87 if (error) {
88 ReConnect();
89 } else {
90 sending_data_idx_ += send_size;
91 if (sending_data_idx_ >= sending_data_size_) {
92 OnSendMessage();
93 } else {
94 OnSend();
95 }
96 }
97 });
98}
99
100void AsyncReplicaClient::ReConnect() {
101 socket_.async_connect(endpoint_, [&](const boost::system::error_code& error) {
102 if (!error) {
103 status_ = 0;
104 OnSendMessage();
105 } else {
106 usleep(10000);
107 ReConnect();
108 }
109 });
110}
111
112} // namespace resdb
std::string data
virtual int SendMessage(const std::string &data)
AsyncReplicaClient(boost::asio::io_service *io_service, const std::string &ip, int port, bool is_use_long_conn=false)
void Push(std::unique_ptr< T > data)
std::unique_ptr< T > Pop(int timeout_ms=100)