Skip to content
Snippets Groups Projects
Commit 9795de2f authored by Henrik (Grubba) Grubbström's avatar Henrik (Grubba) Grubbström
Browse files

System.Inotify, Filesystem.Monitor: Updates to use new Inotify API.

System.Inotify.Instance now inherits _Instance directly. This
simplifies the code and caused some functions to become redundant.

Filesystem.Monitor now has some support for Inotify in blocking mode.
parent d2386411
Branches
Tags
No related merge requests found
......@@ -880,7 +880,6 @@ constant DefaultMonitor = EventStreamMonitor;
#elseif HAVE_INOTIFY
protected System.Inotify._Instance instance;
protected Stdio.File file;
protected string(8bit) inotify_cookie(int wd)
{
......@@ -888,33 +887,19 @@ protected string(8bit) inotify_cookie(int wd)
return sprintf("\0%8c", wd);
}
//! Read callback for events on the Inotify file.
protected void inotify_parse(mixed id, string data)
//! Event callback for Inotify.
protected void inotify_event(int wd, int event, int cookie, string(8bit) path)
{
MON_WERR("inotify_parse(%O, %O)...\n", id, data);
while (sizeof(data)) {
array a;
mixed err = catch {
a = System.Inotify.parse_event(data);
};
if (err) {
// TODO: might have a partial event struct here which gets completed
// by the next call?? maybe add an internal buffer.
MON_WERR("Could not parse inotify event: %s\n", describe_error(err));
return;
}
MON_WERR("### Event: %O\n", a);
string(8bit) cookie = inotify_cookie(a[0]);
string path;
path = a[3];
MON_WERR("inotify_event(%O, %s, %O, %O)...\n",
wd, System.Inotify.describe_mask(event), cookie, path);
string(8bit) icookie = inotify_cookie(wd);
Monitor m;
if((m = monitors[cookie])) {
if (a[1] == System.Inotify.IN_IGNORED) {
if((m = monitors[icookie])) {
if (event == System.Inotify.IN_IGNORED) {
// This Inotify watch has been removed
// (either by us or automatically).
MON_WERR("### Monitor watch descriptor %d is no more.\n", a[0]);
m_delete(monitors, cookie);
MON_WERR("### Monitor watch descriptor %d is no more.\n", wd);
m_delete(monitors, icookie);
}
mixed err = catch {
m->check(0);
......@@ -928,10 +913,6 @@ protected void inotify_parse(mixed id, string data)
check_all();
// No need to look at the other entries if we're going to do
// a full scan.
return;
}
data = data[a[4]..];
}
}
......@@ -981,12 +962,12 @@ protected class InotifyMonitor
if (initial && !instance) {
MON_WERR("Creating Inotify monitor instance.\n");
instance = System.Inotify._Instance();
file = Stdio.File();
if (backend) file->set_backend(backend);
file->assign(instance->fd());
file->set_nonblocking();
file->set_read_callback(inotify_parse);
MON_WERR("File: %O\n", file);
if (backend) instance->set_backend(backend);
instance->set_event_callback(inotify_event);
if (co_id) {
MON_WERR("Turning on nonblocking mode for Inotify.\n");
instance->set_nonblocking();
}
}
catch {
......@@ -1517,12 +1498,8 @@ void set_backend(Pike.Backend|void backend)
}
#endif
#elif HAVE_INOTIFY
if (file) {
if (backend) {
file->set_backend(backend);
} else {
file->set_backend(Pike.DefaultBackend);
}
if (instance) {
instance->set_backend(backend || Pike.DefaultBackend);
}
#endif
if (was_nonblocking) {
......@@ -1541,6 +1518,11 @@ void set_blocking()
else remove_call_out(co_id);
co_id = 0;
}
#if HAVE_INOTIFY
if (instance) {
instance->set_blocking();
}
#endif
}
//! Backend check callback function.
......@@ -1581,6 +1563,11 @@ protected void backend_check()
//! @[set_blocking()], @[check()].
void set_nonblocking(int|void t)
{
#if HAVE_INOTIFY
if (instance) {
instance->set_nonblocking();
}
#endif
if (co_id) return;
// NB: Other stuff than plain files may be used with the monitoring
// system, so the call_out may be needed even with accellerators.
......
......@@ -67,30 +67,6 @@ class FileWatch {
}
}
// The reason for this extra indirection is to remove
// cyclic references from the Instance class to make
// sure inotify instances are destructed when they go out of
// external references. This would not be happening otherwise
// since File objects still have references from the backend.
function parse_fun(mapping watches) {
void parse(mixed id, string data) {
while (sizeof(data)) {
array a = parse_event(data);
object watch;
if (watch = watches[a[0]]) {
if (a[1] == IN_IGNORED) {
m_delete(watches, a[0]);
}
watch->handle_event(a[0], a[1], a[2], a[3]);
}
data = data[a[4]..];
}
};
return parse;
}
//! More convenient interface to inotify(7). Automatically reads events
//! from the inotify file descriptor and parses them.
//!
......@@ -101,16 +77,24 @@ function parse_fun(mapping watches) {
//! @note
//! The number of inotify instances is limited by ulimits.
class Instance {
protected object instance;
protected Stdio.File file;
inherit _Instance;
protected mapping(int:object) watches = ([]);
void event_callback(int wd, int event, int cookie, string path)
{
Watch watch = watches[wd];
if (watch) {
if (event == IN_IGNORED) {
m_delete(watches, wd);
werror("Watch %O (wd: %d) deleted.\n", watch, wd);
}
watch->handle_event(wd, event, cookie, path);
}
}
void create() {
instance = _Instance();
file = Stdio.File();
file->assign(instance->fd());
file->set_nonblocking();
file->set_read_callback(parse_fun(watches));
set_event_callback(event_callback);
set_nonblocking();
}
//! Add a watch for a certain file and a set of events specified by
......@@ -135,8 +119,9 @@ class Instance {
//!
int add_watch(string filename, int mask,
function(int, int, string, mixed ...:void) callback,
mixed ... extra) {
int wd = instance->add_watch(filename, mask);
mixed ... extra)
{
int wd = ::add_watch(filename, mask);
//! @ignore
# if constant(@module@.IN_MASK_ADD)
......@@ -157,24 +142,4 @@ class Instance {
return wd;
}
//! Remove the watch associated with the watch descriptor @expr{wd@}.
void rm_watch(int wd) {
if (!has_index(watches, wd)) {
error("Watch %d does not exist.\n", wd);
}
m_delete(watches, wd);
instance->rm_watch(wd);
}
void destroy() {
file->set_read_callback(0);
/*
* closing the last copy of an inotify fd currently takes a long time (~100ms).
* make sure to close the file first, to allow releasing the interpreter lock
* during the last close call in the instance EXIT handler.
*/
file->close();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment