cs-filesystem is a read-only filesystem for exposing Cybershuttle dataset
metadata as ordinary directories and JSON files.
Cargo.toml Rust package metadata and dependencies
Cargo.lock Locked dependency graph
README.md Project overview and quick start
docs/ Distribution, developer, and user documentation
examples/ Tiny metadata tables for demos and tests
scripts/package-release.sh Local release archive builder
src/main.rs CLI, FUSE filesystem, materialization path, NFS wiring
src/atlas.rs ATLAS TSV parser and virtual data source
src/table_dataset.rs Generic TSV/CSV-backed data source
src/dataset_registry.rs Built-in official dataset registry
src/nfs_server.rs Read-only NFS server implementation
The data/ directory is intentionally local-only. Full metadata tables can be
large or subject to external access rules, so only small examples are committed.
The filesystem has one logical tree that can be exposed three ways:
fuse: mount the virtual tree through FUSE.materialize: write the same tree to a normal directory.nfs: serve the same metadata tree through a read-only NFS server.
The root contains:
index.json
registry.json
datasets/
atlas/
<optional table datasets>/
Each dataset root contains one directory per entry. Each entry directory contains
a metadata.json file.
atlas/
1r6w_A/
metadata.json
src/main.rs defines the shared data source interface:
pub trait VirtualDataSource {
fn name(&self) -> &str;
fn kind(&self) -> &str;
fn inode(&self) -> u64;
fn entry_count(&self) -> usize;
fn lookup(&self, parent: u64, name: &OsStr) -> Option<FileAttr>;
fn getattr(&self, ino: u64) -> Option<FileAttr>;
fn read(&self, ino: u64, offset: i64, size: u32) -> Option<Vec<u8>>;
fn readdir(&self, ino: u64, offset: i64, reply: &mut ReplyDirectory) -> bool;
}FUSE uses this trait directly. materialize uses each data source's
materialization helper. NFS converts data sources into NfsDataset values and
serves them through src/nfs_server.rs.
Inodes are allocated by InodeGenerator in one pass while building data
sources. The root-level inode values in main.rs are reserved for
/, hello.txt, index.json, and registry.json; generated dataset inodes
start after those values.
src/dataset_registry.rs contains the built-in registry of known AI-for-science
datasets. It exposes the registry in two forms:
registry.json: one JSON file containing all registry entries.datasets/<dataset-id>/metadata.json: one directory per registry entry.
Registry entries include:
- stable ID
- display name
- domain
- access pattern
- implementation status
- source URL
- intended connector type
- notes
The registry is metadata-first. Planned or restricted datasets should be listed without implying that raw data will be downloaded automatically.
Current connectors are implemented as data sources:
AtlasDataSource: parses ATLAS-specific TSV metadata.TableDataSource: parses generic TSV or CSV metadata, using the first column as the entry directory name.
The registry connector field describes the expected access pattern for future
connectors, such as api, bundle, zenodo_metadata, or table. A connector
should expose metadata first and avoid surprising bulk downloads during normal
mount or demo flows.
If the dataset can be represented by a TSV or CSV table, no code change is required. Put a stable entry ID in the first column:
entry_id family source
sample_001 protein local-demo
Run:
cargo run --release -- materialize \
examples/atlas_sample.tsv \
my_dataset=/path/to/my_dataset.tsv \
/tmp/cs_exportThe output will include:
/tmp/cs_export/my_dataset/sample_001/metadata.json
Use a dedicated data source when a dataset needs custom parsing, remote API metadata, caching, or non-table layout.
- Add a module under
src/. - Parse external metadata into stable entry records.
- Allocate inodes with
InodeGenerator. - Implement
VirtualDataSource. - Add a
materializehelper if the source should support static export. - Wire the source into
main.rs. - Add or update a registry entry in
dataset_registry.rs. - Add unit tests for parsing, lookup, read slicing, and directory listing.
Keep data sources read-only unless the project explicitly adds a write contract.
Install dependencies:
Linux:
sudo apt install cargo libfuse3-dev libfuse-dev pkg-configmacOS:
brew install pkgconf
brew install --cask macfuseBuild and test:
cargo test
cargo build --releaseRun a sample export:
rm -rf /tmp/cs_sample_export
cargo run --release -- materialize \
examples/atlas_sample.tsv \
mdcath=examples/mdcath_sample.tsv \
memprotmd=examples/memprotmd_sample.tsv \
gpcrmd=examples/gpcrmd_sample.tsv \
/tmp/cs_sample_export