svn commit: samba r8694 - in trunk/source: . smbd

jra at samba.org jra at samba.org
Fri Jul 22 01:14:07 GMT 2005


Author: jra
Date: 2005-07-22 01:14:06 +0000 (Fri, 22 Jul 2005)
New Revision: 8694

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8694

Log:
Patch from James Peach for hires timestamps and efficient
notify code. Bugid #2285. The last commit by me on behalf
of James as he will be able to do his own now :-).
Jeremy.

Modified:
   trunk/source/configure.in
   trunk/source/smbd/notify_hash.c


Changeset:
Modified: trunk/source/configure.in
===================================================================
--- trunk/source/configure.in	2005-07-21 22:33:47 UTC (rev 8693)
+++ trunk/source/configure.in	2005-07-22 01:14:06 UTC (rev 8694)
@@ -1197,6 +1197,57 @@
   fi
 fi
 
+#################################################
+# Check whether struct stat has timestamps with sub-second resolution.
+# At least IRIX and Solaris have these.
+#
+# We check that 
+#	all of st_mtim, st_atim and st_ctim exist
+#	all of the members are in fact of type struct timespec
+#
+# There is some conflicting standards weirdness about whether we should use
+# "struct timespec" or "timespec_t". Linux doesn't have timespec_t, so we
+# prefer struct timespec.
+
+AC_CACHE_CHECK([whether struct stat has sub-second timestamps], samba_stat_hires,
+    [
+	AC_TRY_COMPILE(
+	    [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+	    ],
+	    [
+		struct timespec t;
+		struct stat s = {0};
+		t.tv_sec = s.st_mtim.tv_sec;
+		t.tv_nsec = s.st_mtim.tv_nsec;
+		t.tv_sec = s.st_ctim.tv_sec;
+		t.tv_nsec = s.st_ctim.tv_nsec;
+		t.tv_sec = s.st_atim.tv_sec;
+		t.tv_nsec = s.st_atim.tv_nsec;
+	    ],
+	    samba_stat_hires=yes, samba_stat_hires=no)
+    ])
+
+if test x"$samba_stat_hires" = x"yes" ; then
+    AC_DEFINE(HAVE_STAT_ST_MTIM, 1, [whether struct stat contains st_mtim])
+    AC_DEFINE(HAVE_STAT_ST_ATIM, 1, [whether struct stat contains st_atim])
+    AC_DEFINE(HAVE_STAT_ST_CTIM, 1, [whether struct stat contains st_ctim])
+    AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1,
+	    [whether struct stat has sub-second timestamps])
+fi
+
 #####################################
 # we might need the resolv library on some systems
 AC_CHECK_LIB(resolv, dn_expand)

Modified: trunk/source/smbd/notify_hash.c
===================================================================
--- trunk/source/smbd/notify_hash.c	2005-07-21 22:33:47 UTC (rev 8693)
+++ trunk/source/smbd/notify_hash.c	2005-07-22 01:14:06 UTC (rev 8694)
@@ -23,14 +23,28 @@
 
 struct change_data {
 	time_t last_check_time; /* time we last checked this entry */
+#ifdef HAVE_STAT_HIRES_TIMESTAMPS
+	struct timespec modify_time;
+	struct timespec status_time;
+#else
 	time_t modify_time; /* Info from the directory we're monitoring. */ 
 	time_t status_time; /* Info from the directory we're monitoring. */
+#endif
 	time_t total_time; /* Total time of all directory entries - don't care if it wraps. */
 	unsigned int num_entries; /* Zero or the number of files in the directory. */
 	unsigned int mode_sum;
 	unsigned char name_hash[16];
 };
 
+
+#ifdef HAVE_STAT_HIRES_TIMESTAMPS
+/* Compare struct timespec. */
+#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec))
+#else
+/* Compare time_t . */
+#define TIMESTAMP_NEQ(x, y) ((x) != (y))
+#endif
+
 /****************************************************************************
  Create the hash we will use to determine if the contents changed.
 *****************************************************************************/
@@ -52,20 +66,36 @@
 	if(SMB_VFS_STAT(conn,path, &st) == -1)
 		return False;
 
+#ifdef HAVE_STAT_HIRES_TIMESTAMPS
+	data->modify_time = st.st_mtim;
+	data->status_time = st.st_ctim;
+#else
 	data->modify_time = st.st_mtime;
 	data->status_time = st.st_ctime;
+#endif
 
 	if (old_data) {
 		/*
 		 * Shortcut to avoid directory scan if the time
 		 * has changed - we always must return true then.
 		 */
-		if (old_data->modify_time != data->modify_time ||
-			old_data->status_time != data->status_time ) {
+		if (TIMESTAMP_NEQ(old_data->modify_time, data->modify_time) ||
+		    TIMESTAMP_NEQ(old_data->status_time, data->status_time) ) {
 				return True;
 		}
 	}
  
+        if (S_ISDIR(st.st_mode) && 
+            (flags & ~(FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME)) == 0)
+        {
+		/* This is the case of a client wanting to know only when
+		 * the contents of a directory changes. Since any file
+		 * creation, rename or deletion will update the directory
+		 * timestamps, we don't need to create a hash.
+		 */
+                return True;
+        }
+
 	/*
 	 * If we are to watch for changes that are only stored
 	 * in inodes of files, not in the directory inode, we must
@@ -176,8 +206,8 @@
 	}
 
 	if (!notify_hash(conn, path, flags, &data2, data) ||
-	    data2.modify_time != data->modify_time ||
-	    data2.status_time != data->status_time ||
+	    TIMESTAMP_NEQ(data2.modify_time, data->modify_time) ||
+	    TIMESTAMP_NEQ(data2.status_time, data->status_time) ||
 	    data2.total_time != data->total_time ||
 	    data2.num_entries != data->num_entries ||
 		data2.mode_sum != data->mode_sum ||



More information about the samba-cvs mailing list