[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, ¬ify);
+ 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),
¬icedata);
+ 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
- PATCH 2/2 - monitor backing store changes and update. (was XMLFS for GSoC),
Michael Walker <=