162 lines
4.7 KiB
C
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_
|
||
|
|