Ejemplo n.º 1
0
		void
		redis_connection::connect(const std::string &host, std::size_t port,
		                          const disconnection_handler_t &client_disconnection_handler,
		                          const reply_callback_t &client_reply_callback,
		                          std::uint32_t timeout_ms) {
			try {
				__CPP_REDIS_LOG(debug, "cpp_redis::network::redis_connection attempts to connect");

/**
 * connect client
 */
				m_client->connect(host, (uint32_t) port, timeout_ms);
				m_client->set_on_disconnection_handler(std::bind(&redis_connection::tcp_client_disconnection_handler, this));

/**
 * start to read asynchronously
 */
				tcp_client_iface::read_request request = {__CPP_REDIS_READ_SIZE,
				                                          std::bind(&redis_connection::tcp_client_receive_handler, this,
				                                                    std::placeholders::_1)};
				m_client->async_read(request);

				__CPP_REDIS_LOG(debug, "cpp_redis::network::redis_connection connected");
			}
			catch (const std::exception &e) {
				__CPP_REDIS_LOG(error, std::string("cpp_redis::network::redis_connection ") + e.what());
				throw redis_error(e.what());
			}

			m_reply_callback = client_reply_callback;
			m_disconnection_handler = client_disconnection_handler;
		}
Ejemplo n.º 2
0
void
tcp_client::connect(const std::string& host, unsigned int port,
                    const disconnection_handler_t& disconnection_handler,
                    const receive_handler_t& receive_handler)
{
  if (m_is_connected)
    return ;

  //! create the socket
  m_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (m_fd < 0)
      throw redis_error("Can't open a socket");

  //! get the server's DNS entry
  struct hostent *server = gethostbyname(host.c_str());
  if (not server)
    throw redis_error("No such host: " + host);

  //! build the server's Internet address
  struct sockaddr_in server_addr;
  std::memset(&server_addr, 0, sizeof(server_addr));
  std::memcpy(server->h_addr, &server_addr.sin_addr.s_addr, server->h_length);
  server_addr.sin_port = htons(port);
  server_addr.sin_family = AF_INET;

  //! create a connection with the server
  if (::connect(m_fd, reinterpret_cast<const struct sockaddr *>(&server_addr), sizeof(server_addr)) < 0)
    throw redis_error("Fail to connect to " + host + ":" + std::to_string(port));

  //! add fd to the io_service and set the disconnection & recv handlers
  m_disconnection_handler = disconnection_handler;
  m_receive_handler = receive_handler;
  m_io_service.track(m_fd, std::bind(&tcp_client::io_service_disconnection_handler, this, std::placeholders::_1));
  m_is_connected = true;

  //! start async read
  async_read();
}
Ejemplo n.º 3
0
void
tcp_client::connect(const std::string& host, unsigned int port) {
    if (m_is_connected)
        throw redis_error("Already connected");

    std::condition_variable conn_cond_var;

    //! resolve host name
    boost::asio::ip::tcp::resolver resolver(m_io_service.get());
    boost::asio::ip::tcp::resolver::query query(host, std::to_string(port));
    boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
    boost::asio::ip::tcp::endpoint endpoint = iter->endpoint();

    //! async connect
    std::atomic_bool is_notified(false);
    m_socket.async_connect(endpoint, [&](boost::system::error_code error) {
        if (not error) {
            m_is_connected = true;
            async_read();
        }

        is_notified = true;
        conn_cond_var.notify_one();
    });

    //! start loop and wait for async connect result
    std::mutex conn_mutex;
    std::unique_lock<std::mutex> lock(conn_mutex);
    m_io_service.run();

    if (not is_notified)
      conn_cond_var.wait(lock);

    if (not m_is_connected)
        throw redis_error("Fail to connect to " + host + ":" + std::to_string(port));
}
Ejemplo n.º 4
0
bool
array_builder::fetch_array_size(std::string& buffer) {
    if (m_int_builder.reply_ready())
        return true;

    m_int_builder << buffer;
    if (not m_int_builder.reply_ready())
        return false;

    int size = m_int_builder.get_integer();
    if (size < 0)
        throw redis_error("Invalid array size");
    else if (size == 0)
        m_reply_ready = true;

    m_array_size = size;

    return true;
}
Ejemplo n.º 5
0
void
tcp_client::send(const std::vector<char>& buffer) {
  if (not m_is_connected)
    throw redis_error("Not connected");

  if (not buffer.size())
    return ;

  std::lock_guard<std::mutex> lock(m_write_buffer_mutex);

  bool bytes_in_buffer = m_write_buffer.size() > 0;

  //! concat buffer
  m_write_buffer.insert(m_write_buffer.end(), buffer.begin(), buffer.end());

  //! if there were already bytes in buffer, simply return
  //! async_write callback will process the new buffer
  if (bytes_in_buffer)
    return ;

  async_write();
}
Ejemplo n.º 6
0
void
tcp_client::disconnect(void) {
    if (not m_is_connected)
        throw redis_error("Not connected");

    m_is_connected = false;

    std::mutex close_socket_mutex;
    std::condition_variable close_socket_cond_var;
    std::unique_lock<std::mutex> lock(close_socket_mutex);

    std::atomic_bool is_notified(false);
    m_io_service.post([this, &close_socket_cond_var, &is_notified]() {
        m_socket.close();

        is_notified = true;
        close_socket_cond_var.notify_one();
    });

    if (not is_notified)
      close_socket_cond_var.wait(lock);
}
Ejemplo n.º 7
0
		/**
		 * commit pipelined transaction
		 */
		redis_connection &
		redis_connection::commit() {
			std::lock_guard<std::mutex> lock(m_buffer_mutex);

			/**
			 * ensure buffer is cleared
			 */
			__CPP_REDIS_LOG(debug, "cpp_redis::network::redis_connection attempts to send pipelined commands");
			std::string buffer = std::move(m_buffer);

			try {
				tcp_client_iface::write_request request = {std::vector<char>{buffer.begin(), buffer.end()}, nullptr};
				m_client->async_write(request);
			}
			catch (const std::exception &e) {
				__CPP_REDIS_LOG(error, std::string("cpp_redis::network::redis_connection ") + e.what());
				throw redis_error(e.what());
			}

			__CPP_REDIS_LOG(debug, "cpp_redis::network::redis_connection sent pipelined commands");

			return *this;
		}