Connection registry

Now we can use leak sanitizer. Yay!
This commit is contained in:
2025-08-21 18:09:36 -04:00
parent 810b5e006d
commit d1b1e6d589
7 changed files with 500 additions and 34 deletions

View File

@@ -0,0 +1,93 @@
#pragma once
#include <cstddef>
#include <memory>
#include <sys/mman.h>
#include <sys/resource.h>
class Connection;
/**
* mmap-based Connection Registry for tracking active connections.
*
* This registry provides a lock-free mechanism for tracking all connections
* owned by the server, indexed by file descriptor. The design uses mmap to
* allocate a large virtual address space efficiently, with physical memory
* allocated on-demand as connections are created.
*
* CRITICAL ORDERING REQUIREMENT:
* All connection cleanup MUST follow this exact sequence:
* 1. Remove from registry: auto conn = registry.remove(fd)
* 2. Delete the connection: unique_ptr destructor handles it automatically
*
* This ordering prevents race conditions between cleanup and fd reuse.
* The unique_ptr interface ensures ownership is always clear and prevents
* double-delete bugs.
*/
class ConnectionRegistry {
public:
/**
* Initialize the connection registry.
* Allocates virtual address space based on RLIMIT_NOFILE.
*
* @throws std::runtime_error if mmap fails or RLIMIT_NOFILE cannot be read
*/
ConnectionRegistry();
/**
* Destructor ensures proper cleanup of mmap'd memory.
*/
~ConnectionRegistry();
/**
* Store a connection in the registry, indexed by its file descriptor.
* Takes ownership of the connection via unique_ptr.
*
* @param fd File descriptor (must be valid and < max_fds_)
* @param connection unique_ptr to the connection (ownership transferred)
*/
void store(int fd, std::unique_ptr<Connection> connection);
/**
* Check if a connection exists in the registry by file descriptor.
*
* @param fd File descriptor
* @return true if connection exists, false otherwise
*/
bool has(int fd) const;
/**
* Remove a connection from the registry and transfer ownership to caller.
* This transfers ownership via unique_ptr move semantics.
*
* @param fd File descriptor
* @return unique_ptr to the connection, or nullptr if not found
*/
std::unique_ptr<Connection> remove(int fd);
/**
* Get the maximum number of file descriptors supported.
*
* @return Maximum file descriptor limit
*/
size_t max_fds() const { return max_fds_; }
/**
* Perform graceful shutdown cleanup.
* Iterates through all registry entries and cleans up any remaining
* connections using the critical ordering: remove -> close -> delete.
*
* This method is called during server shutdown to ensure no connections leak.
*/
virtual void shutdown_cleanup();
// Non-copyable and non-movable
ConnectionRegistry(const ConnectionRegistry &) = delete;
ConnectionRegistry &operator=(const ConnectionRegistry &) = delete;
ConnectionRegistry(ConnectionRegistry &&) = delete;
ConnectionRegistry &operator=(ConnectionRegistry &&) = delete;
private:
Connection **connections_; ///< mmap'd array of raw connection pointers
size_t max_fds_; ///< Maximum file descriptor limit
};