From d3b403afdf6b3cb2d1f6d1af1810a6b82164870b Mon Sep 17 00:00:00 2001 From: Quantum Date: Sat, 12 Feb 2022 23:53:20 -0500 Subject: [PATCH] Leave a spare judge when rejudging if possible --- judge/bridge/judge_list.py | 21 ++++++++++++++++++++- judge/judge_priority.py | 4 ++++ judge/judgeapi.py | 6 +----- 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 judge/judge_priority.py diff --git a/judge/bridge/judge_list.py b/judge/bridge/judge_list.py index 3b65f4771..7d44c89a3 100644 --- a/judge/bridge/judge_list.py +++ b/judge/bridge/judge_list.py @@ -3,6 +3,8 @@ from collections import namedtuple from random import random from threading import RLock +from judge.judge_priority import REJUDGE_PRIORITY + try: from llist import dllist except ImportError: @@ -27,8 +29,14 @@ class JudgeList(object): def _handle_free_judge(self, judge): with self.lock: node = self.queue.first + priority = 0 while node: - if not isinstance(node.value, PriorityMarker): + if isinstance(node.value, PriorityMarker): + priority = node.value.priority + 1 + elif priority >= REJUDGE_PRIORITY and len(self.judges) > 1 and sum( + not judge.working for judge in self.judges) <= 1: + return + else: id, problem, language, source, judge_id = node.value if judge.can_judge(problem, language, judge_id): self.submission_map[id] = judge @@ -71,6 +79,13 @@ class JudgeList(object): pass self.judges.discard(judge) + # Since we reserve a judge for high priority submissions when there are more than one, + # we'll need to start judging if there is exactly one judge and it's free. + if len(self.judges) == 1: + judge = next(iter(self.judges)) + if not judge.working: + self._handle_free_judge(judge) + def __iter__(self): return iter(self.judges) @@ -114,6 +129,10 @@ class JudgeList(object): logger.info('Specified judge %s is%savailable', judge_id, ' ' if candidates else ' not ') else: logger.info('Free judges: %d', len(candidates)) + + if len(candidates) == 1 and priority >= REJUDGE_PRIORITY: + candidates = [] + if candidates: # Schedule the submission on the judge reporting least load. judge = min(candidates, key=lambda judge: (judge.load, random())) diff --git a/judge/judge_priority.py b/judge/judge_priority.py new file mode 100644 index 000000000..c7ea61f56 --- /dev/null +++ b/judge/judge_priority.py @@ -0,0 +1,4 @@ +CONTEST_SUBMISSION_PRIORITY = 0 +DEFAULT_PRIORITY = 1 +REJUDGE_PRIORITY = 2 +BATCH_REJUDGE_PRIORITY = 3 diff --git a/judge/judgeapi.py b/judge/judgeapi.py index df781206b..42bc000f5 100644 --- a/judge/judgeapi.py +++ b/judge/judgeapi.py @@ -8,6 +8,7 @@ from django.conf import settings from django.utils import timezone from judge import event_poster as event +from judge.judge_priority import BATCH_REJUDGE_PRIORITY, CONTEST_SUBMISSION_PRIORITY, DEFAULT_PRIORITY, REJUDGE_PRIORITY logger = logging.getLogger('judge.judgeapi') size_pack = struct.Struct('!I') @@ -52,11 +53,6 @@ def judge_request(packet, reply=True): def judge_submission(submission, rejudge=False, batch_rejudge=False, judge_id=None): from .models import ContestSubmission, Submission, SubmissionTestCase - CONTEST_SUBMISSION_PRIORITY = 0 - DEFAULT_PRIORITY = 1 - REJUDGE_PRIORITY = 2 - BATCH_REJUDGE_PRIORITY = 3 - updates = {'time': None, 'memory': None, 'points': None, 'result': None, 'case_points': 0, 'case_total': 0, 'error': None, 'rejudged_date': timezone.now() if rejudge or batch_rejudge else None, 'status': 'QU'} try: