Skip to content

Commit

Permalink
Implement batched testcase updates in bridge; DMOJ/judge-server#408
Browse files Browse the repository at this point in the history
  • Loading branch information
Xyene committed Oct 1, 2019
1 parent 7bb557d commit 87124ce
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 61 deletions.
125 changes: 65 additions & 60 deletions judge/bridge/judgecallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,73 +326,78 @@ def on_batch_end(self, packet):
def on_test_case(self, packet, max_feedback=SubmissionTestCase._meta.get_field('feedback').max_length):
super(DjangoJudgeHandler, self).on_test_case(packet)
id = packet['submission-id']
updates = packet['cases']

if not Submission.objects.filter(id=id).update(current_testcase=packet['position'] + 1):
if not Submission.objects.filter(id=id).update(current_testcase=packet['position'] + len(updates)):
logger.warning('Unknown submission: %d', id)
json_log.error(self._make_json_log(packet, action='test-case', info='unknown submission'))
return

test_case = SubmissionTestCase(submission_id=id, case=packet['position'])
status = packet['status']
if status & 4:
test_case.status = 'TLE'
elif status & 8:
test_case.status = 'MLE'
elif status & 64:
test_case.status = 'OLE'
elif status & 2:
test_case.status = 'RTE'
elif status & 16:
test_case.status = 'IR'
elif status & 1:
test_case.status = 'WA'
elif status & 32:
test_case.status = 'SC'
else:
test_case.status = 'AC'
test_case.time = packet['time']
test_case.memory = packet['memory']
test_case.points = packet['points']
test_case.total = packet['total-points']
test_case.batch = self.batch_id if self.in_batch else None
test_case.feedback = (packet.get('feedback') or '')[:max_feedback]
test_case.extended_feedback = packet.get('extended-feedback') or ''
test_case.output = packet['output']
test_case.save()

json_log.info(self._make_json_log(
packet, action='test-case', case=test_case.case, batch=test_case.batch,
time=test_case.time, memory=test_case.memory, feedback=test_case.feedback,
extended_feedback=test_case.extended_feedback, output=test_case.output,
points=test_case.points, total=test_case.total, status=test_case.status,
))
bulk_test_case_updates = []
for result in updates:
test_case = SubmissionTestCase(submission_id=id, case=result['position'])
status = result['status']
if status & 4:
test_case.status = 'TLE'
elif status & 8:
test_case.status = 'MLE'
elif status & 64:
test_case.status = 'OLE'
elif status & 2:
test_case.status = 'RTE'
elif status & 16:
test_case.status = 'IR'
elif status & 1:
test_case.status = 'WA'
elif status & 32:
test_case.status = 'SC'
else:
test_case.status = 'AC'
test_case.time = result['time']
test_case.memory = result['memory']
test_case.points = result['points']
test_case.total = result['total-points']
test_case.batch = self.batch_id if self.in_batch else None
test_case.feedback = (result.get('feedback') or '')[:max_feedback]
test_case.extended_feedback = result.get('extended-feedback') or ''
test_case.output = result['output']
bulk_test_case_updates.append(test_case)

json_log.info(self._make_json_log(
packet, action='test-case', case=test_case.case, batch=test_case.batch,
time=test_case.time, memory=test_case.memory, feedback=test_case.feedback,
extended_feedback=test_case.extended_feedback, output=test_case.output,
points=test_case.points, total=test_case.total, status=test_case.status,
))

do_post = True
do_post = True

if id in self.update_counter:
cnt, reset = self.update_counter[id]
cnt += 1
if TIMER() - reset > UPDATE_RATE_TIME:
del self.update_counter[id]
else:
self.update_counter[id] = (cnt, reset)
if cnt > UPDATE_RATE_LIMIT:
do_post = False
if id not in self.update_counter:
self.update_counter[id] = (1, TIMER())

if do_post:
event.post('sub_%s' % Submission.get_id_secret(id), {
'type': 'test-case',
'id': packet['position'],
'status': test_case.status,
'time': '%.3f' % round(float(packet['time']), 3),
'memory': packet['memory'],
'points': float(test_case.points),
'total': float(test_case.total),
'output': packet['output'],
})
self._post_update_submission(id, state='test-case')
if id in self.update_counter:
cnt, reset = self.update_counter[id]
cnt += 1
if TIMER() - reset > UPDATE_RATE_TIME:
del self.update_counter[id]
else:
self.update_counter[id] = (cnt, reset)
if cnt > UPDATE_RATE_LIMIT:
do_post = False
if id not in self.update_counter:
self.update_counter[id] = (1, TIMER())

if do_post:
event.post('sub_%s' % Submission.get_id_secret(id), {
'type': 'test-case',
'id': packet['position'],
'status': test_case.status,
'time': '%.3f' % round(float(packet['time']), 3),
'memory': packet['memory'],
'points': float(test_case.points),
'total': float(test_case.total),
'output': packet['output'],
})
self._post_update_submission(id, state='test-case')

SubmissionTestCase.objects.bulk_create(bulk_test_case_updates)

def on_supported_problems(self, packet):
super(DjangoJudgeHandler, self).on_supported_problems(packet)
Expand Down
2 changes: 1 addition & 1 deletion judge/bridge/judgehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def on_batch_end(self, packet):
logger.info('%s: Batch ended on: %s', self.name, packet['submission-id'])

def on_test_case(self, packet):
logger.info('%s: Test case completed on: %s', self.name, packet['submission-id'])
logger.info('%s: %d test case(s) completed on: %s', len(packet['cases']), self.name, packet['submission-id'])

def on_malformed(self, packet):
logger.error('%s: Malformed packet: %s', self.name, packet)
Expand Down

0 comments on commit 87124ce

Please sign in to comment.