Leave a spare judge when rejudging if possible

This commit is contained in:
Quantum 2022-02-12 23:53:20 -05:00 committed by Guanzhong Chen
parent 051643342a
commit d3b403afdf
3 changed files with 25 additions and 6 deletions

View File

@ -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()))

4
judge/judge_priority.py Normal file
View File

@ -0,0 +1,4 @@
CONTEST_SUBMISSION_PRIORITY = 0
DEFAULT_PRIORITY = 1
REJUDGE_PRIORITY = 2
BATCH_REJUDGE_PRIORITY = 3

View File

@ -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: