stable_fs/
storage.rs

1use ic_stable_structures::Memory;
2
3use crate::{
4    error::Error,
5    fs::{ChunkSize, ChunkType},
6    storage::types::{
7        DirEntry, DirEntryIndex, FileName, FileSize, Metadata, MountedFileSizePolicy, Node,
8    },
9};
10
11mod allocator;
12mod chunk_iterator;
13pub mod dummy;
14mod journal;
15mod metadata_provider;
16mod ptr_cache;
17pub mod stable;
18pub mod transient;
19pub mod types;
20
21/// Abstraction of the underlying storage layer.
22pub trait Storage {
23    /// Get the root node ID of the storage.
24    fn root_node(&self) -> Node;
25
26    /// Get version of the file system.
27    fn get_version(&self) -> u32;
28
29    /// Generate the next available node ID.
30    fn new_node(&mut self) -> Node;
31
32    /// mark node as mounted.
33    fn mount_node(
34        &mut self,
35        node: Node,
36        memory: Box<dyn Memory>,
37        mount_policy: MountedFileSizePolicy,
38    ) -> Result<(), Error>;
39
40    /// mark note as not mounted.
41    fn unmount_node(&mut self, node: Node) -> Result<Box<dyn Memory>, Error>;
42    /// return true if the node is mounted.
43    fn is_mounted(&self, node: Node) -> bool;
44    /// return mounted memory related to the node, or None.
45    fn get_mounted_memory(&self, node: Node) -> Option<&dyn Memory>;
46
47    /// initialize memory with the contents from file.
48    fn init_mounted_memory(&mut self, node: Node) -> Result<(), Error>;
49    /// store mounted memory state back to host file.
50    fn store_mounted_memory(&mut self, node: Node) -> Result<(), Error>;
51
52    /// Get the metadata associated with the node.
53    fn get_metadata(&self, node: Node) -> Result<Metadata, Error>;
54    /// Update the metadata associated with the node.
55    fn put_metadata(&mut self, node: Node, metadata: &Metadata) -> Result<(), Error>;
56
57    /// Retrieve the DirEntry instance given the Node and DirEntryIndex.
58    fn get_direntry(&self, node: Node, index: DirEntryIndex) -> Result<DirEntry, Error>;
59
60    /// Retrieve the DirEntryIndex instance given the Node and DirEntryIndex.
61    fn get_direntry_index_by_name(&self, el: &(Node, FileName)) -> Option<DirEntryIndex>;
62
63    /// get entries iterator
64    fn with_direntries(
65        &self,
66        node: Node,
67        initial_index: Option<DirEntryIndex>,
68        f: &mut dyn FnMut(&DirEntryIndex, &DirEntry) -> bool,
69    );
70
71    /// Return the DirEntryIndex that can be used for a new entry
72    fn new_direntry_index(&self, node: Node) -> DirEntryIndex;
73
74    // Update or insert the DirEntry instance given the Node and DirEntryIndex.
75    fn put_direntry(&mut self, node: Node, index: DirEntryIndex, entry: DirEntry);
76    // Remove the DirEntry instance given the Node and DirEntryIndex.
77    fn rm_direntry(&mut self, node: Node, index: DirEntryIndex);
78
79    // read node data into buf
80    fn read(
81        &mut self,
82        node: Node,
83        read_offset: FileSize,
84        buf: &mut [u8],
85    ) -> Result<FileSize, Error>;
86
87    // Write file at the current file cursor, the cursor position will NOT be updated after reading.
88    fn write(&mut self, node: Node, offset: FileSize, buf: &[u8]) -> Result<FileSize, Error>;
89
90    // delete chunks to match the new file size specified
91    fn resize_file(&mut self, node: Node, new_size: FileSize) -> Result<(), Error>;
92
93    // remove all file chunks
94    fn rm_file(&mut self, node: Node) -> Result<(), Error>;
95
96    // configure desired chunk size
97    fn set_chunk_size(&mut self, chunk_size: ChunkSize) -> Result<(), Error>;
98    // the current FS chunk size in bytes
99    fn chunk_size(&self) -> usize;
100
101    // configure desired chunk type (V1, V2)
102    fn set_chunk_type(&mut self, chunk_type: ChunkType);
103    fn chunk_type(&self) -> ChunkType;
104
105    // flush changes related to the node
106    fn flush(&mut self, node: Node);
107}