mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
r8695: 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.
This commit is contained in:
parent
217cc66e46
commit
524298b3f3
@ -1196,6 +1196,57 @@ if test x$ac_cv_func_fstat64 = xno ; then
|
||||
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)
|
||||
|
@ -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 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
|
||||
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 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
|
||||
}
|
||||
|
||||
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 ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user