bug-hurd
[Top][All Lists]
Advanced

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

PATCH 2/2 - monitor backing store changes and update. (was XMLFS for GSo


From: Michael Walker
Subject: PATCH 2/2 - monitor backing store changes and update. (was XMLFS for GSoC)
Date: Mon, 4 Apr 2011 13:37:12 +0100

The below patch monitors the backing store for changes (if it's a
separate file rather than the underlying node) and updates the
presented directory hierarchy when a change is detected.

diff --git a/Makefile b/Makefile
index d646475..747739e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,15 +3,15 @@ CFLAGS = `pkg-config libxml-2.0 --cflags` -ggdb3 -O0
-std=c99 -D_FILE_OFFSET_BIT
 WARN = -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align
-Wwrite-strings -Wmissing-declarations -Wredundant-decls
-Wnested-externs -Winline -Wno-long-long -Winit-self
-Wmissing-prototypes -Wstrict-prototypes -Wconversion -pedantic
 COMPILE=$(CC) $(CFLAGS) $(WARN)
 LDFLAGS = `pkg-config libxml-2.0 --libs` -lnetfs -liohelp -lfshelp -lports
-OBJS = fs.o xmlfs.o xml.o netfs.o fsutils.o
+OBJS = fs.o xmlfs.o xml.o netfs.o fsutils.o monitor.o
 BINARY = xmlfs


 all: $(OBJS)
-       $(CC) -o $(BINARY) $(OBJS) $(LDFLAGS)
+       @$(CC) -o $(BINARY) $(OBJS) $(LDFLAGS)

 .c.o:
-       $(COMPILE) -c $<
+       @$(COMPILE) -c $<

 clean:
-       rm -f *.o core *.obj *~ $(BINARY)
+       @rm -f *.o core *.obj *~ $(BINARY) fs_notify.c
diff --git a/fs.c b/fs.c
index d59385b..09415a5 100644
--- a/fs.c
+++ b/fs.c
@@ -50,7 +50,7 @@ xmlfs_create (file_t fd, struct xmlfs *thexmlfs)

   /* Build an XML tree from the file */
   thexmlfs->doc = xmlReadFd ((int) fd, NULL, NULL, XML_PARSE_NOCDATA);
-
+
   if (thexmlfs->doc == NULL)
     error (-1, 0, "E: (%s, %d): couldn't parse",
           __FILE__, __LINE__);
diff --git a/monitor.c b/monitor.c
new file mode 100644
index 0000000..1a441ca
--- /dev/null
+++ b/monitor.c
@@ -0,0 +1,86 @@
+#include "monitor.h"
+#include "xmlfs.h"
+
+#include <hurd.h>
+#include <hurd/ports.h>
+#include <hurd/fs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <cthreads.h>
+
+static struct port_bucket *bucket;
+static struct port_class  *class;
+
+static void (*handler) (void*);
+static void *params;
+
+int
+notice_change (mach_msg_header_t *inp, mach_msg_header_t *outp)
+{
+  (void) inp;
+  (void) outp;
+
+  DEBUG ("Entering %s\n", __PRETTY_FUNCTION__);
+
+  if (handler != NULL)
+    (*handler) (params);
+
+  return 0;
+}
+
+any_t
+managefork (any_t param)
+{
+  (void) param;
+
+  ports_manage_port_operations_one_thread (bucket, notice_change, 0);
+
+  /* Never reached */
+  return 0;
+}
+
+/* Only works with one file for now. TODO: work with multiple files */
+error_t
+set_file_monitor (file_t thefile, void (*thehandler) (void*), void *theparams)
+{
+  mach_port_t notify;
+  error_t err;
+  notice_t noticedata;
+  cthread_t noticethread;
+
+  if (thefile == MACH_PORT_NULL)
+    error (1, 0, "Null file port given\n");
+
+  if (handler != NULL || params != NULL)
+    DEBUG ("NOTICE: Overwrote previous handler.\n");
+
+  handler = thehandler;
+  params  = theparams;
+
+  bucket = ports_create_bucket ();
+  class  = ports_create_class (NULL, NULL);
+
+  DEBUG ("Entering %s\n", __PRETTY_FUNCTION__);
+
+  /* Try to open a port and monitor changes */
+  DEBUG ("INFO: Attempting to open port\n");
+  err = mach_port_allocate (mach_task_self (),
MACH_PORT_RIGHT_RECEIVE, &notify);
+  if (err)
+    return err;
+
+  DEBUG ("INFO: Attempting to start change notifer\n");
+  err = file_notice_changes (thefile, notify, MACH_MSG_TYPE_MAKE_SEND);
+  if (err)
+    return err;
+
+  /* Add to the bucket */
+  DEBUG ("INFO: Attempting to add to bucket\n");
+  err = ports_import_port (class, bucket, notify, sizeof (notice_t),
&noticedata);
+  if (err)
+    return err;
+
+  /* Monitor changes */
+  noticethread = cthread_fork (&managefork, NULL);
+
+  return 0;
+}
diff --git a/monitor.h b/monitor.h
new file mode 100644
index 0000000..0587241
--- /dev/null
+++ b/monitor.h
@@ -0,0 +1,41 @@
+#ifndef __MONITOR_H__
+#define __MONITOR_H__
+
+/* Use GNU extentions */
+#define _GNU_SOURCE 1
+
+#include <hurd.h>
+#include <hurd/ports.h>
+
+typedef struct
+{
+  struct port_info pi;
+
+  int changes;
+  char filename[1024]; /* Hard filename length limit of 1024, TODO:
better solution */
+} notice_t;
+
+/* Called when the monitored file is changed. All parameters are
discarded, and the
+ * handler function is called with the set parameter(s). */
+int
+notice_change (mach_msg_header_t *inp, mach_msg_header_t *outp);
+
+/* Start monitoring for file changes, this should be called by a
separate thread
+ * as it will never return.
+ * Parameter is discarded. */
+any_t
+managefork (any_t param);
+
+/* Start the monitoring. Currently only one file can be monitored.]
+ *
+ * thefile: A previously opened file_t. A filename is not passed, as
this allows the monitoring
+ *          of ports, as well as files.
+ *
+ * thehandler: A function to be called when the file changes.
+ *
+ * theparams: Parameter(s) to be passed to the handler function when called.
+ */
+error_t
+set_file_monitor (file_t thefile, void (*thehandler) (void*), void *theparams);
+
+#endif
diff --git a/xmlfs.c b/xmlfs.c
index bd39dec..da4e5d3 100644
--- a/xmlfs.c
+++ b/xmlfs.c
@@ -20,6 +20,7 @@
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 */

+#include "monitor.h"
 #include "xmlfs.h"
 #include "version.h"

@@ -75,13 +76,30 @@ error_t parse_opt (int key, char *arg, struct
argp_state *state)
     return 0;
 }

