Skip to content

Commit

Permalink
feat(Judger): ✨ add compile and assert logic for language
Browse files Browse the repository at this point in the history
  • Loading branch information
Eason0729 committed May 13, 2024
1 parent fc7cf4c commit 74daeda
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 147 deletions.
11 changes: 10 additions & 1 deletion judger/src/filesystem/adapter/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::{ffi::OsStr, num::NonZeroU32, path::Path, sync::Arc};
use futures_core::Future;
use spin::Mutex;
use tokio::io::{AsyncRead, AsyncSeek};
use tokio::sync::{Mutex as AsyncMutex, OwnedSemaphorePermit};
use tokio::sync::Mutex as AsyncMutex;

use crate::filesystem::entry::{Entry, TarTree, BLOCKSIZE};
use crate::filesystem::resource::Resource;
use crate::filesystem::table::to_internal_path;

use super::{error::FuseError, handle::HandleTable, reply::*};
use fuse3::{
Expand Down Expand Up @@ -50,6 +51,14 @@ where
.mount_with_unprivileged(self, path.as_ref())
.await
}
pub fn insert_by_path(&self, path: impl AsRef<Path>, content: Vec<u8>) {
let mut tree = self.tree.lock();
tree.insert_by_path(
to_internal_path(path.as_ref()),
|| Entry::Directory,
Entry::new_file_with_content(content),
);
}
}

