Механизм отслеживания записи в файл (без фиксации изменений в журнал)

This commit is contained in:
Alexander Zhirov 2025-08-30 20:32:44 +03:00
parent 377d5c1f94
commit aa214dcf96
Signed by: alexander
GPG key ID: C8D8BE544A27C511
5 changed files with 383 additions and 446 deletions

View file

@ -2,7 +2,7 @@ module depoll;
import core.sys.linux.epoll;
import core.sys.posix.unistd : close;
import core.stdc.errno : errno, EINTR;
import core.stdc.errno : errno, EINTR, EEXIST;
import core.stdc.string : strerror;
import std.string : fromStringz;
import std.exception : enforce;
@ -26,39 +26,52 @@ class Epoll
}
}
/// Добавление дескриптора с произвольным tag (например, tag=0 для fanotify, tag=pid для pidfd)
void add(int fd, uint tag, uint events = EPOLLIN | EPOLLERR | EPOLLHUP)
{
epoll_event ev;
ev.events = events;
ev.data.u32 = tag;
enforce(epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ev) == 0,
"epoll_ctl ADD: " ~ strerror(errno).fromStringz.idup);
auto rc = epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ev);
if (rc != 0 && errno == EEXIST)
{
// Если уже добавлен — делаем MOD
rc = epoll_ctl(epfd_, EPOLL_CTL_MOD, fd, &ev);
}
enforce(rc == 0, "epoll_ctl ADD/MOD: " ~ strerror(errno).fromStringz.idup);
}
// Опционально: метод для удаления fd
/// Опционально: явное удаление
void remove(int fd)
{
enforce(epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, null) == 0,
"epoll_ctl DEL: " ~ strerror(errno).fromStringz.idup);
auto rc = epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, null);
enforce(rc == 0, "epoll_ctl DEL: " ~ strerror(errno).fromStringz.idup);
}
struct Event
{
uint tag;
uint events;
uint tag; // то самое, что передавали в add()
uint events; // EPOLL* биты
}
/// Возвращает события; пустой массив — если таймаут/прерывание
Event[] wait(int maxevents = 16, int timeout = -1)
{
epoll_event[] evs = new epoll_event[maxevents];
int n = epoll_wait(epfd_, evs.ptr, maxevents, timeout);
if (n <= 0)
int n;
// Терпим EINTR и повторяем
while (true)
{
// Игнорируем EINTR и другие (как в оригинале: continue)
return [];
n = epoll_wait(epfd_, evs.ptr, maxevents, timeout);
if (n < 0 && errno == EINTR)
continue;
break;
}
if (n <= 0)
return [];
Event[] res;
res.reserve(n);
foreach (i; 0 .. n)
{
res ~= Event(evs[i].data.u32, evs[i].events);