[RFC] Simple file monitoring API for GLib



Hi everyone.

A while ago, on IRC, Christian Persch made the request[1] that the
monitoring of the storage file used by the GtkRecentManager could be
overridden by libgnome, so that every application using the GnomeProgram
API would automagically have notifications of file changes using
gnome-vfs, instead of the default implementation which stat()s the file
once in a while[2].

This spawned a more interesting discussion about how to implement a
simple file monitoring API inside GLib; my approach and Christian's were
equivalent, and resolved in a new object with a vtable to be overridden
per-process.  Matthias, instead, suggested using a GSource, and having
the file monitor to play nice with the main loop.  Thus GFileMonitor was
born[3].

* Description
The file monitoring API is as simple as the current API for idle and
timeout sources:

  GSource *g_file_monitor_source_new (const gchar      *uri);
  gint     g_file_monitor_add_full   (gint              priority
                                      const gchar      *uri,
                                      GFileMonitorFunc  function,
                                      gpointer          data,
                                      GDestroyNotify    notify);
  gint     g_file_monitor_add        (const gchar      *uri,
                                      GFileMonitorFunc  function,
                                      gpointer          data);

Where GFileMonitorFunc has the signature:

  typedef gboolean (*GFileMonitorFunc) (const gchar *uri,
                                        GFileEvent   event,
                                        gpointer     data);

And works like every other GSourceFunc (continues until you return
FALSE); GFileEvent is an enumeration:

  typedef enum {
    G_FILE_CREATED_EVENT,
    G_FILE_CHANGED_EVENT,
    G_FILE_REMOVED_EVENT,
    G_FILE_UNKNOWN_EVENT
  } GFileEvent;

The default implementation uses stat() for checking for file changes; it
uses a quantum-based timeout delay; that is: the more time passes
between one file event and the next, the more the timeout will be
increased.

The nice part is that the file monitor is "pluggable" - that is, you can
use another file notification mechanism (like gnome-vfs) to actually get
the notification of the changes.  This is done using hooks:

  typedef struct _GFileMonitorHooks GFileMonitorHooks;
  struct _GFileMonitorHooks
  {
    gboolean (*add_monitor)    (const gchar *uri,
                                gpointer     data);
    gboolean (*cancel_monitor) (const gchar *uri,
                                gpointer     data);
    gboolean (*check_uri)      (const gchar *uri,
                                GFileEvent  *event,
                                gpointer     data);
  };

  void g_set_file_monitor_hooks (GFileMonitorHooks *hooks,
                                 gpointer           data);

The add_monitor hook will be invoked before the source created by
g_file_monitor_add() and g_file_monitor_add_full() is attached to the
main loop; the cancel_monitor hook will be invoked if the callback
returns FALSE; the check_uri hook is where the magic happens: it will be
called at each iteration of the main loop, and will be used to check if
uri has changed.  The gnome-vfs implementation (attached to [3]) uses
this hook to check for a flag inside a structure; the flag is set by the
callback invoked by the GnomeVFSMonitor created inside the add_monitor
hook and destroyed inside the cancel_monitor hook.

* Rationale
It's important (*very* important: please don't reply with "you should
use gnome-vfs" - I know that, and you missed the point of this RFC) to
note that this file monitoring is *not* intended to either be more
complicated than this and to replace in any way gnome-vfs; it's useful
only if you can't depend on gnome-vfs, and for monitoring a single,
local file without too much accuracy.  If you need directory monitoring,
more events, efficiency and remote files support, then by all means you
should use gnome-vfs.

* Further improvements
A possible further enhancement would be changing the default
implementation to use i-notify if it's found at compile time, and to
fall back to the stat() implementation if not (or on other platforms
than linux >= 2.6.13, unless they have a native file monitoring API we
could hook into).

Comments?

+++

[1] Bug 336671 - recent file monitoring
    http://bugzilla.gnome.org/show_bug.cgi?id=336671

[2] The current implementation polls the file for changes twice per 
    second, actually reading the file only if its mtime has changed.

[3] Bug 340746 - Add a file monitor source
    http://bugzilla.gnome.org/show_bug.cgi?id=340746

-- 
Emmanuele Bassi - <ebassi gmail com>
Log: http://log.emmanuelebassi.net




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]