web: unnecessary refactor before compilation
This commit is contained in:
@@ -5,7 +5,8 @@ const Connection = @import("Connection.zig");
|
||||
const FileDescriptor = @import("FileDescriptor.zig").FileDescriptor;
|
||||
const http = @import("http.zig");
|
||||
const openssl = @import("openssl.zig");
|
||||
const RequestRouter = @import("RequestRouter.zig");
|
||||
const Request = @import("Request.zig");
|
||||
const RequestHandler = @import("RequestHandler.zig");
|
||||
const Worker = @import("Worker.zig");
|
||||
|
||||
const linux = std.os.linux;
|
||||
@@ -16,7 +17,7 @@ address: std.net.Address,
|
||||
ssl_ctx: ?*openssl.SslContext,
|
||||
workers: []Worker,
|
||||
threads: []std.Thread,
|
||||
request_router: RequestRouter,
|
||||
request_handler: RequestHandler,
|
||||
|
||||
connection_queue: std.DoublyLinkedList,
|
||||
// NOTE Connection pool has no need for being doubly-linked, but the queue has
|
||||
@@ -30,11 +31,13 @@ mutex: std.Thread.Mutex,
|
||||
cond_connection_queued: std.Thread.Condition,
|
||||
cond_connection_freed: std.Thread.Condition,
|
||||
|
||||
/// 4 kiB
|
||||
const page_size = 4 * 1024;
|
||||
/// 2 MiB
|
||||
const huge_page_size = 2 * 1024 * 1024;
|
||||
|
||||
pub const Options = struct {
|
||||
request_router: RequestRouter,
|
||||
request_handler: RequestHandler,
|
||||
address: std.net.Address = .initIp4(.{ 127, 0, 0, 1 }, 8000),
|
||||
/// If not `null`, the server will use TLS with the provided OpenSSL
|
||||
/// context.
|
||||
@@ -43,14 +46,25 @@ pub const Options = struct {
|
||||
/// The number of worker threads. If set to `0`, the number of worker
|
||||
/// threads will be equal to the number of logical CPU cores.
|
||||
worker_count: u32 = 0,
|
||||
/// The maximum number of header fields the `Request` object will be able to
|
||||
/// store. An HTTP request will be rejected if it has more header fields
|
||||
/// than the capacity.
|
||||
max_header_fields: u32 = 256,
|
||||
/// The number of 2 MiB pages reserved for a single read buffer. Each worker
|
||||
/// has its own read buffer. An HTTP request (headers and content combined)
|
||||
/// will be rejected if it is larger than the read buffer.
|
||||
read_buffer_pages: u32 = 1,
|
||||
/// The number of 2 MiB pages reserved for a single write buffer. Each
|
||||
/// worker has its own write buffer. An HTTP response (headers and content
|
||||
/// combined) must be larger than the write buffer.
|
||||
write_buffer_pages: u32 = 1,
|
||||
read_buffer_huge_pages: u32 = 1,
|
||||
/// The number of 4 kiB pages reserved for a single header write buffer.
|
||||
/// Each worker has its own header write buffer. The HTTP status line, all
|
||||
/// header fields and the CRLF terminator must all fit in the header write
|
||||
/// buffer.
|
||||
header_write_buffer_pages: u32 = 1,
|
||||
/// The number of 2 MiB pages reserved for a single body write buffer. Each
|
||||
/// worker has its own body write buffer. The HTTP response body must fit
|
||||
/// entirely within the body write buffer. This restriction only applies to
|
||||
/// bodies generated with the body writer and not to bodies sent with
|
||||
/// `sendfile`.
|
||||
body_write_buffer_huge_pages: u32 = 1,
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, options: Options) !Server {
|
||||
@@ -134,35 +148,62 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !Server {
|
||||
));
|
||||
}
|
||||
|
||||
// Allocate write buffer
|
||||
// Allocate header write buffer
|
||||
|
||||
const single_write_buffer_size = @as(usize, options.write_buffer_pages) * huge_page_size;
|
||||
const all_write_buffers_size = worker_count * single_write_buffer_size;
|
||||
const single_header_write_buffer_size = @as(usize, options.header_write_buffer_pages) * page_size;
|
||||
const all_header_write_buffers_size = worker_count * single_header_write_buffer_size;
|
||||
|
||||
const write_buffer_ptr = try errOrPtr(linux.mmap(
|
||||
const header_write_buffer_ptr = try errOrPtr(linux.mmap(
|
||||
null,
|
||||
all_write_buffers_size,
|
||||
all_header_write_buffers_size,
|
||||
linux.PROT.READ | linux.PROT.WRITE,
|
||||
linux.MAP{ .TYPE = .PRIVATE, .ANONYMOUS = true },
|
||||
-1,
|
||||
0,
|
||||
));
|
||||
errdefer _ = linux.munmap(write_buffer_ptr, all_write_buffers_size);
|
||||
_ = linux.madvise(write_buffer_ptr, all_write_buffers_size, linux.MADV.HUGEPAGE);
|
||||
errdefer _ = linux.munmap(header_write_buffer_ptr, all_header_write_buffers_size);
|
||||
|
||||
// Allocate body write buffer
|
||||
|
||||
const single_body_write_buffer_size = @as(usize, options.write_buffer_pages) * huge_page_size;
|
||||
const all_body_write_buffers_size = worker_count * single_body_write_buffer_size;
|
||||
|
||||
const body_write_buffer_ptr = try errOrPtr(linux.mmap(
|
||||
null,
|
||||
all_body_write_buffers_size,
|
||||
linux.PROT.READ | linux.PROT.WRITE,
|
||||
linux.MAP{ .TYPE = .PRIVATE, .ANONYMOUS = true },
|
||||
-1,
|
||||
0,
|
||||
));
|
||||
errdefer _ = linux.munmap(body_write_buffer_ptr, all_body_write_buffers_size);
|
||||
_ = linux.madvise(body_write_buffer_ptr, all_body_write_buffers_size, linux.MADV.HUGEPAGE);
|
||||
|
||||
// Initialize workers
|
||||
|
||||
var workers_initialized: usize = 0;
|
||||
errdefer {
|
||||
for (workers[0..workers_initialized]) |*worker| {
|
||||
worker.deinit(allocator);
|
||||
}
|
||||
}
|
||||
|
||||
for (workers, 0..) |*worker, i| {
|
||||
const read_offset = i * double_single_read_buffer_size;
|
||||
const write_offset = i * single_write_buffer_size;
|
||||
worker.* = .{
|
||||
const header_write_offset = i * single_header_write_buffer_size;
|
||||
const body_write_offset = i * single_body_write_buffer_size;
|
||||
worker.* = try Worker.init(allocator, .{
|
||||
.worker_id = i,
|
||||
|
||||
.max_header_fields = options.max_header_fields,
|
||||
|
||||
.read_buffer_ptr = read_buffer_ptr + read_offset,
|
||||
.read_buffer_size = single_read_buffer_size,
|
||||
.read_head = 0,
|
||||
.read_tail = 0,
|
||||
|
||||
.write_buffer = (write_buffer_ptr + write_offset)[0..single_write_buffer_size],
|
||||
};
|
||||
.header_write_buffer = (header_write_buffer_ptr + header_write_offset)[0..single_header_write_buffer_size],
|
||||
.body_write_buffer = (body_write_buffer_ptr + body_write_offset)[0..single_body_write_buffer_size],
|
||||
});
|
||||
workers_initialized += 1;
|
||||
}
|
||||
|
||||
// Fill connection pool
|
||||
@@ -178,7 +219,7 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !Server {
|
||||
.ssl_ctx = options.ssl_ctx,
|
||||
.workers = workers,
|
||||
.threads = threads,
|
||||
.request_router = options.request_router,
|
||||
.request_handler = options.request_handler,
|
||||
|
||||
.connection_queue = .{},
|
||||
.connection_pool = connection_pool,
|
||||
@@ -191,11 +232,36 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !Server {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Server, allocator: std.mem.Allocator) void {
|
||||
// TODO Deinitialize workers
|
||||
self.fd.close();
|
||||
const worker_count = self.workers.len;
|
||||
|
||||
const single_read_buffers_size = self.workers[0].read_buffer_size;
|
||||
const all_read_buffers_size = worker_count * single_read_buffers_size;
|
||||
const double_all_read_buffers_size = 2 * all_read_buffers_size;
|
||||
|
||||
const single_header_write_buffer_size = self.workers[0].header_write_buffer.len;
|
||||
const all_header_write_buffers_size = worker_count * single_header_write_buffer_size;
|
||||
|
||||
const single_body_write_buffer_size = self.workers[0].body_write_buffer.len;
|
||||
const all_body_write_buffers_size = worker_count * single_body_write_buffer_size;
|
||||
|
||||
const read_buffer_ptr = self.workers[0].read_buffer_ptr;
|
||||
const header_write_buffer_ptr = self.workers[0].header_write_buffer.ptr;
|
||||
const body_write_buffer_ptr = self.workers[0].body_write_buffer.ptr;
|
||||
|
||||
for (self.workers) |*worker| {
|
||||
worker.deinit(allocator);
|
||||
}
|
||||
|
||||
_ = linux.munmap(body_write_buffer_ptr, all_body_write_buffers_size);
|
||||
_ = linux.munmap(header_write_buffer_ptr, all_header_write_buffers_size);
|
||||
_ = linux.munmap(read_buffer_ptr, double_all_read_buffers_size);
|
||||
|
||||
allocator.free(self.threads);
|
||||
allocator.free(self.connection_buffer);
|
||||
allocator.free(self.workers);
|
||||
|
||||
self.fd.close();
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user