From 2c9e13baaf7285052a3a7cad3654b4a347850387 Mon Sep 17 00:00:00 2001 From: Nikola Petrov Date: Tue, 28 Jan 2025 15:49:36 +0100 Subject: [PATCH] Add checking of data --- CMakeLists.txt | 1 + server/inc/checker.hpp | 3 ++ server/inc/sql.hpp | 6 +++ server/src/checker.cpp | 112 +++++++++++++++++++++++++++++++++++++++++ server/src/server.cpp | 3 ++ 5 files changed, 125 insertions(+) create mode 100644 server/inc/checker.hpp create mode 100644 server/src/checker.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index aec95dc..ac0baf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ target_link_libraries(app ${CMAKE_BINARY_DIR}/raylib/lib/libraylib.a) add_executable(server server/src/server.cpp server/src/sql.cpp + server/src/checker.cpp shared/src/TcpSocket.cpp shared/src/values/Dna.cpp diff --git a/server/inc/checker.hpp b/server/inc/checker.hpp new file mode 100644 index 0000000..fcab009 --- /dev/null +++ b/server/inc/checker.hpp @@ -0,0 +1,3 @@ + + +void checker(); \ No newline at end of file diff --git a/server/inc/sql.hpp b/server/inc/sql.hpp index 9a04e4b..9c39099 100644 --- a/server/inc/sql.hpp +++ b/server/inc/sql.hpp @@ -10,6 +10,12 @@ const char max_gen[] = "SELECT MAX(GEN) FROM prim_table WHERE USER_ID = ?;"; const char get_unchecked[] = "SELECT USER_ID FROM prim_table WHERE CHECKED = 0 GROUP BY USER_ID;"; +const char get_gen[] = "SELECT HASH, POS, LIKED FROM prim_table WHERE USER_ID = ? AND GEN = ? ORDER BY POS ASC;"; + +const char remove_gen[] = "DELETE FROM prim_table WHERE USER_ID = ? AND GEN >= ?;"; + +const char set_checked[] = "UPDATE prim_table SET CHECKED = 1 WHERE USER_ID = ? AND GEN = ?;"; + constexpr char DB_NAME[] = "data.db"; struct sqlite3; diff --git a/server/src/checker.cpp b/server/src/checker.cpp new file mode 100644 index 0000000..42c4d5e --- /dev/null +++ b/server/src/checker.cpp @@ -0,0 +1,112 @@ + +#include "sql.hpp" +#include +#include +#include +#include +#include "values/DnaManager.hpp" + +void checker() +{ + using namespace std::chrono_literals; + + sqlite3 *db; + int rc = sql::open(DB_NAME, &db); + if (rc) + { + fprintf(stderr, "Can't open database: %s\n", sql::errmsg(db)); + } + + sqlite3_stmt *get_unchecked_stmt; + sql::prepare_v2(db, get_unchecked, -1, &get_unchecked_stmt, NULL); + + sqlite3_stmt *get_gen_stmt; + sql::prepare_v2(db, get_gen, -1, &get_gen_stmt, NULL); + + sqlite3_stmt *remove_gen_stmt; + sql::prepare_v2(db, remove_gen, -1, &remove_gen_stmt, NULL); + + sqlite3_stmt *set_checked_stmt; + sql::prepare_v2(db, set_checked, -1, &set_checked_stmt, NULL); + + while (true) + { + int64_t user_id = 0; + if (sql::step(get_unchecked_stmt) != SQL_DONE) + { + int type = sql::column_type(get_unchecked_stmt, 0); + if (type != SQL_NULL) + { + user_id = sql::column_int64(get_unchecked_stmt, 0); + } + } + sql::reset(get_unchecked_stmt); + if (user_id == 0) + { + std::this_thread::sleep_for(60s); + continue; + } + + DnaManagerData data; + data.id = user_id; + data.randSeed = mrand::getState(data.id); + data.queued = 0; + data.showed = 0; + data.generation = 0; + data.vector.resize(NUM_PER_GEN); + + for (std::size_t i = 0; i < NUM_PER_GEN; i++) + { + DNA::newDna(&data.vector[i], &data.randSeed); + } + bool found_err = false; + while (found_err != true) + { + sql::bind_int64(get_gen_stmt, 1, data.id); + sql::bind_int64(get_gen_stmt, 2, data.generation); + + bool new_gen = false; + while (sql::step(get_gen_stmt) != SQL_DONE) + { + int64_t hash = sql::column_int64(get_gen_stmt, 0); + int64_t pos = sql::column_int64(get_gen_stmt, 1); + int64_t liked = sql::column_int64(get_gen_stmt, 2); + UiUnit unit = DnaManager::next(&data); + int64_t cal_hash = mrand::computeCRC32(unit.dna, sizeof(Dna)); + if ((unit.index != pos) || (hash != cal_hash)) + { + found_err = true; + sql::bind_int64(remove_gen_stmt, 1, data.id); + sql::bind_int64(remove_gen_stmt, 2, data.generation); + sql::step(remove_gen_stmt); + sql::reset(remove_gen_stmt); + break; + } + unit.liked = (Liked)liked; + new_gen = DnaManager::like(unit, &data); + } + + if (!found_err) + { + sql::bind_int64(set_checked_stmt, 1, data.id); + sql::bind_int64(set_checked_stmt, 2, data.generation); + sql::step(set_checked_stmt); + sql::reset(set_checked_stmt); + } + if (!new_gen) + { + found_err = true; + sql::bind_int64(remove_gen_stmt, 1, data.id); + sql::bind_int64(remove_gen_stmt, 2, data.generation); + sql::step(remove_gen_stmt); + sql::reset(remove_gen_stmt); + } + else + { + DnaManager::newGen(&data); + } + + sql::reset(get_gen_stmt); + } + } +} \ No newline at end of file diff --git a/server/src/server.cpp b/server/src/server.cpp index 035ccc6..0d547c5 100644 --- a/server/src/server.cpp +++ b/server/src/server.cpp @@ -2,9 +2,11 @@ #include "NetConst.hpp" #include "sql.hpp" #include "values/DnaManager.hpp" +#include "checker.hpp" #include #include +#include // use pthread rw_lock to lock db so you can safy clone .db file @@ -105,6 +107,7 @@ void call(int sock, sockaddr_in newSocketInfo) int main() { sql::init(); + std::thread t(checker); // Bind the server to a port. int err = TcpSocket::listent("0.0.0.0", 8888, call); if (err < 0)