Skip to content

API Reference

Core Types

database

The top-level handle to a PsiTri database. Thread-safe. Typically held as a std::shared_ptr<database>.

namespace psitri {
class database : public std::enable_shared_from_this<database> {
public:
    // Construction
    database(const std::filesystem::path& dir,
             const runtime_config& cfg,
             recovery_mode mode = recovery_mode::none);

    static std::shared_ptr<database> create(std::filesystem::path dir,
                                            const runtime_config& = {});

    // Sessions
    std::shared_ptr<write_session> start_write_session();
    std::shared_ptr<read_session>  start_read_session();

    // Durability
    void sync();

    // Statistics
    database_stats get_stats() const;

    // Low-Level Diagnostics
    sal::seg_alloc_dump dump() const;
    uint64_t reachable_size();

    // Recovery
    bool ref_counts_stale() const;
    void reclaim_leaked_memory();
    void recover();

    // Maintenance
    void compact_and_truncate();
    bool wait_for_compactor(std::chrono::milliseconds timeout = 10000ms);
};
}
Method Description
create(dir) Create or open a database with default config
start_write_session() Create a session for reading and writing. Thread-affine: call from the thread that will use it
start_read_session() Create a lightweight read-only session. Thread-affine: call from the thread that will use it
sync() Flush all data to disk
reachable_size() Total bytes of live, reachable objects
compact_and_truncate() Wait for compaction, then shrink the data file
recover() Full recovery: rebuild control blocks from segments

Sessions are thread-affine

Sessions are backed by thread_local storage. Always create them on the thread that will use them. Do not create a session on one thread and pass it to another -- this causes cross-thread aliasing on the underlying allocator session, which is not thread-safe.

For multi-threaded code, pass the database (or a shared_ptr to it) to each worker thread and let each thread call start_write_session() or start_read_session() itself.

write_session

A session for reading and writing. One per logical writer thread. Extends read_session.

class write_session : public read_session {
public:
    transaction start_transaction(uint32_t root_index);

    write_cursor_ptr create_write_cursor();
    write_cursor_ptr create_write_cursor(smart_ptr<alloc_header> root);

    smart_ptr<alloc_header> get_root(uint32_t root_index);
    void set_root(uint32_t root_index, smart_ptr<alloc_header> root,
                  sync_type sync = sync_type::none);

    void set_sync(sync_type sync);
    sync_type get_sync() const;

    uint64_t get_total_allocated_objects() const;
    uint64_t get_pending_release_count() const;
};

read_session

A lightweight read-only session. Supports snapshot reads and cursor creation.

class read_session : public std::enable_shared_from_this<read_session> {
public:
    smart_ptr<alloc_header> get_root(uint32_t root_index);
    cursor create_cursor(uint32_t root_index);
};

transaction

An ACID transaction on a single root index. Auto-aborts on destruction if not committed.

class transaction {
public:
    // Mutations
    bool insert(key_view key, value_view value);
    bool update(key_view key, value_view value);
    void upsert(key_view key, value_view value);
    void upsert(key_view key, smart_ptr<alloc_header> subtree_root);
    int  remove(key_view key);
    uint64_t remove_range(key_view lower, key_view upper);

    // Reads
    template<ConstructibleBuffer T>
    std::optional<T> get(key_view key) const;
    int32_t get(key_view key, Buffer auto* buffer) const;

    // Subtrees
    bool is_subtree(key_view key) const;
    smart_ptr<alloc_header> get_subtree(key_view key) const;
    write_cursor get_subtree_cursor(key_view key) const;

    // Control
    void commit() noexcept;
    void abort() noexcept;
    transaction sub_transaction() noexcept;

    // Read cursor from current transaction state
    cursor read_cursor() const;
};
Method Returns Description
insert(key, value) bool Insert only if key doesn't exist
update(key, value) bool Update only if key exists
upsert(key, value) void Insert or update
remove(key) int Remove key, returns bytes freed or -1
remove_range(lower, upper) uint64_t Remove keys in [lower, upper), returns count
get<T>(key) optional<T> Read value as type T (e.g., std::string)
commit() void Atomically make all changes visible
abort() void Discard all changes
sub_transaction() transaction Nested transaction that commits back to parent

cursor

Read-only ordered iteration over a tree snapshot.

class cursor {
public:
    static constexpr int32_t value_not_found = -1;
    static constexpr int32_t value_subtree   = -2;

    // Positioning
    bool seek_begin() noexcept;      // first key
    bool seek_last() noexcept;       // last key
    bool seek_end() noexcept;        // past last key
    bool seek_rend() noexcept;       // before first key
    bool lower_bound(key_view key) noexcept;
    bool upper_bound(key_view key) noexcept;
    bool seek(key_view key) noexcept;
    bool first(key_view prefix = {}) noexcept;
    bool last(key_view prefix = {}) noexcept;

    // Traversal
    bool next() noexcept;
    bool prev() noexcept;

    // State
    bool is_end() const noexcept;
    bool is_rend() const noexcept;
    key_view key() const noexcept;

    // Value access
    int32_t get(key_view key, Buffer auto* buffer) const;
    template<ConstructibleBuffer T>
    std::optional<T> get(key_view key) const;
};

Type Aliases

Type Definition
key_view std::string_view
value_view std::string_view
database_ptr std::shared_ptr<database>
write_session_ptr std::shared_ptr<write_session>

Recovery Modes

Mode When to use What it does
none Clean shutdown detected No recovery needed
deferred_cleanup App crash, fast restart Mark ref counts stale, defer leak reclamation
app_crash App crash, full cleanup Reset ref counts, reclaim leaked memory
power_loss OS or hardware crash Validate segments, rebuild control blocks and roots
full_verify Suspected corruption Deep checksum verification of all objects

Sync Types

Mode Durability Performance
none No durability (OS flushes when convenient) Fastest
mprotect + Write protection on committed data Fast
msync_async + OS flush initiated Moderate
msync_sync + Block until OS writes Slower
fsync + Block until drive acknowledges Slow
full + F_FULLFSYNC (flush drive cache) Slowest, safest

Constants

Constant Value Description
num_top_roots 512 Independent top-level tree roots
Max segments ~1 million 32 TB max database
Max threads 64 Concurrent sessions
Max object size 16 MB Half a segment
Cacheline 64 bytes Allocation alignment
Max leaf size 2,048 bytes Per leaf node
Max branches per leaf Limited by 2,048 byte leaf size Keys per leaf (typically ~58)
Max inner branches 256 16 cachelines x 16 slots