impl<F> fuse3::raw::Filesystem for Filesystem<F>
Expand Down
3 changes: 3 additions & 0 deletions judger/src/filesystem/entry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ where
pub fn new_file() -> Self {
Self::MemFile(MemBlock::default())
}
pub fn new_file_with_content(content: Vec<u8>) -> Self {
Self::MemFile(MemBlock::new(content))
}
pub fn kind(&self) -> FileType {
match self {
Self::SymLink(_) => FileType::Symlink,
Expand Down
30 changes: 30 additions & 0 deletions judger/src/language/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use super::stage::{AssertionMode, StatusCode};

pub struct JudgeArgs {
pub(super) mem: u64,
pub(super) cpu: u64,
pub(super) input: Vec<u8>,
pub(super) output: Vec<u8>,
pub(super) mode: AssertionMode,
pub(super) source: Vec<u8>,
}

pub struct ExecuteArgs {
pub(super) mem: u64,
pub(super) cpu: u64,
pub(super) input: Vec<u8>,
pub(super) source: Vec<u8>,
}

pub struct JudgeResult {
pub status: StatusCode,
pub time: u64,
pub memory: u64,
}

pub struct ExecuteResult {
pub time: u64,
pub memory: u64,
pub output: Vec<u8>,
pub code: i32,
}
1 change: 1 addition & 0 deletions judger/src/language/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod builder;
mod daemon;
mod plugin;
mod spec;
Expand Down
70 changes: 59 additions & 11 deletions judger/src/language/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ use std::{path::Path, sync::Arc};
use rustix::path::Arg;
use tokio::fs::{read_dir, File};

use crate::filesystem::*;
use crate::{
filesystem::*,
sandbox::{Cpu, Memory},
};

use super::{spec::Spec, stage::CompileRunner};
use super::{
builder::*,
spec::Spec,
stage::{AssertionMode, Compiler, StatusCode},
};
use crate::Result;

static EXTENSION: &str = "lang";
Expand All @@ -24,9 +31,19 @@ pub async fn load_plugins(path: impl AsRef<Path>) -> Result<Vec<Plugin>> {
Ok(plugins)
}

impl JudgeResult {
fn new(status: StatusCode) -> Self {
Self {
status,
time: 0,
memory: 0,
}
}
}

pub struct Plugin {
spec: Arc<Spec>,
template: Template<File>,
pub(super) spec: Arc<Spec>,
pub(super) template: Template<File>,
}

impl Plugin {
Expand All @@ -40,12 +57,43 @@ impl Plugin {

Ok(Self { spec, template })
}
pub async fn as_runner(self: Arc<Self>) -> Result<CompileRunner> {
let filesystem = self
.template
.as_filesystem(self.spec.fs_limit)
.mount()
.await?;
Ok(CompileRunner::new(self.spec.clone(), filesystem))
pub async fn as_compiler(self: Arc<Self>, source: Vec<u8>) -> Result<Compiler> {
let filesystem = self.template.as_filesystem(self.spec.fs_limit);
filesystem.insert_by_path(self.spec.file.as_os_str(), source);
Ok(Compiler::new(self.spec.clone(), filesystem.mount().await?))
}
pub async fn judge(self: Arc<Self>, args: JudgeArgs) -> Result<JudgeResult> {
// for judge: it has three stages: compile, run, judge
let compiler = self.as_compiler(args.source).await?;
Ok(match compiler.compile().await? {
Some(runner) => {
let judger = runner.run((args.mem, args.cpu), args.input).await?;
let status = judger.get_result(&args.output, args.mode);

let stat = judger.stat();

JudgeResult {
status,
time: stat.cpu.total,
memory: stat.memory.total,
}
}
None => JudgeResult::new(StatusCode::CompileError),
})
}
pub async fn execute(self: Arc<Self>, args: ExecuteArgs) -> Result<Option<ExecuteResult>> {
let compiler = self.as_compiler(args.source).await?;
Ok(match compiler.compile().await? {
Some(runner) => {
let judger = runner.run((args.mem, args.cpu), args.input).await?;

todo!("stream output");

let stat = judger.stat();

Some(todo!())
}
None => None,
})
}
}
65 changes: 42 additions & 23 deletions judger/src/language/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use tokio::{
};
use uuid::Uuid;

use crate::sandbox::{Cpu, Memory};
use crate::sandbox::{Cpu, Memory, Stat};

async fn load_plugin(path: impl AsRef<Path>) {
let dir_list = read_dir(path).await;
Expand All @@ -19,42 +19,48 @@ pub struct Spec {
judge_limit: (Cpu, Memory, u64, Duration),
pub compile_command: Vec<OsString>,
pub judge_command: Vec<OsString>,
pub file: OsString,
}

impl Spec {
pub fn get_judge_limit(&self, cpu: Cpu, mem: Memory) -> (Cpu, Memory, u64, Duration) {
pub fn get_judge_limit(&self, cpu: u64, mem: u64) -> Stat {
todo!()
}
pub fn get_raw_stat(&self, stat: &Stat) -> Stat {
todo!()
}
pub fn from_str(content: &str) -> Self {
let mut raw: Raw = toml::from_str(content).unwrap();
raw.compile.fill();
raw.judge.fill();
raw.fill();

Self {
fs_limit: todo!(),
fs_limit: raw.fs_limit.unwrap(),
compile_limit: (
Cpu {
kernel: todo!(),
user: todo!(),
total: todo!(),
kernel: raw.compile.rt_time.unwrap(),
user: raw.compile.cpu_time.unwrap(),
total: raw.compile.time.unwrap(),
},
Memory {
kernel: todo!(),
user: todo!(),
total: todo!(),
kernel: raw.compile.kernel_mem.unwrap(),
user: raw.compile.user_mem.unwrap(),
total: raw.compile.memory.unwrap(),
},
raw.compile.output_limit.unwrap(),
Duration::from_millis(raw.compile.walltime.unwrap()),
),
judge_limit: todo!(),
compile_command: todo!(),
judge_command: todo!(),
compile_command: raw.compile.command,
judge_command: raw.judge.command,
file: raw.file,
}
}
}

#[derive(Deserialize)]
struct Raw {
fs_limit: Option<u64>,
file: OsString,
info: String,
extension: String,
name: String,
Expand All @@ -63,14 +69,25 @@ struct Raw {
judge: RawJudge,
}

impl Raw {
pub fn fill(&mut self) {
if self.fs_limit.is_none() {
self.fs_limit = Some(67108864);
}
self.compile.fill();
self.judge.fill();
}
}

#[derive(Deserialize)]
struct RawCompile {
command: Vec<OsString>,
kernel_mem: Option<u64>,
memory: Option<u64>,
user_mem: Option<u64>,
rt_time: Option<u64>,
cpu_time: Option<u64>,
total_time: Option<u64>,
time: Option<u64>,
output_limit: Option<u64>,
walltime: Option<u64>,
}
Expand All @@ -94,9 +111,10 @@ impl RawCompile {
user_mem,
rt_time,
cpu_time,
total_time,
time,
output_limit,
walltime
walltime,
memory
);
}
}
Expand All @@ -105,12 +123,13 @@ impl Default for RawCompile {
fn default() -> Self {
Self {
command: Vec::new(),
kernel_mem: Some(67108864),
user_mem: Some(268435456),
kernel_mem: Some(268435456),
memory: Some(268435456),
user_mem: Some(8589934592),
rt_time: Some(1000000),
cpu_time: Some(1000000),
total_time: Some(10000000),
output_limit: Some(4096),
cpu_time: Some(10000000000),
time: Some(10000000),
output_limit: Some(33554432),
walltime: Some(360000000),
}
}
Expand Down Expand Up @@ -154,8 +173,8 @@ impl Default for RawJudge {
fn default() -> Self {
Self {
command: Vec::new(),
kernel_mem: Some(67108864),
rt_time: Some(1000000),
kernel_mem: Some(268435456),
rt_time: Some(10000000),
memory_multiplier: Some(1.0),
cpu_multiplier: Some(1.0),
walltime: Some(360000000),
Expand Down
51 changes: 0 additions & 51 deletions judger/src/language/stage/assert.rs

This file was deleted.

10 changes: 5 additions & 5 deletions judger/src/language/stage/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ use crate::{
Result,
};

use super::JudgeRunner;
use super::Runner;

pub struct CompileRunner {
pub struct Compiler {
spec: Arc<Spec>,
handle: MountHandle,
}

impl CompileRunner {
impl Compiler {
pub fn new(spec: Arc<Spec>, handle: MountHandle) -> Self {
Self { spec, handle }
}
pub async fn run(self) -> Result<Option<JudgeRunner>> {
pub async fn compile(self) -> Result<Option<Runner>> {
let ctx = CompileCtx {
spec: self.spec.clone(),
path: self.handle.get_path().to_path_buf(),
Expand All @@ -30,7 +30,7 @@ impl CompileRunner {
return Ok(None);
}

let runner = JudgeRunner::new(self.handle, self.spec);
let runner = Runner::new(self.handle, self.spec);
Ok(Some(runner))
}
}
Expand Down
Loading

0 comments on commit 74daeda

Please sign in to comment.