]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid caching file status when they are about to change
authorPo Lu <luangruo@yahoo.com>
Tue, 8 Aug 2023 08:17:10 +0000 (16:17 +0800)
committerPo Lu <luangruo@yahoo.com>
Tue, 8 Aug 2023 08:17:10 +0000 (16:17 +0800)
* java/org/gnu/emacs/EmacsSafThread.java (EmacsSafThread)
(cacheFileStatus): New argument NO_CACHE.
(cacheDirectoryFromCursor, statDocument1):
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(statDocument): Plumb that argument through each of these wrapper
functions.
* src/android.c (android_init_emacs_service): Adjust JNI
function signatures to agree with statDocument1.
* src/androidvfs.c (android_saf_stat): Plumb that argument
through here.
(android_saf_tree_stat, android_saf_file_open): And don't cache
file status if a write is imminent.

java/org/gnu/emacs/EmacsSafThread.java
java/org/gnu/emacs/EmacsService.java
src/android.c
src/androidvfs.c

index 421e82c5759e64672164e88fa62d7fb8f5045db6..1b62662b4fcaacd0985d572ddf8c81903e36d0de 100644 (file)
@@ -437,11 +437,14 @@ public final class EmacsSafThread extends HandlerThread
   /* Cache file status for DOCUMENTID within TOPLEVEL.  Value is the
      new cache entry.  CURSOR is the cursor from where to retrieve the
      file status, in the form of the columns COLUMN_FLAGS,
-     COLUMN_SIZE, COLUMN_MIME_TYPE and COLUMN_LAST_MODIFIED.  */
+     COLUMN_SIZE, COLUMN_MIME_TYPE and COLUMN_LAST_MODIFIED.
+
+     If NO_CACHE, don't cache the file status; just return the
+     entry.  */
 
   private StatCacheEntry
   cacheFileStatus (String documentId, CacheToplevel toplevel,
-                  Cursor cursor)
+                  Cursor cursor, boolean no_cache)
   {
     StatCacheEntry entry;
     int flagsIndex, columnIndex, typeIndex;
@@ -482,7 +485,8 @@ public final class EmacsSafThread extends HandlerThread
       entry.mtime = cursor.getLong (mtimeIndex);
 
     /* Finally, add this entry to the cache and return.  */
-    toplevel.statCache.put (documentId, entry);
+    if (!no_cache)
+      toplevel.statCache.put (documentId, entry);
     return entry;
   }
 
@@ -546,7 +550,7 @@ public final class EmacsSafThread extends HandlerThread
               directory listing is being requested, it's very likely
               that a series of calls for file status will follow.  */
 
-           cacheFileStatus (id, toplevel, cursor);
+           cacheFileStatus (id, toplevel, cursor, false);
 
            /* If this constituent is a directory, don't cache any
               information about it.  It cannot be cached without
@@ -1217,7 +1221,7 @@ public final class EmacsSafThread extends HandlerThread
 
   private long[]
   statDocument1 (String uri, String documentId,
-                CancellationSignal signal)
+                CancellationSignal signal, boolean noCache)
   {
     Uri uriObject, tree;
     String[] projection;
@@ -1266,7 +1270,8 @@ public final class EmacsSafThread extends HandlerThread
            if (!cursor.moveToFirst ())
              return null;
 
-           cache = cacheFileStatus (documentId, toplevel, cursor);
+           cache = cacheFileStatus (documentId, toplevel, cursor,
+                                    noCache);
          }
        finally
          {
@@ -1332,18 +1337,22 @@ public final class EmacsSafThread extends HandlerThread
      last modification to this file in milliseconds since 00:00,
      January 1st, 1970.
 
+     If NOCACHE, refrain from placing the file status within the
+     status cache.
+
      OperationCanceledException and other typical exceptions may be
      signaled upon receiving async input or other errors.  */
 
   public long[]
-  statDocument (final String uri, final String documentId)
+  statDocument (final String uri, final String documentId,
+               final boolean noCache)
   {
     return (long[]) runObjectFunction (new SafObjectFunction () {
        @Override
        public Object
        runObject (CancellationSignal signal)
        {
-         return statDocument1 (uri, documentId, signal);
+         return statDocument1 (uri, documentId, signal, noCache);
        }
       });
   }
