forked from QingdaoU/JudgeServer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
144 lines (120 loc) · 5.47 KB
/
Copy pathserver.py
File metadata and controls
144 lines (120 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import json
import os
import shutil
import uuid
from flask import Flask, request, Response
from compiler import Compiler
from config import JUDGER_WORKSPACE_BASE, SPJ_SRC_DIR, SPJ_EXE_DIR
from exception import TokenVerificationFailed, CompileError, SPJCompileError, JudgeClientError
from judge_client import JudgeClient
from utils import server_info, logger, token
app = Flask(__name__)
DEBUG = os.environ.get("judger_debug") == "1"
app.debug = DEBUG
class InitSubmissionEnv(object):
def __init__(self, judger_workspace, submission_id):
self.path = os.path.join(judger_workspace, submission_id)
def __enter__(self):
try:
os.mkdir(self.path)
os.chmod(self.path, 0o777)
except Exception as e:
logger.exception(e)
raise JudgeClientError("failed to create runtime dir")
return self.path
def __exit__(self, exc_type, exc_val, exc_tb):
if not DEBUG:
try:
shutil.rmtree(self.path)
except Exception as e:
logger.exception(e)
raise JudgeClientError("failed to clean runtime dir")
class JudgeServer:
@classmethod
def ping(cls):
data = server_info()
data["action"] = "pong"
return data
@classmethod
def judge(cls, language_config, src, max_cpu_time, max_memory, test_case_id,
spj_version=None, spj_config=None, spj_compile_config=None, spj_src=None, output=False):
# init
compile_config = language_config.get("compile")
run_config = language_config["run"]
submission_id = uuid.uuid4().hex
if spj_version and spj_config:
spj_exe_path = os.path.join(SPJ_EXE_DIR, spj_config["exe_name"].format(spj_version=spj_version))
# spj src has not been compiled
if not os.path.isfile(spj_exe_path):
logger.warning("%s does not exists, spj src will be recompiled")
cls.compile_spj(spj_version=spj_version, src=spj_src,
spj_compile_config=spj_compile_config)
with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=str(submission_id)) as submission_dir:
if compile_config:
src_path = os.path.join(submission_dir, compile_config["src_name"])
# write source code into file
with open(src_path, "w") as f:
f.write(src)
# compile source code, return exe file path
exe_path = Compiler().compile(compile_config=compile_config,
src_path=src_path,
output_dir=submission_dir)
else:
exe_path = os.path.join(submission_dir, run_config["exe_name"])
with open(exe_path, "w") as f:
f.write(src)
judge_client = JudgeClient(run_config=language_config["run"],
exe_path=exe_path,
max_cpu_time=max_cpu_time,
max_memory=max_memory,
test_case_id=str(test_case_id),
submission_dir=submission_dir,
spj_version=spj_version,
spj_config=spj_config,
output=output)
run_result = judge_client.run()
return run_result
@classmethod
def compile_spj(cls, spj_version, src, spj_compile_config):
spj_compile_config["src_name"] = spj_compile_config["src_name"].format(spj_version=spj_version)
spj_compile_config["exe_name"] = spj_compile_config["exe_name"].format(spj_version=spj_version)
spj_src_path = os.path.join(SPJ_SRC_DIR, spj_compile_config["src_name"])
# if spj source code not found, then write it into file
if not os.path.exists(spj_src_path):
with open(spj_src_path, "w") as f:
f.write(src)
try:
Compiler().compile(compile_config=spj_compile_config,
src_path=spj_src_path,
output_dir=SPJ_EXE_DIR)
# turn common CompileError into SPJCompileError
except CompileError as e:
raise SPJCompileError(e.message)
return "success"
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods=["POST"])
def server(path):
if path in ("judge", "ping", "compile_spj"):
_token = request.headers.get("X-Judge-Server-Token")
try:
if _token != token:
raise TokenVerificationFailed("invalid token")
try:
data = request.json
except Exception:
data = {}
ret = {"err": None, "data": getattr(JudgeServer, path)(**data)}
except (CompileError, TokenVerificationFailed, SPJCompileError, JudgeClientError) as e:
logger.exception(e)
ret = {"err": e.__class__.__name__, "data": e.message}
except Exception as e:
logger.exception(e)
ret = {"err": "JudgeClientError", "data": e.__class__.__name__ + " :" + str(e)}
else:
ret = {"err": "InvalidRequest", "data": "404"}
return Response(json.dumps(ret), mimetype='application/json')
if DEBUG:
logger.info("DEBUG=ON")
# gunicorn -w 4 -b 0.0.0.0:8080 server:app
if __name__ == "__main__":
app.run(debug=DEBUG)