From 87e37f0ac2d4d77a5b444bfb7d26335545073243 Mon Sep 17 00:00:00 2001 From: pk4wt2yal <1330800687@qq.com> Date: Mon, 25 Nov 2024 12:13:53 +0800 Subject: [PATCH] Delete 'src/my-online-judge-master/MYOJ/OJ_server/OJ_Control.hpp' --- .../MYOJ/OJ_server/OJ_Control.hpp | 372 ------------------ 1 file changed, 372 deletions(-) delete mode 100644 src/my-online-judge-master/MYOJ/OJ_server/OJ_Control.hpp diff --git a/src/my-online-judge-master/MYOJ/OJ_server/OJ_Control.hpp b/src/my-online-judge-master/MYOJ/OJ_server/OJ_Control.hpp deleted file mode 100644 index cd8108e..0000000 --- a/src/my-online-judge-master/MYOJ/OJ_server/OJ_Control.hpp +++ /dev/null @@ -1,372 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "OJ_view.hpp" -#include "../comm/Comm_model_MySQL.hpp" -#include "../comm/util.hpp" -#include "../comm/httplib.h" - -namespace ns_control -{ - const std::string http_pattern = "/compile_and_run"; - - class Machine - { - public: - Machine(const std::string &IP, const uint16_t port) - : _IP(IP), _port(port), a_loads(0) - { - } - ~Machine() - { - } - - void inLoad() - { - a_loads.fetch_add(1, std::memory_order_relaxed); - } - - void deLoad() - { - a_loads.fetch_sub(1, std::memory_order_relaxed); - } - - void resetLoad() - { - a_loads.store(0, std::memory_order_relaxed); - } - - uint32_t getLoad() const - { - return a_loads.load(std::memory_order_relaxed); - } - - std::string getIP() const - { - return _IP; - } - - uint16_t getPort() const - { - return _port; - } - - Machine(const Machine &) = delete; - Machine &operator=(const Machine &) = delete; - - Machine(Machine &&other) noexcept - : _IP(std::move(other._IP)), _port(other._port), a_loads(other.a_loads.load()) - { - } - - // 移动赋值运算符 - Machine &operator=(Machine &&other) noexcept - { - if (this != &other) - { - _IP = std::move(other._IP); - _port = other._port; - a_loads.store(other.a_loads.load()); - other.a_loads.store(0); - } - return *this; - } - - private: - std::string _IP; // 主机IP地址 - uint16_t _port; // 主机端口号 - std::atomic_uint a_loads; // 负载量,原子类型,保证线程安全 - }; - - const std::string conf_path = "/home/zzy1/2024/my-online-judge/MYOJ/OJ_server/service_machine.conf"; - - class LoadBalance - { - public: - LoadBalance() - { - // 导入配置文件 - if (!loadConf()) - { - // 导入失败,差错问题以在loadConf中说明,此处直接退出 - exit(1); - } - lg(Info, "加载配置文件%s成功!\n", conf_path.c_str()); - } - - ~LoadBalance() - { - } - - bool loadConf() - { - // 1.打开文件流 - std::ifstream in(conf_path); - if (!in.is_open()) - { - // 打开失败的情况 - lg(Error, "加载配置文件%s失败, 请检查! errno: %d, strerror: %s\n", conf_path.c_str(), errno, strerror(errno)); - return false; - } - - std::string line; // 从文件流中读取缓冲区 - std::vector tokens; // 分割字符串后的结果缓冲区 - - while (getline(in, line)) - { - ns_util::splitUtil::splitString(line, ":", &tokens); - if (tokens.size() != 2) - { - lg(Error, "分割字符串失败, errno: %d, strerror: %s\n", errno, strerror(errno)); - return false; - } - - Machine machine(tokens[0], stoi(tokens[1])); - - // 先将配置文件中的所有主机按照上线处理 - _onlines.push_back(_machines.size()); - _machines.push_back(std::move(machine)); - } - - // 从文件流中读取完毕,回收资源 - in.close(); - return true; - } - - // 两个输出型参数,分别是主机的ID号,和描述主机的二级指针,以及返回是否选择成功 - bool smartChoice(int *num, Machine **ppmachine) - { - // 1. 判断是否还有主机在线 - _mutex.lock(); - if (_onlines.size() == 0) - { - // 所有主机均已下线 - lg(Fatal, "所有主机均已下线, 请运维人员检查主机状况!\n"); - return false; - } - - // 2.遍历所有在线的主机表,找到负载最小的主机号 - int min_num = _onlines[0]; // 用来存储负载最小的主机的编号 - uint32_t min_load = _machines[min_num].getLoad(); // 用来存储负载最小的主机的负载量 - - for (int i = 1; i < _onlines.size(); i++) - { - int tmp_num = _onlines[i]; - uint32_t tmp_load = _machines[tmp_num].getLoad(); - if (min_load > tmp_load) - { - min_load = tmp_load; - min_num = tmp_num; - } - } - - _mutex.unlock(); - - *num = min_num; - *ppmachine = &_machines[min_num]; - return true; - } - - // 上线所有主机 - void onlineMachine() - { - _mutex.lock(); - _onlines.insert(_onlines.end(), _offlines.begin(), _offlines.end()); - _offlines.clear(); - _mutex.unlock(); - } - - // 展示所有主机,分别将离线主机,在线主机打印出来,主要debug使用 - void showMachine() - { - std::cout << "在线主机: "; - for (int x : _onlines) - { - std::cout << x << " "; - } - std::cout << std::endl; - - std::cout << "离线主机: "; - for (int x : _offlines) - { - std::cout << x << " "; - } - std::cout << std::endl; - } - - // 下线指定主机 - void offlineMachine(int host_id) - { - _mutex.lock(); - if (_machines.size() <= host_id) - { - lg(Warning, "要下线的主机: %d 不存在!\n", host_id); - return; - } - - for (auto it = _onlines.begin(); it != _onlines.end(); it++) - { - if (*it == host_id) - { - // 由于直接break,所以不需要考虑迭代器失效的问题 - _onlines.erase(it); - _offlines.push_back(host_id); - break; - } - } - - _mutex.unlock(); - } - - private: - std::vector _machines; // 存储所有的主机,每个主机的下标就是天然的主机编号 - std::vector _onlines; // 记录所有上线状态的主机编号 - std::vector _offlines; // 记录所有下线状态的主机编号 - std::mutex _mutex; // 锁,由于STL不保证线程安全,需要加锁保护 - }; - - // 核心控制器 - class Control - { - public: - Control() - { - } - ~Control() - { - } - - // 将所有主机恢复为在线状态 - void recoveryMachine() - { - _lb.onlineMachine(); - } - - // 获取所有问题 - bool allQuestions(std::string *html) - { - std::vector questions; - - if (!_model.getAllQuestions(&questions)) - { - lg(Error, "获取所有题目失败, 无法构成网页!\n"); - *html = "获取所有题目失败, 无法构成网页!"; - return false; - } - - std::sort(questions.begin(), questions.end(), - [](const ns_model_MySQL::Question &q1, const ns_model_MySQL::Question &q2) - { - int num1 = std::stoi(q1.number); - int num2 = std::stoi(q2.number); - assert(!(num1 == num2)); - - return (num1 < num2); - }); - - _view.AllExpandHtml(questions, html); - - return true; - } - - bool oneQuestion(const std::string &num, std::string *html) - { - ns_model_MySQL::Question q; - - if (!_model.getOneQuestion(num, &q)) - { - lg(Error, "获取题号%s的题目信息失败, 无法构建网页!\n", num.c_str()); - *html = "获取单个题目失败,无法构成网页!"; - return false; - } - - _view.OneExpandHtml(q, html); - return true; - } - - void Judge(const std::string &num, const std::string &in_json, std::string *out_json) - { - // 1.根据题号,拿到相应的题目信息 - ns_model_MySQL::Question q; - _model.getOneQuestion(num, &q); - - // 2.对题目信息反序列化,保存到json串中,其中in_json中的主要信息有code和input - Json::Value in_value; - Json::Reader reader; - reader.parse(in_json, in_value); - - // 3.构建compile_server所需要的json串 - Json::Value compile_value; - std::string code = in_value["code"].asString(); - code += "\n"; - code += q.tail; - - compile_value["code"] = code; - compile_value["input"] = in_value["input"].asString(); - compile_value["cpu_limit"] = q.cpu_limit; - compile_value["mem_limit"] = q.mem_limit; - - Json::FastWriter writer; - std::string compile_string = writer.write(compile_value); - - // 4.选择负载均衡最低的主机 - // 注意:并不是一寻找就能找到的,可能找到的主机已经挂掉了 - // 这个时候就要将挂掉的主机放入offlines中 - // 然后再去寻找新的主机 - // 这样结果要么就直接找到,要么就全部挂掉 - int host_id = 0; - while (true) - { - Machine *pmachine = nullptr; - if (!_lb.smartChoice(&host_id, &pmachine)) - { - // 主机全挂了 - break; - } - - // 选到了一个主机 - // 5. 向主机发送http请求,得到结果,通过返回的状态码判断主机是否还在线 - httplib::Client cli(pmachine->getIP(), pmachine->getPort()); - - // 发送post请求,并增加负载 - pmachine->inLoad(); - - lg(Info, "选择主机id: %d, ip: %s, port: %d, load: %d 尝试进行编译运行服务...\n", - host_id, pmachine->getIP().c_str(), pmachine->getPort(), pmachine->getLoad()); - // std::cout << "发起判题请求" << http_pattern.c_str() << std::endl; - httplib::Result res = cli.Post(http_pattern.c_str(), compile_string, "application/json;charset=utf-8"); - // httplib::Result 类型使httplib库中的定义的类,其中重载了->操作符 - // 可以用于获取response中的各种信息 - - // 判断结果有效,并且状态码为200才说明是成功的 - if (res && res->status == 200) - { - *out_json = res->body; - // 请求完毕,减少负载 - pmachine->deLoad(); - lg(Info, "编译运行服务完成...\n"); - break; - } - else - { - // 失败,需要重新请求,并且将此次选择的主机放到下线表中 - lg(Warning, "本次请求的主机id: %d, 请求失败, ip: %s, port: %d\n", - host_id, pmachine->getIP().c_str(), pmachine->getPort()); - pmachine->resetLoad(); - _lb.offlineMachine(host_id); - _lb.showMachine(); // for debug - } - } - } - - private: - ns_view::View _view; - ns_model_MySQL::Model _model; - LoadBalance _lb; - }; - -} \ No newline at end of file