diff --git a/db2/create_sqlite3.sql b/db2/create_sqlite3.sql new file mode 100644 index 0000000..e43a1d3 --- /dev/null +++ b/db2/create_sqlite3.sql @@ -0,0 +1,39 @@ +-- Users 表创建脚本 +-- 数据库类型: SQLite + +CREATE TABLE IF NOT EXISTS Users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password_hash TEXT NOT NULL, + create_at DATETIME DEFAULT CURRENT_TIMESTAMP, + last_login DATETIME, + is_active BOOLEAN DEFAULT 1 +); + +CREATE TABLE IF NOT EXISTS Notes ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + pid INTEGER NOT NULL, + owner VARCHAR(128) DEFAULT 'Unknow', + title VARCHAR(128) NOT NULL, + content TEXT NOT NULL +); + +-- 旧版增量 +-- ALTER TABLE Notes ADD COLUMN owner VARCHAR(128) DEFAULT 'Unknow'; + +-- ── 日志表(db 内置日志模块)───────────────────────────────────────── + +CREATE TABLE IF NOT EXISTS Logs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ts TEXT NOT NULL, + service TEXT NOT NULL, + level TEXT NOT NULL, + message TEXT NOT NULL, + trace_id TEXT, + extra TEXT +); + +CREATE INDEX IF NOT EXISTS idx_logs_service_ts ON Logs(service, ts); +CREATE INDEX IF NOT EXISTS idx_logs_level_ts ON Logs(level, ts); +CREATE INDEX IF NOT EXISTS idx_logs_ts ON Logs(ts); +CREATE INDEX IF NOT EXISTS idx_logs_trace ON Logs(trace_id); diff --git a/libmemdb/.gitignore b/libmemdb/.gitignore new file mode 100644 index 0000000..f152158 --- /dev/null +++ b/libmemdb/.gitignore @@ -0,0 +1,69 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Linker files +*.ilk + +# Debugger Files +*.pdb + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll +*.so.* + + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Build directories +build/ +Build/ +build-*/ + +# CMake generated files +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +#Makefile +install_manifest.txt +compile_commands.json + +# Temporary files +*.tmp +*.log +*.bak +*.swp + +# vcpkg +vcpkg_installed/ + +# debug information files +*.dwo + +# test output & cache +Testing/ +.cache/ diff --git a/libmemdb/Makefile b/libmemdb/Makefile new file mode 100644 index 0000000..43ecf59 --- /dev/null +++ b/libmemdb/Makefile @@ -0,0 +1,25 @@ +VERSION := 1.0.0 +FRAMEWORK_NAME := us +LIB_NAME := libus_memdb +INSTL_TDIR := /lib +INCLU_TDIR := /usr/include +INCLU_SDIR := inc +CPP := g++ +INCS := -I inc +CPPFLAGS := --std=c++20 -O3 -pipe -Wall -Werror +LIBS := +BUILD_TDIR := build +$(shell mkdir -p $(BUILD_TDIR)) + + + +install: + @echo "install UniServe_libmemdb..." + @mkdir -vp $(INCLU_TDIR)/${FRAMEWORK_NAME} + @cp -vf $(INCLU_SDIR)/$(FRAMEWORK_NAME)/memdb.hpp $(INCLU_TDIR)/$(FRAMEWORK_NAME)/ + @echo "done." + +uninstall: + @echo "uninstall UniServe_libmemdb..." + @rm -vf $(INCLU_TDIR)/$(FRAMEWORK_NAME)/memdb.hpp + @echo "done." \ No newline at end of file diff --git a/libmemdb/README.md b/libmemdb/README.md new file mode 100644 index 0000000..f6805f9 --- /dev/null +++ b/libmemdb/README.md @@ -0,0 +1,5 @@ +# UniServe_libmemdb +UniServe Framework memdb Library + +# Dependancy +libmemdb-dev diff --git a/libmemdb/_set.sh b/libmemdb/_set.sh new file mode 100644 index 0000000..d3c371b --- /dev/null +++ b/libmemdb/_set.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd "$(dirname "$0")" || exit +make install \ No newline at end of file diff --git a/libmemdb/inc/us/memdb.hpp b/libmemdb/inc/us/memdb.hpp new file mode 100644 index 0000000..ec3873a --- /dev/null +++ b/libmemdb/inc/us/memdb.hpp @@ -0,0 +1,148 @@ +#pragma once +#include +#include +#include +#include +#include +#include + + + +template + +class Memdb { + + +struct memdb_column { + T key; + U value; + std::chrono::system_clock::time_point timestamp; +}; + +struct index_keys { + T key; + std::list ::iterator item; +}; + +struct index_timestamp { + std::list ::iterator item; + + bool operator<(const index_timestamp& a) const { + return this -> item -> timestamp < a.item -> timestamp; + } +}; + + +private: + std::list db; + std::unordered_map keys; + std::multiset time_touch; + size_t __size = 0; + int MAX_TIME = 60 * 10; // 10分钟 + void flush(); + + + +public: + using key_t = T; + using value_t = U; + static constexpr bool fail = false; + static constexpr bool succ = true; + + + + explicit Memdb() = default; + explicit Memdb(int max_time) : MAX_TIME(std::max(0, max_time)) {} + explicit Memdb& operator=(const Memdb& to_be_cp_memdb) = default; + explicit ~Memdb() = default; + + + size_t size() const { + return this -> __size; + } + + const std::unordered_map & get_keys() const { + return this -> keys; + } + + const std::list & get_db() const { + return this -> db; + } + + const std::multiset ::index_timestamp>& get_time_touch() const { + return this -> time_touch; + } + + + bool insert(key_t to_be_ins_k, value_t ins_v) { + this -> flush(); + if (this -> keys.find(to_be_ins_k) != this -> keys.end()) { + return this -> fail; + } + + std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now(); + + Memdb::memdb_column new_column; + new_column.key = to_be_ins_k; + new_column.value = ins_v; + new_column.timestamp = now_time + std::chrono::seconds(MAX_TIME); + this -> db.push_back(new_column); + + Memdb::index_keys new_key; + new_key.key = to_be_ins_k; + new_key.item = std::prev(this -> db.end()); + this -> keys[to_be_ins_k] = new_key; + + Memdb::index_timestamp new_time_touch; + new_time_touch.item = std::prev(this -> db.end()); + this -> time_touch.insert(new_time_touch); + + this -> __size++; + + return this -> succ; + } + + bool remove(key_t to_be_del_k) { + this -> flush(); + if (this -> keys.find(to_be_del_k) == this -> keys.end()) { + return this -> fail; + } + + typename std::list ::iterator it = this -> keys[to_be_del_k].item; + this -> keys.erase(it -> key); + this -> time_touch.erase({it}); + this -> db.erase(it); + this -> __size--; + + return this -> succ; + } + + bool update(key_t to_be_udt_k, value_t udt_v, bool need_to_udt_timetouch=false) { + this -> flush(); + if (this -> keys.find(to_be_udt_k) == this -> keys.end()) { + return this -> fail; + } + + typename std::list ::iterator it = this -> keys[to_be_udt_k].item; + it -> value = udt_v; + if (need_to_udt_timetouch == true) { + std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now(); + T copy_k = it -> key; + U copy_v = it -> value; + this -> remove(copy_k); + this -> insert(copy_k, copy_v); + } + + return this -> succ; + } + + std::optional search(key_t to_be_sch_k) { + this -> flush(); + if (this -> keys.find(to_be_sch_k) == this -> keys.end()) { + return std::nullopt; + } + + typename std::list ::iterator it = this -> keys[to_be_sch_k].item; + return it -> value; + } +}; \ No newline at end of file diff --git a/memdb/.gitignore b/memdb/.gitignore new file mode 100644 index 0000000..839a556 --- /dev/null +++ b/memdb/.gitignore @@ -0,0 +1,72 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Linker files +*.ilk + +# Debugger Files +*.pdb + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll +*.so.* + + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Build directories +build/ +Build/ +build-*/ + +# CMake generated files +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +#Makefile +install_manifest.txt +compile_commands.json + +# Temporary files +*.tmp +*.log +*.bak +*.swp + +# vcpkg +vcpkg_installed/ + +# debug information files +*.dwo + +# test output & cache +Testing/ +.cache/ + +# Databases +*.db* \ No newline at end of file diff --git a/memdb/src/main.cpp b/memdb/Makefile similarity index 100% rename from memdb/src/main.cpp rename to memdb/Makefile diff --git a/memdb/_run.sh b/memdb/_run.sh new file mode 100644 index 0000000..e69de29 diff --git a/memdb/_set.sh b/memdb/_set.sh new file mode 100644 index 0000000..e69de29 diff --git a/memdb/include/memdb.hpp b/memdb/include/memdb.hpp deleted file mode 100644 index 8985a60..0000000 --- a/memdb/include/memdb.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - - - -template - -class Memdb { - - -struct memdb_column { - T key; - U value; - std::chrono::system_clock::time_point timestamp; - bool be_del = false; -}; - -struct index_keys { - T key; - std::list ::iterator item; -}; - -struct index_timestamp { - std::list ::iterator item; - - bool operator<(const index_timestamp& a) const; -}; - - -private: - std::list db; - std::unordered_map keys; - std::priority_queue time_touch; - size_t __size; - void flush(); - - -public: - using key_t = T; - using value_t = U; - static constexpr int npos = -1; - - Memdb(); - Memdb& operator=(const Memdb& to_be_cp_memdb); - ~Memdb(); - - size_t size() const; - const std::unordered_map & get_keys() const; - const std::list & get_db() const; - const std::priority_queue & get_time_touch() const; - - void insert(key_t to_be_ins_k, value_t ins_v); //TODO 要加返回值 - void remove(key_t to_be_del_k); //TODO 要加返回值 - void update(key_t to_be_udt_k, value_t udt_v, bool need_to_udt_timetouch=false);//TODO 要加返回值 - value_t search(key_t to_be_sch_k) const; -}; \ No newline at end of file diff --git a/memdb/src/main/memdb.cpp b/memdb/src/main/memdb.cpp deleted file mode 100644 index 9209ec6..0000000 --- a/memdb/src/main/memdb.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "memdb.hpp" - - - -template - -bool Memdb ::index_timestamp::operator<(const index_timestamp& a) const { - return this -> item -> timestamp > a.item -> timestamp; -} - - -template - -void Memdb ::flush() { - std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now(); - std::list ::iterator it = this -> time_touch.front().item; - - while (now_time > it -> timestamp || it -> be_del == true) { - this -> keys.erase(it -> key); - this -> db.erase(it); - this -> time_touch.pop(); - this -> __size--; - it = this -> time_touch.front().item; - now_time = std::chrono::system_clock::now(); - } -} - -template - -Memdb ::Memdb() = default; - - -template - -Memdb & Memdb ::operator=(const Memdb & to_be_cp_memdb) = default; - - -template - -Memdb ::~Memdb() = default; - - -template - -size_t Memdb ::size() const { - return this -> __size; -} - - -template - -const std::unordered_map ::index_keys>& Memdb ::get_keys() const { - return this -> keys; -} - - -template - -const std::list ::memdb_column>& Memdb ::get_db() const { - return this -> db; -} - - -template - -const std::priority_queue ::index_timestamp>& Memdb ::get_time_touch() const { - return this -> time_touch; -} - - -template - -void Memdb ::insert(key_t to_be_ins_k, value_t ins_v) { - this -> flush(); - - std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now(); - - Memdb::memdb_column new_column; - new_column.key = to_be_ins_k; - new_column.value = ins_v; - new_column.timestamp = now_time; - this -> db.push_back(new_column); - - Memdb::index_keys new_key; - new_key.key = to_be_ins_k; - new_key.item = std::prev(this -> db.end()); - this -> keys.insert(new_key); - - Memdb::index_timestamp new_time_touch; - new_time_touch.item = std::prev(this -> db.end()); - this -> time_touch.push(new_time_touch); -} - - -template - -void Memdb ::remove(key_t to_be_del_k) { - this -> flush(); - - std::list ::iterator it = this -> keys[to_be_del_k].item; - it -> be_del = true; -} - - -template - -void Memdb ::update(key_t to_be_udt_k, value_t udt_v, bool need_to_udt_timetouch=false) { - this -> flush(); - - std::list ::iterator it = this -> keys[to_be_udt_k]; //! 这边会默认插入 - it -> value = udt_v; - if (need_to_udt_timetouch == true) { - std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now(); - it -> timestamp = now_time; - } -} - - -template - -Memdb ::value_t Memdb ::search(key_t to_be_sch_k) const { - this -> flush(); - - std::list ::iterator it = this -> keys[to_be_sch_k]; //! 这边会默认插入 - return it -> value; -} diff --git a/memdb/src/memdb.cpp b/memdb/src/memdb.cpp new file mode 100644 index 0000000..55720a8 --- /dev/null +++ b/memdb/src/memdb.cpp @@ -0,0 +1,78 @@ +#include +#include + +#include + +#include + +#include +#include + +namespace json = boost::json; + + + +struct ClientConfig { + std::string connected_host = "127.0.0.1"; + int connected_port = 8005; + std::string service_name = "db2"; + double timeout = 10.0; + bool retry_on_refused = true; +}; + +struct ServerConfig { + std::string listen_host = "127.0.0.1"; + int listen_port = 8011; + int workers = 4; + std::string db_url = "sqlite:///database.db"; +}; + +static std::string get_db_path(const std::string url) { + const std::string prefix = "sqlite:///"; + if (url.rfind(prefix, 0) == 0) { + return url.substr(prefix.size()); + } + return url; +} + + + +class DBConnection { +private: + ClientConfig __cfg; + + +public: + explicit DBConnection(const ClientConfig& cfg) : + __cfg(cfg) {} + ~DBConnection() = default; + + std::string get_from_sql(const std::string& sql_name) { + pmc::net::RpcClient client(__cfg.connected_host, __cfg.connected_port, __cfg.service_name, __cfg.timeout, __cfg.retry_on_refused); + + try { + auto data = client.call("execute", {{"action", "select"}, {"table", "memdb"}, {"where", {"sql_name", sql_name}}}); + + } catch (const std::exception& err) { + std::cerr << "[memdb] Error: 连接失败: " << err.what() << std::endl; + std::exit(1); + } + } +}; + + +class MemdbServer { + + +private: + ServerConfig __cfg; + + +public: + explicit MemdbServer(const ServerConfig& cfg) : + __cfg(cfg) {} + + void start() { + //TODO 编写 + } +}; \ No newline at end of file