index 14ff2cce98fdb257b3d31710724deb9921d9e9f6..379b1d30edac2084da52ef1a4606e837b9bb467b 100644 (file)
@@ -1389,11 +1389,14 @@ public final class EmacsService extends Service
      last modification to this file in milliseconds since 00:00,
      January 1st, 1970.
 
+     If NOCACHE, refrain from placing the file status within the
+     status cache.
+
      OperationCanceledException and other typical exceptions may be
      signaled upon receiving async input or other errors.  */
 
   public long[]
-  statDocument (String uri, String documentId)
+  statDocument (String uri, String documentId, boolean noCache)
   {
     /* Start the thread used to run SAF requests if it isn't already
        running.  */
@@ -1404,7 +1407,7 @@ public final class EmacsService extends Service
        storageThread.start ();
       }
 
-    return storageThread.statDocument (uri, documentId);
+    return storageThread.statDocument (uri, documentId, noCache);
   }
 
   /* Find out whether Emacs has access to the document designated by
index 7f263bc83d1d50c30015485fda1f8ef5e77ced9b..705ef227df3c5e2703e14ac2b6b906d4274a181b 100644 (file)
@@ -1564,7 +1564,7 @@ android_init_emacs_service (void)
               "(Ljava/lang/String;Ljava/lang/String;)"
               "Ljava/lang/String;");
   FIND_METHOD (stat_document, "statDocument",
-              "(Ljava/lang/String;Ljava/lang/String;)[J");
+              "(Ljava/lang/String;Ljava/lang/String;Z)[J");
   FIND_METHOD (access_document, "accessDocument",
               "(Ljava/lang/String;Ljava/lang/String;Z)I");
   FIND_METHOD (open_document_directory, "openDocumentDirectory",
index 8e742f8b26f9251ea417e7d0d31cff77991c3078..0385e7348c678d908c262f09fb874ef448c36b84 100644 (file)
@@ -3932,12 +3932,15 @@ android_saf_exception_check (int n, ...)
 /* Return file status for the document designated by ID_NAME within
    the document tree identified by URI_NAME.
 
+   If NO_CACHE, don't cache the resulting file status.  Enable this
+   option if the file status is subject to imminent change.
+
    If the file status is available, place it within *STATB and return
    0.  If not, return -1 and set errno to EPERM.  */
 
 static int
 android_saf_stat (const char *uri_name, const char *id_name,
-                 struct stat *statb)
+                 struct stat *statb, bool no_cache)
 {
   jmethodID method;
   jstring uri, id;
@@ -3969,10 +3972,12 @@ android_saf_stat (const char *uri_name, const char *id_name,
   /* Try to retrieve the file status.  */
   method = service_class.stat_document;
   inside_saf_critical_section = true;
-  status = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
-                                                           emacs_service,
-                                                           service_class.class,
-                                                           method, uri, id);
+  status
+    = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+                                                      emacs_service,
+                                                      service_class.class,
+                                                      method, uri, id,
+                                                      (jboolean) no_cache);
   inside_saf_critical_section = false;
 
   /* Check for exceptions and release unneeded local references.  */
@@ -5076,7 +5081,7 @@ android_saf_tree_stat (struct android_vnode *vnode,
   vp = (struct android_saf_tree_vnode *) vnode;
 
   return android_saf_stat (vp->tree_uri, vp->document_id,
-                          statb);
+                          statb, false);
 }
 
 static int
@@ -5716,10 +5721,15 @@ android_saf_file_open (struct android_vnode *vnode, int flags,
   ANDROID_DELETE_LOCAL_REF (descriptor);
 
   /* Try to retrieve the modification time of this file from the
-     content provider.  */
+     content provider.
+
+     Refrain from introducing the file status into the file status
+     cache if FLAGS & O_RDWR or FLAGS & O_WRONLY: the cached file
+     status will contain a size and modification time inconsistent
+     with the result of any modifications that later transpire.  */
 
   if (!android_saf_stat (vp->tree_uri, vp->document_id,
-                        &statb))
+                        &statb, write))
     info->mtime = get_stat_mtime (&statb);
   else
     info->mtime = invalid_timespec ();