Git Product home page Git Product logo

jetkv's Introduction

JetKV

JetKV is a key-value store written in Zig intended for use in development web servers.

JetKV can be used for:

  • Background job queuing
  • Persistent data storage
  • Cache

JetKV is used by the Jetzig Web Framework to provide a zero-setup, in-process key-value store for all of the above.

Checklist

  • ✅ In-memory storage.
  • ✅ String value storage.
  • ✅ Array value storage.
  • ✅ Array pop/queue implementation.
  • ✅ On-disk storage.
  • ❌ Key expiry.
  • ❌ Shared memory.

Usage

Memory Allocator

var kv = try JetKV.init(allocator, .{ .backend = .memory });

File Allocator

When using the file allocator, JetKV.init receives an allocator in order to provide a consistent API but does not perform any allocations. It is therefore possible to pass undefined instead of an allocator when using the file allocator.

The file passed as the path field is locked on startup.

var kv = try JetKV.init(
    allocator,
    .{
        .backend = .file,
        .file_backend_options = .{
            // Path to storage file (JetKV stores all data in a single, platform-agnostic file)
            .path = "/path/to/jetkv.db",
            // Set to `true` to clear the store on each launch.
            .truncate = false,
            // Set the size of the on-disk hash table (each address is currently 4 bytes)
            // Use `jetkv.addressSpaceSize` to guarantee a valid size if address size changes in future
            .address_space_size = jetkv.addressSpaceSize(4096),
        },
    },
);

Key-Value Operations

All operations are identical for .file and .memory backends.

All operations are O(1) complexity for both backends.

Read operations receive an allocator to allow separation of internal allocation and value reads. e.g. you may want to use one allocator for the KV store's internal storage and an arena allocator for reading values.

// Put some strings into the KV store
try kv.put("foo", "baz");
try kv.put("bar", "qux");

// `append` and `prepend` create a new array if one does not already exist
try kv.append("example_array", "quux");
try kv.prepend("example_array", "corge");

if (try kv.get(allocator, "foo")) |value| {
    // "baz"
    allocator.free(value);
}

if (try kv.fetchRemove(allocator, "bar")) |value| {
    // "qux"
    allocator.free(value);
}

// Remove a string from the KV store. Does not remove arrays.
try kv.remove("foo");

if (kv.pop(allocator, "example_array")) |value| {
    // "quux"
    allocator.free(value);
}

if (kv.popFirst(allocator, "example_array")) |value| {
    // "corge"
    allocator.free(value);
}

Implementation

Memory

The memory backend uses a Zig std.StringHashMap of []const u8 for string storage and std.DoublyLinkedList([]const u8) for array storage.

File

The file backend implements a fixed-sized hash table at the beginning of the file.

Hash collisions are resolved as singly-linked lists. Arrays are implemented as doubly-linked lists.

Each index in the hash table references a location in the file which provides address information:

  • Value type
  • Next linked item (for collision resolution)
  • Next array item
  • Previous array item
  • End array item
  • Key length
  • Initial key length
  • Value length
  • Initial value length
  • Key
  • Value

Values are inserted with a relative amount of over-allocation to allow re-use of space when replacing values.

Keys have a maximum length of 1024 bytes in order to allow key comparison to operate exclusively on the stack.

Reference counting is used to allow truncating the file when the store becomes empty.

License

MIT

jetkv's People

Contributors

bobf avatar

Stargazers

Leo Shimonaka avatar  avatar astrolemonade avatar

Watchers

 avatar  avatar

jetkv's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.