void
HAService::socketReadyHandler(int tcp_native_fd) {
- std::cout << "HAService::socketReadyHandler - ready socket:" << tcp_native_fd << std::endl;
- // If the socket is not usable/or in a transaction
- // we'll unregister it
- // if (socket bad) /{
- // IfaceMgr::instance().deleteExternalSocket(tcp_native_fd, 0);
- // }
+ // If the socket is ready but does not belong to one of our client's
+ // ongoing transactions we unregister it.
+ if (!client_.isTransactionOngoing(tcp_native_fd)) {
+ IfaceMgr::instance().deleteExternalSocket(tcp_native_fd);
+ }
}
void
/// flagged as ready to read. It is installed by the invocation to
/// register the socket with IfaceMgr made in @ref clientConnectHandler.
///
- /// @todo add logic to determine if the
- /// socket is involved in an ongoing transcation or not. If not, it
- /// will be unregistered from IfaceMgr.
+ /// The handler checks if the ready socket belongs to one our client's
+ /// ongoing transactions. If it does, it simply returns. If it does
+ /// not belong to an ongoing transactions, the socket descriptor is
+ /// unregistered from IfaceMgr.
+ ///
+ /// We do this in case the other peer closed the socket (e.g. idle timeout
+ /// for example), as this will cause the socket /appear ready to read to
+ /// the IfaceMgr::select(). If this happens in while no transcations are
+ /// in progess, we won't have anything to deal with the socket event.
+ /// This causes IfaceMgr::select() to endlessly interrupt on this socket.
///
/// @param tcp_native_fd socket descriptor of the ready socket
void socketReadyHandler(int tcp_native_fd);
/// @return true if transaction has been initiated, false otherwise.
bool isTransactionOngoing() const;
+ /// @brief Checks if a transaction has been initiated over this connection and
+ /// socket descriptor.
+ ///
+ /// @return true if transaction has been initiated, false otherwise.
+ bool isTransactionOngoing(int socket_fd) const;
+
/// @brief Checks and logs if premature transaction timeout is suspected.
///
/// There are cases when the premature timeout occurs, e.g. as a result of
queue_.clear();
}
+ /// @brief Deteremines if there is an ongoing transaction associated
+ /// with a given socket desecriptor.
+ ///
+ /// @param socket_fd socket descriptor to check
+ ///
+ /// @return True if the pool contains a connection which is using the
+ /// given socket descriptor for an ongoing transaction.
+ bool isTransactionOngoing(int socket_fd) {
+ for (auto conns_it = conns_.begin(); conns_it != conns_.end();
+ ++conns_it) {
+ if (conns_it->second->isTransactionOngoing(socket_fd)) {
+ return (true);
+ }
+ }
+ return (false);
+ }
+
private:
/// @brief Holds reference to the IO service.
return (static_cast<bool>(current_request_));
}
+bool
+Connection::isTransactionOngoing(int socket_fd) const {
+ return ((static_cast<bool>(current_request_)) &&
+ (socket_.getNative() == socket_fd));
+}
+
bool
Connection::checkPrematureTimeout(const uint64_t transid) {
// If there is no transaction but the handlers are invoked it means
request_callback, connect_callback, close_callback);
}
+bool
+HttpClient::isTransactionOngoing(int socket_fd) const {
+ return (impl_->conn_pool_->isTransactionOngoing(socket_fd));
+}
+
void
HttpClient::stop() {
impl_->conn_pool_->closeAll();
/// @brief Closes all connections.
void stop();
+ /// @brief Deteremines if a socket is part of an ongoing transaction.
+ ///
+ /// @return True if the given socket descriptor is being used by an
+ /// ongoing transaction
+ bool isTransactionOngoing(int socket_fd) const;
+
private:
/// @brief Pointer to the HTTP client implementation.