Storage Examples

This page is the runnable example index for the CSharpDB.Storage tutorial track.

There are two distinct example tracks:

  1. Study examples -- the shared StorageStudyExamples.* REPL-based walkthroughs for guided exploration
  2. Advanced standalone examples -- larger sample applications that extend CSharpDB.Storage into domain-specific engines

Choose a track

Track Best for Shape
Study examples Learning the storage surface in guided slices Shared REPL host with multiple small examples
Advanced standalone examples Seeing how to build a full storage-backed engine Separate app per domain with its own CLI/API/UI

Start with the study examples if you are learning Pager, WAL, B+tree, and configurability. Start with the advanced standalone examples if you want bigger, self-contained applications that demonstrate how to extend CSharpDB.Storage directly.

Advanced standalone examples

These four apps are the official advanced examples for extending CSharpDB.Storage into domain-specific engines. Each sample keeps its own README as the authoritative deep dive.

Example Scenario Storage pattern Key concepts
CSharpDB.GraphDB Graph database Multi-tree graph adjacency with reverse-edge index Multiple B+trees, composite edge keys, forward/reverse traversal
CSharpDB.SpatialIndex Spatial proximity search Single-tree Hilbert-key locality index Space-filling curves, range scans, post-filtered nearest queries
CSharpDB.TimeSeries Time-series engine Monotonic-key append and range scan Natural key ordering, right-edge inserts, cursor-based time windows
CSharpDB.VirtualFS Virtual file system Multi-tree metadata/content/path/children layout Multiple B+trees, composite child keys, hashed path lookup, transactional file content

What each advanced sample demonstrates

  • GraphDB: a graph database built on multiple B+trees, with separate outgoing and incoming edge indexes for efficient directed traversal
  • SpatialIndex: a geographic index that maps 2D points onto a Hilbert curve so a single B+tree can support nearby and bounding-box queries
  • TimeSeries: a minimal time-series design where DateTime.UtcNow.Ticks becomes the natural B+tree key for append-heavy writes and range scans
  • VirtualFS: a virtual file system split across metadata, content, path, and child trees to support directory listings, file content, and path-based lookup

Study examples

The study examples are an interactive REPL with two categories of examples:

  1. Application patterns -- real-world use cases built entirely on the Database API, proving the storage engine can back much more than traditional SQL tables. Each example provides domain-specific commands for natural interaction (file system commands for virtual-drive, graph queries for graph-store, etc.).
  2. Storage extensibility -- custom caches, checkpoint policies, interceptors, checksum providers, and more. These demonstrate how to plug into the storage engine internals.

Architecture

The examples follow SOLID principles with a multi-project structure:

Project Description
StorageStudyExamples.CoreShared interfaces (IExample, IInteractiveExample), abstract DataStoreBase, CommandInfo record
StorageStudyExamples.ReplInteractive REPL host -- two-state flow (main menu / example mode)
StorageStudyExamples.VirtualDriveVirtual file system with folders, files, and shortcuts
StorageStudyExamples.ConfigStoreHierarchical config store with versioning and change history
StorageStudyExamples.EventLogAppend-only event log with batch inserts and analytics
StorageStudyExamples.TaskQueuePersistent job queue with state machine and retry logic
StorageStudyExamples.GraphStoreSocial network graph with traversal queries
StorageStudyExamples.StorageInternalsStorage engine configuration examples (9 demos)

Run

Start the interactive REPL:

dotnet run --project samples/storage-tutorials/examples/StorageStudyExamples.Repl/StorageStudyExamples.Repl.csproj

REPL flow

The REPL has two states:

Main menu -- lists all available examples grouped by type. Type load <name> to enter an example.

  Main menu:
    list                    List all available examples
    load <name>             Load an example
    help                    Show help
    clear                   Clear the screen
    quit                    Exit the REPL

Example mode -- once loaded, only the example's domain-specific commands are shown. Type back to return to the main menu.

  Common commands (available in all examples):
    demo                    Run the scripted demo
    sql <query>             Execute raw SQL
    back                    Return to main menu
    help                    Show commands for this example
    clear                   Clear the screen
    quit                    Exit the REPL

The REPL creates a temp working directory for each loaded example so no .cdb or .wal files are left in the repository.

Interface design

All application-pattern examples implement IInteractiveExample, which extends IExample:

public interface IExample : IAsyncDisposable
{
    string Name { get; }
    string CommandName { get; }
    string Description { get; }
    Task InitializeAsync(string workingDirectory);
    Task RunDemoAsync(TextWriter output);
}

public sealed record CommandInfo(string Name, string Usage, string Description);

public interface IInteractiveExample : IExample
{
    IReadOnlyList<CommandInfo> GetCommands();
    Task<bool> ExecuteCommandAsync(string commandName, string args, TextWriter output);
}

Each example defines its own domain-specific commands via GetCommands() and handles them in ExecuteCommandAsync(). The abstract DataStoreBase class provides database lifecycle management (InitializeAsync, DisposeAsync), schema/seed hooks, and a raw SQL helper. Storage internals examples implement only IExample (Interface Segregation Principle).

Storage extensibility examples

These show how to customize the storage engine internals via PagerOptions and StorageEngineOptionsBuilder.

