forked from cms-dev/cms
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make ProxyService work without contest_id.
- Loading branch information
Showing
4 changed files
with
87 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
# Copyright © 2010-2012 Matteo Boscariol <[email protected]> | ||
# Copyright © 2013-2018 Luca Wehrstedt <[email protected]> | ||
# Copyright © 2013 Bernard Blackham <[email protected]> | ||
# Copyright © 2014-2024 Vytis Banaitis <[email protected]> | ||
# Copyright © 2015 Luca Versari <[email protected]> | ||
# Copyright © 2015 William Di Luigi <[email protected]> | ||
# Copyright © 2016 Amir Keivan Mohtashami <[email protected]> | ||
|
@@ -40,8 +41,8 @@ | |
from sqlalchemy import not_ | ||
|
||
from cms import config | ||
from cms.db import SessionGen, Contest, Participation, Task, Submission, \ | ||
get_submissions | ||
from cms.db import SessionGen, Participation, Task, Submission, \ | ||
get_submissions, get_active_contest_list | ||
from cms.io import Executor, QueueItem, TriggeredService, rpc_method | ||
from cmscommon.datetime import make_timestamp | ||
|
||
|
@@ -247,7 +248,7 @@ class ProxyService(TriggeredService): | |
""" | ||
|
||
def __init__(self, shard, contest_id): | ||
def __init__(self, shard): | ||
"""Start the service with the given parameters. | ||
Create an instance of the ProxyService and make it listen on | ||
|
@@ -258,13 +259,10 @@ def __init__(self, shard, contest_id): | |
corresponds to the shard-th entry in the list of addresses | ||
(hostname/port pairs) for this kind of service in the | ||
configuration file. | ||
contest_id (int): the ID of the contest to manage. | ||
""" | ||
super().__init__(shard) | ||
|
||
self.contest_id = contest_id | ||
|
||
# Store what data we already sent to rankings, to avoid | ||
# sending it twice. | ||
self.scores_sent_to_rankings = set() | ||
|
@@ -289,28 +287,29 @@ def _missing_operations(self): | |
""" | ||
counter = 0 | ||
with SessionGen() as session: | ||
submissions = get_submissions(session, contest_id=self.contest_id) \ | ||
.filter(not_(Participation.hidden)) \ | ||
.filter(Submission.official).all() | ||
|
||
for submission in submissions: | ||
# The submission result can be None if the dataset has | ||
# been just made live. | ||
sr = submission.get_result() | ||
if sr is None: | ||
continue | ||
|
||
if sr.scored() and \ | ||
submission.id not in self.scores_sent_to_rankings: | ||
for operation in self.operations_for_score(submission): | ||
self.enqueue(operation) | ||
counter += 1 | ||
|
||
if submission.tokened() and \ | ||
submission.id not in self.tokens_sent_to_rankings: | ||
for operation in self.operations_for_token(submission): | ||
self.enqueue(operation) | ||
counter += 1 | ||
for contest in get_active_contest_list(session): | ||
submissions = get_submissions(session, contest_id=contest.id) \ | ||
.filter(not_(Participation.hidden)) \ | ||
.filter(Submission.official).all() | ||
|
||
for submission in submissions: | ||
# The submission result can be None if the dataset has | ||
# been just made live. | ||
sr = submission.get_result() | ||
if sr is None: | ||
continue | ||
|
||
if sr.scored() and \ | ||
submission.id not in self.scores_sent_to_rankings: | ||
for operation in self.operations_for_score(submission): | ||
self.enqueue(operation) | ||
counter += 1 | ||
|
||
if submission.tokened() and \ | ||
submission.id not in self.tokens_sent_to_rankings: | ||
for operation in self.operations_for_token(submission): | ||
self.enqueue(operation) | ||
counter += 1 | ||
|
||
return counter | ||
|
||
|
@@ -327,58 +326,52 @@ def initialize(self): | |
logger.info("Initializing rankings.") | ||
|
||
with SessionGen() as session: | ||
contest = Contest.get_from_id(self.contest_id, session) | ||
|
||
if contest is None: | ||
logger.error("Received request for unexistent contest " | ||
"id %s.", self.contest_id) | ||
raise KeyError("Contest not found.") | ||
|
||
contest_id = encode_id(contest.name) | ||
contest_data = { | ||
"name": contest.description, | ||
"begin": int(make_timestamp(contest.start)), | ||
"end": int(make_timestamp(contest.stop)), | ||
"score_precision": contest.score_precision} | ||
|
||
users = dict() | ||
teams = dict() | ||
|
||
for participation in contest.participations: | ||
user = participation.user | ||
team = participation.team | ||
if not participation.hidden: | ||
users[encode_id(user.username)] = { | ||
"f_name": user.first_name, | ||
"l_name": user.last_name, | ||
"team": encode_id(team.code) | ||
if team is not None else None, | ||
} | ||
if team is not None: | ||
teams[encode_id(team.code)] = { | ||
"name": team.name | ||
for contest in get_active_contest_list(session): | ||
contest_id = encode_id(contest.name) | ||
contest_data = { | ||
"name": contest.description, | ||
"begin": int(make_timestamp(contest.start)), | ||
"end": int(make_timestamp(contest.stop)), | ||
"score_precision": contest.score_precision} | ||
|
||
users = dict() | ||
teams = dict() | ||
|
||
for participation in contest.participations: | ||
user = participation.user | ||
team = participation.team | ||
if not participation.hidden: | ||
users[encode_id(user.username)] = { | ||
"f_name": user.first_name, | ||
"l_name": user.last_name, | ||
"team": encode_id(team.code) | ||
if team is not None else None, | ||
} | ||
if team is not None: | ||
teams[encode_id(team.code)] = { | ||
"name": team.name | ||
} | ||
|
||
tasks = dict() | ||
|
||
for task in contest.tasks: | ||
score_type = task.active_dataset.score_type_object | ||
tasks[encode_id(task.name)] = { | ||
"short_name": task.name, | ||
"name": task.title, | ||
"contest": encode_id(contest.name), | ||
"order": task.num, | ||
"max_score": score_type.max_score, | ||
"extra_headers": score_type.ranking_headers, | ||
"score_precision": task.score_precision, | ||
"score_mode": task.score_mode, | ||
} | ||
|
||
tasks = dict() | ||
|
||
for task in contest.tasks: | ||
score_type = task.active_dataset.score_type_object | ||
tasks[encode_id(task.name)] = { | ||
"short_name": task.name, | ||
"name": task.title, | ||
"contest": encode_id(contest.name), | ||
"order": task.num, | ||
"max_score": score_type.max_score, | ||
"extra_headers": score_type.ranking_headers, | ||
"score_precision": task.score_precision, | ||
"score_mode": task.score_mode, | ||
} | ||
|
||
self.enqueue(ProxyOperation(ProxyExecutor.CONTEST_TYPE, | ||
{contest_id: contest_data})) | ||
self.enqueue(ProxyOperation(ProxyExecutor.TEAM_TYPE, teams)) | ||
self.enqueue(ProxyOperation(ProxyExecutor.USER_TYPE, users)) | ||
self.enqueue(ProxyOperation(ProxyExecutor.TASK_TYPE, tasks)) | ||
self.enqueue(ProxyOperation(ProxyExecutor.CONTEST_TYPE, | ||
{contest_id: contest_data})) | ||
self.enqueue(ProxyOperation(ProxyExecutor.TEAM_TYPE, teams)) | ||
self.enqueue(ProxyOperation(ProxyExecutor.USER_TYPE, users)) | ||
self.enqueue(ProxyOperation(ProxyExecutor.TASK_TYPE, tasks)) | ||
|
||
def operations_for_score(self, submission): | ||
"""Send the score for the given submission to all rankings. | ||
|
@@ -477,13 +470,9 @@ def submission_scored(self, submission_id): | |
"unexistent submission id %s.", submission_id) | ||
raise KeyError("Submission not found.") | ||
|
||
# ScoringService sent us a submission of another contest, they | ||
# do not know about our contest_id in multicontest setup. | ||
if submission.task.contest_id != self.contest_id: | ||
logger.debug("Ignoring submission %d of contest %d " | ||
"(this ProxyService considers contest %d only).", | ||
submission.id, submission.task.contest_id, | ||
self.contest_id) | ||
if not submission.task.contest.active: | ||
logger.debug("Ignoring submission %d of inactive contest %d.", | ||
submission.id, submission.task.contest_id) | ||
return | ||
|
||
if submission.participation.hidden: | ||
|
@@ -521,13 +510,9 @@ def submission_tokened(self, submission_id): | |
"unexistent submission id %s.", submission_id) | ||
raise KeyError("Submission not found.") | ||
|
||
# ScoringService sent us a submission of another contest, they | ||
# do not know about our contest_id in multicontest setup. | ||
if submission.task.contest_id != self.contest_id: | ||
logger.debug("Ignoring submission %d of contest %d " | ||
"(this ProxyService considers contest %d only).", | ||
submission.id, submission.task.contest_id, | ||
self.contest_id) | ||
if not submission.task.contest.active: | ||
logger.debug("Ignoring submission %d of inactive contest %d.", | ||
submission.id, submission.task.contest_id) | ||
return | ||
|
||
if submission.participation.hidden: | ||
|
@@ -564,13 +549,9 @@ def dataset_updated(self, task_id): | |
task = Task.get_from_id(task_id, session) | ||
dataset = task.active_dataset | ||
|
||
# This ProxyService may focus on a different contest, and it should | ||
# ignore this update. | ||
if task.contest_id != self.contest_id: | ||
logger.debug("Ignoring dataset change for task %d of contest " | ||
"%d (this ProxyService considers contest %d " | ||
"only).", task_id, task.contest.id, | ||
self.contest_id) | ||
if not task.contest.active: | ||
logger.debug("Ignoring dataset change for task %d of inactive " | ||
"contest %d.", task_id, task.contest.id) | ||
return | ||
|
||
logger.info("Dataset update for task %d (dataset now is %d).", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
# Copyright © 2010-2012 Matteo Boscariol <[email protected]> | ||
# Copyright © 2013-2017 Luca Wehrstedt <[email protected]> | ||
# Copyright © 2014-2018 William Di Luigi <[email protected]> | ||
# Copyright © 2014 Vytis Banaitis <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU Affero General Public License as | ||
|
@@ -179,10 +180,6 @@ def __init__(self, shard, contest_id=None, autorestart=False): | |
self._prev_cpu_times = self._get_cpu_times() | ||
# Sorted list of ServiceCoord running in the same machine | ||
self._local_services = self._find_local_services() | ||
if "ProxyService" in (s.name for s in self._local_services) and \ | ||
self.contest_id is None: | ||
logger.warning("Will not run ProxyService " | ||
"since it requires a contest id.") | ||
# Dict service with bool to mark if we will restart them. | ||
self._will_restart = dict((service, | ||
None if not self.autorestart else True) | ||
|
@@ -223,9 +220,7 @@ def _restart_services(self): | |
for service in self._local_services: | ||
# We let the user start logservice and resourceservice. | ||
if service.name == "LogService" or \ | ||
service.name == "ResourceService" or \ | ||
(self.contest_id is None and | ||
service.name == "ProxyService"): | ||
service.name == "ResourceService": | ||
continue | ||
|
||
# If the user specified not to restart some service, we | ||
|
@@ -463,10 +458,6 @@ def toggle_autorestart(self, service): | |
logger.error("Unable to decode service string.") | ||
name = service[:idx] | ||
|
||
# ProxyService requires contest_id | ||
if self.contest_id is None and name == "ProxyService": | ||
return None | ||
|
||
try: | ||
shard = int(service[idx + 1:]) | ||
except ValueError: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
# Contest Management System - http://cms-dev.github.io/ | ||
# Copyright © 2013 Luca Wehrstedt <[email protected]> | ||
# Copyright © 2014 Vytis Banaitis <[email protected]> | ||
# Copyright © 2016 Stefano Maggiolo <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
|
@@ -26,7 +27,7 @@ import logging | |
import sys | ||
|
||
from cms import ConfigError, default_argument_parser | ||
from cms.db import ask_for_contest, test_db_connection | ||
from cms.db import test_db_connection | ||
from cms.service.ProxyService import ProxyService | ||
|
||
|
||
|
@@ -39,8 +40,7 @@ def main(): | |
""" | ||
test_db_connection() | ||
success = default_argument_parser("Ranking relayer for CMS.", | ||
ProxyService, | ||
ask_contest=ask_for_contest).run() | ||
ProxyService).run() | ||
return 0 if success is True else 1 | ||
|
||
|
||
|