Permalink
Browse files

Basic implementation. Squashed commit of the following:

commit 023205c
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 24 18:59:49 2011 +0000

    More progress on directory notifications. IN_ATTRIB, IN_MODIFY, IN_MOVED_FROM and IN_MOVED_TO are now supported

commit 11c968b
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 24 15:11:53 2011 +0000

    Added routines to monitor file moves inside the watched directory. Very dirty implementation

commit 91a7b63
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 24 02:01:03 2011 +0000

    Added directory diff implementation + some small refactoring

commit 3dae4a3
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sat Jul 23 14:34:16 2011 +0000

    Introduced dependency watches (they are created when starting monitoring on a directory)

commit a5c1864
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Tue Jul 19 23:04:45 2011 +0000

    Wrote a new test app (actually reused a freely available inotify sample), resolved some TODOs, looks like it works

commit f01a2ba
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 17 21:39:47 2011 +0000

    KISS

commit d003d9d
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 17 14:10:34 2011 +0000

    Decided to make a snaphost of the project before a great simplifying and
    refactory

commit 4361d41
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sat Jul 16 15:36:38 2011 +0000

    Implenentation continued: resolved some TODOs, added some new ones,
    implemented add/edit command processing in the kqueue thread

commit 999dd9b
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Fri Jul 15 00:26:36 2011 +0000

    Implementation continued...

commit 883e6f6
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Mon Jul 11 22:57:31 2011 +0000

    Implementation continued

commit d71922b
Author: Dmitry Matveev <me@dmitrymatveev.co.uk>
Date:   Sun Jul 10 23:33:48 2011 +0000

    Started working on a core implementation. Just an interim commit (one of the few)
  • Loading branch information...
dmatveev committed Jul 24, 2011
1 parent fad0d75 commit 0d54d278256e560d812afa26f387893179324f0c
Showing with 1,256 additions and 0 deletions.
  1. +29 −0 Makefile
  2. +121 −0 controller.c
  3. +73 −0 inotify.h
  4. +133 −0 test.c
  5. +309 −0 worker-sets.c
  6. +56 −0 worker-sets.h
  7. +262 −0 worker-thread.c
  8. +6 −0 worker-thread.h
  9. +209 −0 worker.c
  10. +58 −0 worker.h
