Skip to content

Commit eb0c2e1

Browse files
author
José Molina
committed
Add documentation
1 parent be062b8 commit eb0c2e1

19 files changed

+1948
-219
lines changed

Cargo.lock

Lines changed: 203 additions & 117 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,43 @@ authors = ["José Molina <jmolinacolmenero@gmail.com>"]
66
edition = "2021"
77
license = "Apache-2.0"
88
publish = false
9+
repository = "https://github.com/Moliholy/cvmfs-rust"
10+
keywords = ["cvmfs", "filesystem", "fuse", "cernvm"]
11+
categories = ["filesystem", "science"]
912

1013
[dependencies]
11-
x509-certificate = "0.24.0"
12-
thiserror = "2.0.3"
14+
# Cryptography and hashing
1315
sha1 = "0.10"
14-
md5 = "0.7.0"
15-
chrono = "0.4"
16-
reqwest = { version = "0.12.9", features = ["blocking"] }
17-
compress = "0.2"
18-
rusqlite = { version = "0.32.1", features = ["blob"] }
16+
md5 = "0.8.0"
1917
hex = "0.4"
18+
x509-certificate = "0.24.0" # X.509 certificate handling
19+
20+
# Database and storage
21+
rusqlite = { version = "0.37.0", features = ["blob"] }
22+
23+
# Filesystem integration
2024
fuse_mt = "0.6"
2125
libc = "0.2"
22-
rand = "0.8"
26+
27+
# Network and HTTP
28+
reqwest = { version = "0.12.22", features = ["blocking"] }
29+
30+
# Utilities
31+
chrono = "0.4"
32+
compress = "0.2"
33+
thiserror = "2.0.3"
34+
rand = "0.9.2"
35+
36+
# Logging
2337
log = "0.4.22"
2438
env_logger = "0.11.5"
39+
40+
[profile.release]
41+
opt-level = 3
42+
lto = true
43+
codegen-units = 1
44+
panic = "abort"
45+
strip = true
46+
47+
[profile.dev]
48+
debug = true

