This commit is contained in:
MeiK 2020-08-30 18:15:48 +08:00
parent fdaeb0c7e0
commit 7931f6b2bc
5 changed files with 48 additions and 10 deletions

View File

@ -7,15 +7,12 @@ edition = "2018"
[dependencies]
tonic = "0.3"
prost = "0.6"
tokio = { version = "0.2", features = ["macros", "sync", "stream", "time"] }
tokio = { version = "0.2", features = ["macros", "sync", "stream", "time", "fs"] }
futures = { version = "0.3" }
futures-core = "0.3"
futures-util = { version = "0.3", default-features = false }
async-stream = "0.2"
tower = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.7"
tempfile = "3"
libc = "0.2"

4
runner/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -1,10 +1,15 @@
use crate::river::judge_response::{JudgeResult, JudgeStatus};
use crate::river::JudgeResponse;
use std::fmt;
use std::io;
use std::result;
#[derive(Debug)]
pub enum Error {}
pub enum Error {
CreateTempDirError(io::Error),
LanguageNotFound(i32),
FileWriteError(io::Error),
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -1,6 +1,9 @@
use super::error::Result;
use super::error::{Error, Result};
use crate::river::judge_request::Language;
use crate::river::judge_response::{JudgeResult, JudgeStatus};
use crate::river::{JudgeRequest, JudgeResponse};
use std::path::Path;
use tokio::fs;
pub async fn judger(request: &JudgeRequest) -> Result<JudgeResponse> {
return Ok(JudgeResponse {
@ -16,7 +19,23 @@ pub async fn judger(request: &JudgeRequest) -> Result<JudgeResponse> {
});
}
pub async fn compile(request: &JudgeRequest) -> Result<JudgeResponse> {
pub async fn compile(request: &JudgeRequest, path: &Path) -> Result<JudgeResponse> {
// 写入代码
let filename = match Language::from_i32(request.language) {
Some(Language::C) => "main.c",
Some(Language::Cpp) => "main.cpp",
Some(Language::Python) => "main.py",
Some(Language::Rust) => "main.rs",
Some(Language::Node) => "main.js",
Some(Language::TypeScript) => "main.ts",
Some(Language::Go) => "main.go",
None => return Err(Error::LanguageNotFound(request.language)),
};
if let Err(e) = fs::write(path.join(filename), request.code.clone()).await {
return Err(Error::FileWriteError(e));
};
return Ok(JudgeResponse {
time_used: request.time_limit,
memory_used: 2,

View File

@ -6,6 +6,7 @@ use futures_core::Stream;
use river::river_server::{River, RiverServer};
use river::{JudgeRequest, JudgeResponse};
use std::pin::Pin;
use tempfile::tempdir_in;
use tonic::transport::Server;
use tonic::{Request, Response, Status};
@ -33,15 +34,27 @@ impl River for RiverService {
let output = async_stream::try_stream! {
let mut need_compile = true;
// TODO: 使用锁或者资源量等机制限制并发
yield judger::pending();
// 创建评测使用的临时目录
// 无需主动删除,变量在 drop 之后会自动删除临时文件夹
let pwd = match tempdir_in("./runner") {
Ok(val) => val,
Err(err) => {
yield error::system_error(error::Error::CreateTempDirError(err));
return
},
};
println!("{:?}", pwd);
while let Some(req) = stream.next().await {
// TODO: 使用锁或者资源量等机制限制并发
yield judger::pending();
let req = req?;
// 首次获取流进行编译
if need_compile {
yield judger::compiling();
let result = match judger::compile(&req).await {
let result = match judger::compile(&req, &pwd.path()).await {
Ok(res) => res,
Err(e) => error::system_error(e)
};