Command What it demonstrates
default-configOpen a database with all default settings
production-configBounded LRU cache, CRC32 checksums, caching indexes
debug-configVerbose interceptor logging on every page operation
batch-importDisable auto-checkpoint for high-throughput bulk writes
metrics-cacheInstrument the page cache with hit/miss/eviction stats
multiple-interceptorsCombine a logger and latency tracker in one pipeline
crash-recovery-testFault-inject a write failure and verify WAL recovery
checkpoint-policy-testDeterministic test of TimeIntervalCheckpointPolicy with a fake clock
wal-size-policy-testDeterministic test of WalSizeCheckpointPolicy thresholds

Suggested starting points: default-config, debug-config, metrics-cache

Application pattern examples

These show the storage engine used as a general-purpose embedded data store for non-traditional workloads. Each is self-contained: it creates a schema, populates sample data, and provides domain-specific commands for interactive exploration. A scripted demo is also available in each example.

virtual-drive -- Virtual file system

Stores folders, files, and shortcuts in a single .cdb file. Supports path-based navigation with a current directory, recursive tree walking, and shortcut (symlink) following.

Command Usage Description
treetreeShow the full directory tree
lsls [path]List contents of a directory
cdcd <path>Change current directory
pwdpwdPrint current directory path
catcat <filename>Print file contents
mkdirmkdir <name>Create a folder
touchtouch <name> [content...]Create a file
lnln <name> <target-path>Create a shortcut
rmrm <name>Remove a file or folder (recursive)
mvmv <name> <new-name>Rename an entry
infoinfo <name>Show entry details (type, size, created)
statsstatsDrive statistics (counts by type, total size)

CSharpDB features used: CREATE INDEX, INSERT with PrepareInsertBatch (for BLOB content), SELECT WHERE parent_id = ?, GROUP BY, SUM, UPDATE (rename via SET name, move via SET parent_id, retarget via SET target_path), DELETE (single row and recursive cascade), transactional read-modify-write for BLOB updates.

config-store -- Key-value configuration store

A persistent hierarchical config system similar to etcd or Windows Registry. Supports namespaced keys, typed values, versioning (auto-incremented on update), and a full change history log.

Command Usage Description
listlist [namespace]List config entries (all or filtered)
getget <namespace> <key>Get a config value
setset <namespace> <key> <value> [type]Set a config value (default type: string)
deletedelete <namespace> <key>Delete a config entry
historyhistory [namespace]Show change history
namespacesnamespacesList all namespaces with counts
rename-nsrename-ns <old> <new>Rename a namespace
drop-nsdrop-ns <namespace>Delete all entries in a namespace

CSharpDB features used: Transactions (BEGIN/COMMIT/ROLLBACK) for atomic read-then-write, two-table design (entries + history), CREATE INDEX, GROUP BY, ORDER BY, batch UPDATE (rename namespace across multiple rows), bulk DELETE with history logging.

event-log -- Append-only event log

An audit trail / event store with 34 events from five services (AuthService, PaymentGateway, Scheduler, Monitor, ApiGateway). Queries by time range, severity threshold, and source.

Command Usage Description
tailtail [count]Show most recent events (default: 20)
loglog <source> <severity> <message>Append a new event
filterfilter <source|severity|category> <value>Filter events by field
statsstatsSeverity histogram and error rates by source
reclassifyreclassify <id> <new-severity>Change event severity
purgepurge <count>Delete the oldest N events

CSharpDB features used: PrepareInsertBatch for bulk writes, CREATE INDEX on timestamp and severity, GROUP BY with COUNT(*), multiple aggregate queries, UPDATE (reclassify severity on indexed column), DELETE (range-based log rotation).

task-queue -- Persistent job queue

A job scheduler with state machine transitions (pending -> running -> completed/failed), priority-based dequeue, and retry logic.

Command Usage Description
listlist [queue]List jobs (all or by queue)
enqueueenqueue <queue> <priority> <payload...>Add a job
claimclaim <queue>Claim highest-priority pending job
completecomplete <id>Mark job as completed
failfail <id> <error...>Mark job as failed
retryretry <id>Re-queue a failed job
cancelcancel <id>Cancel a pending job
dashboarddashboardStatus summary per queue
reprioritizereprioritize <id> <priority>Change job priority
movemove <id> <queue>Move job to different queue
purgepurgeDelete all completed jobs

CSharpDB features used: Transactions for atomic state transitions, ORDER BY priority DESC LIMIT 1 for priority dequeue, GROUP BY queue, status for dashboard, UPDATE with computed values, UPDATE (reprioritize, move between queues via SET queue), conditional DELETE (cancel pending), bulk DELETE (purge completed).

graph-store -- Social network graph

Nodes and edges stored relationally, with traversal queries over a 10-person social network. All commands accept person names instead of IDs.

Command Usage Description
nodesnodesList all people
graphgraphFull adjacency list
followsfollows <name>Who this person follows
followersfollowers <name>Who follows this person
foffof <name>Friends-of-friends (2-hop)
mutualmutual <name1> <name2>People both follow
reciprocalreciprocalAll mutual follow-back pairs
followfollow <source> <target>Add a follow edge
unfollowunfollow <source> <target>Remove a follow edge
add-personadd-person <name>Add a new person
renamerename <old-name> <new-name>Rename a person
removeremove <name>Remove person and all edges
statsstatsConnection counts per person

CSharpDB features used: PrepareInsertBatch, CREATE INDEX on source_id and target_id, JOIN (including 3-table JOINs and self-JOINs), GROUP BY with COUNT(*), DISTINCT, post-query filtering in C# for set operations, UPDATE (rename node label), DELETE (unfollow edge, cascading user removal across tables in a transaction).