Asynchronous Reads for Dirmonitor (#930)

Change dirmonitor reads to be synchronous, in a secondary thread.
This commit is contained in:
Adam
2022-04-24 13:40:58 -04:00
committed by GitHub
parent c112bd8d7c
commit 97174706fe
8 changed files with 190 additions and 195 deletions
+32 -37
View File
@@ -1,58 +1,53 @@
#include <sys/inotify.h>
#include <limits.h>
#include <unistd.h>
#include <sys/select.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
struct dirmonitor {
struct dirmonitor_internal {
int fd;
// a pipe is used to wake the thread in case of exit
int sig[2];
};
struct dirmonitor* init_dirmonitor_inotify() {
struct dirmonitor* monitor = calloc(sizeof(struct dirmonitor), 1);
struct dirmonitor_internal* init_dirmonitor() {
struct dirmonitor_internal* monitor = calloc(sizeof(struct dirmonitor_internal), 1);
monitor->fd = inotify_init();
fcntl(monitor->fd, F_SETFL, O_NONBLOCK);
pipe(monitor->sig);
return monitor;
}
void deinit_dirmonitor_inotify(struct dirmonitor* monitor) {
void deinit_dirmonitor(struct dirmonitor_internal* monitor) {
close(monitor->sig[0]);
close(monitor->sig[1]);
close(monitor->fd);
free(monitor);
}
int check_dirmonitor_inotify(struct dirmonitor* monitor, int (*change_callback)(int, const char*, void*), void* data) {
char buf[PATH_MAX + sizeof(struct inotify_event)];
ssize_t offset = 0;
while (1) {
ssize_t len = read(monitor->fd, &buf[offset], sizeof(buf) - offset);
if (len == -1 && errno != EAGAIN) {
return errno;
}
if (len <= 0) {
return 0;
}
while (len > sizeof(struct inotify_event) && len >= ((struct inotify_event*)buf)->len + sizeof(struct inotify_event)) {
change_callback(((const struct inotify_event *)buf)->wd, NULL, data);
len -= sizeof(struct inotify_event) + ((struct inotify_event*)buf)->len;
memmove(buf, &buf[sizeof(struct inotify_event) + ((struct inotify_event*)buf)->len], len);
offset = len;
}
}
int get_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int length) {
fd_set set;
FD_ZERO(&set);
FD_SET(monitor->fd, &set);
FD_SET(monitor->sig[0], &set);
select(FD_SETSIZE, &set, NULL, NULL, NULL);
return read(monitor->fd, buffer, length);
}
int add_dirmonitor_inotify(struct dirmonitor* monitor, const char* path) {
int translate_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int length, int (*change_callback)(int, const char*, void*), void* data) {
for (struct inotify_event* info = (struct inotify_event*)buffer; (char*)info < buffer + length; info = (struct inotify_event*)((char*)info + sizeof(struct inotify_event)))
change_callback(info->wd, NULL, data);
return 0;
}
int add_dirmonitor(struct dirmonitor_internal* monitor, const char* path) {
return inotify_add_watch(monitor->fd, path, IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO);
}
void remove_dirmonitor_inotify(struct dirmonitor* monitor, int fd) {
void remove_dirmonitor(struct dirmonitor_internal* monitor, int fd) {
inotify_rm_watch(monitor->fd, fd);
}
}