change judge params

This commit is contained in:
Himit_ZH 2022-01-07 21:54:58 +08:00
parent 6cf91067cf
commit 33375ee5a4
16 changed files with 299 additions and 225 deletions

View File

@ -24,11 +24,11 @@ public class AsyncTaskConfig implements AsyncConfigurer {
// 线程池维护线程的最少数量
taskExecutor.setCorePoolSize(10);
// 线程池维护线程的最大数量
taskExecutor.setMaxPoolSize(100);
taskExecutor.setMaxPoolSize(20);
// 缓存队列
taskExecutor.setQueueCapacity(200);
//活跃时间
taskExecutor.setKeepAliveSeconds(10);
taskExecutor.setKeepAliveSeconds(3);
// 对拒绝task的处理策略
//(1) 默认的ThreadPoolExecutor.AbortPolicy 处理程序遭到拒绝将抛出运行时RejectedExecutionException;
//(2) ThreadPoolExecutor.CallerRunsPolicy 线程调用运行该任务的 execute 本身此策略提供简单的反馈控制机制能够减缓新任务的提交速度

View File

@ -24,9 +24,9 @@ public class JudgeAsyncTaskConfig {
//最大线程数
executor.setMaxPoolSize(10);
//队列容量
executor.setQueueCapacity(300);
executor.setQueueCapacity(500);
//活跃时间
executor.setKeepAliveSeconds(10);
executor.setKeepAliveSeconds(3);
//线程名字前缀
executor.setThreadNamePrefix("JudgeExecutor-");

View File

@ -23,8 +23,8 @@ public class RestTemplateConfig {
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(100000);//单位为ms
factory.setConnectTimeout(10000);//单位为ms
factory.setReadTimeout(600000);//单位为ms
factory.setConnectTimeout(50000);//单位为ms
return factory;
}
}

View File

@ -1,13 +1,8 @@
package top.hcode.hoj.controller.admin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
@ -15,58 +10,25 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.judge.remote.RemoteJudgeDispatcher;
import top.hcode.hoj.judge.self.JudgeDispatcher;
import top.hcode.hoj.pojo.entity.judge.Judge;
import top.hcode.hoj.pojo.entity.judge.JudgeCase;
import top.hcode.hoj.pojo.entity.user.UserAcproblem;
import top.hcode.hoj.pojo.entity.contest.ContestRecord;
import top.hcode.hoj.pojo.entity.problem.Problem;
import top.hcode.hoj.service.contest.impl.ContestRecordServiceImpl;
import top.hcode.hoj.service.judge.impl.JudgeCaseServiceImpl;
import top.hcode.hoj.service.judge.impl.JudgeServiceImpl;
import top.hcode.hoj.service.problem.impl.ProblemServiceImpl;
import top.hcode.hoj.service.user.impl.UserAcproblemServiceImpl;
import top.hcode.hoj.utils.Constants;
import top.hcode.hoj.service.judge.impl.RejudgeServiceImpl;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import javax.annotation.Resource;
/**
* @Author: Himit_ZH
* @Date: 2021/1/3 14:09
* @Description:
* @Description: 超管重判提交
*/
@RestController
@RequestMapping("/api/admin/judge")
@RefreshScope
public class AdminJudgeController {
@Autowired
private JudgeServiceImpl judgeService;
@Resource
private RejudgeServiceImpl rejudgeService;
@Autowired
private UserAcproblemServiceImpl userAcproblemService;
@Autowired
private ContestRecordServiceImpl contestRecordService;
@Autowired
private JudgeCaseServiceImpl judgeCaseService;
@Autowired
private ProblemServiceImpl problemService;
@Value("${hoj.judge.token}")
private String judgeToken;
@Autowired
private JudgeDispatcher judgeDispatcher;
@Autowired
private RemoteJudgeDispatcher remoteJudgeDispatcher;
@GetMapping("/rejudge")
@RequiresAuthentication
@ -74,60 +36,7 @@ public class AdminJudgeController {
@RequiresPermissions("rejudge")
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public CommonResult rejudge(@RequestParam("submitId") Long submitId) {
Judge judge = judgeService.getById(submitId);
boolean isContestSubmission = judge.getCid() != 0;
boolean resetContestRecordResult = true;
// 如果是非比赛题目
if (!isContestSubmission) {
// 重判前需要将该题目对应记录表一并更新
// 如果该题已经是AC通过状态更新该题目的用户ac做题表 user_acproblem
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
userAcproblemQueryWrapper.eq("submit_id", judge.getSubmitId());
userAcproblemService.remove(userAcproblemQueryWrapper);
}
} else {
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("submit_id", submitId).setSql("status=null,score=null");
resetContestRecordResult = contestRecordService.update(updateWrapper);
}
// 清除该提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.eq("submit_id", submitId);
judgeCaseService.remove(judgeCaseQueryWrapper);
boolean hasSubmitIdRemoteRejudge = isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), judge.getStatus());
// 设置默认值
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus()); // 开始进入判题队列
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("")
.setTime(null)
.setMemory(null)
.setErrorMessage(null)
.setOiRankScore(null)
.setScore(null);
boolean result = judgeService.updateById(judge);
if (result && resetContestRecordResult) {
// 调用判题服务
Problem problem = problemService.getById(judge.getPid());
if (problem.getIsRemote()) { // 如果是远程oj判题
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(),
isContestSubmission, 1, hasSubmitIdRemoteRejudge);
} else {
judgeDispatcher.sendTask(judge, judgeToken, isContestSubmission, 1);
}
return CommonResult.successResponse(judge, "重判成功!该提交已进入判题队列!");
} else {
return CommonResult.successResponse(judge, "重判失败!请重新尝试!");
}
return rejudgeService.rejudge(submitId);
}
@GetMapping("/rejudge-contest-problem")
@ -136,74 +45,6 @@ public class AdminJudgeController {
@RequiresPermissions("rejudge")
@Transactional(rollbackFor = Exception.class)
public CommonResult rejudgeContestProblem(@RequestParam("cid") Long cid, @RequestParam("pid") Long pid) {
QueryWrapper<Judge> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("cid", cid).eq("pid", pid);
List<Judge> rejudgeList = judgeService.list(queryWrapper);
if (rejudgeList.size() == 0) {
return CommonResult.errorResponse("当前该题目无提交,不可重判!");
}
List<Long> submitIdList = new LinkedList<>();
HashMap<Long, Integer> idMapStatus = new HashMap<>();
// 全部设置默认值
for (Judge judge : rejudgeList) {
idMapStatus.put(judge.getSubmitId(), judge.getStatus());
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus()); // 开始进入判题队列
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("")
.setTime(null)
.setMemory(null)
.setErrorMessage(null)
.setOiRankScore(null)
.setScore(null);
submitIdList.add(judge.getSubmitId());
}
boolean resetJudgeResult = judgeService.updateBatchById(rejudgeList);
// 清除每个提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.in("submit_id", submitIdList);
judgeCaseService.remove(judgeCaseQueryWrapper);
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("submit_id", submitIdList).setSql("status=null,score=null");
boolean resetContestRecordResult = contestRecordService.update(updateWrapper);
if (resetContestRecordResult && resetJudgeResult) {
// 调用重判服务
Problem problem = problemService.getById(pid);
if (problem.getIsRemote()) { // 如果是远程oj判题
for (Judge judge : rejudgeList) {
// 进入重判队列等待调用判题服务
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(),
judge.getCid() != 0, 1,
isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), idMapStatus.get(judge.getSubmitId())));
}
} else {
for (Judge judge : rejudgeList) {
// 进入重判队列等待调用判题服务
judgeDispatcher.sendTask(judge, judgeToken, judge.getCid() != 0, 1);
}
}
return CommonResult.successResponse(null, "重判成功!该题目对应的全部提交已进入判题队列!");
} else {
return CommonResult.errorResponse("重判失败!请重新尝试!");
}
return rejudgeService.rejudgeContestProblem(cid, pid);
}
public boolean isHasSubmitIdRemoteRejudge(Long vjudgeSubmitId, int status) {
boolean isHasSubmitIdRemoteRejudge = false;
if (vjudgeSubmitId != null &&
(status == Constants.Judge.STATUS_SUBMITTED_FAILED.getStatus()
|| status == Constants.Judge.STATUS_COMPILING.getStatus()
|| status == Constants.Judge.STATUS_PENDING.getStatus()
|| status == Constants.Judge.STATUS_JUDGING.getStatus()
|| status == Constants.Judge.STATUS_SYSTEM_ERROR.getStatus())) {
isHasSubmitIdRemoteRejudge = true;
}
return isHasSubmitIdRemoteRejudge;
}
}
}

