Separate Connection, ConnectionHandler, Server

This commit is contained in:
2025-08-19 13:23:18 -04:00
parent addac1b0b7
commit cb322bbb2b
7 changed files with 888 additions and 492 deletions

136
src/server.hpp Normal file
View File

@@ -0,0 +1,136 @@
#pragma once
#include "config.hpp"
#include "connection_handler.hpp"
#include <atomic>
#include <memory>
#include <thread>
#include <vector>
/**
* High-performance multi-threaded server for handling network connections.
*
* The Server class encapsulates all networking logic including:
* - Socket management and configuration
* - Multi-threaded epoll-based I/O multiplexing
* - Connection lifecycle management
* - Graceful shutdown handling
*
* The server uses a configurable thread pool architecture:
* - Accept threads: Handle incoming connections with load balancing
* - Network threads: Process I/O events for established connections
*
* All protocol-specific logic is delegated to the provided ConnectionHandler,
* maintaining clean separation between networking and application logic.
*
* IMPORTANT: Server uses a factory pattern and MUST be created via
* Server::create(). This ensures:
* - Proper shared_ptr semantics for enable_shared_from_this
* - Safe weak_ptr references from Connection objects
* - Prevention of accidental stack allocation that would break safety
* guarantees
*/
class Server : public std::enable_shared_from_this<Server> {
public:
/**
* Factory method to create a Server instance.
*
* This is the only way to create a Server - ensures proper shared_ptr
* semantics and prevents accidental stack allocation that would break
* weak_ptr safety.
*
* @param config Server configuration (threads, ports, limits, etc.)
* @param handler Protocol handler for processing connection data
* @return shared_ptr to the newly created Server
*/
static std::shared_ptr<Server> create(const weaseldb::Config &config,
ConnectionHandler &handler);
/**
* Destructor ensures proper cleanup of all resources.
*/
~Server();
/**
* Start the server and begin accepting connections.
*
* This method:
* - Creates and configures the listen socket
* - Starts all worker threads
* - Blocks until shutdown() is called or an error occurs
*
* @throws std::runtime_error on socket creation or configuration errors
*/
void run();
/**
* Initiate graceful server shutdown.
*
* This method is async-signal-safe and can be called from signal handlers.
* It signals all threads to stop processing and begin cleanup.
*
* The run() method will return after all threads have completed shutdown.
*/
void shutdown();
/**
* Release a connection back to its server for continued processing.
*
* This static method safely returns ownership of a connection back to its
* server. If the server has been destroyed, the connection will be safely
* cleaned up.
*
* This method is thread-safe and can be called from any thread.
*
* @param connection unique_ptr to the connection being released back
*/
static void releaseBackToServer(std::unique_ptr<Connection> connection);
private:
/**
* Private constructor - use create() factory method instead.
*
* @param config Server configuration (threads, ports, limits, etc.)
* @param handler Protocol handler for processing connection data
*/
explicit Server(const weaseldb::Config &config, ConnectionHandler &handler);
const weaseldb::Config &config_;
ConnectionHandler &handler_;
// Thread management
std::vector<std::thread> threads_;
std::atomic<int64_t> connection_id_{0};
// Shutdown coordination
int shutdown_pipe_[2] = {-1, -1};
// Epoll file descriptors
int network_epollfd_ = -1;
int accept_epollfd_ = -1;
int listen_sockfd_ = -1;
// Private helper methods
void setup_shutdown_pipe();
void setup_signal_handling();
int create_listen_socket();
void start_network_threads();
void start_accept_threads();
void cleanup_resources();
/**
* Called internally to return ownership to the server.
*
* This method is thread-safe and can be called from any thread.
* The connection will be re-added to the epoll for continued processing.
*
* @param connection Raw pointer to the connection being released back
*/
void receiveConnectionBack(Connection *connection);
// Make non-copyable and non-movable
Server(const Server &) = delete;
Server &operator=(const Server &) = delete;
Server(Server &&) = delete;
Server &operator=(Server &&) = delete;
};