+void
+rebuild_xmlfs (void* param)
+{
+  file_t xmlfile;
+  error_t err;
+
+  (void) param;
+
+  DEBUG ("NOTICE: Reloading XML file\n");
+
+  xmlfile = (file_t) open (xmlfilename, O_READ);
+
+  err = xmlfs_create (xmlfile, xmlfs);
+  if (err)
+    error (1, err, "Cannot update filesystem");
+}
+
 int
 main (int argc, char **argv)
 {
-  mach_port_t bootstrap, underlying_node;
+  mach_port_t bootstrap, underlying_node, xmlport;
   io_statbuf_t underlying_stat;
-  file_t xmlfile;
   error_t err;
+  file_t xmlfile;

   xmlfilename = NULL;
   debug = NULL;
@@ -108,10 +126,16 @@ main (int argc, char **argv)
   if (!xmlfilename)
       /* Try to open the underlying node, which is incidently
         our default XML file. */
-    xmlfile = (file_t) openport (underlying_node, O_READ);
+    {
+      xmlfile = (file_t) openport (underlying_node, O_READ);
+      xmlport = MACH_PORT_NULL;
+    }
   else
-    xmlfile = (file_t) open (xmlfilename, O_READ);
-
+    {
+      xmlfile = (file_t) open (xmlfilename, O_READ);
+      xmlport = file_name_lookup (xmlfilename, 0, 0);
+    }
+
   xmlfs = malloc (sizeof (struct xmlfs));

   err = xmlfs_create (xmlfile, xmlfs);
@@ -123,6 +147,16 @@ main (int argc, char **argv)
   if (err)
     error (1, err, "Cannot create filesystem");

+  /* Monitor changes on the underlying XML file */
+  DEBUG ("INFO: Starting file change monitor\n");
+
+  if (xmlport != MACH_PORT_NULL)
+    {
+      err = set_file_monitor (xmlport, &rebuild_xmlfs, NULL);
+      if (err)
+        error (1, err, "Cannot start file change monitor\n");
+    }
+
   DEBUG ("INFO: Entering main loop\n");

   netfs_server_loop ();
diff --git a/xmlfs.h b/xmlfs.h
index d47613e..fa5aeb2 100644
--- a/xmlfs.h
+++ b/xmlfs.h
@@ -62,6 +62,9 @@ extern struct xmlfs *xmlfs;

 error_t xmlfs_create (file_t, struct xmlfs *);

+/* Rebuild the XMLFS data structure */
+void rebuild_xmlfs (void* param);
+
 /* Parse an option from the argv array */
 error_t parse_opt (int key, char *arg, struct argp_state *state);


-- 
Michael Walker (http://www.barrucadu.co.uk)

Arch Hurd Developer;      GNU Webmaster;       FSF member #8385
http://www.archhurd.org   http://www.gnu.org   http://www.fsf.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]