vfs.vfs_db #
Database Filesystem Implementation (vfs_db)
A virtual filesystem implementation that uses OurDB as its storage backend, providing a complete filesystem interface with database-backed storage.
Features
- Persistent storage in OurDB database
- Full support for files, directories, and symlinks
- Transactional operations
- Structured metadata storage
- Hierarchical filesystem structure
- Thread-safe operations
Implementation Details
Structure
vfs_db/
├── factory.v # VFS factory implementation
├── vfs_implementation.v # Core VFS interface implementation
├── vfs.v # DatabaseVFS type definition
├── model_file.v # File type implementation
├── model_directory.v # Directory type implementation
├── model_symlink.v # Symlink type implementation
├── model_fsentry.v # Common FSEntry interface
├── metadata.v # Metadata structure
├── encoder.v # Data encoding utilities
├── vfs_directory.v # Directory operations
├── vfs_getters.v # Common getter methods
└── *_test.v # Implementation tests
Key Components
DatabaseVFS
: Main implementation struct
pub struct DatabaseVFS {
pub mut:
root_id u32
block_size u32
data_dir string
metadata_dir string
db_data &Database
last_inserted_id u32
}
FSEntry
implementations:
pub type FSEntry = Directory | File | Symlink
Data Storage
Metadata Structure
struct Metadata {
id u32 // Unique identifier
name string // Entry name
file_type FileType
size u64
created_at i64 // Unix timestamp
modified_at i64
accessed_at i64
mode u32 // Permissions
owner string
group string
}
Database Interface
pub interface Database {
mut:
get(id u32) ![]u8
set(ourdb.OurDBSetArgs) !u32
delete(id u32)!
}
Usage
import freeflowuniverse.herolib.vfs.vfs_db
// Create separate databases for data and metadata
mut db_data := ourdb.new(
path: os.join_path(test_data_dir, 'data')
incremental_mode: false
)!
mut db_metadata := ourdb.new(
path: os.join_path(test_data_dir, 'metadata')
incremental_mode: false
)!
// Create VFS with separate databases for data and metadata
mut fs := new(mut db_data, mut db_metadata)!
// Create directory structure
fs.dir_create('documents')!
fs.dir_create('documents/reports')!
// Create and write files
fs.file_create('documents/reports/q1.txt')!
fs.file_write('documents/reports/q1.txt', 'Q1 Report Content'.bytes())!
// Create symbolic links
fs.link_create('documents/reports/q1.txt', 'documents/latest.txt')!
// List directory contents
entries := fs.dir_list('documents')!
for entry in entries {
println('${entry.get_path()} (${entry.get_metadata().size} bytes)')
}
// Clean up
fs.destroy()!
Implementation Notes
- Data Encoding:
- Version byte for format compatibility
- Entry type indicator
- Entry-specific binary data
- Efficient storage format
- Thread Safety:
- Mutex protection for concurrent access
- Atomic operations
- Clear ownership semantics
- Error Handling:
- Descriptive error messages
- Proper error propagation
- Recovery mechanisms
- Consistency checks
Limitations
- Performance overhead compared to direct filesystem access
- Database size grows with filesystem usage
- Requires proper database maintenance
- Limited by database backend capabilities
Testing
The implementation includes tests for:- Basic operations (create, read, write, delete)
- Directory operations and traversal
- Symlink handling
- Concurrent access
- Error conditions
- Edge cases
- Data consistency
Run tests with:
v test vfs/vfs_db/
Future Improvements
- Performance Optimizations:
- Entry caching
- Batch operations
- Improved traversal algorithms
- Feature Additions:
- Extended attributes
- Access control lists
- Quota management
- Transaction support
- Robustness:
- Automated recovery
- Consistency verification
- Better error handling
- Backup/restore capabilities
fn decode_directory #
fn decode_directory(data []u8) !Directory
decode_directory decodes a binary format back to Directory
fn decode_file_metadata #
fn decode_file_metadata(data []u8) !File
decode_file decodes a binary format back to File (without the actual file data) returns file without data and the sequence of keys of chunks of data in data db
fn decode_symlink #
fn decode_symlink(data []u8) !Symlink
decode_symlink decodes a binary format back to Symlink
fn new #
fn new(mut data_db Database, mut metadata_db Database) !&DatabaseVFS
Factory method for creating a new DatabaseVFS instance
interface Database #
interface Database {
mut:
get(id u32) ![]u8
set(ourdb.OurDBSetArgs) !u32
delete(id u32) !
}
type FSEntry #
type FSEntry = Directory | File | Symlink
FSEntry represents any type of filesystem entry
struct CopyDirArgs #
struct CopyDirArgs {
pub mut:
src_entry_name string @[required] // source entry name
dst_entry_name string @[required] // destination entry name
dst_parent_dir &Directory @[required] // destination Directory
}
struct DatabaseVFS #
struct DatabaseVFS {
pub mut:
root_id u32 // ID of root directory
block_size u32 // Size of data blocks in bytes
db_data &Database @[str: skip] // Database instance for file data storage
db_metadata &Database @[str: skip] // Database instance for metadata storage
last_inserted_id u32
id_table map[u32]u32
}
DatabaseVFS represents the virtual filesystem
fn (DatabaseVFS) copy #
fn (mut self DatabaseVFS) copy(src_path_ string, dst_path_ string) !vfs.FSEntry
fn (DatabaseVFS) copy_directory #
fn (mut fs DatabaseVFS) copy_directory(dir Directory) !&Directory
copy_directory creates a new directory with the same metadata as the source
fn (DatabaseVFS) copy_file #
fn (mut self DatabaseVFS) copy_file(file File) !&File
copy_file creates a copy of a file
fn (DatabaseVFS) delete #
fn (mut self DatabaseVFS) delete(path_ string) !
fn (DatabaseVFS) destroy #
fn (mut self DatabaseVFS) destroy() !
fn (DatabaseVFS) dir_create #
fn (mut self DatabaseVFS) dir_create(path_ string) !vfs.FSEntry
fn (DatabaseVFS) dir_delete #
fn (mut self DatabaseVFS) dir_delete(path string) !
fn (DatabaseVFS) dir_list #
fn (mut self DatabaseVFS) dir_list(path string) ![]vfs.FSEntry
fn (DatabaseVFS) directory_add_symlink #
fn (mut fs DatabaseVFS) directory_add_symlink(mut dir Directory, mut symlink Symlink) !
add_symlink adds an existing symlink to this directory
fn (DatabaseVFS) directory_children #
fn (mut fs DatabaseVFS) directory_children(mut dir Directory, recursive bool) ![]FSEntry
get_children returns all immediate children as FSEntry objects
fn (DatabaseVFS) directory_copy #
fn (mut fs DatabaseVFS) directory_copy(mut dir Directory, args_ CopyDirArgs) !&Directory
fn (DatabaseVFS) directory_mkdir #
fn (mut fs DatabaseVFS) directory_mkdir(mut dir Directory, name_ string) !&Directory
mkdir creates a new directory with default permissions
fn (DatabaseVFS) directory_move #
fn (mut fs DatabaseVFS) directory_move(dir_ Directory, args_ MoveDirArgs) !&Directory
fn (DatabaseVFS) directory_print #
fn (mut fs DatabaseVFS) directory_print(dir Directory) string
str returns a formatted string of directory contents (non-recursive)
fn (DatabaseVFS) directory_printall #
fn (mut fs DatabaseVFS) directory_printall(dir Directory, indent string) !string
printall prints the directory structure recursively
fn (DatabaseVFS) directory_rename #
fn (mut fs DatabaseVFS) directory_rename(dir Directory, src_name string, dst_name string) !FSEntry
fn (DatabaseVFS) directory_rm #
fn (mut fs DatabaseVFS) directory_rm(mut dir Directory, name string) !
rm removes a file or directory by name
fn (DatabaseVFS) directory_touch #
fn (mut fs DatabaseVFS) directory_touch(mut dir Directory, name_ string) !&File
touch creates a new empty file with default permissions
fn (DatabaseVFS) exists #
fn (mut self DatabaseVFS) exists(path_ string) bool
fn (DatabaseVFS) file_concatenate #
fn (mut self DatabaseVFS) file_concatenate(path_ string, data []u8) !
fn (DatabaseVFS) file_create #
fn (mut self DatabaseVFS) file_create(path_ string) !vfs.FSEntry
fn (DatabaseVFS) file_delete #
fn (mut self DatabaseVFS) file_delete(path string) !
fn (DatabaseVFS) file_read #
fn (mut self DatabaseVFS) file_read(path_ string) ![]u8
fn (DatabaseVFS) file_write #
fn (mut self DatabaseVFS) file_write(path_ string, data []u8) !
fn (DatabaseVFS) get #
fn (mut fs DatabaseVFS) get(path_ string) !vfs.FSEntry
fn (DatabaseVFS) get_next_id #
fn (mut fs DatabaseVFS) get_next_id() u32
Get the next ID, it should be some kind of auto-incrementing ID
fn (DatabaseVFS) get_path #
fn (mut self DatabaseVFS) get_path(entry_ &vfs.FSEntry) !string
fn (DatabaseVFS) link_create #
fn (mut self DatabaseVFS) link_create(target_path string, link_path string) !vfs.FSEntry
fn (DatabaseVFS) link_delete #
fn (mut self DatabaseVFS) link_delete(path string) !
fn (DatabaseVFS) link_read #
fn (mut self DatabaseVFS) link_read(path string) !string
fn (DatabaseVFS) move #
fn (mut self DatabaseVFS) move(src_path string, dst_path string) !vfs.FSEntry
fn (DatabaseVFS) new_directory #
fn (mut fs DatabaseVFS) new_directory(dir NewDirectory) !&Directory
mkdir creates a new directory with default permissions
fn (DatabaseVFS) print #
fn (mut fs DatabaseVFS) print() !
fn (DatabaseVFS) rename #
fn (mut self DatabaseVFS) rename(old_path string, new_path string) !vfs.FSEntry
fn (DatabaseVFS) root_get #
fn (mut fs DatabaseVFS) root_get() !vfs.FSEntry
Implementation of VFSImplementation interface
fn (DatabaseVFS) root_get_as_dir #
fn (mut fs DatabaseVFS) root_get_as_dir() !&Directory
Implementation of VFSImplementation interface
fn (DatabaseVFS) save_entry #
fn (mut fs DatabaseVFS) save_entry(entry FSEntry) !
save_entry saves an entry to the database
fn (DatabaseVFS) save_file #
fn (mut fs DatabaseVFS) save_file(file_ File, data []u8) !u32
save_entry saves an entry to the database
struct Directory #
struct Directory {
pub mut:
metadata vfs.Metadata // vfs.Metadata from models_common.v
children []u32 // List of child entry IDs (instead of actual entries)
parent_id u32 // ID of parent directory (0 for root)
}
Directory represents a directory in the virtual filesystem
fn (Directory) encode #
fn (dir Directory) encode() []u8
encode encodes a Directory to binary format
fn (Directory) is_dir #
fn (d &Directory) is_dir() bool
is_dir returns true if the entry is a directory
fn (Directory) is_file #
fn (d &Directory) is_file() bool
is_file returns true if the entry is a file
fn (Directory) is_symlink #
fn (d &Directory) is_symlink() bool
is_symlink returns true if the entry is a symlink
struct File #
struct File {
pub mut:
metadata vfs.Metadata // vfs.Metadata from models_common.v
parent_id u32 // ID of parent directory
chunk_ids []u32 // a list of data addresses for chunks of 64 kb in data_db
}
File represents a file in the virtual filesystem
fn (File) encode #
fn (f File) encode() []u8
File encoding/decoding encode encodes a File metadata to binary format (without the actual file data)
fn (File) is_dir #
fn (f &File) is_dir() bool
is_dir returns true if the entry is a directory
fn (File) is_file #
fn (f &File) is_file() bool
is_file returns true if the entry is a file
fn (File) is_symlink #
fn (f &File) is_symlink() bool
is_symlink returns true if the entry is a symlink
struct MoveDirArgs #
struct MoveDirArgs {
pub mut:
src_entry_name string @[required] // source entry name
dst_entry_name string @[required] // destination entry name
dst_parent_dir &Directory @[required] // destination OurDBFSDirectory
}
struct NewDirectory #
struct NewDirectory {
pub:
name string @[required] // name of file or directory
mode u32 = 0o755 // file permissions
owner string = 'user'
group string = 'user'
parent_id u32
children []u32
}
struct NewFile #
struct NewFile {
pub:
name string @[required] // name of file or directory
path string @[required] // path of file or directory
data string
mode u32 = 0o644 // file permissions
owner string = 'user'
group string = 'user'
parent_id u32
}
struct Symlink #
struct Symlink {
pub mut:
metadata vfs.Metadata // vfs.Metadata from models_common.v
target string // Path that this symlink points to
parent_id u32 // ID of parent directory
}
Symlink represents a symbolic link in the virtual filesystem
fn (Symlink) encode #
fn (sl Symlink) encode() []u8
encode encodes a Symlink to binary format
fn (Symlink) get_target #
fn (mut sl Symlink) get_target() !string
get_target returns the current target path
fn (Symlink) is_dir #
fn (self &Symlink) is_dir() bool
is_dir returns true if the entry is a directory
fn (Symlink) is_file #
fn (self &Symlink) is_file() bool
is_file returns true if the entry is a file
fn (Symlink) is_symlink #
fn (self &Symlink) is_symlink() bool
is_symlink returns true if the entry is a symlink
fn (Symlink) update_target #
fn (mut sl Symlink) update_target(new_target string) !
update_target changes the symlink's target path
- README
- fn decode_directory
- fn decode_file_metadata
- fn decode_symlink
- fn new
- interface Database
- type FSEntry
- struct CopyDirArgs
- struct DatabaseVFS
- fn copy
- fn copy_directory
- fn copy_file
- fn delete
- fn destroy
- fn dir_create
- fn dir_delete
- fn dir_list
- fn directory_add_symlink
- fn directory_children
- fn directory_copy
- fn directory_mkdir
- fn directory_move
- fn directory_print
- fn directory_printall
- fn directory_rename
- fn directory_rm
- fn directory_touch
- fn exists
- fn file_concatenate
- fn file_create
- fn file_delete
- fn file_read
- fn file_write
- fn get
- fn get_next_id
- fn get_path
- fn link_create
- fn link_delete
- fn link_read
- fn move
- fn new_directory
- fn print
- fn rename
- fn root_get
- fn root_get_as_dir
- fn save_entry
- fn save_file
- struct Directory
- struct File
- struct MoveDirArgs
- struct NewDirectory
- struct NewFile
- struct Symlink