View File

@ -48,7 +48,6 @@ public class JudgeReceiver extends AbstractReceiver {
@Override
public void handleJudgeMsg(String taskJsonStr) {
JSONObject task = JSONUtil.parseObj(taskJsonStr);
Judge judge = task.get("judge", Judge.class);
String token = task.getStr("token");

View File

@ -14,4 +14,6 @@ public interface ScheduleService {
void deleteUserSession();
void syncNoticeToRecentHalfYearUser();
void checkHalfAnHourPendingSubmission();
}

View File

@ -15,6 +15,9 @@ import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.pojo.entity.judge.Judge;
import top.hcode.hoj.pojo.entity.user.Session;
import top.hcode.hoj.pojo.entity.user.UserInfo;
import top.hcode.hoj.pojo.entity.user.UserRecord;
@ -22,6 +25,8 @@ import top.hcode.hoj.pojo.entity.msg.AdminSysNotice;
import top.hcode.hoj.pojo.entity.common.File;
import top.hcode.hoj.pojo.entity.msg.UserSysNotice;
import top.hcode.hoj.service.common.impl.FileServiceImpl;
import top.hcode.hoj.service.judge.impl.JudgeServiceImpl;
import top.hcode.hoj.service.judge.impl.RejudgeServiceImpl;
import top.hcode.hoj.service.user.UserInfoService;
import top.hcode.hoj.service.user.UserRecordService;
import top.hcode.hoj.service.msg.impl.AdminSysNoticeServiceImpl;
@ -85,6 +90,11 @@ public class ScheduleServiceImpl implements ScheduleService {
@Resource
private UserSysNoticeServiceImpl userSysNoticeService;
@Resource
private JudgeServiceImpl judgeService;
@Resource
private RejudgeServiceImpl rejudgeService;
/**
* @MethodName deleteAvatar
@ -371,4 +381,23 @@ public class ScheduleServiceImpl implements ScheduleService {
}
@Override
@Scheduled(cron = "0 0/30 * * * ?")
public void checkHalfAnHourPendingSubmission() {
DateTime dateTime = DateUtil.offsetMinute(new Date(), -30);
String strTime = DateFormatUtils.format(dateTime, "yyyy-MM-dd HH:mm:ss");
QueryWrapper<Judge> judgeQueryWrapper = new QueryWrapper<>();
judgeQueryWrapper.select("distinct submit_id");
judgeQueryWrapper.eq("status", Constants.Judge.STATUS_PENDING.getStatus());
judgeQueryWrapper.apply("UNIX_TIMESTAMP('" + strTime + "') > UNIX_TIMESTAMP(gmt_modified)");
List<Judge> judgeList = judgeService.list(judgeQueryWrapper);
if (!CollectionUtils.isEmpty(judgeList)) {
log.info("Half An Hour Check Pending Submission to Rejudge:" + Arrays.toString(judgeList.toArray()));
for (Judge judge : judgeList) {
rejudgeService.rejudge(judge.getSubmitId());
}
}
}
}

View File

@ -0,0 +1,10 @@
package top.hcode.hoj.service.judge;
import top.hcode.hoj.common.result.CommonResult;
public interface RejudgeService {
CommonResult rejudge(Long submitId);
CommonResult rejudgeContestProblem(Long cid,Long pid);
}

View File

@ -0,0 +1,188 @@
package top.hcode.hoj.service.judge.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.judge.remote.RemoteJudgeDispatcher;
import top.hcode.hoj.judge.self.JudgeDispatcher;
import top.hcode.hoj.pojo.entity.contest.ContestRecord;
import top.hcode.hoj.pojo.entity.judge.Judge;
import top.hcode.hoj.pojo.entity.judge.JudgeCase;
import top.hcode.hoj.pojo.entity.problem.Problem;
import top.hcode.hoj.pojo.entity.user.UserAcproblem;
import top.hcode.hoj.service.contest.impl.ContestRecordServiceImpl;
import top.hcode.hoj.service.judge.RejudgeService;
import top.hcode.hoj.service.problem.impl.ProblemServiceImpl;
import top.hcode.hoj.service.user.impl.UserAcproblemServiceImpl;
import top.hcode.hoj.utils.Constants;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
/**
* @Author: Himit_ZH
* @Date: 2022/1/7 18:12
* @Description:
*/
@Service
@RefreshScope
public class RejudgeServiceImpl implements RejudgeService {
@Resource
private JudgeServiceImpl judgeService;
@Resource
private UserAcproblemServiceImpl userAcproblemService;
@Resource
private ContestRecordServiceImpl contestRecordService;
@Resource
private JudgeCaseServiceImpl judgeCaseService;
@Resource
private ProblemServiceImpl problemService;
@Value("${hoj.judge.token}")
private String judgeToken;
@Resource
private JudgeDispatcher judgeDispatcher;
@Resource
private RemoteJudgeDispatcher remoteJudgeDispatcher;
@Override
public CommonResult rejudge(Long submitId) {
Judge judge = judgeService.getById(submitId);
boolean isContestSubmission = judge.getCid() != 0;
boolean resetContestRecordResult = true;
// 如果是非比赛题目
if (!isContestSubmission) {
// 重判前需要将该题目对应记录表一并更新
// 如果该题已经是AC通过状态更新该题目的用户ac做题表 user_acproblem
if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus().intValue()) {
QueryWrapper<UserAcproblem> userAcproblemQueryWrapper = new QueryWrapper<>();
userAcproblemQueryWrapper.eq("submit_id", judge.getSubmitId());
userAcproblemService.remove(userAcproblemQueryWrapper);
}
} else {
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("submit_id", submitId).setSql("status=null,score=null");
resetContestRecordResult = contestRecordService.update(updateWrapper);
}
// 清除该提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.eq("submit_id", submitId);
judgeCaseService.remove(judgeCaseQueryWrapper);
boolean hasSubmitIdRemoteRejudge = isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), judge.getStatus());
// 设置默认值
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus()); // 开始进入判题队列
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("")
.setTime(null)
.setMemory(null)
.setErrorMessage(null)
.setOiRankScore(null)
.setScore(null);
boolean result = judgeService.updateById(judge);
if (result && resetContestRecordResult) {
// 调用判题服务
Problem problem = problemService.getById(judge.getPid());
if (problem.getIsRemote()) { // 如果是远程oj判题
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(),
isContestSubmission, 1, hasSubmitIdRemoteRejudge);
} else {
judgeDispatcher.sendTask(judge, judgeToken, isContestSubmission, 1);
}
return CommonResult.successResponse(judge, "重判成功!该提交已进入判题队列!");
} else {
return CommonResult.successResponse(judge, "重判失败!请重新尝试!");
}
}
@Override
public CommonResult rejudgeContestProblem(Long cid, Long pid) {
QueryWrapper<Judge> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("cid", cid).eq("pid", pid);
List<Judge> rejudgeList = judgeService.list(queryWrapper);
if (rejudgeList.size() == 0) {
return CommonResult.errorResponse("当前该题目无提交,不可重判!");
}
List<Long> submitIdList = new LinkedList<>();
HashMap<Long, Integer> idMapStatus = new HashMap<>();
// 全部设置默认值
for (Judge judge : rejudgeList) {
idMapStatus.put(judge.getSubmitId(), judge.getStatus());
judge.setStatus(Constants.Judge.STATUS_PENDING.getStatus()); // 开始进入判题队列
judge.setVersion(judge.getVersion() + 1);
judge.setJudger("")
.setTime(null)
.setMemory(null)
.setErrorMessage(null)
.setOiRankScore(null)
.setScore(null);
submitIdList.add(judge.getSubmitId());
}
boolean resetJudgeResult = judgeService.updateBatchById(rejudgeList);
// 清除每个提交对应的测试点结果
QueryWrapper<JudgeCase> judgeCaseQueryWrapper = new QueryWrapper<>();
judgeCaseQueryWrapper.in("submit_id", submitIdList);
judgeCaseService.remove(judgeCaseQueryWrapper);
// 将对应比赛记录设置成默认值
UpdateWrapper<ContestRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("submit_id", submitIdList).setSql("status=null,score=null");
boolean resetContestRecordResult = contestRecordService.update(updateWrapper);
if (resetContestRecordResult && resetJudgeResult) {
// 调用重判服务
Problem problem = problemService.getById(pid);
if (problem.getIsRemote()) { // 如果是远程oj判题
for (Judge judge : rejudgeList) {
// 进入重判队列等待调用判题服务
remoteJudgeDispatcher.sendTask(judge, judgeToken, problem.getProblemId(),
judge.getCid() != 0, 1,
isHasSubmitIdRemoteRejudge(judge.getVjudgeSubmitId(), idMapStatus.get(judge.getSubmitId())));
}
} else {
for (Judge judge : rejudgeList) {
// 进入重判队列等待调用判题服务
judgeDispatcher.sendTask(judge, judgeToken, judge.getCid() != 0, 1);
}
}
return CommonResult.successResponse(null, "重判成功!该题目对应的全部提交已进入判题队列!");
} else {
return CommonResult.errorResponse("重判失败!请重新尝试!");
}
}
private boolean isHasSubmitIdRemoteRejudge(Long vjudgeSubmitId, int status) {
boolean isHasSubmitIdRemoteRejudge = false;
if (vjudgeSubmitId != null &&
(status == Constants.Judge.STATUS_SUBMITTED_FAILED.getStatus()
|| status == Constants.Judge.STATUS_COMPILING.getStatus()
|| status == Constants.Judge.STATUS_PENDING.getStatus()
|| status == Constants.Judge.STATUS_JUDGING.getStatus()
|| status == Constants.Judge.STATUS_SYSTEM_ERROR.getStatus())) {
isHasSubmitIdRemoteRejudge = true;
}
return isHasSubmitIdRemoteRejudge;
}
}