View
@@ -0,0 +1,29 @@
+APP=test
+APP_CFLAGS=-O2 -Wall -ggdb
+APP_LDFLAGS=-lpthread
+
+CC=gcc
+COBJ=$(CC) $(APP_CFLAGS) -c
+
+OBJS=worker-sets.o worker-thread.o worker.o controller.o test.o
+
+test: $(OBJS)
+ $(CC) $(OBJS) $(APP_LDFLAGS) -o $(APP)
+
+worker-sets.o: worker-sets.c
+ $(COBJ) worker-sets.c
+
+worker-thread.o: worker-thread.c
+ $(COBJ) worker-thread.c
+
+worker.o: worker.c
+ $(COBJ) worker.c
+
+controller.o: controller.c
+ $(COBJ) controller.c
+
+test.o: test.c
+ $(COBJ) test.c
+
+clean:
+ rm -f *~ *.o
View
@@ -0,0 +1,121 @@
+#include <sys/event.h>
+#include <stddef.h> /* NULL */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h> /* printf */
+
+#include "worker.h"
+#include "inotify.h"
+
+
+#define WORKER_SZ 100
+static worker* workers[WORKER_SZ] = {NULL};
+static pthread_mutex_t workers_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int
+inotify_init (void) __THROW
+{
+ // TODO: a dynamic structure here
+ pthread_mutex_lock (&workers_mutex);
+ int i;
+ for (i = 0; i < WORKER_SZ; i++) {
+ if (workers[i] == NULL) {
+ worker *wrk = worker_create ();
+ if (wrk != NULL) {
+ workers[i] = wrk;
+ pthread_mutex_unlock (&workers_mutex);
+ return wrk->io[INOTIFY_FD];
+ }
+ }
+ }
+
+ // TODO: errno is set when an original inotify_init fails
+ pthread_mutex_unlock (&workers_mutex);
+ return -1;
+}
+
+int
+inotify_init1 (int flags) __THROW
+{
+ // TODO: implementation
+ return 0;
+}
+
+int
+inotify_add_watch (int fd,
+ const char *name,
+ uint32_t mask) __THROW
+{
+ /* look up for an appropriate thread */
+ pthread_mutex_lock (&workers_mutex);
+
+ int i;
+ for (i = 0; i < WORKER_SZ; i++) {
+ if (workers[i]->io[INOTIFY_FD] == fd) {
+ worker *wrk = workers[i];
+
+ pthread_mutex_lock (&wrk->mutex);
+
+ // TODO: hide these details
+ worker_cmd_reset (&wrk->cmd);
+ wrk->cmd.type = WCMD_ADD;
+ wrk->cmd.add.filename = strdup (name);
+ wrk->cmd.add.mask = mask;
+ pthread_barrier_init (&wrk->cmd.sync, NULL, 2);
+
+ write (wrk->io[INOTIFY_FD], "*", 1); // TODO: EINTR
+ pthread_barrier_wait (&wrk->cmd.sync);
+
+ // TODO: hide these details too
+ pthread_barrier_destroy (&wrk->cmd.sync);
+
+ // TODO: check error here
+ pthread_mutex_unlock (&workers_mutex);
+ return wrk->cmd.retval;
+ }
+ }
+
+ // TODO: unlock workers earlier?
+ pthread_mutex_unlock (&workers_mutex);
+ return -1;
+}
+
+int
+inotify_rm_watch (int fd,
+ int wd) __THROW
+{
+ assert (fd != -1);
+ assert (wd != -1);
+
+ pthread_mutex_lock (&workers_mutex);
+
+ int i;
+ for (i = 0; i < WORKER_SZ; i++) {
+ if (workers[i]->io[INOTIFY_FD] == fd) {
+ worker *wrk = workers[i];
+ pthread_mutex_lock (&wrk->mutex);
+
+ // TODO: hide these details
+ worker_cmd_reset (&wrk->cmd);
+ wrk->cmd.type = WCMD_REMOVE;
+ wrk->cmd.rm_id = fd;
+ pthread_barrier_init (&wrk->cmd.sync, NULL, 2);
+
+ write (wrk->io[INOTIFY_FD], "*", 1); // TODO: EINTR
+ pthread_barrier_wait (&wrk->cmd.sync);
+
+ // TODO: hide these details too
+ pthread_barrier_destroy (&wrk->cmd.sync);
+
+ // TODO: check error here
+ // TODO: unlock workers earlier?
+ pthread_mutex_unlock (&workers_mutex);
+ return -1; // TODO: obtain return value
+ }
+ }
+
+ pthread_mutex_unlock (&workers_mutex);
+ return 0;
+}
View
@@ -0,0 +1,73 @@
+#ifndef __BSD_INOTIFY_H__
+#define __BSD_INOTIFY_H__
+
+#include <stdint.h>
+
+#ifndef __THROW
+ #ifdef __cplusplus
+ #define __THROW throw()
+ #else
+ #define __THROW
+ #endif
+#endif
+
+
+/* Flags for the parameter of inotify_init1. */
+enum {
+ IN_CLOEXEC = 02000000,
+ IN_NONBLOCK = 04000
+};
+
+
+/* Structure describing an inotify event. */
+struct inotify_event
+{
+ int wd; /* Watch descriptor. */
+ uint32_t mask; /* Watch mask. */
+ uint32_t cookie; /* Cookie to synchronize two events. */
+ uint32_t len; /* Length (including NULs) of name. */
+ char name[]; /* Name. */
+};
+
+
+/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */
+#define IN_ACCESS 0x00000001 /* File was accessed. */
+#define IN_MODIFY 0x00000002 /* File was modified. */
+#define IN_ATTRIB 0x00000004 /* Metadata changed. */
+#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */
+#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */
+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
+#define IN_OPEN 0x00000020 /* File was opened. */
+#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */
+#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */
+#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
+#define IN_CREATE 0x00000100 /* Subfile was created. */
+#define IN_DELETE 0x00000200 /* Subfile was deleted. */
+#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */
+#define IN_MOVE_SELF 0x00000800 /* Self was moved. */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility. Apps will get only the
+ * events that they originally wanted. Be sure to add new events here!
+ */
+#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
+ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
+ IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
+
+
+/* Create and initialize inotify-kqueue instance. */
+int inotify_init (void) __THROW;
+
+/* Create and initialize inotify-kqueue instance. */
+int inotify_init1 (int flags) __THROW;
+
+/* Add watch of object NAME to inotify-kqueue instance FD. Notify about
+ events specified by MASK. */
+int inotify_add_watch (int fd, const char *name, uint32_t mask) __THROW;
+
+/* Remove the watch specified by WD from the inotify instance FD. */
+int inotify_rm_watch (int fd, int wd) __THROW;
+
+
+#endif /* __BSD_INOTIFY_H__ */
View
133 test.c
@@ -0,0 +1,133 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "inotify.h"
+
+void get_event (int fd, const char * target);
+void handle_error (int error);
+
+/* ----------------------------------------------------------------- */
+
+int main (int argc, char *argv[])
+{
+ char target[FILENAME_MAX];
+ int fd;
+ int wd; /* watch descriptor */
+
+ if (argc < 2) {
+ fprintf (stderr, "Watching the current directory\n");
+ strcpy (target, ".");
+ }
+ else {
+ fprintf (stderr, "Watching %s\n", argv[1]);
+ strcpy (target, argv[1]);
+ }
+
+ fd = inotify_init();
+ if (fd < 0) {
+ printf("inotify_init failed\n");
+ handle_error (errno);
+ return 1;
+ }
+
+ wd = inotify_add_watch (fd, target, IN_ALL_EVENTS);
+ if (wd < 0) {
+ printf("add_watch failed\n");
+ handle_error (errno);
+ return 1;
+ }
+
+ while (1) {
+ get_event(fd, target);
+ }
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------- */
+/* Allow for 1024 simultanious events */
+#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024)
+
+void get_event (int fd, const char * target)
+{
+ ssize_t len, i = 0;
+ char buff[BUFF_SIZE] = {0};
+
+ len = read (fd, buff, BUFF_SIZE);
+
+ while (i < len) {
+ struct inotify_event *pevent = (struct inotify_event *)&buff[i];
+ char action[81+FILENAME_MAX] = {0};
+
+ if (pevent->len)
+ strcpy (action, pevent->name);
+ else
+ strcpy (action, target);
+
+ if (pevent->mask & IN_ACCESS)
+ strcat(action, " was read");
+ if (pevent->mask & IN_ATTRIB)
+ strcat(action, " Metadata changed");
+ if (pevent->mask & IN_CLOSE_WRITE)
+ strcat(action, " opened for writing was closed");
+ if (pevent->mask & IN_CLOSE_NOWRITE)
+ strcat(action, " not opened for writing was closed");
+ if (pevent->mask & IN_CREATE)
+ strcat(action, " created in watched directory");
+ if (pevent->mask & IN_DELETE)
+ strcat(action, " deleted from watched directory");
+ if (pevent->mask & IN_DELETE_SELF)
+ strcat(action, "Watched file/directory was itself deleted");
+ if (pevent->mask & IN_MODIFY)
+ strcat(action, " was modified");
+ if (pevent->mask & IN_MOVE_SELF)
+ strcat(action, "Watched file/directory was itself moved");
+ if (pevent->mask & IN_MOVED_FROM)
+ strcat(action, " moved out of watched directory");
+ if (pevent->mask & IN_MOVED_TO)
+ strcat(action, " moved into watched directory");
+ if (pevent->mask & IN_OPEN)
+ strcat(action, " was opened");
+
+ /*
+ printf ("wd=%d mask=%d cookie=%d len=%d dir=%s\n",
+ pevent->wd, pevent->mask, pevent->cookie, pevent->len,
+ (pevent->mask & IN_ISDIR)?"yes":"no");
+
+ if (pevent->len) printf ("name=%s\n", pevent->name);
+ */
+
+ printf ("%s [%s]\n", action, pevent->name);
+
+ i += sizeof(struct inotify_event) + pevent->len;
+
+ }
+
+} /* get_event */
+
+/* ----------------------------------------------------------------- */
+
+void handle_error (int error)
+{
+ fprintf (stderr, "Error: %s\n", strerror(error));
+
+} /* handle_error */
+
+/* ----------------------------------------------------------------- */
+
+
+
+
+
+/* #include "inotify.h" */
+
+/* int main (int argc, char *argv[]) { */
+/* int fd = inotify_init(); */
+/* (void) fd; */
+/* return 0; */
+/* } */
Oops, something went wrong.

0 comments on commit 0d54d27

Please sign in to comment.