emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 27113c22f77 1/2: Minor improvements to write-region heuristic


From: Po Lu
Subject: master 27113c22f77 1/2: Minor improvements to write-region heuristic
Date: Tue, 8 Aug 2023 04:19:02 -0400 (EDT)

branch: master
commit 27113c22f77b7a409c33b956a1a8d8be2d5bc673
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Minor improvements to write-region heuristic
    
    * src/androidvfs.c (android_saf_stat): Set STATB->st_dev.
    (android_fstat): Likewise.
    (NATIVE_NAME): Seek to start of file after truncation.
    * src/fileio.c (write_region): Use stat instead of open+fstat
    to obtain updated mtime.
---
 src/androidvfs.c | 15 ++++++++++++-
 src/fileio.c     | 68 +++++++++++++++++++++++++++++---------------------------
 2 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/src/androidvfs.c b/src/androidvfs.c
index 93927ccc86b..8e742f8b26f 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -4013,6 +4013,7 @@ android_saf_stat (const char *uri_name, const char 
*id_name,
   memset (statb, 0, sizeof *statb);
   statb->st_size = MAX (0, MIN (TYPE_MAXIMUM (off_t), size));
   statb->st_mode = mode;
+  statb->st_dev = -4;
 #ifdef STAT_TIMESPEC
   STAT_TIMESPEC (statb, st_mtim).tv_sec = mtim / 1000;
   STAT_TIMESPEC (statb, st_mtim).tv_nsec = (mtim % 1000) * 1000000;
@@ -6169,7 +6170,14 @@ NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject 
object)
 JNIEXPORT jboolean JNICALL
 NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd)
 {
-  return ftruncate (fd, 0) != -1;
+  if (ftruncate (fd, 0) < 0)
+    return false;
+
+  /* Reset the file pointer.  */
+  if (lseek (fd, 0, SEEK_SET) < 0)
+    return false;
+
+  return true;
 }
 
 #ifdef __clang__
@@ -6722,6 +6730,11 @@ android_fstat (int fd, struct stat *statb)
   parcel_fd = open_parcel_fds;
   for (; parcel_fd; parcel_fd = parcel_fd->next)
     {
+      if (parcel_fd->fd == fd)
+       /* Set STATB->st_dev to a negative device number, signifying
+          that it's contained within a content provider.  */
+       statb->st_dev = -4;
+
       if (parcel_fd->fd == fd
          && timespec_valid_p (parcel_fd->mtime))
        {
diff --git a/src/fileio.c b/src/fileio.c
index 26b7e193f0a..5d01e10f0ef 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5582,42 +5582,44 @@ write_region (Lisp_Object start, Lisp_Object end, 
Lisp_Object filename,
   if (timespec_valid_p (modtime)
       && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
     {
-      int desc1 = emacs_open (fn, O_WRONLY, 0);
-      if (desc1 >= 0)
+      struct stat st1;
+
+      /* The code below previously tried to open FN O_WRONLY,
+         subsequently calling fstat on the opened file descriptor.
+         This proved inefficient and resulted in FN being truncated
+         under several Android filesystems, and as such has been
+         changed to a call to `stat'.  */
+
+      if (emacs_fstatat (AT_FDCWD, fn, &st1, 0) == 0
+         && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
        {
-         struct stat st1;
-         if (sys_fstat (desc1, &st1) == 0
-             && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
+         /* Use the heuristic if it appears to be valid.  With neither
+            O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
+            file, the time stamp won't change.  Also, some non-POSIX
+            systems don't update an empty file's time stamp when
+            truncating it.  Finally, file systems with 100 ns or worse
+            resolution sometimes seem to have bugs: on a system with ns
+            resolution, checking ns % 100 incorrectly avoids the heuristic
+            1% of the time, but the problem should be temporary as we will
+            try again on the next time stamp.  */
+         bool use_heuristic
+           = ((open_flags & (O_EXCL | O_TRUNC)) != 0
+              && st.st_size != 0
+              && modtime.tv_nsec % 100 != 0);
+
+         struct timespec modtime1 = get_stat_mtime (&st1);
+         if (use_heuristic
+             && timespec_cmp (modtime, modtime1) == 0
+             && st.st_size == st1.st_size)
            {
-             /* Use the heuristic if it appears to be valid.  With neither
-                O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
-                file, the time stamp won't change.  Also, some non-POSIX
-                systems don't update an empty file's time stamp when
-                truncating it.  Finally, file systems with 100 ns or worse
-                resolution sometimes seem to have bugs: on a system with ns
-                resolution, checking ns % 100 incorrectly avoids the heuristic
-                1% of the time, but the problem should be temporary as we will
-                try again on the next time stamp.  */
-             bool use_heuristic
-               = ((open_flags & (O_EXCL | O_TRUNC)) != 0
-                  && st.st_size != 0
-                  && modtime.tv_nsec % 100 != 0);
-
-             struct timespec modtime1 = get_stat_mtime (&st1);
-             if (use_heuristic
-                 && timespec_cmp (modtime, modtime1) == 0
-                 && st.st_size == st1.st_size)
-               {
-                 timestamp_file_system = st.st_dev;
-                 valid_timestamp_file_system = 1;
-               }
-             else
-               {
-                 st.st_size = st1.st_size;
-                 modtime = modtime1;
-               }
+             timestamp_file_system = st.st_dev;
+             valid_timestamp_file_system = 1;
+           }
+         else
+           {
+             st.st_size = st1.st_size;
+             modtime = modtime1;
            }
-         emacs_close (desc1);
        }
     }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]