Fix some issues with transferring conn back to server
This commit is contained in:
@@ -9,18 +9,19 @@
|
|||||||
|
|
||||||
std::unique_ptr<Connection>
|
std::unique_ptr<Connection>
|
||||||
Connection::createForServer(struct sockaddr_storage addr, int fd, int64_t id,
|
Connection::createForServer(struct sockaddr_storage addr, int fd, int64_t id,
|
||||||
ConnectionHandler *handler,
|
size_t epoll_index, ConnectionHandler *handler,
|
||||||
std::weak_ptr<Server> server) {
|
std::weak_ptr<Server> server) {
|
||||||
// Use unique_ptr constructor with private access (friend function)
|
// Use unique_ptr constructor with private access (friend function)
|
||||||
// We can't use make_unique here because constructor is private
|
// We can't use make_unique here because constructor is private
|
||||||
return std::unique_ptr<Connection>(
|
return std::unique_ptr<Connection>(
|
||||||
new Connection(addr, fd, id, handler, server));
|
new Connection(addr, fd, id, epoll_index, handler, server));
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(struct sockaddr_storage addr, int fd, int64_t id,
|
Connection::Connection(struct sockaddr_storage addr, int fd, int64_t id,
|
||||||
ConnectionHandler *handler, std::weak_ptr<Server> server)
|
size_t epoll_index, ConnectionHandler *handler,
|
||||||
: fd_(fd), id_(id), addr_(addr), arena_(), handler_(handler),
|
std::weak_ptr<Server> server)
|
||||||
server_(server) {
|
: fd_(fd), id_(id), epoll_index_(epoll_index), addr_(addr), arena_(),
|
||||||
|
handler_(handler), server_(server) {
|
||||||
if (auto server_ptr = server_.lock()) {
|
if (auto server_ptr = server_.lock()) {
|
||||||
server_ptr->active_connections_.fetch_add(1, std::memory_order_relaxed);
|
server_ptr->active_connections_.fetch_add(1, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -323,7 +323,8 @@ private:
|
|||||||
* @param server Weak reference to the server for safe cleanup
|
* @param server Weak reference to the server for safe cleanup
|
||||||
*/
|
*/
|
||||||
Connection(struct sockaddr_storage addr, int fd, int64_t id,
|
Connection(struct sockaddr_storage addr, int fd, int64_t id,
|
||||||
ConnectionHandler *handler, std::weak_ptr<Server> server);
|
size_t epoll_index, ConnectionHandler *handler,
|
||||||
|
std::weak_ptr<Server> server);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Server-only factory method for creating connections.
|
* @brief Server-only factory method for creating connections.
|
||||||
@@ -345,7 +346,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
static std::unique_ptr<Connection>
|
static std::unique_ptr<Connection>
|
||||||
createForServer(struct sockaddr_storage addr, int fd, int64_t id,
|
createForServer(struct sockaddr_storage addr, int fd, int64_t id,
|
||||||
ConnectionHandler *handler, std::weak_ptr<Server> server);
|
size_t epoll_index, ConnectionHandler *handler,
|
||||||
|
std::weak_ptr<Server> server);
|
||||||
|
|
||||||
// Networking interface - only accessible by Server
|
// Networking interface - only accessible by Server
|
||||||
int readBytes(char *buf, size_t buffer_size);
|
int readBytes(char *buf, size_t buffer_size);
|
||||||
@@ -357,8 +359,10 @@ private:
|
|||||||
int getFd() const { return fd_; }
|
int getFd() const { return fd_; }
|
||||||
bool hasMessages() const { return !messages_.empty(); }
|
bool hasMessages() const { return !messages_.empty(); }
|
||||||
bool shouldClose() const { return closeConnection_; }
|
bool shouldClose() const { return closeConnection_; }
|
||||||
|
size_t getEpollIndex() const { return epoll_index_; }
|
||||||
const int fd_;
|
const int fd_;
|
||||||
const int64_t id_;
|
const int64_t id_;
|
||||||
|
const size_t epoll_index_; // Index of the epoll instance this connection uses
|
||||||
struct sockaddr_storage addr_; // sockaddr_storage handles IPv4/IPv6
|
struct sockaddr_storage addr_; // sockaddr_storage handles IPv4/IPv6
|
||||||
ArenaAllocator arena_;
|
ArenaAllocator arena_;
|
||||||
ConnectionHandler *handler_;
|
ConnectionHandler *handler_;
|
||||||
|
|||||||
@@ -100,16 +100,19 @@ void Server::releaseBackToServer(std::unique_ptr<Connection> connection) {
|
|||||||
|
|
||||||
// Try to get the server from the connection's weak_ptr
|
// Try to get the server from the connection's weak_ptr
|
||||||
if (auto server = connection->server_.lock()) {
|
if (auto server = connection->server_.lock()) {
|
||||||
// Server still exists - release raw pointer and let server take over
|
// Server still exists - pass unique_ptr directly
|
||||||
Connection *raw_conn = connection.release();
|
server->receiveConnectionBack(std::move(connection));
|
||||||
server->receiveConnectionBack(raw_conn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If server is gone, connection will be automatically cleaned up when
|
// If server is gone, connection will be automatically cleaned up when
|
||||||
// unique_ptr destructs
|
// unique_ptr destructs
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::receiveConnectionBack(Connection *connection) {
|
void Server::receiveConnectionBack(std::unique_ptr<Connection> connection) {
|
||||||
|
if (!connection) {
|
||||||
|
return; // Nothing to process
|
||||||
|
}
|
||||||
|
|
||||||
// Re-add the connection to epoll for continued processing
|
// Re-add the connection to epoll for continued processing
|
||||||
struct epoll_event event{};
|
struct epoll_event event{};
|
||||||
|
|
||||||
@@ -120,17 +123,19 @@ void Server::receiveConnectionBack(Connection *connection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connection->tsan_release();
|
connection->tsan_release();
|
||||||
event.data.fd = connection->getFd();
|
int fd = connection->getFd();
|
||||||
|
event.data.fd = fd;
|
||||||
|
|
||||||
// Distribute connections round-robin across epoll instances
|
// Store connection in registry before adding to epoll
|
||||||
size_t epoll_index =
|
// This mirrors the pattern used in process_connection_batch
|
||||||
connection_distribution_counter_.fetch_add(1, std::memory_order_relaxed) %
|
size_t epoll_index = connection->getEpollIndex();
|
||||||
epoll_fds_.size();
|
|
||||||
int epollfd = epoll_fds_[epoll_index];
|
int epollfd = epoll_fds_[epoll_index];
|
||||||
|
connection_registry_.store(fd, std::move(connection));
|
||||||
|
|
||||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connection->getFd(), &event) == -1) {
|
if (epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event) == -1) {
|
||||||
perror("epoll_ctl ADD in receiveConnectionBack");
|
perror("epoll_ctl MOD in receiveConnectionBack");
|
||||||
delete connection; // Clean up on failure
|
// Remove from registry and clean up on failure
|
||||||
|
(void)connection_registry_.remove(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,10 +422,11 @@ void Server::start_io_threads(std::vector<std::thread> &threads) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer ownership from registry to batch processing
|
// Transfer ownership from registry to batch processing
|
||||||
|
size_t epoll_index = thread_id % epoll_fds_.size();
|
||||||
batch[batch_count] = std::unique_ptr<Connection>(new Connection(
|
batch[batch_count] = std::unique_ptr<Connection>(new Connection(
|
||||||
addr, fd,
|
addr, fd,
|
||||||
connection_id_.fetch_add(1, std::memory_order_relaxed),
|
connection_id_.fetch_add(1, std::memory_order_relaxed),
|
||||||
&handler_, weak_from_this()));
|
epoll_index, &handler_, weak_from_this()));
|
||||||
batch_events[batch_count] =
|
batch_events[batch_count] =
|
||||||
EPOLLIN; // New connections always start with read
|
EPOLLIN; // New connections always start with read
|
||||||
batch_count++;
|
batch_count++;
|
||||||
|
|||||||
@@ -142,9 +142,9 @@ private:
|
|||||||
* This method is thread-safe and can be called from any thread.
|
* This method is thread-safe and can be called from any thread.
|
||||||
* The connection will be re-added to the epoll for continued processing.
|
* The connection will be re-added to the epoll for continued processing.
|
||||||
*
|
*
|
||||||
* @param connection Raw pointer to the connection being released back
|
* @param connection Unique pointer to the connection being released back
|
||||||
*/
|
*/
|
||||||
void receiveConnectionBack(Connection *connection);
|
void receiveConnectionBack(std::unique_ptr<Connection> connection);
|
||||||
|
|
||||||
// Make non-copyable and non-movable
|
// Make non-copyable and non-movable
|
||||||
Server(const Server &) = delete;
|
Server(const Server &) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user