FANNG1 commented on code in PR #5878:
URL: https://github.com/apache/gravitino/pull/5878#discussion_r1889720461


##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -201,6 +246,74 @@ pub(crate) struct OpenedFile {
     pub writer: Option<Box<dyn FileWriter>>,
 }
 
+impl OpenedFile {
+    pub fn new(file_stat: FileStat) -> Self {

Review Comment:
   it's odd to create an open file with file stat



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -190,6 +193,48 @@ pub struct FileStat {
     pub(crate) nlink: u32,
 }
 
+impl FileStat {
+    pub fn new_file_with_path(path: &str, size: u64) -> Self {

Review Comment:
   It's confusing to implement `new_file_xx` in `FileStat`



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;
+        file.map(|x| x.file_name).unwrap_or_else(|_| "".to_string())
+    }
+
+    async fn valid_file_handle_id(&self, file_id: u64, fh: u64) -> Result<()> {
+        let fh_file_id = self
+            .opened_file_manager
+            .get_file(fh)
+            .ok_or(Errno::from(libc::EBADF))?
+            .lock()
+            .await
+            .file_stat
+            .file_id;
+
+        (file_id == fh_file_id)
+            .then_some(())
+            .ok_or(Errno::from(libc::EBADF))
+    }
+
+    async fn stat(&self, file_id: u64) -> Result<FileStat> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut stat = self.fs.stat(&file.file_name).await?;
+        stat.set_file_id(file.parent_file_id, file.file_id);
+        Ok(stat)
+    }
+
+    async fn lookup(&self, parent_file_id: u64, name: &str) -> 
Result<FileStat> {
+        let parent_file = self.get_file_entry(parent_file_id).await?;
+        let mut stat = self.fs.lookup(&parent_file.file_name, name).await?;
+        // fill the file id to file stat
+        self.fill_file_id(&mut stat, parent_file_id).await;
+        Ok(stat)
+    }
+
+    async fn read_dir(&self, file_id: u64) -> Result<Vec<FileStat>> {
+        let file = self.get_file_entry(file_id).await?;

Review Comment:
   please keep the same style, it's `stats` not `files`?



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;
+        file.map(|x| x.file_name).unwrap_or_else(|_| "".to_string())
+    }
+
+    async fn valid_file_handle_id(&self, file_id: u64, fh: u64) -> Result<()> {
+        let fh_file_id = self
+            .opened_file_manager
+            .get_file(fh)
+            .ok_or(Errno::from(libc::EBADF))?
+            .lock()
+            .await
+            .file_stat
+            .file_id;
+
+        (file_id == fh_file_id)
+            .then_some(())
+            .ok_or(Errno::from(libc::EBADF))
+    }
+
+    async fn stat(&self, file_id: u64) -> Result<FileStat> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut stat = self.fs.stat(&file.file_name).await?;
+        stat.set_file_id(file.parent_file_id, file.file_id);
+        Ok(stat)
+    }
+
+    async fn lookup(&self, parent_file_id: u64, name: &str) -> 
Result<FileStat> {
+        let parent_file = self.get_file_entry(parent_file_id).await?;
+        let mut stat = self.fs.lookup(&parent_file.file_name, name).await?;
+        // fill the file id to file stat
+        self.fill_file_id(&mut stat, parent_file_id).await;
+        Ok(stat)
+    }
+
+    async fn read_dir(&self, file_id: u64) -> Result<Vec<FileStat>> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut files = self.fs.read_dir(&file.file_name).await?;
+        for file in files.iter_mut() {
+            self.fill_file_id(file, file.file_id).await;
+        }
+        Ok(files)
+    }
+
+    async fn open_file(&self, file_id: u64, flags: u32) -> Result<FileHandle> {
+        self.open_file_internal(file_id, flags, FileType::RegularFile)
+            .await
+    }
+
+    async fn open_dir(&self, file_id: u64, flags: u32) -> Result<FileHandle> {
+        self.open_file_internal(file_id, flags, FileType::Directory)
+            .await
+    }
+
+    async fn create_file(&self, parent_file_id: u64, name: &str, flags: u32) 
-> Result<FileHandle> {
+        let parent = self.get_file_entry(parent_file_id).await?;
+        let mut file = self
+            .fs
+            .create_file(&parent.file_name, name, OpenFileFlags(flags))
+            .await?;
+
+        file.set_file_id(parent_file_id, self.next_file_id());
+
+        // insert the new file to file entry manager
+        {
+            let mut file_manager = self.file_entry_manager.write().await;
+            file_manager.insert(parent_file_id, file.file_stat.file_id, 
&file.file_stat.path);
+        }
+
+        // put the file to the opened file manager
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+
+    async fn create_dir(&self, parent_file_id: u64, name: &str) -> Result<u64> 
{
+        let parent = self.get_file_entry(parent_file_id).await?;
+        let mut file = self.fs.create_dir(&parent.file_name, name).await?;

Review Comment:
   use stat?



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -201,6 +246,74 @@ pub(crate) struct OpenedFile {
     pub writer: Option<Box<dyn FileWriter>>,
 }
 
+impl OpenedFile {
+    pub fn new(file_stat: FileStat) -> Self {
+        OpenedFile {
+            file_stat: file_stat,
+            handle_id: 0,
+            reader: None,
+            writer: None,
+        }
+    }
+
+    async fn read(&mut self, offset: u64, size: u32) -> Result<Bytes> {
+        let reader = self.reader.as_mut().ok_or(Errno::from(libc::EBADF))?;
+        let result = reader.read(offset, size).await?;
+
+        // update the atime
+        self.file_stat.atime = Timestamp::from(SystemTime::now());
+
+        Ok(result)
+    }
+
+    async fn write(&mut self, offset: u64, data: &[u8]) -> Result<u32> {
+        let writer = self.writer.as_mut().ok_or(Errno::from(libc::EBADF))?;
+        let written = writer.write(offset, data).await?;
+
+        // update the file size ,mtime and atime
+        let end = offset + data.len() as u64;
+        if end > self.file_stat.size {
+            self.file_stat.size = end;
+        }
+        self.file_stat.atime = Timestamp::from(SystemTime::now());
+        self.file_stat.mtime = self.file_stat.atime;
+
+        Ok(written)
+    }
+
+    async fn close(&mut self) -> Result<()> {
+        if let Some(mut reader) = self.reader.take() {
+            reader.close().await?;

Review Comment:
   if close reader raise exception, we'd better try to close writer too.



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;

Review Comment:
   Does `file_name` represent `file_path`?



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;
+        file.map(|x| x.file_name).unwrap_or_else(|_| "".to_string())

Review Comment:
   why not throw an error here?



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;
+        file.map(|x| x.file_name).unwrap_or_else(|_| "".to_string())
+    }
+
+    async fn valid_file_handle_id(&self, file_id: u64, fh: u64) -> Result<()> {
+        let fh_file_id = self
+            .opened_file_manager
+            .get_file(fh)
+            .ok_or(Errno::from(libc::EBADF))?
+            .lock()
+            .await
+            .file_stat
+            .file_id;
+
+        (file_id == fh_file_id)
+            .then_some(())
+            .ok_or(Errno::from(libc::EBADF))
+    }
+
+    async fn stat(&self, file_id: u64) -> Result<FileStat> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut stat = self.fs.stat(&file.file_name).await?;
+        stat.set_file_id(file.parent_file_id, file.file_id);
+        Ok(stat)
+    }
+
+    async fn lookup(&self, parent_file_id: u64, name: &str) -> 
Result<FileStat> {
+        let parent_file = self.get_file_entry(parent_file_id).await?;
+        let mut stat = self.fs.lookup(&parent_file.file_name, name).await?;
+        // fill the file id to file stat
+        self.fill_file_id(&mut stat, parent_file_id).await;

Review Comment:
   `fill_file_id` is confusing, you changed too many things in one function, 
suggest to rewrite  something like
   ```rust
       let id = self.try_update_file_mapping(stat.file_name, 
parent_file_id).await
       stat.file_id = id
   ```



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {

Review Comment:
   please provide an meaningful name



##########
clients/filesystem-fuse/src/filesystem.rs:
##########
@@ -239,3 +352,406 @@ pub trait FileWriter: Sync + Send {
         Ok(())
     }
 }
+
+/// SimpleFileSystem is a simple implementation for the file system.
+/// it is used to manage the file metadata and file handle.
+/// The operations of the file system are implemented by the PathFileSystem.
+/// Note: This class is not use in the production code, it is used for the 
demo and testing
+pub struct SimpleFileSystem<T: PathFileSystem> {
+    /// file entries
+    file_entry_manager: RwLock<FileEntryManager>,
+    /// opened files
+    opened_file_manager: OpenedFileManager,
+    /// inode id generator
+    file_id_generator: AtomicU64,
+
+    /// real filesystem
+    fs: T,
+}
+
+impl<T: PathFileSystem> SimpleFileSystem<T> {
+    const INITIAL_FILE_ID: u64 = 10000;
+    const ROOT_DIR_PARENT_FILE_ID: u64 = 0;
+    const ROOT_DIR_FILE_ID: u64 = 1;
+    const ROOT_DIR_NAME: &'static str = "";
+
+    pub(crate) fn new(fs: T) -> Self {
+        Self {
+            file_entry_manager: RwLock::new(FileEntryManager::new()),
+            opened_file_manager: OpenedFileManager::new(),
+            file_id_generator: AtomicU64::new(Self::INITIAL_FILE_ID),
+            fs,
+        }
+    }
+
+    fn next_file_id(&self) -> u64 {
+        self.file_id_generator
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
+    }
+
+    async fn get_file_entry(&self, file_id: u64) -> Result<FileEntry> {
+        self.file_entry_manager
+            .read()
+            .await
+            .get_file_by_id(file_id)
+            .ok_or(Errno::from(libc::ENOENT))
+    }
+
+    async fn get_file_entry_by_path(&self, path: &str) -> Option<FileEntry> {
+        self.file_entry_manager.read().await.get_file_by_name(path)
+    }
+
+    async fn fill_file_id(&self, file_stat: &mut FileStat, parent_file_id: 
u64) {
+        let mut file_manager = self.file_entry_manager.write().await;
+        let file = file_manager.get_file_by_name(&file_stat.path);
+        match file {
+            None => {
+                // allocate new file id
+                file_stat.set_file_id(parent_file_id, self.next_file_id());
+                file_manager.insert(file_stat.parent_file_id, 
file_stat.file_id, &file_stat.path);
+            }
+            Some(file) => {
+                // use the exist file id
+                file_stat.set_file_id(file.parent_file_id, file.file_id);
+            }
+        }
+    }
+
+    async fn open_file_internal(
+        &self,
+        file_id: u64,
+        flags: u32,
+        kind: FileType,
+    ) -> Result<FileHandle> {
+        let file_entry = self.get_file_entry(file_id).await?;
+
+        let mut file = {
+            match kind {
+                FileType::Directory => {
+                    self.fs
+                        .open_dir(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                FileType::RegularFile => {
+                    self.fs
+                        .open_file(&file_entry.file_name, OpenFileFlags(flags))
+                        .await?
+                }
+                _ => return Err(Errno::from(libc::EINVAL)),
+            }
+        };
+        // set the exists file id
+        file.set_file_id(file_entry.parent_file_id, file_id);
+        let file = self.opened_file_manager.put_file(file);
+        let file = file.lock().await;
+        Ok(file.file_handle())
+    }
+}
+
+#[async_trait]
+impl<T: PathFileSystem> RawFileSystem for SimpleFileSystem<T> {
+    async fn init(&self) -> Result<()> {
+        // init root directory
+        self.file_entry_manager.write().await.insert(
+            Self::ROOT_DIR_PARENT_FILE_ID,
+            Self::ROOT_DIR_FILE_ID,
+            Self::ROOT_DIR_NAME,
+        );
+        self.fs.init().await
+    }
+
+    async fn get_file_path(&self, file_id: u64) -> String {
+        let file = self.get_file_entry(file_id).await;
+        file.map(|x| x.file_name).unwrap_or_else(|_| "".to_string())
+    }
+
+    async fn valid_file_handle_id(&self, file_id: u64, fh: u64) -> Result<()> {
+        let fh_file_id = self
+            .opened_file_manager
+            .get_file(fh)
+            .ok_or(Errno::from(libc::EBADF))?
+            .lock()
+            .await
+            .file_stat
+            .file_id;
+
+        (file_id == fh_file_id)
+            .then_some(())
+            .ok_or(Errno::from(libc::EBADF))
+    }
+
+    async fn stat(&self, file_id: u64) -> Result<FileStat> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut stat = self.fs.stat(&file.file_name).await?;
+        stat.set_file_id(file.parent_file_id, file.file_id);
+        Ok(stat)
+    }
+
+    async fn lookup(&self, parent_file_id: u64, name: &str) -> 
Result<FileStat> {
+        let parent_file = self.get_file_entry(parent_file_id).await?;
+        let mut stat = self.fs.lookup(&parent_file.file_name, name).await?;
+        // fill the file id to file stat
+        self.fill_file_id(&mut stat, parent_file_id).await;
+        Ok(stat)
+    }
+
+    async fn read_dir(&self, file_id: u64) -> Result<Vec<FileStat>> {
+        let file = self.get_file_entry(file_id).await?;
+        let mut files = self.fs.read_dir(&file.file_name).await?;
+        for file in files.iter_mut() {
+            self.fill_file_id(file, file.file_id).await;
+        }
+        Ok(files)
+    }
+
+    async fn open_file(&self, file_id: u64, flags: u32) -> Result<FileHandle> {
+        self.open_file_internal(file_id, flags, FileType::RegularFile)
+            .await
+    }
+
+    async fn open_dir(&self, file_id: u64, flags: u32) -> Result<FileHandle> {
+        self.open_file_internal(file_id, flags, FileType::Directory)
+            .await
+    }
+
+    async fn create_file(&self, parent_file_id: u64, name: &str, flags: u32) 
-> Result<FileHandle> {
+        let parent = self.get_file_entry(parent_file_id).await?;
+        let mut file = self

Review Comment:
   use `openedFile`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@gravitino.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to