#include #include #include #include "pgxx/pgxx.hpp" #include "thread/pool.hpp" const int MAX_QUERY_IN_DB = 10'000; const float MAX_OVERLAP = 12.f; struct bit { std::string m_id; std::string m_url; std::string m_artist; std::string m_song; std::vector m_key; std::vector m_duration; }; bit target; std::vector parse_array(const std::string& arr_str) { std::vector result; std::stringstream ss(arr_str); std::string item; while (std::getline(ss, item, ',')) { try { result.push_back(std::stoi(item)); } catch (const std::invalid_argument&) { std::cerr << "Ошибка преобразования: " << item << std::endl; } } return result; } namespace calc { inline int calculation(int db_offset) { std::vector vb; vb.reserve(MAX_QUERY_IN_DB); std::string query = "SELECT * FROM t_media LIMIT " + std::to_string(MAX_QUERY_IN_DB) + " OFFSET " + std::to_string(db_offset); auto r = PGXX().execute("con_1", query); for (auto el : r) { bit b; b.m_id = el["m_id"].as(); b.m_url = el["m_url"].as(); b.m_artist = el["m_artist"].as(); b.m_song = el["m_song"].as(); std::string str = el["m_key"].as(); b.m_key = parse_array(str); str = el["m_duration"].as(); b.m_duration = parse_array(str); vb.push_back(b); } return vb.size(); } } namespace executor { inline void get_recomended() { try { int count = 0; std::string query = "SELECT count(*) FROM t_media WHERE m_cleared = 0;"; auto r = PGXX().execute("con_1", query); for (auto eld : r) count = eld["count"].as(); thread::pool pool; auto start = std::chrono::high_resolution_clock::now(); int i = 0; int def = count / MAX_QUERY_IN_DB + 1; int db_offset = 0; std::vector> futures; futures.reserve(def); while (def > 0) { futures.push_back(pool.enqueue(calc::calculation, db_offset)); db_offset += MAX_QUERY_IN_DB; --def; } for (auto &f : futures) { int r = f.get(); i += r; } std::chrono::duration elapsed = std::chrono::high_resolution_clock::now() - start; hack::log()(i, elapsed.count()); } catch(const std::exception& e) { hack::log()(e.what()); throw; } catch(hack::exception& ex) { ex.log(); throw; } catch(...) { hack::log()("ooops!"); throw; } } } void convert_db() { bool is_work = true; int count = 0; while (is_work) { try { std::string query = "SELECT * FROM t_media WHERE m_cleared = 0 LIMIT " + std::to_string(1) + ";"; auto r = PGXX().execute("con_1", query); hack::log("")("size = ", r.size(), ", count = ", count); for (auto el : r) { target.m_id = el["m_id"].as(); target.m_url = el["m_url"].as(); target.m_artist = el["m_artist"].as(); target.m_song = el["m_song"].as(); std::string key = el["m_key"].as(); std::string duration = el["m_duration"].as(); query = "UPDATE t_media SET m_cleared = 1 WHERE m_id = '" + target.m_id + "';"; PGXX().execute("con_1", query); executor::get_recomended(); } query = "SELECT count(*) FROM t_media WHERE m_cleared = 0;"; r = PGXX().execute("con_1", query); for (auto eld : r) { auto c = eld["count"].as(); if (count - c > 1) hack::log()("DOUBLE"); count = c; } if (count == 0) is_work = false; } catch(hack::exception& e) { e.log(); } } } auto main(int argc, char* args[]) -> int { const std::string con = "postgres://chatlanin:password_for_connection_to_test_db@localhost:5423/test.db?sslmode=disable"; try { PGXX().init("con_1", 300, con); } catch(hack::exception& ex) { ex.log(); throw; } if (!PGXX().ready()) hack::log()("error connection"); convert_db(); }