mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(cdclient): open the client's fdb next to CDServer.sqlite
CDFdb opens cdclient.fdb once per process and hands out a table when its columns match the CDServer.sqlite table of the same name. CDServer.sqlite stays the source of truth: the CDServer migrations change a few rows, so FindChangedKeys compares both files row by row (a hash per row, summed per key) and returns the keys that differ, for the tables to read from SQLite. RowFields reads an fdb row with CppSQLite3Query's accessors and defaults, so a table fills its entries from either file with one piece of code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
72
dDatabase/CDClientDatabase/CDFdb.h
Normal file
72
dDatabase/CDClientDatabase/CDFdb.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef CDFDB_H
|
||||
#define CDFDB_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "FdbReader.h"
|
||||
|
||||
/**
|
||||
* Reading CDClient tables straight from the client's cdclient.fdb.
|
||||
*
|
||||
* The fdb is mapped read-only, so every server process on the machine shares one copy of it
|
||||
* through the OS page cache, and a row is found through the fdb's own hash buckets instead of
|
||||
* a per-process cache of the whole table.
|
||||
*
|
||||
* CDServer.sqlite stays the source of truth: the server's CDServer migrations change a few rows
|
||||
* of it, so at load each table compares its rows in both files and reads the keys that differ
|
||||
* from SQLite (see FindChangedKeys).
|
||||
*/
|
||||
namespace CDFdb {
|
||||
/**
|
||||
* Opens the fdb. Does nothing and returns false if the file is missing or unreadable, and
|
||||
* then the tables keep reading CDServer.sqlite as before.
|
||||
*/
|
||||
bool Open(const std::filesystem::path& path, bool allowMapping = true);
|
||||
void Close();
|
||||
|
||||
// The open fdb, or nullptr
|
||||
const FdbReader* Get();
|
||||
|
||||
/**
|
||||
* The fdb table that can stand in for the SQLite table of the same name: it exists in both,
|
||||
* has the same columns in the same order, and its first column is an integer. nullptr otherwise.
|
||||
*/
|
||||
const FdbReader::Table* GetTable(const std::string& name);
|
||||
|
||||
/**
|
||||
* The first-column keys whose rows differ between the fdb table and the SQLite table of the
|
||||
* same name (values compared by type and content, rows as a set per key). Keys only in one of
|
||||
* the two are included. nullopt if the tables can't be compared.
|
||||
*/
|
||||
std::optional<std::vector<int64_t>> FindChangedKeys(const FdbReader::Table& table);
|
||||
|
||||
/**
|
||||
* Reads one fdb row with the same accessors, defaults and conversions as CppSQLite3Query, so
|
||||
* a table can fill its entries from either source with the same code.
|
||||
*/
|
||||
class RowFields {
|
||||
public:
|
||||
RowFields(const FdbReader::Table& table, const FdbReader::Row& row);
|
||||
|
||||
int getIntField(const char* field, int nullValue = 0) const;
|
||||
int64_t getInt64Field(const char* field, int64_t nullValue = 0) const;
|
||||
double getFloatField(const char* field, double nullValue = 0.0) const;
|
||||
std::string getStringField(const char* field, const char* nullValue = "") const;
|
||||
bool fieldIsNull(const char* field) const;
|
||||
|
||||
private:
|
||||
// -1 when the table has no such column, which reads as null
|
||||
int32_t Column(const char* field) const;
|
||||
|
||||
const FdbReader::Table& m_Table;
|
||||
const FdbReader::Row& m_Row;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // CDFDB_H
|
||||
Reference in New Issue
Block a user