diff --git a/PKGBUILD b/PKGBUILD index 64ab212..a057d7f 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -13,25 +13,31 @@ source=( ) md5sums=('SKIP') # SKIP if local files build() { - cd "$srcdir" - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr - make + cmake -S "${srcdir}" \ + -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr + + cmake --build build } package() { - install -Dm755 "$srcdir/${pkgname}" \ + local src="${srcdir}" + + # Binary (built by CMake into build/) + install -Dm755 "$src/build/${pkgname}" \ "$pkgdir/usr/bin/${pkgname}" # Frontend build output install -d "$pkgdir/usr/share/${pkgname}/frontend/build" - cp -a "$srcdir/frontend/build/." \ - "$pkgdir/usr/share/${pkgname}/frontend/build" + cp -a "$src/frontend/build/." \ + "$pkgdir/usr/share/${pkgname}/frontend/build/" # Assets directory install -d "$pkgdir/usr/share/${pkgname}/assets" - cp -a "$srcdir/assets/." \ + cp -a "$src/assets/." \ "$pkgdir/usr/share/${pkgname}/assets/" # systemd service - install -Dm644 "$srcdir/shadowrun-server.service" \ + install -Dm644 "$src/shadowrun-server.service" \ "$pkgdir/usr/lib/systemd/system/shadowrun-server.service" } \ No newline at end of file diff --git a/assets/settings.json b/assets/settings.json index 6bb46b7..bd6747c 100644 --- a/assets/settings.json +++ b/assets/settings.json @@ -1,3 +1,4 @@ { - "httpPort" : 3010 + "http_port" : 3010, + "db_path": "/var/lib/shadowrun-server/shadowrun.db" } \ No newline at end of file diff --git a/src/database/database.cpp b/src/database/database.cpp index 4680b36..fe96507 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -1,3 +1,4 @@ #include "databasepool.h" -DatabasePool dbpool(std::thread::hardware_concurrency()); \ No newline at end of file +std::unique_ptr dbpool = nullptr; + diff --git a/src/database/database.hpp b/src/database/database.hpp index 94bce4b..f8d1d14 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -6,12 +6,8 @@ #include "ShadowrunDb.hpp" #include "loginDb.hpp" -namespace Database { - static constexpr std::string dbFile = "shadowrun.db"; -} - -inline auto make_database() { - auto storage = sqlite_orm::make_storage(Database::dbFile, +inline auto make_database(const std::string& path) { + auto storage = sqlite_orm::make_storage(path, sqlite_orm::make_table("users", sqlite_orm::make_column("id", &login::User::id, sqlite_orm::primary_key()), sqlite_orm::make_column("username", &login::User::username, sqlite_orm::unique() ), diff --git a/src/database/databasepool.h b/src/database/databasepool.h index 0b34b47..7388df7 100644 --- a/src/database/databasepool.h +++ b/src/database/databasepool.h @@ -7,19 +7,35 @@ class DatabasePool { public: - DatabasePool(size_t size) { - // allow multithreaded access to database + // Construct pool with path + size + DatabasePool(const std::string& path) + : db_path(path) + { + // Enable multithreaded SQLite assert(sqlite3_config(SQLITE_CONFIG_MULTITHREAD) == SQLITE_OK); assert(sqlite3_initialize() == SQLITE_OK); + } - for (size_t i = 0; i < size; ++i){ - auto db = std::make_shared(make_database()); - db->sync_schema(); - pool.push(db); + bool init(size_t size){ + try{ + // Pre-create the pool + for (size_t i = 0; i < size; ++i) { + auto db = std::make_shared(make_database(db_path)); + db->sync_schema(); + pool.push(db); + } + // init the database + auto db = acquire(); + release(db); + return true; + } + catch (...) { + return false; } } - std::shared_ptr acquire() { + // Acquire a database connection from the pool + std::shared_ptr acquire() { std::unique_lock lock(mutex); cv.wait(lock, [&]{ return !pool.empty(); }); auto db = pool.front(); @@ -27,7 +43,8 @@ public: return db; } - void release(std::shared_ptr db) { + // Return a connection to the pool + void release(std::shared_ptr db) { std::unique_lock lock(mutex); pool.push(db); lock.unlock(); @@ -35,9 +52,10 @@ public: } private: - std::queue> pool; + std::queue> pool; std::mutex mutex; std::condition_variable cv; + const std::string db_path; }; -extern DatabasePool dbpool; \ No newline at end of file +extern std::unique_ptr dbpool; \ No newline at end of file diff --git a/src/json_settings.cpp b/src/json_settings.cpp index 007568a..106fbee 100644 --- a/src/json_settings.cpp +++ b/src/json_settings.cpp @@ -10,7 +10,8 @@ using namespace::AppSettings; Settings AppSettings::deafult(){ return Settings { - .httpPort = 3010 + .http_port = 3010, + .db_path = "/var/lib/shadowrun-server/shadowrun.db" }; } diff --git a/src/json_settings.h b/src/json_settings.h index 6dd363f..88aea3d 100644 --- a/src/json_settings.h +++ b/src/json_settings.h @@ -2,17 +2,19 @@ #define JSON_SETTINGS_H #include "json.hpp" +#include namespace AppSettings { static constexpr char settingsFile[] = "assets/settings.json"; struct Settings { - int httpPort; + int http_port; + std::string db_path; }; Settings load(); Settings deafult(); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings, httpPort); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings, http_port, db_path); } #endif // JSON_SETTINGS_H \ No newline at end of file diff --git a/src/login/loginDb.cpp b/src/login/loginDb.cpp index f8e7f7b..183b28a 100644 --- a/src/login/loginDb.cpp +++ b/src/login/loginDb.cpp @@ -59,7 +59,7 @@ int createUser(const std::string& username, const std::string& password){ return -1; int64_t id = -1; - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); for (auto &u : db->get_all()) { if (u.username == username){ @@ -73,16 +73,16 @@ int createUser(const std::string& username, const std::string& password){ createPasswordHash(usr, password); id = db->insert(usr); } - dbpool.release(db); + dbpool->release(db); return id; } std::optional getUser(const std::string& username){ - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto user = db->get_all( where(c(&login::User::username) == username) ); - dbpool.release(db); + dbpool->release(db); if(user.size() > 0){ return user[0]; diff --git a/src/main.cpp b/src/main.cpp index 56b7cee..36461db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,23 +4,26 @@ #include "utils.hpp" #include "login.hpp" #include "ShadowrunApi.hpp" +#include "databasepool.h" using namespace std; int main() { 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 opt_isPortOpen = utils::isLocalPortOpen(settings.httpPort); + + // create global database + dbpool = std::make_unique(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.value()){ - CROW_LOG_ERROR << "Local port : " << settings.httpPort << " is already open"; + CROW_LOG_ERROR << "Local port : " << settings.http_port << " is already open"; return 1; } } @@ -29,6 +32,12 @@ int main() { 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); login::initLogin(app); @@ -53,5 +62,5 @@ int main() { }); 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(); } diff --git a/src/shadowrun/ShadowrunDb.cpp b/src/shadowrun/ShadowrunDb.cpp index 15c34be..7530bf3 100644 --- a/src/shadowrun/ShadowrunDb.cpp +++ b/src/shadowrun/ShadowrunDb.cpp @@ -14,7 +14,7 @@ int64_t createCharacter(const string& name){ return -1; int64_t id; - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto character = db->get_optional( where(c(&ShadowrunCharacter::name) == name) @@ -26,38 +26,38 @@ int64_t createCharacter(const string& name){ auto c = newShadowrunCharacter(name); id = db->insert(c); } - dbpool.release(db); + dbpool->release(db); return id; } std::vector getCharacters(){ - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto characters = db->get_all(); - dbpool.release(db); + dbpool->release(db); return characters; } optional getChracter(int id) { - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); optional character = db->get_optional(id); - dbpool.release(db); + dbpool->release(db); return character; } vector getChracterData(int character_id) { - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto characterData = db->get_all( where(c(&ShadowrunCharacterData::character_id) == character_id) ); - dbpool.release(db); + dbpool->release(db); return characterData; } int storeCharacterData(int characterId, const Type type, const string& json){ int id; - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto characterData = db->get_all( where( (c(&ShadowrunCharacterData::character_id) == characterId) and @@ -78,13 +78,13 @@ int storeCharacterData(int characterId, const Type type, const string& json){ db->update(character); id = character.id; } - dbpool.release(db); + dbpool->release(db); return id; } int storeCharacterData(const ShadowrunCharacterData& data){ int id; - auto db = dbpool.acquire(); + auto db = dbpool->acquire(); auto characterData = db->get_optional(data.id); if(!characterData.has_value()){ @@ -94,7 +94,7 @@ int storeCharacterData(const ShadowrunCharacterData& data){ db->update(data); id = data.id; } - dbpool.release(db); + dbpool->release(db); return id; }