README.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,83 @@
11
# cvmfs-rust
2-
CernVM-FS implementation written in Rust
2+
3+
[![Rust](https://img.shields.io/badge/rust-1.87.0%2B-orange.svg)](https://www.rust-lang.org/)
4+
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5+
6+
A [CernVM-FS](https://github.com/cvmfs/cvmfs) client implementation written in Rust. This project aims to provide a
7+
modern, secure, and performant alternative to the original C++ implementation.
8+
9+
## Features
10+
11+
- Native Rust implementation of the CernVM-FS client.
12+
- Improved performance and memory safety.
13+
- FUSE integration for filesystem mounting.
14+
- Support for compression and decompression.
15+
- Cryptographic verification of repository content.
16+
- SQLite-based catalog handling.
17+
18+
## Prerequisites
19+
20+
- Rust 1.87.0 or higher.
21+
- FUSE libraries for your operating system.
22+
23+
## Installation
24+
25+
### From Source
26+
27+
```bash
28+
# Clone the repository
29+
git clone https://github.com/Moliholy/cvmfs-rust.git
30+
cd cvmfs-rust
31+
32+
# Build the project
33+
cargo build --release
34+
35+
# Install the binary (optional)
36+
cargo install --path .
37+
```
38+
39+
## Usage
40+
41+
```bash
42+
# Mount a CernVM-FS repository
43+
cvmfs-rust mount repo.example.org /cvmfs/repo.example.org
44+
45+
# Unmount the repository
46+
fusermount -u /cvmfs/repo.example.org
47+
```
48+
49+
## Configuration
50+
51+
Configuration can be provided via a TOML file:
52+
53+
```bash
54+
cvmfs-rust --config /etc/cvmfs-rust/config.toml mount repo.example.org /cvmfs/repo.example.org
55+
```
56+
57+
## Development
58+
59+
### Dependencies
60+
61+
This project uses the following key dependencies:
62+
63+
- sha1 (0.10.5) - SHA-1 hashing.
64+
- log (0.4.22) - Logging infrastructure.
65+
- fuse_mt (0.6.0) - FUSE filesystem integration.
66+
- rusqlite (0.32.1) - SQLite bindings.
67+
- x509-certificate (0.24.0) - Certificate handling.
68+
- reqwest (0.12.9) - HTTP client.
69+
70+
### Running Tests
71+
72+
```bash
73+
cargo test
74+
```
75+
76+
## License
77+
78+
This project is licensed under the MIT License - see the LICENSE file for details.
79+
80+
## Acknowledgments
81+
82+
- The original [CernVM-FS project](https://github.com/cvmfs/cvmfs).
83+
- All contributors and maintainers.

src/cache.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,78 @@
1+
//! # Local Cache Management for CernVM-FS
2+
//!
3+
//! This module provides functionality for managing the local cache of CernVM-FS objects.
4+
//! The cache stores downloaded repository objects to improve performance and allow
5+
//! offline access to previously accessed content.
6+
//!
7+
//! ## Cache Structure
8+
//!
9+
//! The cache follows a two-level directory structure:
10+
//! - The main cache directory contains a `data` subdirectory
11+
//! - Inside `data`, objects are organized into 256 subdirectories (00-ff) based on
12+
//! the first two hex characters of their content hash
13+
//!
14+
//! ## Cache Operations
15+
//!
16+
//! The cache supports the following operations:
17+
//! - Initialization: Creating the directory structure
18+
//! - Adding: Determining the path where a file should be stored
19+
//! - Retrieval: Looking up files by their identifier
20+
//! - Eviction: Clearing the cache and rebuilding the structure
21+
122
use std::fs::{create_dir_all, remove_dir_all};
223
use std::path::{Path, PathBuf};
324

425
use crate::common::{CvmfsError, CvmfsResult};
526

27+
/// A cache for storing repository objects locally
28+
///
29+
/// The `Cache` struct manages a local directory structure where CernVM-FS objects
30+
/// are stored. It provides methods for initialization, file lookup, and cache management.
631
#[derive(Debug, Clone)]
732
pub struct Cache {
33+
/// The root directory where cache files are stored.
834
pub cache_directory: String,
935
}
1036

1137
impl Cache {
38+
/// Creates a new cache instance with the specified root directory.
39+
///
40+
/// This constructor creates a new cache that will store files in the specified
41+
/// directory. It validates that the path can be properly represented as a string.
42+
///
43+
/// # Arguments
44+
///
45+
/// * `cache_directory` - The path to the root cache directory.
46+
///
47+
/// # Returns
48+
///
49+
/// Returns a `CvmfsResult<Self>` containing the new cache instance, or an error
50+
/// if the path is invalid.
51+
///
52+
/// # Errors
53+
///
54+
/// Returns `CvmfsError::FileNotFound` if the path cannot be converted to a string.
1255
pub fn new(cache_directory: String) -> CvmfsResult<Self> {
1356
let path = Path::new(&cache_directory);
1457
Ok(Self {
1558
cache_directory: path.to_str().ok_or(CvmfsError::FileNotFound)?.into(),
1659
})
1760
}
1861

62+
/// Initializes the cache directory structure.
63+
///
64+
/// This method creates the cache directory structure if it doesn't exist. It creates
65+
/// a `data` subdirectory with 256 subdirectories (00-ff) to store objects based on
66+
/// the first two hex characters of their hash.
67+
///
68+
/// # Returns
69+
///
70+
/// Returns `Ok(())` if initialization is successful, or an error if directory
71+
/// creation fails.
72+
///
73+
/// # Errors
74+
///
75+
/// Returns filesystem errors if directory creation fails, or path conversion errors.
1976
pub fn initialize(&self) -> CvmfsResult<()> {
2077
let base_path = self.create_directory("data")?;
2178
for i in 0x00..=0xff {
@@ -26,6 +83,24 @@ impl Cache {
2683
Ok(())
2784
}
2885

86+
/// Creates a directory within the cache root
87+
///
88+
/// This helper method creates a directory at the specified path relative to the
89+
/// cache root directory, ensuring all parent directories are created as needed.
90+
///
91+
/// # Arguments
92+
///
93+
/// * `path` - The relative path to create within the cache directory
94+
///
95+
/// # Returns
96+
///
97+
/// Returns a `CvmfsResult<String>` containing the full path to the created directory,
98+
/// or an error if directory creation or path conversion fails.
99+
///
100+
/// # Errors
101+
///
102+
/// Returns filesystem errors if directory creation fails, or `CvmfsError::FileNotFound`
103+
/// if the path cannot be converted to a string.
29104
fn create_directory(&self, path: &str) -> CvmfsResult<String> {
30105
let cache_full_path = Path::new(&self.cache_directory).join(path);
31106
create_dir_all(cache_full_path.clone())?;
@@ -35,10 +110,35 @@ impl Cache {
35110
.map_err(|_| CvmfsError::FileNotFound)
36111
}
37112

113+
/// Gets the path where a file would be stored in the cache
114+
///
115+
/// This method determines the full path where a file with the given name would
116+
/// be stored in the cache, without checking if it actually exists.
117+
///
118+
/// # Arguments
119+
///
120+
/// * `file_name` - The name of the file
121+
///
122+
/// # Returns
123+
///
124+
/// Returns a `PathBuf` with the full path where the file would be stored.
38125
pub fn add(&self, file_name: &str) -> PathBuf {
39126
Path::join(self.cache_directory.as_ref(), file_name)
40127
}
41128

129+
/// Retrieves the path to a file if it exists in the cache
130+
///
131+
/// This method checks if a file with the given name exists in the cache and
132+
/// returns its path if found.
133+
///
134+
/// # Arguments
135+
///
136+
/// * `file_name` - The name of the file to look up
137+
///
138+
/// # Returns
139+
///
140+
/// Returns an `Option<PathBuf>` containing the path to the file if it exists,
141+
/// or `None` if the file is not in the cache.
42142
pub fn get(&self, file_name: &str) -> Option<PathBuf> {
43143
let path = self.add(file_name);
44144
if path.exists() || path.is_file() {
@@ -47,6 +147,20 @@ impl Cache {
47147
None
48148
}
49149

150+
/// Clears the cache and re-initializes the directory structure.
151+
///
152+
/// This method removes all cached objects by deleting and recreating the data
153+
/// directory structure. It's useful for clearing corrupted cache data or freeing
154+
/// disk space.
155+
///
156+
/// # Returns
157+
///
158+
/// Returns `Ok(())` if eviction is successful, or an error if directory removal
159+
/// or reinitialization fails.
160+
///
161+
/// # Errors
162+
///
163+
/// Returns filesystem errors if directory operations fail.
50164
pub fn evict(&self) -> CvmfsResult<()> {
51165
let data_path = Path::new(&self.cache_directory).join("data");
52166
if data_path.exists() && data_path.is_dir() {

0 commit comments

Comments
 (0)