xtreemfs/cpp/include/rpc/client_connection.h
2020-09-22 02:25:22 +02:00

162 lines
4.7 KiB
C++

/*
* Copyright (c) 2009-2010 by Bjoern Kolbeck, Zuse Institute Berlin
* 2012 by Michael Berlin, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/
#ifndef CPP_INCLUDE_RPC_CLIENT_CONNECTION_H_
#define CPP_INCLUDE_RPC_CLIENT_CONNECTION_H_
#include <stdint.h>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/system/error_code.hpp>
#include <boost/version.hpp>
#include <queue>
#include <string>
#include "pbrpc/RPC.pb.h"
#include "rpc/abstract_socket_channel.h"
#include "rpc/client_request.h"
#include "rpc/record_marker.h"
#include "rpc/ssl_options.h"
#if (BOOST_VERSION / 100000 > 1) || (BOOST_VERSION / 100 % 1000 > 35)
#include <boost/unordered_map.hpp>
#else
#include <map>
#endif
namespace xtreemfs {
namespace rpc {
// Boost introduced unordered_map in version 1.36 but we need to support
// older versions for Debian 5.
// TODO(bjko): Remove this typedef when support for Debian 5 is dropped.
#if (BOOST_VERSION / 100000 > 1) || (BOOST_VERSION / 100 % 1000 > 35)
typedef boost::unordered_map<int32_t, ClientRequest*> request_map;
#else
typedef std::map<int32_t, ClientRequest*> request_map;
#endif
/** Created by xtreemfs::rpc::Client for every connection.
*
* This class contains the per-connection data.
*
* @remarks Special care has to be taken regarding the boost::asio callback
* functions. In particular, every callback must not access members
* when the error_code equals asio::error::operation_aborted.
* Additionally, no further actions must be taken when
* connection_state_ is set to CLOSED.
*/
class ClientConnection {
public:
struct PendingRequest {
PendingRequest(uint32_t call_id, ClientRequest* rq)
: call_id(call_id), rq(rq) {}
uint32_t call_id;
ClientRequest* rq;
};
ClientConnection(const std::string& server_name,
const std::string& port,
boost::asio::io_service& service,
request_map *request_table,
int32_t connect_timeout_s,
int32_t max_reconnect_interval_s
#ifdef HAS_OPENSSL
,bool use_gridssl,
boost::asio::ssl::context* ssl_context
#endif // HAS_OPENSSL
);
virtual ~ClientConnection();
void DoProcess();
void AddRequest(ClientRequest *request);
void Close(const std::string& error);
void SendError(xtreemfs::pbrpc::POSIXErrno posix_errno,
const std::string& error_message);
void Reset();
boost::posix_time::ptime last_used() const {
return last_used_;
}
std::string GetServerAddress() const {
return server_name_ + ":" + server_port_;
}
private:
enum State {
CONNECTING,
IDLE,
ACTIVE,
CLOSED,
WAIT_FOR_RECONNECT
};
RecordMarker *receive_marker_;
char *receive_hdr_, *receive_msg_, *receive_data_;
char *receive_marker_buffer_;
State connection_state_;
/** Queue of requests which have not been sent out yet. */
std::queue<PendingRequest> requests_;
ClientRequest* current_request_;
const std::string server_name_;
const std::string server_port_;
boost::asio::io_service &service_;
boost::asio::ip::tcp::resolver resolver_;
AbstractSocketChannel* socket_;
boost::asio::ip::tcp::endpoint* endpoint_;
/** Points to the Client's request_table_. */
request_map* request_table_;
boost::asio::deadline_timer timer_;
const int32_t connect_timeout_s_;
const int32_t max_reconnect_interval_s_;
boost::posix_time::ptime next_reconnect_at_;
boost::posix_time::ptime last_connect_was_at_;
int32_t reconnect_interval_s_;
boost::posix_time::ptime last_used_;
#ifdef HAS_OPENSSL
bool use_gridssl_;
boost::asio::ssl::context* ssl_context_;
#endif // HAS_OPENSSL
/** Deletes "socket".
*
* @remark Ownership of "socket" is transferred.
*/
void static DelayedSocketDeletionHandler(AbstractSocketChannel* socket);
void Connect();
void SendRequest();
void ReceiveRequest();
void PostResolve(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
void PostConnect(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
void OnConnectTimeout(const boost::system::error_code& err);
void PostReadMessage(const boost::system::error_code& err);
void PostReadRecordMarker(const boost::system::error_code& err);
void PostWrite(const boost::system::error_code& err,
std::size_t bytes_written);
void DeleteInternalBuffers();
void CreateChannel();
};
} // namespace rpc
} // namespace xtreemfs
#endif // CPP_INCLUDE_RPC_CLIENT_CONNECTION_H_