Skip to content

Commit

Permalink
Added routines to monitor file moves inside the watched directory. Ve…
Browse files Browse the repository at this point in the history
…ry dirty implementation
  • Loading branch information
dmatveev committed Jul 24, 2011
1 parent 91a7b63 commit 11c968b
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 22 deletions.
46 changes: 40 additions & 6 deletions worker-sets.c
Expand Up @@ -11,20 +11,31 @@
#include "worker-sets.h"


dep_list *
void
dl_print (dep_list *dl)
{
while (dl != NULL) {
printf ("%lld:%s ", dl->inode, dl->path);
dl = dl->next;
}
printf ("\n");
}

dep_list*
dl_shallow_copy (dep_list *dl)
{
assert (dl != NULL);

dep_list *head = malloc (sizeof (dep_list)); // TODO: check allocation
dep_list *head = calloc (1, sizeof (dep_list)); // TODO: check allocation
dep_list *cp = head;
dep_list *it = dl;

while (it != NULL) {
cp->fd = it->fd;
cp->path = it->path;
cp->inode = it->inode;
if (it->next) {
cp->next = malloc (sizeof (dep_list)); // TODO: check allocation
cp->next = calloc (1, sizeof (dep_list)); // TODO: check allocation
cp = cp->next;
}
it = it->next;
Expand All @@ -33,7 +44,29 @@ dl_shallow_copy (dep_list *dl)
return head;
}

dep_list *
void
dl_shallow_free (dep_list *dl)
{
while (dl != NULL) {
dep_list *ptr = dl;
dl = dl->next;
free (ptr);
}
}

void
dl_free (dep_list *dl)
{
while (dl != NULL) {
dep_list *ptr = dl;
dl = dl->next;

free (ptr->path);
free (ptr);
}
}

dep_list*
dl_listing (const char *path)
{
assert (path != NULL);
Expand All @@ -52,6 +85,7 @@ dl_listing (const char *path)
// TODO: check allocation
dep_list *iter = (prev == NULL) ? head : calloc (1, sizeof (dep_list));
iter->path = strdup (ent->d_name);
iter->inode = ent->d_ino;
iter->next = NULL;
if (prev) {
prev->next = iter;
Expand Down Expand Up @@ -94,7 +128,7 @@ void dl_diff (dep_list **before, dep_list **after)
} else {
*after = after_iter->next;
}
free (after_iter);
free (after_iter); // TODO: dl_free?
break;
}
after_prev = after_iter;
Expand All @@ -106,7 +140,7 @@ void dl_diff (dep_list **before, dep_list **after)
if (matched == 0) {
before_prev = oldptr;
} else {
free (oldptr);
free (oldptr); // TODO: dl_free?
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion worker-sets.h
Expand Up @@ -8,10 +8,14 @@ typedef struct dep_list {
struct dep_list *next;

int fd;
const char *path;
char *path;
ino_t inode;
} dep_list;

void dl_print (dep_list *dl);
dep_list* dl_shallow_copy (dep_list *dl);
void dl_shallow_free (dep_list *dl);
void dl_free (dep_list *dl);
dep_list* dl_listing (const char *path);
void dl_diff (dep_list **before, dep_list **after);

Expand Down
114 changes: 101 additions & 13 deletions worker-thread.c
Expand Up @@ -4,9 +4,11 @@
#include <unistd.h> /* write */
#include <stdlib.h> /* calloc */
#include <stdio.h> /* perror */
#include <string.h> /* memset */

#include "inotify.h"
#include "worker.h"
#include "worker-sets.h"
#include "worker-thread.h"

static uint32_t
Expand Down Expand Up @@ -44,27 +46,115 @@ process_command (worker *wrk)
pthread_barrier_wait (&wrk->cmd.sync);
}

struct inotify_event*
produce_notification (worker *wrk, struct kevent *event)
// TODO: drop unnecessary arguments
void
produce_directory_moves (worker *wrk,
watch *w,
struct kevent *event,
dep_list **was, // TODO: removed
dep_list **now) // TODO: added
{
assert (wrk != NULL);
assert (w != NULL);
assert (event != NULL);
assert (was != NULL);
assert (now != NULL);

dep_list *was_iter = *was;
dep_list *was_prev = NULL;

assert (was_iter != NULL);

while (was_iter != NULL) {
dep_list *now_iter = *now;
dep_list *now_prev = NULL;

int matched = 0;
while (now_iter != NULL) {
if (was_iter->inode == now_iter->inode) {
matched = 1;
printf ("%s was renamed to %s\n", was_iter->path, now_iter->path);

if (was_prev) {
was_prev->next = was_iter->next;
} else {
*was = was_iter->next;
}

if (now_prev) {
now_prev->next = now_iter->next;
} else {
*now = now_iter->next;
}
// TODO: free smt
break;
}
}

dep_list *oldptr = was_iter;
was_iter = was_iter->next;
if (matched == 0) {
was_prev = oldptr;
} else {
free (oldptr); // TODO: dl_free?
}
}
}

// TODO: drop unnecessary arguments
void
produce_directory_diff (worker *wrk, watch *w, struct kevent *event)
{
assert (wrk != NULL);
assert (w != NULL);
assert (event != NULL);

assert (w->type == WATCH_USER);
assert (w->is_directory);

dep_list *was = NULL, *now = NULL;
was = dl_shallow_copy (w->deps);
dl_shallow_free (w->deps);

w->deps = dl_listing (w->filename);
now = dl_shallow_copy (w->deps);

dl_diff (&was, &now);

produce_directory_moves (wrk, w, event, &was, &now);

printf ("Removed:\n");
dl_print (was);
printf ("Added:\n");
dl_print (now);

dl_shallow_free (now);
dl_free (was);
}

void
produce_notifications (worker *wrk, struct kevent *event)
{
assert (wrk != NULL);
assert (event != NULL);

struct inotify_event *ie = calloc (1, sizeof (struct inotify_event));
struct inotify_event ie;
memset (&ie, 0, sizeof (struct inotify_event));

if (wrk->sets.watches[event->udata].type == WATCH_USER) {
if (event->fflags & (NOTE_WRITE | NOTE_EXTEND)) {
// a change has occured in a directory
// calculate diffs here
if (wrk->sets.watches[event->udata].is_directory
&& (event->fflags & (NOTE_WRITE | NOTE_EXTEND))) {
produce_directory_diff (wrk, &wrk->sets.watches[event->udata], event);
}
// TODO: write also name
ie->wd = event->ident; /* remember that watch id is a fd? */
ie.wd = event->ident; /* remember that watch id is a fd? */
} else {
ie->wd = wrk->sets.watches[event->udata].parent->fd;
ie.wd = wrk->sets.watches[event->udata].parent->fd;
}
ie->mask = kqueue_to_inotify (event->fflags);
ie.mask = kqueue_to_inotify (event->fflags);

return ie;
// TODO: EINTR
write (wrk->io[KQUEUE_FD], &ie, sizeof (struct inotify_event));
}

void*
Expand All @@ -89,9 +179,7 @@ worker_thread (void *arg)
if (received.ident == wrk->io[KQUEUE_FD]) {
process_command (wrk);
} else {
struct inotify_event *event = produce_notification (wrk, &received);
write (wrk->io[KQUEUE_FD], event, sizeof (struct inotify_event));
free (event);
produce_notifications (wrk, &received);
}
}
return NULL;
Expand Down
11 changes: 9 additions & 2 deletions worker.c
Expand Up @@ -83,6 +83,7 @@ worker_add_dependencies (worker *wrk,
DIR *dir = opendir (parent->filename);
if (dir != NULL) {
struct dirent *ent;
dep_list *iter = parent->deps;

while ((ent = readdir (dir)) != NULL) {
if (!strcmp (ent->d_name, ".") || !strcmp (ent->d_name, "..")) {
Expand Down Expand Up @@ -111,10 +112,16 @@ worker_add_dependencies (worker *wrk,
wrk->sets.watches[index].parent = parent;

dep_list *entry = calloc (1, sizeof (dep_list));
entry->next = parent->deps;
entry->fd = wrk->sets.events[index].ident;
entry->path = strdup (ent->d_name);
parent->deps = entry;
entry->inode = ent->d_ino;

if (iter) {
iter->next = entry;
} else {
parent->deps = entry;
}
iter = entry;
}
printf ("Watching also on %s\n", full_path);
free (full_path);
Expand Down

0 comments on commit 11c968b

Please sign in to comment.