|
YAACC - UPNP Client and Server
|
LRU cache for SAF (Storage Access Framework) file metadata with background preloading. More...

Classes | |
| interface | DurationExtractor |
| The two ways a duration is read from a file. More... | |
Public Member Functions | |
| SAFMetadata | getMetadata (Uri uri, String name, String providerMimeType, long fileSize) |
| Get complete metadata for a SAF file (duration, MIME type, encoded ID). | |
| SAFMetadata[] | getMetadataBulk (List< SafMetadataRequest > requests) |
The metadata of many files at once (a Browse of a folder): the same results as getMetadata called for each one, in the same order, for the cost of one load check, a lock acquisition per {@value BULK_CHUNK} files instead of one per file and ONE write of what was new (a cold cache of N files is N new entries; the single calls schedule a write after every {@value FLUSH_MAX_CHANGES} of them, and every write rewrites the whole preferences file). | |
| SafBrowseGate | browseGate () |
The gate a Browse of the SAF content opens while it is answered (SafBrowseGate#enter() / exit()); the duration preload and the background duration tasks wait (at most {@value PRELOAD_BACKOFF_MAX_MILLIS} ms each time) between two files while it is open, so a Browse does not compete with them for the provider and the processor. | |
| String | getOrCreateShortId (String uri) |
| Get or create a short ID for a URI. | |
| String | getUriForShortId (String shortId) |
| Get URI for a short ID. | |
| String | guessMimeTypeFromExtension (String filename) |
| String | getDuration (Uri uri) |
| Get duration from cache or extract if not cached. | |
| void | preloadSafDurations () |
| Preload durations for SAF files in background. | |
| void | trimCache () |
| Writes what waits in memory (on the I/O thread, so this returns at once). | |
| void | removeCachedUnder (String treeUri) |
| Forgets the cached metadata (durations) of every file below a SAF tree whose permission was given up, in memory at once and in the stored state on the I/O thread. | |
| void | clearCache () |
| Clear all cached metadata and ID mappings. | |
| void | shutdown () |
| boolean | isPreloading () |
| int | getTotalFilesIndexed () |
| int | getCacheSize () |
Static Public Member Functions | |
| static synchronized SAFCacheManager | getInstance (Context context) |
| static void | flushIfCreated (long waitMillis) |
| Writes the changes that wait in memory, if the manager exists; for the exit of the app, where the timer of the I/O thread would not run any more. | |
LRU cache for SAF (Storage Access Framework) file metadata with background preloading.
Caches duration, MIME type, and encoded IDs for fast browsing.
Persistence: the cache lives in its own preferences file ({@value SafCacheMigration.STORE_NAME}), not in the default preferences (every write rewrites the whole XML file, and the cache was large). Entries of the old place are moved once (SafCacheMigration). Reads are served from memory. Changes are collected in memory (SafCacheWriteBuffer) and committed in one go by the cache's own I/O thread when SafCacheFlushPolicy says so (every {@value FLUSH_MAX_CHANGES} changes or {@value FLUSH_MAX_AGE_MILLIS} ms) and at the end of a preload, with commit() - never on the main thread. The stored state is loaded on that thread too; the constructor does no I/O. A caller on the main thread that comes before the load ended gets metadata computed without the stored state and nothing is persisted for it; other threads wait for the load.
The short id maps are not stored on their own: they are rebuilt from the stored metadata entries (the short id is part of the serialized SAFMetadata), the counter is stored under {@value SafCacheMigration.ID_COUNTER_KEY}. A short id created in the last {@value FLUSH_MAX_AGE_MILLIS} ms before the process is killed is lost; flushIfCreated(long) writes the pending changes when the app exits.
|
static |
Writes the changes that wait in memory, if the manager exists; for the exit of the app, where the timer of the I/O thread would not run any more.
Blocks the caller for at most waitMillis.
| String de.yaacc.util.SAFCacheManager.getDuration | ( | Uri | uri | ) |
Get duration from cache or extract if not cached.
| SAFMetadata de.yaacc.util.SAFCacheManager.getMetadata | ( | Uri | uri, |
| String | name, | ||
| String | providerMimeType, | ||
| long | fileSize ) |
Get complete metadata for a SAF file (duration, MIME type, encoded ID).
Returns cached data if available, otherwise builds it from the given values - without a further query to the document provider. The values come from the directory listing.
| uri | the file's document uri (the cache key) |
| name | its display name, may be null |
| providerMimeType | the mime type the provider reports for it, may be null |
| fileSize | its size in bytes as the provider reports it |
| SAFMetadata[] de.yaacc.util.SAFCacheManager.getMetadataBulk | ( | List< SafMetadataRequest > | requests | ) |
The metadata of many files at once (a Browse of a folder): the same results as getMetadata called for each one, in the same order, for the cost of one load check, a lock acquisition per {@value BULK_CHUNK} files instead of one per file and ONE write of what was new (a cold cache of N files is N new entries; the single calls schedule a write after every {@value FLUSH_MAX_CHANGES} of them, and every write rewrites the whole preferences file).
getMetadata would answer null (no uri) | String de.yaacc.util.SAFCacheManager.getOrCreateShortId | ( | String | uri | ) |
Get or create a short ID for a URI.
On the main thread before the stored state is loaded the id is a transient one that only this process knows ("t1", ...), see SafShortIds.
| String de.yaacc.util.SAFCacheManager.getUriForShortId | ( | String | shortId | ) |
Get URI for a short ID.
Before the stored state is loaded, threads other than the main thread wait for it (a stored id would not be known yet), the main thread gets null.
| void de.yaacc.util.SAFCacheManager.trimCache | ( | ) |
Writes what waits in memory (on the I/O thread, so this returns at once).
The LRU of the memory is not mirrored in the stored state: an entry the LRU dropped stays stored, so the short id of a file beyond the {@value MAX_CACHE_SIZE}th still resolves after a restart (the former trim never removed anything in practice).