195 lines
4.2 KiB
C++
195 lines
4.2 KiB
C++
#include <future>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#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<int> m_key;
|
|
std::vector<int> m_duration;
|
|
};
|
|
|
|
bit target;
|
|
|
|
std::vector<int> parse_array(const std::string& arr_str)
|
|
{
|
|
std::vector<int> 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<bit> 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<std::string>();
|
|
b.m_url = el["m_url"].as<std::string>();
|
|
b.m_artist = el["m_artist"].as<std::string>();
|
|
b.m_song = el["m_song"].as<std::string>();
|
|
|
|
std::string str = el["m_key"].as<std::string>();
|
|
b.m_key = parse_array(str);
|
|
|
|
str = el["m_duration"].as<std::string>();
|
|
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<int>();
|
|
|
|
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<std::future<int>> 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<double> 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<std::string>();
|
|
target.m_url = el["m_url"].as<std::string>();
|
|
target.m_artist = el["m_artist"].as<std::string>();
|
|
target.m_song = el["m_song"].as<std::string>();
|
|
|
|
std::string key = el["m_key"].as<std::string>();
|
|
std::string duration = el["m_duration"].as<std::string>();
|
|
|
|
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<int>();
|
|
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();
|
|
}
|