added configurable database path
This commit is contained in:
22
PKGBUILD
22
PKGBUILD
@@ -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"
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"httpPort" : 3010
|
"http_port" : 3010,
|
||||||
|
"db_path": "/var/lib/shadowrun-server/shadowrun.db"
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
#include "databasepool.h"
|
#include "databasepool.h"
|
||||||
|
|
||||||
DatabasePool dbpool(std::thread::hardware_concurrency());
|
std::unique_ptr<DatabasePool> dbpool = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -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() ),
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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];
|
||||||
|
|||||||
27
src/main.cpp
27
src/main.cpp
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user