[vhffs-dev] [1903] now watching files as well as directories to catch "no path" events, i.e. |
[ Thread Index |
Date Index
| More vhffs.org/vhffs-dev Archives
]
Revision: 1903
Author: gradator
Date: 2011-08-21 18:12:56 +0200 (Sun, 21 Aug 2011)
Log Message:
-----------
now watching files as well as directories to catch "no path" events, i.e. file modified through inode reference only, which can happen using NFS when the VFS cache gets cleared
Modified Paths:
--------------
trunk/vhffs-fssync/vhffsfssync_master.c
trunk/vhffs-fssync/vhffsfssync_slave.c
Modified: trunk/vhffs-fssync/vhffsfssync_master.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_master.c 2011-08-04 22:28:25 UTC (rev 1902)
+++ trunk/vhffs-fssync/vhffsfssync_master.c 2011-08-21 16:12:56 UTC (rev 1903)
@@ -1,7 +1,7 @@
/*
* VHFFSFSSYNC: Scalable file system replication over TCP
*
- * Copyright 2008 Sylvain Rochet <gradator@xxxxxxxxxxxx>
+ * Copyright 2008-2011 Sylvain Rochet <gradator@xxxxxxxxxxxx>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,9 +57,9 @@
/* -- inotify stuff -- */
#define VHFFSFSSYNC_BUF_LEN 4096
-#define VHFFSFSSYNC_WATCH_MASK IN_ATTRIB|IN_CREATE|IN_DELETE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR
+#define VHFFSFSSYNC_WATCH_MASK IN_ATTRIB|IN_CREATE|IN_DELETE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DONT_FOLLOW
// Not used yet: IN_DELETE_SELF, IN_MOVE_SELF
-// Use to be used: IN_CLOSE_WRITE
+// Use to be used: IN_CLOSE_WRITE, IN_ONLYDIR
// Will never be used: IN_ACCESS, IN_OPEN, IN_CLOSE_NOWRITE
// each monitor entry is associated with a path, we need to keep it to compute the path
@@ -70,7 +70,7 @@
typedef struct vhffsfssync_watch_ {
int wd;
- char *dirname;
+ char *name;
struct vhffsfssync_watch_ *parent;
} vhffsfssync_watch;
@@ -684,7 +684,7 @@
}
} */
#if DEBUG_NET
- printf(" file: %s, offset = %lld, size = %lld\n", filemsg->file->file_pathname, (long long int)filemsg->file_offset, (long long int)filemsg->file_stat.st_size);
+ printf(" file: %s, offset = %lld, size = %lld\n", filemsg->file->file_pathname, (long long int)filemsg->file_offset, (long long int)filemsg->file->file_stat.st_size);
#endif
/* new chunk */
if(filemsg->file_chunksize < 0) {
@@ -1245,7 +1245,7 @@
curnames = dirnames+a-16;
endnames = dirnames+a;
}
- *(curnames++) = watch->dirname;
+ *(curnames++) = watch->name;
watch = watch->parent;
}
@@ -1262,13 +1262,13 @@
}
-vhffsfssync_watch *vhffsfssync_add_watch(int inotifyfd, vhffsfssync_watch *parent, const char *dirname, uint32_t mask) {
+vhffsfssync_watch *vhffsfssync_add_watch(int inotifyfd, vhffsfssync_watch *parent, const char *name, uint32_t mask) {
int wd;
char *pathname;
vhffsfssync_watch *watch;
- pathname = vhffsfssync_pathname(parent, dirname);
+ pathname = vhffsfssync_pathname(parent, name);
#if DEBUG_INOTIFY
printf("t+ %s\n", pathname);
#endif
@@ -1285,8 +1285,8 @@
if( (watch = g_hash_table_lookup(vhffsfssync_wd_to_watch, &wd)) ) {
// this was already watched, update name and reattach to the new parent
- free(watch->dirname);
- watch->dirname = g_strdup(dirname);
+ free(watch->name);
+ watch->name = g_strdup(name);
watch->parent = parent;
#if DEBUG_INOTIFY
@@ -1298,7 +1298,7 @@
watch = malloc(sizeof(vhffsfssync_watch));
watch->wd = wd;
- watch->dirname = g_strdup(dirname);
+ watch->name = g_strdup(name);
watch->parent = parent;
// _wd = g_new(int, 1);
@@ -1327,7 +1327,7 @@
#endif
g_hash_table_remove(vhffsfssync_wd_to_watch, &watch->wd);
inotify_rm_watch(inotifyfd, watch->wd);
- free(watch->dirname);
+ free(watch->name);
free(watch);
return 0;
}
@@ -1348,13 +1348,42 @@
if(d) {
struct dirent *dir;
while( (dir = readdir(d)) ) {
- if(dir->d_type == DT_UNKNOWN) {
- struct stat st;
- if( !lstat(dir->d_name, &st) && S_ISDIR(st.st_mode) ) dir->d_type = DT_DIR;
+ if( strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..") ) {
+ /* We need to watch every file due to a kernel limitation.
+ * When a file is modified through its inode reference we do not know
+ * the filename hence we do not receive an inotify event about it.
+ * For example this is the case when a file is modified through NFS.
+ */
+
+ /* If the filesystem supports dirent->d_type */
+ if(dir->d_type != DT_UNKNOWN) {
+ if( dir->d_type == DT_REG || dir->d_type == DT_LNK ) {
+ if( !vhffsfssync_add_watch(inotifyfd, watch, dir->d_name, mask) )
+ return NULL;
+ }
+ else if(dir->d_type == DT_DIR) {
+ if( !vhffsfssync_add_watch_recursively(inotifyfd, watch, dir->d_name, mask) )
+ return NULL;
+ }
+ /* we don't need other file types (chr, block, fifo, socket, ...) */
+
+ // If the filesystem does NOT support dirent->d_type
+ } else {
+ struct stat st;
+ if( !lstat(dir->d_name, &st) ) {
+ if( S_ISREG(st.st_mode) || S_ISLNK(st.st_mode) ) {
+ if( !vhffsfssync_add_watch(inotifyfd, watch, dir->d_name, mask) )
+ return NULL;
+ }
+ else if(S_ISDIR(st.st_mode)) {
+ if( !vhffsfssync_add_watch_recursively(inotifyfd, watch, dir->d_name, mask) )
+ return NULL;
+ }
+ /* we don't need other file types (chr, block, fifo, socket, ...) */
+ }
+ }
+
}
- if(dir->d_type == DT_DIR && strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..") ) {
- vhffsfssync_add_watch_recursively(inotifyfd, watch, dir->d_name, mask);
- }
}
closedir(d);
}
@@ -1399,6 +1428,7 @@
#if DEBUG_INOTIFY
printf("==> CREATE %s\n", pathname);
#endif
+ vhffsfssync_add_watch(inotifyfd, watch, filename, VHFFSFSSYNC_WATCH_MASK);
if(!st.st_size) {
vhffsfssync_net_broadcast_event( g_strdup_printf("create%c%s%c%ld%c%d%c%d%c%d%c", '\0', pathname, '\0', st.st_mtime, '\0', st.st_mode&07777, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
@@ -1431,6 +1461,7 @@
#if DEBUG_INOTIFY
printf("==> SYMLINK %s -> %s\n", pathname, linkto);
#endif
+ vhffsfssync_add_watch(inotifyfd, watch, filename, VHFFSFSSYNC_WATCH_MASK);
vhffsfssync_net_broadcast_event( g_strdup_printf("symlink%c%s%c%s%c%ld%c%d%c%d%c", '\0', pathname, '\0', linkto, '\0', st.st_mtime, '\0', st.st_uid, '\0', st.st_gid, '\0') , VHFFSFSSYNC_NET_PRIO_MEDIUM);
vhffsfssync_net_broadcast_event( vhffsfssync_net_parent_attrib(pathname) , VHFFSFSSYNC_NET_PRIO_MEDIUM);
}
@@ -1526,18 +1557,6 @@
#endif
vhffsfssync_manage_event_remove(inotifyfd, watch, event->name);
- // watch deleted, not used
- } else if( event->mask & IN_DELETE_SELF ) {
-#if DEBUG_INOTIFY
- printf("IN_DELETE_SELF\n");
-#endif
- // We don't send REMOVE here because the dir can be deleted before the
- // event was added, in this case the add_watch failed to monitor this dir
- // and we'll not receive a IN_DELETE_SELF for it
- //
- // Anyway, a IN_IGNORE event will be sent, IN_DELETE_SELF is only
- // useful for monitored files, that is not used here.
-
// file modified
} else if( event->mask & IN_MODIFY ) {
#if DEBUG_INOTIFY
@@ -1547,27 +1566,11 @@
#endif
vhffsfssync_net_broadcast_file(pathname);
- // file modified and closed
- } else if( event->mask & IN_CLOSE_WRITE ) {
-#if DEBUG_INOTIFY
- printf("IN_CLOSE_WRITE\n");
- /* we must send the data here */
- printf("==> SEND %s\n", pathname);
-#endif
- vhffsfssync_net_broadcast_file(pathname);
-
- // watch moved, not used
- } else if( event->mask & IN_MOVE_SELF ) {
-#if DEBUG_INOTIFY
- printf("IN_MOVE_SELF\n");
-#endif
- // not needed (we can rely on IN_MOVED_FROM and IN_MOVED_TO)
-
// file/symlink/directory moved
//
// only from: delete the file/symlink/directory
// only to: create the file/symlink/directory
- // both: mv the file/symlink/directory
+ // both: mv the directory, delete and create file/symlink
//
} else if( event->mask & IN_MOVED_FROM ) {
#if DEBUG_INOTIFY
Modified: trunk/vhffs-fssync/vhffsfssync_slave.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_slave.c 2011-08-04 22:28:25 UTC (rev 1902)
+++ trunk/vhffs-fssync/vhffsfssync_slave.c 2011-08-21 16:12:56 UTC (rev 1903)
@@ -1,7 +1,7 @@
/*
* VHFFSFSSYNC: Scalable file system replication over TCP
*
- * Copyright 2008 Sylvain Rochet <gradator@xxxxxxxxxxxx>
+ * Copyright 2008-2011 Sylvain Rochet <gradator@xxxxxxxxxxxx>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by