telodendria/include/Cytoplasm/Db.h
LDA b87979e9a2 [MOD/WIP] Start separating the main DB API
Not everything is available as of now, I'm still working on it, but it
builds and seems to work, and its 9PM, so that's worthapush.
2024-08-07 20:45:53 +02:00

179 lines
6.1 KiB
C

/*
* Copyright (C) 2022-2024 Jordan Bancino <@jordan:bancino.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef CYTOPLASM_DB_H
#define CYTOPLASM_DB_H
/***
* @Nm Db
* @Nd A minimal flat-file database with mutex locking and cache.
* @Dd April 27 2023
* @Xr Json
*
* Cytoplasm operates on a flat-file database instead of a
* traditional relational database. This greatly simplifies the
* persistent storage code, and creates a relatively basic API,
* described here.
*/
#include <stddef.h>
#include <stdbool.h>
#include "HashMap.h"
#include "Array.h"
/**
* All functions in this API operate on a database structure that is
* opaque to the caller.
*/
typedef struct Db Db;
/**
* When an object is locked, a reference is returned. This reference
* is owned by the current thread, and the database is inaccessible to
* other threads until all references have been returned to the
* database.
* .Pp
* This reference is opaque, but can be manipulated by the functions
* defined here.
*/
typedef struct DbRef DbRef;
/**
* Open a data directory. This function takes a path to open, and a
* cache size in bytes. If the cache size is 0, then caching is
* disabled and objects are loaded off the disk every time they are
* locked. Otherwise, objects are stored in the cache, and they are
* evicted in a least-recently-used manner.
*/
extern Db * DbOpen(char *, size_t);
/**
* Open a LMDB data directory. This function is similar to
* .Fn DbOpen ,
* but works with a LMDB-based backend, with the second argument
* being the maximum filesize. This function fails with NULL if ever
* called without LMDB enabled at compiletime.
*/
extern Db * DbOpenLMDB(char *, size_t);
/**
* Close the database. This function will flush anything in the cache
* to the disk, and then close the data directory. It assumes that
* all references have been unlocked. If a reference has not been
* unlocked, undefined behavior results.
*/
extern void DbClose(Db *);
/**
* Set the maximum cache size allowed before
* .Nm
* starts evicting old objects. If this is set to 0, everything in the
* cache is immediately evicted and caching is disabled. If the
* database was opened with a cache size of 0, setting this will
* initialize the cache, and subsequent calls to
* .Fn DbLock
* will begin caching objects.
*/
extern void DbMaxCacheSet(Db *, size_t);
/**
* Create a new object in the database with the specified name. This
* function will fail if the object already exists in the database. It
* takes a variable number of C strings, with the exact number being
* specified by the second parameter. These C strings are used to
* generate a filesystem path at which to store the object. These paths
* ensure each object is uniquely identifiable, and provides semantic
* meaning to an object.
*/
extern DbRef * DbCreate(Db *, size_t,...);
/**
* Lock an existing object in the database. This function will fail
* if the object does not exist. It takes a variable number of C
* strings, with the exact number being specified by the second
* parameter. These C strings are used to generate the filesystem path
* at which to load the object. These paths ensure each object is
* uniquely identifiable, and provides semantic meaning to an object.
*/
extern DbRef * DbLock(Db *, size_t,...);
/**
* Immediately and permanently remove an object from the database.
* This function assumes the object is not locked, otherwise undefined
* behavior will result.
*/
extern bool DbDelete(Db *, size_t,...);
/**
* Unlock an object and return it back to the database. This function
* immediately syncs the object to the filesystem. The cache is a
* read cache; writes are always immediate to ensure data integrity in
* the event of a system failure.
*/
extern bool DbUnlock(Db *, DbRef *);
/**
* Check the existence of the given database object in a more efficient
* manner than attempting to lock it with
* .Fn DbLock .
* This function does not lock the object, nor does it load it into
* memory if it exists.
*/
extern bool DbExists(Db *, size_t,...);
/**
* List all of the objects at a given path. Unlike the other varargs
* functions, this one does not take a path to a specific object; it
* takes a directory to be iterated, where each path part is its own
* C string. Note that the resulting list only contains the objects
* in the specified directory, it does not list any subdirectories.
* .Pp
* The array returned is an array of C strings containing the object
* name.
*/
extern Array * DbList(Db *, size_t,...);
/**
* Free the list returned by
* .Fn DbListFree .
*/
extern void DbListFree(Array *);
/**
* Convert a database reference into JSON that can be manipulated.
* At this time, the database actually stores objects as JSON on the
* disk, so this function just returns an internal pointer, but in the
* future it may have to be generated by decompressing a binary blob,
* or something of that nature.
*/
extern HashMap * DbJson(DbRef *);
/**
* Free the existing JSON associated with the given reference, and
* replace it with new JSON. This is more efficient than duplicating
* a separate object into the database reference.
*/
extern bool DbJsonSet(DbRef *, HashMap *);
#endif