mirror of
https://github.com/MeshEnvy/lobbs.git
synced 2026-11-07 05:22:24 +01:00
120 lines
3.6 KiB
C++
120 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <lofs/LoFS.h>
|
|
#include <loscalar/LoScalar.h>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
/**
|
|
* LoDB - Synchronous LoScalar Database
|
|
*
|
|
* Filesystem-backed records under `<root>/<name>` after `open(root)`. I/O goes through LoFS.
|
|
*/
|
|
|
|
#ifndef LODB_VERSION
|
|
#define LODB_VERSION "2.0.0"
|
|
#endif
|
|
|
|
/**
|
|
* Max encoded record size (single knob): insert/update encode buffer and get() read cap.
|
|
*/
|
|
#ifndef LODB_MAX_RECORD_BYTES
|
|
#define LODB_MAX_RECORD_BYTES 1024
|
|
#endif
|
|
#ifndef LODB_FILE_IO_BUFFER_SIZE
|
|
#define LODB_FILE_IO_BUFFER_SIZE LODB_MAX_RECORD_BYTES
|
|
#endif
|
|
#ifndef LODB_MAX_RECORD_FILE_BYTES
|
|
#define LODB_MAX_RECORD_FILE_BYTES LODB_MAX_RECORD_BYTES
|
|
#endif
|
|
|
|
#ifndef LODB_LOG_DEBUG
|
|
#define LODB_LOG_DEBUG(...) ((void)0)
|
|
#endif
|
|
#ifndef LODB_LOG_INFO
|
|
#define LODB_LOG_INFO(...) ((void)0)
|
|
#endif
|
|
#ifndef LODB_LOG_WARN
|
|
#define LODB_LOG_WARN(...) ((void)0)
|
|
#endif
|
|
#ifndef LODB_LOG_ERROR
|
|
#define LODB_LOG_ERROR(...) ((void)0)
|
|
#endif
|
|
|
|
typedef uint64_t lodb_uuid_t;
|
|
|
|
#define LODB_UUID_FMT "%08x%08x"
|
|
#define LODB_UUID_ARGS(uuid) (uint32_t)((uuid) >> 32), (uint32_t)((uuid)&0xFFFFFFFF)
|
|
|
|
typedef enum {
|
|
LODB_OK = 0,
|
|
LODB_ERR_NOT_FOUND,
|
|
LODB_ERR_IO,
|
|
LODB_ERR_DECODE,
|
|
LODB_ERR_ENCODE,
|
|
LODB_ERR_INVALID,
|
|
/** Write refused or cut short: the mount lacks room above its reserve (`LoFS::hasRoom`). */
|
|
LODB_ERR_FULL
|
|
} LoDbError;
|
|
|
|
typedef std::function<bool(const LoScalar &)> LoDbFilter;
|
|
typedef std::function<int(const LoScalar &, const LoScalar &)> LoDbComparator;
|
|
|
|
/** LoScalar field numbers are 0..99 inclusive. */
|
|
static constexpr uint32_t LODB_F_MAX = 99;
|
|
/** App fields use 0 .. LODB_F_USER_LIMIT - 1. */
|
|
static constexpr uint32_t LODB_F_USER_LIMIT = 94;
|
|
|
|
static constexpr uint32_t LODB_F_ERROR = 94;
|
|
static constexpr uint32_t LODB_F_UPDATED = 95;
|
|
static constexpr uint32_t LODB_F_CREATED = 96;
|
|
static constexpr uint32_t LODB_F_DESCRIPTION = 97;
|
|
static constexpr uint32_t LODB_F_TITLE = 98;
|
|
static constexpr uint32_t LODB_F_ID = 99;
|
|
|
|
void lodb_uuid_to_hex(lodb_uuid_t uuid, char hex_out[17]);
|
|
lodb_uuid_t lodb_new_uuid(const char *str, uint64_t salt);
|
|
|
|
/** Weak by default (`millis()`); override with a strong definition for wall time. */
|
|
uint32_t lodb_now_ms(void);
|
|
/** Unix seconds from getTime() when RTC is linked; else 0. */
|
|
uint32_t lodb_now_unix(void);
|
|
|
|
class LoDb
|
|
{
|
|
public:
|
|
LoDb(const char *db_name);
|
|
~LoDb();
|
|
|
|
bool isOpen() const { return opened_; }
|
|
LoDbError open(const char *root);
|
|
LoDbError registerTable(const char *table_name);
|
|
LoDbError insert(const char *table_name, lodb_uuid_t uuid, const LoScalar &record);
|
|
LoDbError get(const char *table_name, lodb_uuid_t uuid, LoScalar &record_out);
|
|
LoDbError update(const char *table_name, lodb_uuid_t uuid, const LoScalar &record);
|
|
LoDbError upsert(const char *table_name, lodb_uuid_t uuid, const LoScalar &record);
|
|
LoDbError deleteRecord(const char *table_name, lodb_uuid_t uuid);
|
|
std::vector<LoScalar> select(const char *table_name, LoDbFilter filter = LoDbFilter(),
|
|
LoDbComparator comparator = LoDbComparator(), size_t limit = 0);
|
|
int count(const char *table_name, LoDbFilter filter = LoDbFilter());
|
|
|
|
private:
|
|
struct TableMetadata {
|
|
std::string table_name;
|
|
char table_path[160];
|
|
};
|
|
|
|
std::string db_name;
|
|
char db_path[128];
|
|
bool opened_ = false;
|
|
std::map<std::string, TableMetadata> tables;
|
|
|
|
TableMetadata *getTable(const char *table_name);
|
|
bool recordPath(const char *table_name, lodb_uuid_t uuid, char *out, size_t cap);
|
|
static bool mkdirPathSegments(const char *path);
|
|
};
|