From 5f8f2acf823a1634786ba0f8bc464317ca5f95a4 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 6 Jul 2015 18:59:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E9=87=8D=E5=AE=9A=E5=90=91=E9=94=99=E8=AF=AF=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=BE=93?= =?UTF-8?q?=E5=87=BA=E7=BB=93=E6=9E=9C=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lrun在运行的时候,输入输出重定向的context是当前的shell,所以不能重定向到进程的tmpfs中。考虑在docker中开辟tmpfs缓存空间。 输出结果比较是采用的md5,暂时没考虑格式错误的情况。 --- judge/client.py | 62 +++++++++++++++++++++++++++++++++-------------- judge/settings.py | 8 +++--- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/judge/client.py b/judge/client.py index 53f0827..5cae0ac 100644 --- a/judge/client.py +++ b/judge/client.py @@ -1,10 +1,9 @@ # coding=utf-8 import commands -from copy_reg import pickle -from types import MethodType +import hashlib from multiprocessing import Pool -from settings import max_running_number, lrun_gid, lrun_uid, use_tmpfs +from settings import max_running_number, lrun_gid, lrun_uid, judger_workspace from consts import Language, Result @@ -57,14 +56,15 @@ class JudgeClient(object): { "1": {"input_name": "1.in", "output_name": "1.out", - "output_md5": "yyy", + "output_md5": "b10a8db164e0754105b7a99be72e3fe5", "output_size": 100}, "2": {"input_name": "2.in", "output_name": "2.out", - "output_md5": "yyy", + "output_md5": "3e25960a79dbc69b674cd4ec67a72c62", "output_size": 100} - } + }, + "output_total_size": 200 } def generate_command(self, test_case_id): @@ -80,17 +80,14 @@ class JudgeClient(object): " --network false" + \ " --uid " + str(lrun_uid) + \ " --gid " + str(lrun_gid) - #if use_tmpfs: - # command += (" --tmpfs /var " + - # str(int(self.test_case_info["test_cases"][str(test_case_id)]["output_size"] * 1.2))) if self.language == Language.JAVA: command += (" java " + self.exec_file_path) else: command += (" " + self.exec_file_path) - # fixme 输出路径 + command += (" 0<" + self.test_case_dir + str(test_case_id) + ".in" + - " 1>" + "/var/judge/" + str(test_case_id) + ".out" + + " 1>" + judger_workspace + str(test_case_id) + ".out" + " 3>&2") return command @@ -115,9 +112,9 @@ class JudgeClient(object): if name == "MEMORY": result[translate[name]] = int(value) elif name == "CPUTIME": - result[translate[name]] = float(value) * 1000 + result[translate[name]] = int(float(value) * 1000) elif name == "REALTIME": - result[translate[name]] = float(value) * 1000 + result[translate[name]] = int(float(value) * 1000) elif name == "EXITCODE": result[translate[name]] = int(value) elif name == "TERMSIG": @@ -131,6 +128,30 @@ class JudgeClient(object): result[translate[name]] = translate[value] return result + def compare_output(self, test_case_id): + test_case_md5 = self.test_case_info["test_cases"][str(test_case_id)]["output_md5"] + output_path = judger_workspace + str(test_case_id) + ".out" + + try: + f = open(output_path, "rb") + except IOError: + # 文件不存在等引发的异常 返回结果错误 + return False + + # 计算输出文件的md5 和之前测试用例文件的md5进行比较 + md5 = hashlib.md5() + while True: + data = f.read(2 ** 8) + if not data: + break + md5.update(data) + + # 对比文件是否一致 + print "my", md5.hexdigest() + print test_case_md5 + # todo 去除最后的空行 + return md5.hexdigest() == test_case_md5 + def judge_one(self, test_case_id): # 运行lrun程序 接收返回值 command = self.generate_command(test_case_id) @@ -156,8 +177,13 @@ class JudgeClient(object): raise JudgeClientException("Error exceeded type: " + run_result["exceed"]) return run_result - # 下面就是代码正常运行了 - run_result["result"] = Result.ACCEPTED + # 下面就是代码正常运行了 需要判断代码的输出是否正确 + + if self.compare_output(test_case_id): + run_result["result"] = Result.ACCEPTED + else: + run_result["result"] = Result.WRONG_ANSWER + return run_result def collect_result(self, result): @@ -177,6 +203,7 @@ class JudgeClient(object): try: results.append(item.get()) except Exception as e: + print e results.append({"result": Result.SYSTEM_ERROR}) return results @@ -188,11 +215,10 @@ class JudgeClient(object): return self_dict -# pickle(MethodType, _pickle_method, _unpickle_method) client = JudgeClient(language=Language.C, - exec_file_path="/var/judge/a.out", + exec_file_path="/var/judger/a.out", max_cpu_time=1000000, max_real_time=200000, max_memory=1, - test_case_dir="/var/test_case/1/") + test_case_dir="/var/test_cases/1/") print client.run() diff --git a/judge/settings.py b/judge/settings.py index e647239..8fea94b 100644 --- a/judge/settings.py +++ b/judge/settings.py @@ -5,11 +5,11 @@ # 这样可以避免同时运行的程序过多导致的cpu占用太高 max_running_number = 10 -# 是否使用tmpfs来缓存程序输出。开启可以提高性能,在内存不足的情况下,可以关闭 -use_tmpfs = True - # lrun运行用户的uid lrun_uid = 1001 # lrun用户组gid -lrun_gid = 1002 \ No newline at end of file +lrun_gid = 1002 + +#judger工作目录 +judger_workspace = "/var/judger/"