Avoid caching file status when they are about to change
* 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.
This commit is contained in:
parent
27113c22f7
commit
440f017658
4 changed files with 41 additions and 19 deletions
|
@ -437,11 +437,14 @@ private static final class CacheEntry
|
|||
/* 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 @@ private static final class CacheEntry
|
|||
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 @@ private static final class CacheEntry
|
|||
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 @@ type is either NULL (in which case id should also be NULL) or
|
|||
|
||||
private long[]
|
||||
statDocument1 (String uri, String documentId,
|
||||
CancellationSignal signal)
|
||||
CancellationSignal signal, boolean noCache)
|
||||
{
|
||||
Uri uriObject, tree;
|
||||
String[] projection;
|
||||
|
@ -1266,7 +1270,8 @@ type is either NULL (in which case id should also be NULL) or
|
|||
if (!cursor.moveToFirst ())
|
||||
return null;
|
||||
|
||||
cache = cacheFileStatus (documentId, toplevel, cursor);
|
||||
cache = cacheFileStatus (documentId, toplevel, cursor,
|
||||
noCache);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -1332,18 +1337,22 @@ type is either NULL (in which case id should also be NULL) or
|
|||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1389,11 +1389,14 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
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 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|||
storageThread.start ();
|
||||
}
|
||||
|
||||
return storageThread.statDocument (uri, documentId);
|
||||
return storageThread.statDocument (uri, documentId, noCache);
|
||||
}
|
||||
|
||||
/* Find out whether Emacs has access to the document designated by
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 ();
|
||||
|
|
Loading…
Add table
Reference in a new issue