in src/nodes/caches.rs [76:120]
fn get_or_create(&self, ids: &IdGenerator, underlying_path: &Path, attr: &fs::Metadata,
writable: bool) -> ArcNode {
if attr.is_dir() {
// Directories cannot be cached because they contain entries that are created only
// in memory based on the mappings configuration.
//
// TODO(jmmv): Actually, they *could* be cached, but it's hard. Investigate doing so
// after quantifying how much it may benefit performance.
return Dir::new_mapped(ids.next(), underlying_path, attr, writable);
}
let mut entries = self.entries.lock().unwrap();
if let Some(node) = entries.get(underlying_path) {
if node.writable() == writable {
// We have a match from the cache! Return it immediately.
//
// It is tempting to ensure that the type of the cached node matches the type we
// want to return based on the metadata we have now in `attr`... but doing so does
// not really prevent problems: the type of the underlying file can change at any
// point in time. We could check this here and the type could change immediately
// afterwards behind our backs, so don't bother.
return node.clone();
}
// We had a match... but node writability has changed; recreate the node.
//
// You may wonder why we care about this and not the file type as described above: the
// reason is that the writability property is a setting of the mappings, not a property
// of the underlying files, and thus it's a setting that we fully control and must keep
// correct across reconfigurations or across different mappings of the same files.
info!("Missed node caching opportunity because writability has changed for {:?}",
underlying_path)
}
let node: ArcNode = if attr.is_dir() {
panic!("Directory entries cannot be cached and are handled above");
} else if attr.file_type().is_symlink() {
Symlink::new_mapped(ids.next(), underlying_path, attr, writable)
} else {
File::new_mapped(ids.next(), underlying_path, attr, writable)
};
entries.insert(underlying_path.to_path_buf(), node.clone());
node
}