feat(meta): refactor inode memory tree to id-only model#776
Conversation
| let parent_path = self.build_path_recursive(f.parent_id())?; | ||
| // Note: name is stored in parent's children key, not in InodeFile | ||
| // For now, use inode_id as placeholder | ||
| let name = format!("inode_{}", f.id()); |
There was a problem hiding this comment.
This turns TTL path reconstruction into a placeholder path (/inode_<id>/...) instead of the real namespace path. execute_by_id() still calls filesystem.delete(&path, ...) / filesystem.free(&path, ...), so once this lands, expired inodes will start issuing operations against non-existent paths rather than the actual file or directory. Could we resolve the edge name from the parent DirEntry tree here instead of synthesizing a fake basename?
| return Ok(()); | ||
| } | ||
| let opts = curvine_common::state::MkdirOpts::with_create(true); | ||
| let inp = fs_dir.create_parent_dir(inp, opts)?; |
There was a problem hiding this comment.
create_parent_dir() is a mutating helper from the normal write path, and it eventually goes through create_single_dir(), which calls journal_writer.log_mkdir(...). In other words, this replay path can now generate fresh journal entries while it is applying an old Mkdir / CreateFile record, if an ancestor is missing. That makes recovery semantics self-modifying and can append synthetic operations back into Raft instead of keeping replay side-effect free. Could we use a replay-only parent creation path here (or otherwise suppress journaling) before reusing create_parent_dir()?
Refactor the master metadata tree to separate lightweight navigation from rich metadata storage, solving memory waste from Rust enum variant alignment. Core changes: - Add DirEntry as lightweight tree node struct (id + children) - Add InodeEntry enum: File(id) | Dir(id) - Remove FileEntry variant from InodeView enum - Remove children field from InodeDir (now pure metadata) - InodePath stores rich InodePtr data loaded from InodeStore Tree navigation uses DirEntry (lightweight), business operations use InodeView loaded from InodeStore on demand. Name is stored only in parent's children map key, not duplicated in inode.
Tighten the inode rich-view write path and reuse the latest flushed file blocks when FUSE refreshes concurrent readers. Record the current investigation progress, validation status, and remaining git clone risks in the regression document. Made-with: Cursor
Summary
DirEntrystores only inode id and children,InodeViewholds rich metadataDirEntryRefinInodePathduring resolve to avoid tree re-traversalset_attrandfreeusing DirEntry tree traversalChanges
Core Refactoring
DirEntrystruct: lightweight tree node withentry: InodeEntry(File/Dir id) andchildrenInodeViewenum: rich metadata (File/Dir), name NOT stored insideInodePath: stores bothVec<InodePtr>andVec<DirEntryRef>for efficient navigationBug Fixes
child_nameparameter to store methods (name not in InodeView)is_dir_empty()to use saved entriesadd_child_to_tree()andremove_child_to_tree()to use saved entriesFeatures
unprotected_set_attrusing DirEntry treeunprotected_freeusing DirEntry treefind_entry_by_id()helper for safe tree traversalTest Plan
cargo test -p curvine-server -- --test-threads=1)🤖 Generated with Claude Code