added configurable database path

This commit is contained in:
2026-02-15 00:44:49 +01:00
parent 7a79e8e803
commit 14b8234e77
10 changed files with 88 additions and 54 deletions

View File

@@ -13,25 +13,31 @@ source=(
) )
md5sums=('SKIP') # SKIP if local files md5sums=('SKIP') # SKIP if local files
build() { build() {
cd "$srcdir" cmake -S "${srcdir}" \
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -B build \
make -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build
} }
package() { package() {
install -Dm755 "$srcdir/${pkgname}" \ local src="${srcdir}"
# Binary (built by CMake into build/)
install -Dm755 "$src/build/${pkgname}" \
"$pkgdir/usr/bin/${pkgname}" "$pkgdir/usr/bin/${pkgname}"
# Frontend build output # Frontend build output
install -d "$pkgdir/usr/share/${pkgname}/frontend/build" install -d "$pkgdir/usr/share/${pkgname}/frontend/build"
cp -a "$srcdir/frontend/build/." \ cp -a "$src/frontend/build/." \
"$pkgdir/usr/share/${pkgname}/frontend/build" "$pkgdir/usr/share/${pkgname}/frontend/build/"
# Assets directory # Assets directory
install -d "$pkgdir/usr/share/${pkgname}/assets" install -d "$pkgdir/usr/share/${pkgname}/assets"
cp -a "$srcdir/assets/." \ cp -a "$src/assets/." \
"$pkgdir/usr/share/${pkgname}/assets/" "$pkgdir/usr/share/${pkgname}/assets/"
# systemd service # systemd service
install -Dm644 "$srcdir/shadowrun-server.service" \ install -Dm644 "$src/shadowrun-server.service" \
"$pkgdir/usr/lib/systemd/system/shadowrun-server.service" "$pkgdir/usr/lib/systemd/system/shadowrun-server.service"
} }

View File

@@ -1,3 +1,4 @@
{ {
"httpPort" : 3010 "http_port" : 3010,
"db_path": "/var/lib/shadowrun-server/shadowrun.db"
} }

View File

@@ -1,3 +1,4 @@
#include "databasepool.h" #include "databasepool.h"
DatabasePool dbpool(std::thread::hardware_concurrency()); std::unique_ptr<DatabasePool> dbpool = nullptr;

View File