View File

@ -74,7 +74,7 @@ public class JudgeRun {
.userFileId(userFileId)
.runDir(runDir)
.testTime(testTime)
.maxMemory(problem.getMemoryLimit() * 1024L)
.maxMemory((long) problem.getMemoryLimit())
.maxTime((long) problem.getTimeLimit())
.maxStack(problem.getStackLimit())
.testCaseInfo(testCasesInfo)

View File

@ -302,6 +302,7 @@ public class SandboxRun {
List<String> envs,
String testCasePath,
Long maxTime,
Long maxMemory,
Long maxOutputSize,
Integer maxStack,
String exeName,
@ -332,7 +333,11 @@ public class SandboxRun {
cmd.set("cpuLimit", maxTime * 1000 * 1000L);
cmd.set("clockLimit", maxTime * 1000 * 1000L * 3);
// byte
cmd.set("memoryLimit", MEMORY_LIMIT_MB * 1024 * 1024L);
if (maxMemory >= MEMORY_LIMIT_MB) {
cmd.set("memoryLimit", (maxMemory + 100) * 1024 * 1024L);
} else {
cmd.set("memoryLimit", MEMORY_LIMIT_MB * 1024 * 1024L);
}
cmd.set("procLimit", maxProcessNumber);
cmd.set("stackLimit", maxStack * 1024 * 1024L);
@ -413,6 +418,7 @@ public class SandboxRun {
cmd.set("procLimit", maxProcessNumber);
cmd.set("stackLimit", STACK_LIMIT_MB * 1024 * 1024L);
JSONObject spjExeFile = new JSONObject();
spjExeFile.set("src", spjExeSrc);
@ -475,6 +481,7 @@ public class SandboxRun {
String userExeName,
String userFileId,
Long userMaxTime,
Long userMaxMemory,
Integer userMaxStack,
String testCaseInputPath,
String testCaseInputFileName,
@ -509,10 +516,12 @@ public class SandboxRun {
// ms-->ns
pipeInputCmd.set("cpuLimit", userMaxTime * 1000 * 1000L);
pipeInputCmd.set("realCpuLimit", userMaxTime * 1000 * 1000L * 3);
pipeInputCmd.set("clockLimit", userMaxTime * 1000 * 1000L * 3);
// byte
pipeInputCmd.set("memoryLimit", MEMORY_LIMIT_MB * 1024 * 1024L);
pipeInputCmd.set("clockLimit", maxProcessNumber);
pipeInputCmd.set("memoryLimit", (userMaxMemory + 100) * 1024 * 1024L);
pipeInputCmd.set("procLimit", maxProcessNumber);
pipeInputCmd.set("stackLimit", userMaxStack * 1024 * 1024L);
JSONObject exeFile = new JSONObject();
@ -542,10 +551,10 @@ public class SandboxRun {
pipeOutputCmd.set("files", JSONUtil.parseArray(outTmp, false));
// ms-->ns
pipeOutputCmd.set("cpuLimit", TIME_LIMIT_MS * 1000 * 1000L);
pipeOutputCmd.set("clockLimit", TIME_LIMIT_MS * 1000 * 1000L * 3);
pipeOutputCmd.set("cpuLimit", userMaxTime * 1000 * 1000L * 2);
pipeOutputCmd.set("clockLimit", userMaxTime * 1000 * 1000L * 3 * 2);
// byte
pipeOutputCmd.set("memoryLimit", MEMORY_LIMIT_MB * 1024 * 1024L);
pipeOutputCmd.set("memoryLimit", (userMaxMemory + 100) * 1024 * 1024L * 2);
pipeOutputCmd.set("procLimit", maxProcessNumber);
pipeOutputCmd.set("stackLimit", STACK_LIMIT_MB * 1024 * 1024L);

View File

@ -55,7 +55,7 @@ public class JudgeGlobalDTO implements Serializable {
private Long maxTime;
/**
* 当前题目评测的最大空间限制 kb
* 当前题目评测的最大空间限制 mb
*/
private Long maxMemory;

View File

@ -30,6 +30,7 @@ public class DefaultJudge extends AbstractJudge {
runConfig.getEnvs(),
judgeDTO.getTestCaseInputPath(),
judgeGlobalDTO.getTestTime(),
judgeGlobalDTO.getMaxMemory(),
judgeDTO.getMaxOutputSize(),
judgeGlobalDTO.getMaxStack(),
runConfig.getExeName(),
@ -46,9 +47,9 @@ public class DefaultJudge extends AbstractJudge {
if (sandBoxRes.getStatus().equals(Constants.Judge.STATUS_ACCEPTED.getStatus())) {
// 对结果的时间损耗和空间损耗与题目限制做比较判断是否mle和tle
if (sandBoxRes.getTime() >= judgeGlobalDTO.getMaxTime()) {
if (sandBoxRes.getTime() > judgeGlobalDTO.getMaxTime()) {
result.set("status", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED.getStatus());
} else if (sandBoxRes.getMemory() >= judgeGlobalDTO.getMaxMemory()) {
} else if (sandBoxRes.getMemory() > judgeGlobalDTO.getMaxMemory() * 1024) {
result.set("status", Constants.Judge.STATUS_MEMORY_LIMIT_EXCEEDED.getStatus());
} else {
// 与原测试数据输出的md5进行对比 AC或者是WA

View File

@ -43,6 +43,7 @@ public class InteractiveJudge extends AbstractJudge {
runConfig.getExeName(),
judgeGlobalDTO.getUserFileId(),
judgeGlobalDTO.getTestTime(),
judgeGlobalDTO.getMaxMemory(),
judgeGlobalDTO.getMaxStack(),
judgeDTO.getTestCaseInputPath(),
testCaseInputFileName,
@ -69,37 +70,12 @@ public class InteractiveJudge extends AbstractJudge {
StringBuilder errMsg = new StringBuilder();
int userExitCode = userSandBoxRes.getExitCode();
if (userSandBoxRes.getStatus().equals(Constants.Judge.STATUS_ACCEPTED.getStatus())) {
// 如果运行超过题目限制时间直接TLE
if (userSandBoxRes.getTime() >= judgeGlobalDTO.getMaxTime()) {
result.set("status", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED.getStatus());
} else if (userSandBoxRes.getMemory() >= judgeGlobalDTO.getMaxMemory()) { // 如果运行超过题目限制空间直接MLE
result.set("status", Constants.Judge.STATUS_MEMORY_LIMIT_EXCEEDED.getStatus());
} else {
// 根据交互程序的退出状态码及输出进行判断
JSONObject interactiveCheckRes = checkInteractiveRes(interactiveSandBoxRes);
int code = interactiveCheckRes.getInt("code");
if (code == SPJ_WA) {
result.set("status", Constants.Judge.STATUS_WRONG_ANSWER.getStatus());
} else if (code == SPJ_AC) {
result.set("status", Constants.Judge.STATUS_ACCEPTED.getStatus());
} else if (code == SPJ_PE) {
result.set("status", Constants.Judge.STATUS_PRESENTATION_ERROR.getStatus());
} else if (code == SPJ_PC){
result.set("status", Constants.Judge.STATUS_PARTIAL_ACCEPTED.getStatus());
result.set("percentage", interactiveCheckRes.getDouble("percentage"));
} else {
result.set("status", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
}
String spjErrMsg = interactiveCheckRes.getStr("errMsg");
if (!StringUtils.isEmpty(spjErrMsg)) {
errMsg.append(spjErrMsg).append(" ");
}
}
} else if (userSandBoxRes.getStatus().equals(Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED.getStatus())) {
result.set("status", userSandBoxRes.getStatus());
// 如果运行超过题目限制时间直接TLE
if (userSandBoxRes.getTime() > judgeGlobalDTO.getMaxTime()) {
result.set("status", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED.getStatus());
} else if (userSandBoxRes.getMemory() > judgeGlobalDTO.getMaxMemory() * 1024) { // 如果运行超过题目限制空间直接MLE
result.set("status", Constants.Judge.STATUS_MEMORY_LIMIT_EXCEEDED.getStatus());
} else if ((userExitCode != 0 && userExitCode != 13) || (userExitCode == 13 && interactiveSandBoxRes.getExitCode() == 0)) {
// Broken Pipe
result.set("status", Constants.Judge.STATUS_RUNTIME_ERROR.getStatus());
@ -109,10 +85,28 @@ public class InteractiveJudge extends AbstractJudge {
errMsg.append(String.format("Your program return exitCode: %s\n", userExitCode));
}
} else {
result.set("status", interactiveSandBoxRes.getStatus());
errMsg.append(interactiveSandBoxRes.getStderr()).append(" ");
if (interactiveSandBoxRes.getExitCode() !=0 && !StringUtils.isEmpty(interactiveSandBoxRes.getStderr())) {
errMsg.append(String.format("Interactive program exited with code: %s",interactiveSandBoxRes.getExitCode()));
// 根据交互程序的退出状态码及输出进行判断
JSONObject interactiveCheckRes = checkInteractiveRes(interactiveSandBoxRes);
int code = interactiveCheckRes.getInt("code");
if (code == SPJ_WA) {
result.set("status", Constants.Judge.STATUS_WRONG_ANSWER.getStatus());
} else if (code == SPJ_AC) {
result.set("status", Constants.Judge.STATUS_ACCEPTED.getStatus());
} else if (code == SPJ_PE) {
result.set("status", Constants.Judge.STATUS_PRESENTATION_ERROR.getStatus());
} else if (code == SPJ_PC) {
result.set("status", Constants.Judge.STATUS_PARTIAL_ACCEPTED.getStatus());
result.set("percentage", interactiveCheckRes.getDouble("percentage"));
} else {
result.set("status", Constants.Judge.STATUS_SYSTEM_ERROR.getStatus());
}
String spjErrMsg = interactiveCheckRes.getStr("errMsg");
if (!StringUtils.isEmpty(spjErrMsg)) {
errMsg.append(spjErrMsg).append(" ");
}
if (interactiveSandBoxRes.getExitCode() != 0 && !StringUtils.isEmpty(interactiveSandBoxRes.getStderr())) {
errMsg.append(String.format("Interactive program exited with code: %s", interactiveSandBoxRes.getExitCode()));
}
}
// kb

View File

@ -32,6 +32,7 @@ public class SpecialJudge extends AbstractJudge {
runConfig.getEnvs(),
judgeDTO.getTestCaseInputPath(),
judgeGlobalDTO.getTestTime(),
judgeGlobalDTO.getMaxMemory(),
judgeDTO.getMaxOutputSize(),
judgeGlobalDTO.getMaxStack(),
runConfig.getExeName(),
@ -53,9 +54,9 @@ public class SpecialJudge extends AbstractJudge {
if (sandBoxRes.getStatus().equals(Constants.Judge.STATUS_ACCEPTED.getStatus())) {
// 对结果的时间损耗和空间损耗与题目限制做比较判断是否mle和tle
if (sandBoxRes.getTime() >= judgeGlobalDTO.getMaxTime()) {
if (sandBoxRes.getTime() > judgeGlobalDTO.getMaxTime()) {
result.set("status", Constants.Judge.STATUS_TIME_LIMIT_EXCEEDED.getStatus());
} else if (sandBoxRes.getMemory() >= judgeGlobalDTO.getMaxMemory()) {
} else if (sandBoxRes.getMemory() > judgeGlobalDTO.getMaxMemory() * 1024) {
result.set("status", Constants.Judge.STATUS_MEMORY_LIMIT_EXCEEDED.getStatus());
} else {

View File

@ -18,9 +18,9 @@ public class ThreadPoolUtils {
executorService = new ThreadPoolExecutor(
cpuNum, // 核心线程数
cpuNum * 2, // 最大线程数最多几个线程并发
2,//当非核心线程无任务时几秒后结束该线程
3,//当非核心线程无任务时几秒后结束该线程
TimeUnit.SECONDS,// 结束线程时间单位
new LinkedBlockingDeque<>(100 * cpuNum), //阻塞队列限制等候线程数
new LinkedBlockingDeque<>(200 * cpuNum), //阻塞队列限制等候线程数
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了尝试去和最早的竞争也不会抛出异常
}