change judge params
This commit is contained in:
parent
6cf91067cf
commit
33375ee5a4
|
@ -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 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度
|
||||
|
|
|
@ -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-");
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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("重判失败!请重新尝试!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
return rejudgeService.rejudgeContestProblem(cid, pid);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -14,4 +14,6 @@ public interface ScheduleService {
|
|||
void deleteUserSession();
|
||||
|
||||
void syncNoticeToRecentHalfYearUser();
|
||||
|
||||
void checkHalfAnHourPendingSubmission();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public class JudgeGlobalDTO implements Serializable {
|
|||
private Long maxTime;
|
||||
|
||||
/**
|
||||
* 当前题目评测的最大空间限制 kb
|
||||
* 当前题目评测的最大空间限制 mb
|
||||
*/
|
||||
private Long maxMemory;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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());//队列满了,尝试去和最早的竞争,也不会抛出异常!
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue