Skip to content

FSEntry Cache

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

FSEntry Cache

Caching layer for FSEntry objects with invalidation to reduce filesystem lookup overhead.

Overview

The FSEntry Cache is an in-memory caching mechanism within JNode's Virtual File System (VFS) layer that stores FSEntry objects keyed by absolute path. It operates as part of FileSystemAPIImpl, providing a performance optimization that avoids repeated filesystem lookups when accessing the same files or directories multiple times.

Key Components

Class Location Purpose
FSEntryCache fs/src/fs/org/jnode/fs/service/def/FSEntryCache.java Core cache implementation
FileSystemAPIImpl fs/src/fs/org/jnode/fs/service/def/FileSystemAPIImpl.java Cache consumer and coordinator
FSEntry fs/src/fs/org/jnode/fs/FSEntry.java Cached object interface
FSObject fs/src/fs/org/jnode/fs/FSObject.java Base interface with isValid()
FileHandleManager fs/src/fs/org/jnode/fs/service/def/FileHandleManager.java Related manager for file handles

How It Works

Cache Storage

The cache uses a LinkedHashMap with a maximum size of 100 entries:

private final Map<String, FSEntry> entries = new LinkedHashMap<String, FSEntry>() {
    @Override
    protected boolean removeEldestEntry(Entry<String, FSEntry> eldest) {
        return size() > 100;
    }
};

The LinkedHashMap maintains insertion order, and the removeEldestEntry override implements LRU (Least Recently Used) eviction when the cache reaches capacity.

Cache Operations

Get Entry (getEntry(path)):

  1. Look up the path in the cache map
  2. If found, check entry.isValid() to determine if the cached entry is still valid
  3. If valid, return the cached entry
  4. If invalid or not found, return null

Set Entry (setEntry(path, entry)):

  1. Store the FSEntry in the map, keyed by absolute path
  2. Any existing entry for the path is automatically replaced

Remove Entries (removeEntries(rootPathStr)):

  1. Remove the exact path if present
  2. Scan all cached paths and remove any that start with the given root path
  3. This handles directory deletion by invalidating all child entries

Integration with FileSystemAPIImpl

The cache is tightly integrated with path resolution in FileSystemAPIImpl.getEntry():

private FSEntry getEntry(String path) {
    // First check cache
    FSEntry entry = entryCache.getEntry(path);
    if (entry != null) {
        return entry;
    }
    // If not cached, lookup and cache result
    final FSDirectory parentEntry = getParentDirectoryEntry(path);
    if (parentEntry != null) {
        entry = parentEntry.getEntry(stripParentPath(path));
        if (entry != null) {
            entryCache.setEntry(path, entry);
            return entry;
        }
    }
    return null;
}

The cache is also invalidated when:

  • A file is deleted (delete() method calls entryCache.removeEntries(file))
  • A directory is listed (list() caches all child entries)

Validity Checking

Each FSEntry implements FSObject.isValid(), which returns false when the entry has been removed from the filesystem. The cache checks this before returning a cached entry, ensuring stale entries are not served:

public synchronized FSEntry getEntry(String path) {
    final FSEntry entry = entries.get(path);
    if (entry != null) {
        if (entry.isValid()) {
            return entry;
        } else {
            entries.remove(path);
            return null;
        }
    }
    return null;
}

Gotchas

  • Cache size limit: Hard-coded to 100 entries. Very active filesystems may experience cache thrashing.
  • LRU only by insertion order: The LinkedHashMap maintains insertion order, not access order. Recent inserts are preserved over recent accesses.
  • No TTL: There's no time-based expiration—entries remain until evicted by size or invalidated by delete operations.
  • Synchronized operations: All cache methods are synchronized, which may become a contention point in multi-threaded workloads.
  • Path sensitivity: Cache keys are absolute paths. The same file accessed via different path representations (e.g., with or without trailing slash) would be cached separately.

Related Pages

Clone this wiki locally