refactor: move pending_renames so we don't have to re-allocate it all the time

This commit is contained in:
CJ van den Berg 2026-03-08 21:20:20 +01:00
parent e3c093c729
commit 0548953460
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9

View file

@ -188,9 +188,16 @@ const Backend = switch (builtin.os.tag) {
const INotifyBackend = struct { const INotifyBackend = struct {
const watches_recursively = false; const watches_recursively = false;
const PendingRename = struct {
cookie: u32,
path: []u8, // owned
object_type: ObjectType,
};
handler: *Handler, handler: *Handler,
inotify_fd: std.posix.fd_t, inotify_fd: std.posix.fd_t,
watches: std.AutoHashMapUnmanaged(i32, []u8), // wd -> owned path watches: std.AutoHashMapUnmanaged(i32, []u8), // wd -> owned path
pending_renames: std.ArrayListUnmanaged(PendingRename),
// Used only in linux_read_thread mode: // Used only in linux_read_thread mode:
stop_pipe: if (build_options.linux_read_thread) [2]std.posix.fd_t else void, stop_pipe: if (build_options.linux_read_thread) [2]std.posix.fd_t else void,
thread: if (build_options.linux_read_thread) ?std.Thread else void, thread: if (build_options.linux_read_thread) ?std.Thread else void,
@ -212,6 +219,7 @@ const INotifyBackend = struct {
.handler = handler, .handler = handler,
.inotify_fd = inotify_fd, .inotify_fd = inotify_fd,
.watches = .empty, .watches = .empty,
.pending_renames = .empty,
.stop_pipe = stop_pipe, .stop_pipe = stop_pipe,
.thread = null, .thread = null,
}; };
@ -220,6 +228,7 @@ const INotifyBackend = struct {
.handler = handler, .handler = handler,
.inotify_fd = inotify_fd, .inotify_fd = inotify_fd,
.watches = .empty, .watches = .empty,
.pending_renames = .empty,
.stop_pipe = {}, .stop_pipe = {},
.thread = {}, .thread = {},
}; };
@ -237,6 +246,8 @@ const INotifyBackend = struct {
var it = self.watches.iterator(); var it = self.watches.iterator();
while (it.next()) |entry| allocator.free(entry.value_ptr.*); while (it.next()) |entry| allocator.free(entry.value_ptr.*);
self.watches.deinit(allocator); self.watches.deinit(allocator);
for (self.pending_renames.items) |r| allocator.free(r.path);
self.pending_renames.deinit(allocator);
std.posix.close(self.inotify_fd); std.posix.close(self.inotify_fd);
} }
@ -312,22 +323,14 @@ const INotifyBackend = struct {
len: u32, len: u32,
}; };
// A pending MOVED_FROM waiting to be paired with a MOVED_TO by cookie. var buf: [65536]u8 align(@alignOf(InotifyEvent)) = undefined;
const PendingRename = struct {
cookie: u32,
path: []u8, // owned by drain's allocator
object_type: ObjectType,
};
var buf: [4096]u8 align(@alignOf(InotifyEvent)) = undefined;
var pending_renames: std.ArrayListUnmanaged(PendingRename) = .empty;
defer { defer {
// Any unpaired MOVED_FROM means the file was moved out of the watched tree. // Any unpaired MOVED_FROM means the file was moved out of the watched tree.
for (pending_renames.items) |r| { for (self.pending_renames.items) |r| {
self.handler.change(r.path, EventType.deleted, r.object_type) catch {}; self.handler.change(r.path, EventType.deleted, r.object_type) catch {};
allocator.free(r.path); allocator.free(r.path);
} }
pending_renames.deinit(allocator); self.pending_renames.clearRetainingCapacity();
} }
while (true) { while (true) {
@ -358,7 +361,7 @@ const INotifyBackend = struct {
if (ev.mask & IN.MOVED_FROM != 0) { if (ev.mask & IN.MOVED_FROM != 0) {
// Park it, we may receive a paired MOVED_TO with the same cookie. // Park it, we may receive a paired MOVED_TO with the same cookie.
try pending_renames.append(allocator, .{ try self.pending_renames.append(allocator, .{
.cookie = ev.cookie, .cookie = ev.cookie,
.path = try allocator.dupe(u8, full_path), .path = try allocator.dupe(u8, full_path),
.object_type = if (ev.mask & IN.ISDIR != 0) .dir else .file, .object_type = if (ev.mask & IN.ISDIR != 0) .dir else .file,
@ -366,7 +369,7 @@ const INotifyBackend = struct {
} else if (ev.mask & IN.MOVED_TO != 0) { } else if (ev.mask & IN.MOVED_TO != 0) {
// Look for a paired MOVED_FROM. // Look for a paired MOVED_FROM.
var found: ?usize = null; var found: ?usize = null;
for (pending_renames.items, 0..) |r, i| { for (self.pending_renames.items, 0..) |r, i| {
if (r.cookie == ev.cookie) { if (r.cookie == ev.cookie) {
found = i; found = i;
break; break;
@ -374,7 +377,7 @@ const INotifyBackend = struct {
} }
if (found) |i| { if (found) |i| {
// Complete rename pair: emit a single atomic rename message. // Complete rename pair: emit a single atomic rename message.
const r = pending_renames.swapRemove(i); const r = self.pending_renames.swapRemove(i);
defer allocator.free(r.path); defer allocator.free(r.path);
try self.handler.rename(r.path, full_path, r.object_type); try self.handler.rename(r.path, full_path, r.object_type);
} else { } else {