140 lines
4.4 KiB
C++
140 lines
4.4 KiB
C++
#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();
|
|
|
|
// Helper for processing connection I/O (shared between accept and network
|
|
// threads)
|
|
bool process_connection_io(std::unique_ptr<Connection> &conn, int events);
|
|
|
|
/**
|
|
* 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;
|
|
}; |