compile_run
适配用户请求, 定制通信协议字段
正确的调用compile and run
形成唯一文件名
文件关系
认识jsoncpp功能
安装jsoncpp
sudo yum install jsoncpp-devel
找到json.h
find /usr/ -name json.h
测试
#include <iostream>
#include <json/json.h>
int main()
{
//序列化的工作
//将结构化数据转化成为一个字符串
//Value是一个Json的中间类,可以填充KV值
Json::Value root;
root["code"] = "mycode";
root["user"] = "zzz";
root["age"] = "24";
Json::StyledWriter writer;
std::string str = writer.write(root);
std::cout << str << std::endl;
}
编译
g++ test.cc -std=c++11 -ljsoncpp
运行
./a.out
#include <iostream>
#include <json/json.h>
int main()
{
//序列化的工作
//将结构化数据转化成为一个字符串
//Value是一个Json的中间类,可以填充KV值
Json::Value root;
root["code"] = "mycode";
root["user"] = "zzz";
root["age"] = "24";
//Json::StyledWriter writer;
Json::FastWriter writer;
std::string str = writer.write(root);
std::cout << str << std::endl;
}
基础框架
compile_run.hpp
#pragma once
#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <json/json.h>
namespace ns_compile_and_run
{
using namespace ns_log;
using namespace ns_util;
using namespace ns_compiler;
using namespace ns_runner;
class CompileAndRun
{
public:
/******************************
输入:
code:用户提交的代码
input:用户给自己提交的代码对应的输入,不做处理
cpu_limit:时间要求
mem_limit:空间要求
输出:
必填
status:状态码
reason:请求结果
选填
stdout:程序运行完的结果
stderr:程序运行完的错误结果
参数:
in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
*****************************/
static void Start(const std::string &in_json, std::string *out_json)
{
Json::Value in_value;
Json::Reader reader;
reader.parse(in_json, in_value);
std::string code = in_value["code"].asString();
std::string input = in_value["input"].asString();
int cpu_limit = in_value["cpu_limit"].asInt();
int mem_limit = in_value["men_limit"].asInt();
if(code.size() == 0){
//处理差错问题
}
//形成的文件名只具有唯一性,没有目录,没有后缀
std::string file_name = FileUtil::UniqFileName();
FileUtil::WriteFile(PathUtil::src(file_name), code); //形成临时src文件
Compiler::Compile(file_name);
Runner::Run(file_name, cpu_limit, mem_limit);
}
};
}
util.hpp
class FileUtil {
public:
static bool IsFileExists(const std::string &path_name)
{
struct stat st;
if(stat(path_name.c_str(), &st) == 0){
//获取属性成功,文件已经存在
return true;
}
return false;
}
static std::string UniqFileName()
{
return "";
}
static bool WriteFile(const std::string &target, const std::string &code)
{
}
};
出错处理
v1
compile_run.hpp
#pragma once
#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <json/json.h>
namespace ns_compile_and_run
{
using namespace ns_log;
using namespace ns_util;
using namespace ns_compiler;
using namespace ns_runner;
class CompileAndRun
{
public:
static std::string SignoToDesc(int signo)
{
}
/******************************
输入:
code:用户提交的代码
input:用户给自己提交的代码对应的输入,不做处理
cpu_limit:时间要求
mem_limit:空间要求
输出:
必填
status:状态码
reason:请求结果
选填
stdout:程序运行完的结果
stderr:程序运行完的错误结果
参数:
in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
*****************************/
static void Start(const std::string &in_json, std::string *out_json)
{
Json::Value in_value;
Json::Reader reader;
reader.parse(in_json, in_value);
std::string code = in_value["code"].asString();
std::string input = in_value["input"].asString();
int cpu_limit = in_value["cpu_limit"].asInt();
int mem_limit = in_value["men_limit"].asInt();
int status_code = 0;
Json::Value out_value;
if(code.size() == 0){
//处理差错问题
out_value["status"] = -1;//代码为空
out_value["reason"] = "用户提交的代码时空的";
//序列化过程
return;
}
//形成的文件名只具有唯一性,没有目录,没有后缀
//毫秒级时间戳+原子性递增唯一值:来保证唯一性
std::string file_name = FileUtil::UniqFileName();
//形成临时src文件
if(!FileUtil::WriteFile(PathUtil::src(file_name), code))
{
out_value["status"] = -2;//未知错误
out_value["reason"] = "代码发生了未知错误";
//序列化过程
return;
}
if(!Compiler::Compile(file_name))
{
//编译失败
out_value["status"] = -3; //代码编译的时候发生了错误
out_value["reason"] = FileUtil::ReadFile(PathUtil::CompilerError(file_name));
//序列化过程
return;
}
int code = Runner::Run(file_name, cpu_limit, mem_limit);
if (code < 0)
{
out_value["status"] = -2;//未知错误
out_value["reason"] = "代码发生了未知错误";
//序列化过程
return;
}
else if(code > 0)
{
out_value["status"] = code;//运行报错了
out_value["reason"] = SignoToDesc(code); //将信号报错转化为报错的原因
//序列化过程
}
else
{
//运行成功
}
}
};
}
util.hpp
class FileUtil {
public:
static bool IsFileExists(const std::string &path_name)
{
struct stat st;
if(stat(path_name.c_str(), &st) == 0){
//获取属性成功,文件已经存在
return true;
}
return false;
}
static std::string UniqFileName()
{
return "";
}
static bool WriteFile(const std::string &target, const std::string &code)
{
}
static std::string ReadFile(const std::string &target, )
{
}
};
v2
compile_run.hpp
#pragma once
#include "compiler.hpp"
#include "runner.hpp"
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <signal.h>
#include <json/json.h>
namespace ns_compile_and_run
{
using namespace ns_log;
using namespace ns_util;
using namespace ns_compiler;
using namespace ns_runner;
class CompileAndRun
{
public:
// code > 0 : 进程收到了信号导致异常奔溃
// code < 0 : 整个过程非运行报错(代码为空,编译报错等)
// code = 0 : 整个过程全部完成
static std::string CodeToDesc(int code, const std::string &file_name)
{
std::string desc;
switch (code)
{
case 0:
desc = "编译运行成功";
break;
case -1:
desc = "提交的代码是空";
break;
case -2:
desc = "未知错误";
break;
case -3:
// desc = "代码编译的时候发生了错误";
FileUtil::ReadFile(PathUtil::CompilerError(file_name), &desc, true);
break;
case SIGABRT: // 6
desc = "内存超过范围";
break;
case SIGXCPU: // 24
desc = "CPU使用超时";
break;
case SIGFPE: // 8
desc = "浮点数溢出";
break;
default:
desc = "未知: " + std::to_string(code);
break;
}
return desc;
}
/******************************
输入:
code:用户提交的代码
input:用户给自己提交的代码对应的输入,不做处理
cpu_limit:时间要求
mem_limit:空间要求
输出:
必填
status:状态码
reason:请求结果
选填
stdout:程序运行完的结果
stderr:程序运行完的错误结果
参数:
in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
*****************************/
static void Start(const std::string &in_json, std::string *out_json)
{
Json::Value in_value;
Json::Reader reader;
reader.parse(in_json, in_value);
std::string code = in_value["code"].asString();
std::string input = in_value["input"].asString();
int cpu_limit = in_value["cpu_limit"].asInt();
int mem_limit = in_value["men_limit"].asInt();
int status_code = 0;
Json::Value out_value;
int run_result = 0;
std::string file_name;//需要内部形成的唯一文件名
if(code.size() == 0){
status_code = -1;//代码为空
goto END;
}
//形成的文件名只具有唯一性,没有目录,没有后缀
//毫秒级时间戳+原子性递增唯一值:来保证唯一性
file_name = FileUtil::UniqFileName();
//形成临时src文件
if(!FileUtil::WriteFile(PathUtil::Src(file_name), code))
{
status_code = -2;//未知错误
goto END;
}
if(!Compiler::Compile(file_name))
{
status_code = -3;//编译失败
goto END;
}
run_result = Runner::Run(file_name, cpu_limit, mem_limit);
if (run_result < 0)
{
status_code = -2;//未知错误
}
else if(run_result > 0)
{
//程序运行崩溃
status_code = run_result;
}
else
{
//运行成功
status_code = 0;
}
END:
out_value["status"] = status_code;
out_value["reason"] = CodeToDesc(status_code, file_name);
if(status_code == 0){
//整个过程全部成功
std::string _stdout;
FileUtil::ReadFile(PathUtil::Stdout(file_name), &_stdout, true);
out_value["stdout"] = _stdout;
std::string _stderr;
FileUtil::ReadFile(PathUtil::Stderr(file_name), &_stderr, true);
out_value["stderr"] = _stderr;
}
Json::StyledWriter writer;
*out_json = writer.write(out_value);
}
};
}
util.hpp
#pragma once
#include <iostream>
#include <string>
#include <atomic>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <sys/time.h>
namespace ns_util
{
class TimeUtil
{
public:
static std::string GetTimeStamp()
{
struct timeval _time;
gettimeofday(&_time, nullptr);
return std::to_string(_time.tv_sec);
}
//获得毫秒时间戳
static std::string GetTimeMs()
{
struct timeval _time;
gettimeofday(&_time, nullptr);
return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
}
};
class FileUtil {
public:
static bool IsFileExists(const std::string &path_name)
{
struct stat st;
if(stat(path_name.c_str(), &st) == 0){
//获取属性成功,文件已经存在
return true;
}
return false;
}
static std::string UniqFileName()
{
static std::atomic_uint id(0);
id++;
// 毫秒级时间戳+原子性递增唯一值: 来保证唯一性
std::string ms = TimeUtil::GetTimeMs();
std::string uniq_id = std::to_string(id);
return ms + "_" + uniq_id;
}
static bool WriteFile(const std::string &target, const std::string &content)
{
std::ofstream out(target);
if (!out.is_open())
{
return false;
}
out.write(content.c_str(), content.size());
out.close();
return true;
}
static bool ReadFile(const std::string &target, std::string *content, bool keep = false)
{
(*content).clear();
std::ifstream in(target);
if (!in.is_open())
{
return false;
}
std::string line;
// getline:不保存行分割符,有些时候需要保留\n,
// getline内部重载了强制类型转化
while (std::getline(in, line))
{
(*content) += line;
(*content) += (keep ? "\n" : "");
}
in.close();
return true;
}
};
}
编译通过