@@ -6,12 +6,8 @@
#include "ShadowrunDb.hpp" #include "ShadowrunDb.hpp"
#include "loginDb.hpp" #include "loginDb.hpp"
namespace Database { inline auto make_database(const std::string& path) {
static constexpr std::string dbFile = "shadowrun.db"; auto storage = sqlite_orm::make_storage(path,
}
inline auto make_database() {
auto storage = sqlite_orm::make_storage(Database::dbFile,
sqlite_orm::make_table("users", sqlite_orm::make_table("users",
sqlite_orm::make_column("id", &login::User::id, sqlite_orm::primary_key()), sqlite_orm::make_column("id", &login::User::id, sqlite_orm::primary_key()),
sqlite_orm::make_column("username", &login::User::username, sqlite_orm::unique() ), sqlite_orm::make_column("username", &login::User::username, sqlite_orm::unique() ),

View File

@@ -7,19 +7,35 @@
class DatabasePool { class DatabasePool {
public: public:
DatabasePool(size_t size) { // Construct pool with path + size
// allow multithreaded access to database DatabasePool(const std::string& path)
: db_path(path)
{
// Enable multithreaded SQLite
assert(sqlite3_config(SQLITE_CONFIG_MULTITHREAD) == SQLITE_OK); assert(sqlite3_config(SQLITE_CONFIG_MULTITHREAD) == SQLITE_OK);
assert(sqlite3_initialize() == SQLITE_OK); assert(sqlite3_initialize() == SQLITE_OK);
}
bool init(size_t size){
try{
// Pre-create the pool
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
auto db = std::make_shared<decltype(make_database())>(make_database()); auto db = std::make_shared<decltype(make_database(db_path))>(make_database(db_path));
db->sync_schema(); db->sync_schema();
pool.push(db); pool.push(db);
} }
// init the database
auto db = acquire();
release(db);
return true;
}
catch (...) {
return false;
}
} }
std::shared_ptr<decltype(make_database())> acquire() { // Acquire a database connection from the pool
std::shared_ptr<decltype(make_database(std::string{}))> acquire() {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [&]{ return !pool.empty(); }); cv.wait(lock, [&]{ return !pool.empty(); });
auto db = pool.front(); auto db = pool.front();
@@ -27,7 +43,8 @@ public:
return db; return db;
} }
void release(std::shared_ptr<decltype(make_database())> db) { // Return a connection to the pool
void release(std::shared_ptr<decltype(make_database(std::string{}))> db) {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
pool.push(db); pool.push(db);
lock.unlock(); lock.unlock();
@@ -35,9 +52,10 @@ public:
} }
private: private:
std::queue<std::shared_ptr<decltype(make_database())>> pool; std::queue<std::shared_ptr<decltype(make_database(std::string{}))>> pool;
std::mutex mutex; std::mutex mutex;
std::condition_variable cv; std::condition_variable cv;
const std::string db_path;
}; };
extern DatabasePool dbpool; extern std::unique_ptr<DatabasePool> dbpool;

View File

@@ -10,7 +10,8 @@ using namespace::AppSettings;
Settings AppSettings::deafult(){ Settings AppSettings::deafult(){
return Settings { return Settings {
.httpPort = 3010 .http_port = 3010,
.db_path = "/var/lib/shadowrun-server/shadowrun.db"
}; };
} }

View File

@@ -2,17 +2,19 @@
#define JSON_SETTINGS_H #define JSON_SETTINGS_H
#include "json.hpp" #include "json.hpp"
#include <string>
namespace AppSettings { namespace AppSettings {
static constexpr char settingsFile[] = "assets/settings.json"; static constexpr char settingsFile[] = "assets/settings.json";
struct Settings { struct Settings {
int httpPort; int http_port;
std::string db_path;
}; };
Settings load(); Settings load();
Settings deafult(); Settings deafult();
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings, httpPort); NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings, http_port, db_path);
} }
#endif // JSON_SETTINGS_H #endif // JSON_SETTINGS_H

View File

@@ -59,7 +59,7 @@ int createUser(const std::string& username, const std::string& password){
return -1; return -1;
int64_t id = -1; int64_t id = -1;
auto db = dbpool.acquire(); auto db = dbpool->acquire();
for (auto &u : db->get_all<login::User>()) { for (auto &u : db->get_all<login::User>()) {
if (u.username == username){ if (u.username == username){
@@ -73,16 +73,16 @@ int createUser(const std::string& username, const std::string& password){
createPasswordHash(usr, password); createPasswordHash(usr, password);
id = db->insert(usr); id = db->insert(usr);
} }
dbpool.release(db); dbpool->release(db);
return id; return id;
} }
std::optional<User> getUser(const std::string& username){ std::optional<User> getUser(const std::string& username){
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto user = db->get_all<login::User>( auto user = db->get_all<login::User>(
where(c(&login::User::username) == username) where(c(&login::User::username) == username)
); );
dbpool.release(db); dbpool->release(db);
if(user.size() > 0){ if(user.size() > 0){
return user[0]; return user[0];

View File

@@ -4,23 +4,26 @@
#include "utils.hpp" #include "utils.hpp"
#include "login.hpp" #include "login.hpp"
#include "ShadowrunApi.hpp" #include "ShadowrunApi.hpp"
#include "databasepool.h"
using namespace std; using namespace std;
int main() { int main() {
crow::SimpleApp app; crow::SimpleApp app;
// Root route
CROW_ROUTE(app, "/")([&]() {
auto data = utils::read_file(utils::build_dir / "index.html");
return crow::response(200, "text/html", data);
});
auto settings = AppSettings::load(); auto settings = AppSettings::load();
auto opt_isPortOpen = utils::isLocalPortOpen(settings.httpPort);
// create global database
dbpool = std::make_unique<DatabasePool>(settings.db_path);
if (!dbpool->init(std::thread::hardware_concurrency())){
CROW_LOG_ERROR << "Failed to create database at : " << settings.db_path;
return 1;
}
auto opt_isPortOpen = utils::isLocalPortOpen(settings.http_port);
if (opt_isPortOpen.has_value()){ if (opt_isPortOpen.has_value()){
if (opt_isPortOpen.value()){ if (opt_isPortOpen.value()){
CROW_LOG_ERROR << "Local port : " << settings.httpPort << " is already open"; CROW_LOG_ERROR << "Local port : " << settings.http_port << " is already open";
return 1; return 1;
} }
} }
@@ -29,6 +32,12 @@ int main() {
return 1; return 1;
} }
// Root route
CROW_ROUTE(app, "/")([&]() {
auto data = utils::read_file(utils::build_dir / "index.html");
return crow::response(200, "text/html", data);
});
shadowrun::initApi(app); shadowrun::initApi(app);
login::initLogin(app); login::initLogin(app);
@@ -53,5 +62,5 @@ int main() {
}); });
app.loglevel(crow::LogLevel::INFO); app.loglevel(crow::LogLevel::INFO);
app.bindaddr("0.0.0.0").port(settings.httpPort).multithreaded().run(); app.bindaddr("0.0.0.0").port(settings.http_port).multithreaded().run();
} }

View File

@@ -14,7 +14,7 @@ int64_t createCharacter(const string& name){
return -1; return -1;
int64_t id; int64_t id;
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto character = db->get_optional<ShadowrunCharacter>( auto character = db->get_optional<ShadowrunCharacter>(
where(c(&ShadowrunCharacter::name) == name) where(c(&ShadowrunCharacter::name) == name)
@@ -26,38 +26,38 @@ int64_t createCharacter(const string& name){
auto c = newShadowrunCharacter(name); auto c = newShadowrunCharacter(name);
id = db->insert(c); id = db->insert(c);
} }
dbpool.release(db); dbpool->release(db);
return id; return id;
} }
std::vector<ShadowrunCharacter> getCharacters(){ std::vector<ShadowrunCharacter> getCharacters(){
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto characters = db->get_all<ShadowrunCharacter>(); auto characters = db->get_all<ShadowrunCharacter>();
dbpool.release(db); dbpool->release(db);
return characters; return characters;
} }
optional<ShadowrunCharacter> getChracter(int id) optional<ShadowrunCharacter> getChracter(int id)
{ {
auto db = dbpool.acquire(); auto db = dbpool->acquire();
optional<ShadowrunCharacter> character = db->get_optional<ShadowrunCharacter>(id); optional<ShadowrunCharacter> character = db->get_optional<ShadowrunCharacter>(id);
dbpool.release(db); dbpool->release(db);
return character; return character;
} }
vector<ShadowrunCharacterData> getChracterData(int character_id) vector<ShadowrunCharacterData> getChracterData(int character_id)
{ {
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto characterData = db->get_all<ShadowrunCharacterData>( auto characterData = db->get_all<ShadowrunCharacterData>(
where(c(&ShadowrunCharacterData::character_id) == character_id) where(c(&ShadowrunCharacterData::character_id) == character_id)
); );
dbpool.release(db); dbpool->release(db);
return characterData; return characterData;
} }
int storeCharacterData(int characterId, const Type type, const string& json){ int storeCharacterData(int characterId, const Type type, const string& json){
int id; int id;
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto characterData = db->get_all<ShadowrunCharacterData>( auto characterData = db->get_all<ShadowrunCharacterData>(
where( where(
(c(&ShadowrunCharacterData::character_id) == characterId) and (c(&ShadowrunCharacterData::character_id) == characterId) and
@@ -78,13 +78,13 @@ int storeCharacterData(int characterId, const Type type, const string& json){
db->update(character); db->update(character);
id = character.id; id = character.id;
} }
dbpool.release(db); dbpool->release(db);
return id; return id;
} }
int storeCharacterData(const ShadowrunCharacterData& data){ int storeCharacterData(const ShadowrunCharacterData& data){
int id; int id;
auto db = dbpool.acquire(); auto db = dbpool->acquire();
auto characterData = db->get_optional<ShadowrunCharacterData>(data.id); auto characterData = db->get_optional<ShadowrunCharacterData>(data.id);
if(!characterData.has_value()){ if(!characterData.has_value()){
@@ -94,7 +94,7 @@ int storeCharacterData(const ShadowrunCharacterData& data){
db->update(data); db->update(data);
id = data.id; id = data.id;
} }
dbpool.release(db); dbpool->release(db);
return id; return id;
} }