tfs 0.1.3

Fast, content-addressed, snapshottable filesystem.
Documentation
struct Fs {
    RwLock<HashMap<VolumeId, RwLock<ChunkMap>>>,
    Mutex<LinkedHashMap<ContentId, ImmutableChunk>>,
    IndexedSparseFile
}

struct IndexedSparseFile {
    file: File,
    allocator: IndexAllocator
}

struct ContentId(Hash)

// Conceptually:
struct ChunkMap {
    VecMap<Chunk>
}

enum Chunk {
    Immutable(ContentId),
    Mutable(MutableChunk)
}

struct MutableChunk {
    Index,
    Version,
    Mutex<Option<ContentId>> // None = Dirty, Some(id) = Stable(id)
    Condvar
}

struct ImmutableChunk {
    Index
    Mutex<ImmutableChunkState>,
    Condvar
}

enum ImmutableChunkState {
    Stable,
    Evicted,
    Reserved
}

// Actually:
struct ChunkMap {
    // Can use capn'proto for serde these RawChunks
    memory: Mmap<RawChunk>,
    locks: VecMap<Signal>
}

struct Signal {
    mutex: Mutex<()>,
    cond: Condvar
}

impl Signal {
    fn wait(&'a self, SignalGuard<'a>) -> SignalGuard<'a>;
    fn lock(&'a self) -> SignalGuard<'a>;
    fn notify_one(self);
    fn notify_all(self);
}

enum RawChunk {
    Immutable(ContentId),
    Mutable(Index, Version, Option<ContentId>)
}

// Exposes a similar (safe!) interface to ImmutableChunk above
struct ImmutableChunk<'a> {
    data: *mut RawChunk::Immutable,
    signal: &'a Signal,
}

// Exposes a similar (safe!) interface to MutableChunk above
struct MutableChunk<'a> {
    data: *mut RawChunk::Mutable,
    signal: &'a Signal,
}

// Operations get written in terms of the safe interface to ChunkMap

// Read of immutable chunk proceeds like read of read-only blob today
// Read of mutable chunk always succeeds

// Write of immutable chunk causes a transition to mutable chunk by *copying*
// the data to a new index and transitioning from Chunk::Immutable to
// Chunk::Mutable

// Evict happens by popping from lru, try_locking, and moving on to the next
// candidate if try_lock fails