Exemple #1
0
    def dataset_updated(self, task_id):
        """This function updates RWS with new data about a task. It should be
        called after the live dataset of a task is changed.

        task_id (int): id of the task whose dataset has changed.

        """
        with SessionGen(commit=False) as session:
            task = Task.get_from_id(task_id, session)
            dataset_id = task.active_dataset_id

        logger.info("Dataset update for task %d (dataset now is %d)." % (
            task_id, dataset_id))

        submission_ids = get_submissions(self.contest_id, task_id=task_id)

        subchanges = []
        with SessionGen(commit=False) as session:
            for submission_id in submission_ids:
                submission = Submission.get_from_id(submission_id, session)
                submission_result = SubmissionResult.get_from_id(
                    (submission_id, dataset_id), session)

                if submission_result is None:
                    # Not yet compiled, evaluated or scored.
                    score = None
                    ranking_score_details = None
                else:
                    score = submission_result.score
                    try:
                        ranking_score_details = json.loads(
                                submission_result.ranking_score_details)
                    except (json.decoder.JSONDecodeError, TypeError):
                        # It may be blank.
                        ranking_score_details = None

                # Data to send to remote rankings.
                subchange_id = "%s%ss" % \
                    (int(make_timestamp(submission.timestamp)),
                     submission_id)
                subchange_put_data = {
                    "submission": encode_id(submission_id),
                    "time": int(make_timestamp(submission.timestamp))}
                    # We're sending the unrounded score to RWS
                if score is not None:
                    subchange_put_data["score"] = score
                if ranking_score_details is not None:
                    subchange_put_data["extra"] = ranking_score_details
                subchanges.append((subchange_id, subchange_put_data))

        # Adding operations to the queue.
        with self.operation_queue_lock:
            for ranking in self.rankings:
                for subchange_id, data in subchanges:
                    self.subchange_queue.setdefault(
                        ranking,
                        dict())[encode_id(subchange_id)] = data
Exemple #2
0
    def add_statements():
        """Support for statement translations.

        Add external Statement objects to support statement translations.
        The "official" statement is identified by its language code.

        """
        with SessionGen(commit=True) as session:
            session.execute("""\
CREATE TABLE IF NOT EXISTS statements (
    id SERIAL NOT NULL,
    language VARCHAR NOT NULL,
    digest VARCHAR NOT NULL,
    task_id INTEGER NOT NULL,
    PRIMARY KEY (id),
    CONSTRAINT cst_statements_task_id_language UNIQUE (task_id, language),
    FOREIGN KEY(task_id) REFERENCES tasks (id)
    ON DELETE CASCADE ON UPDATE CASCADE
)""")
            session.execute("DROP INDEX IF EXISTS ix_statements_task_id;")
            session.execute("CREATE INDEX ix_statements_task_id "
                            "ON statements (task_id)")
            for task_id, digest in session.execute(
                    "SELECT id, statement FROM tasks;"):
                session.execute("INSERT INTO statements "
                                "(language, digest, task_id) "
                                "VALUES ('', '%s', %s);" % (digest, task_id))
            session.execute("ALTER TABLE tasks " "DROP COLUMN statement;")
            session.execute("ALTER TABLE tasks "
                            "ADD COLUMN official_language VARCHAR;")
            session.execute("UPDATE tasks " "SET official_language = '';")
            session.execute("ALTER TABLE tasks "
                            "ALTER COLUMN official_language SET NOT NULL;")
Exemple #3
0
    def add_unique_constraints():
        """Add a bunch of constraints to the DB...

        ...that we were too lazy to do right away. See code for the
        constraints.

        """
        # First value of the pair is the table name, the second is the
        # list of columns.
        constraints = [
            ["attachments", ["task_id", "filename"]],
            ["evaluations", ["submission_id", "num"]],
            ["executables", ["submission_id", "filename"]],
            ["files", ["submission_id", "filename"]],
            ["managers", ["task_id", "filename"]],
            ["scores", ["rankingview_id", "task_id", "user_id"]],
            ["task_testcases", ["task_id", "num"]],
            ["tasks", ["contest_id", "num"]],
            ["tokens", ["submission_id"]],
            ["users", ["contest_id", "username"]],
            ["tasks", ["contest_id", "name"]],
        ]

        with SessionGen(commit=True) as session:
            for table, columns in constraints:
                name = "cst_" + table + "_" + "_".join(columns)
                columns_list = "(" + ", ".join(columns) + ")"
                session.execute("ALTER TABLE %s "
                                "ADD CONSTRAINT %s "
                                "UNIQUE %s;" % (table, name, columns_list))
Exemple #4
0
    def changed_batch_iofile_parameters():
        """Params for Batch tasktype changed to support custom I/O filenames.
        """
        import simplejson as json
        with SessionGen(commit=True) as session:
            for task_id, task_type_parameters in session.execute(
                    "SELECT id, task_type_parameters "
                    "FROM tasks WHERE task_type = 'Batch';"):
                try:
                    parameters = json.loads(task_type_parameters)
                except json.decoder.JSONDecodeError:
                    raise ValueError("Unable to decode parameter string "
                                     "`%s'." % task_type_parameters)
                if parameters[1] == "file":
                    parameters[1] = ["input.txt", "output.txt"]
                elif parameters[1] == "nofile":
                    parameters[1] = ["", ""]
                elif isinstance(parameters[1], list):
                    print "WARNING: already updated or unrecognized "\
                        "parameters in task %d" % task_id
                else:
                    raise ValueError("I/O type `%s' not recognized." %
                                     parameters[1])

                session.execute(
                    "UPDATE tasks SET "
                    "task_type_parameters = :parameters "
                    "WHERE id = :task_id", {
                        "parameters": json.dumps(parameters),
                        "task_id": task_id
                    })
Exemple #5
0
    def put_file(self, digest, origin, description=""):
        """See FileCacherBackend.put_file().

        """
        with SessionGen() as session:

            # Check digest uniqueness
            if FSObject.get_from_digest(digest, session) is not None:
                logger.debug("File %s already on database, "
                             "dropping this one." % digest)
                session.rollback()

            # If it is not already present, copy the file into the
            # lobject
            else:
                fso = FSObject(description=description)
                logger.debug("Sending file %s to the database." % digest)
                with open(origin, 'rb') as temp_file:
                    with fso.get_lobject(session, mode='wb') as lobject:
                        logger.debug("Large object created.")
                        buf = temp_file.read(self.CHUNK_SIZE)
                        while buf != '':
                            while len(buf) > 0:
                                written = lobject.write(buf)
                                buf = buf[written:]
                                if self.service is not None:
                                    self.service._step()
                            buf = temp_file.read(self.CHUNK_SIZE)
                fso.digest = digest
                session.add(fso)
                session.commit()
                logger.debug("File %s sent to the database." % digest)
Exemple #6
0
    def fix_primary_statements():
        """Change the way primary submissions are stored.

        """
        import simplejson as json
        with SessionGen(commit=True) as session:
            t_primary = dict()
            for t_id, lang in session.execute(
                "SELECT id, official_language "
                "FROM tasks;"):
                t_primary[t_id] = json.dumps([lang],
                                             sort_keys=True,
                                             separators=(',', ':'))

            u_primary = dict()
            ids = dict()
            for s_id, task, lang in session.execute(
                "SELECT s.id, t.name, s.language "
                "FROM statements AS s, tasks AS t "
                "WHERE s.task_id = t.id;"):
                ids[s_id] = (task, lang)

            for u_id, statements in session.execute(
                "SELECT id, statements FROM users;"):
                data = dict()
                for s_id in statements:
                    task, lang = ids[s_id]
                    data.setdefault(task, []).append(lang)
                for v in data.itervalues():
                    v.sort()
                u_primary[u_id] = json.dumps(data,
                                             sort_keys=True,
                                             separators=(',', ':'))

            session.execute("""\
ALTER TABLE tasks
DROP COLUMN official_language,
ADD COLUMN primary_statements VARCHAR;""")
            session.execute("""\
ALTER TABLE users
DROP COLUMN statements,
ADD COLUMN primary_statements VARCHAR;""")

            for t_id, txt in t_primary.iteritems():
                session.execute(
                    "UPDATE tasks "
                    "SET primary_statements = '%s' "
                    "WHERE id = %d" % (txt, t_id))
            for u_id, txt in u_primary.iteritems():
                session.execute(
                    "UPDATE users "
                    "SET primary_statements = '%s' "
                    "WHERE id = %d" % (txt, u_id))

            session.execute("""\
ALTER TABLE tasks
ALTER COLUMN primary_statements SET NOT NULL;""")
            session.execute("""\
ALTER TABLE users
ALTER COLUMN primary_statements SET NOT NULL;""")
Exemple #7
0
    def add_evaluation_text_to_user_test():
        """Add the evaluation_text column to table user tests.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE user_tests "
                            "ADD COLUMN evaluation_text VARCHAR;")
Exemple #8
0
    def add_time_and_memory_on_tests():
        """Add memory_used and execution_time on UserTests.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE user_tests "
                            "ADD COLUMN memory_used INTEGER, "
                            "ADD COLUMN execution_time DOUBLE PRECISION;")
Exemple #9
0
    def delete(self, digest):
        """See FileCacherBackend.delete().

        """
        with SessionGen() as session:
            fso = FSObject.get_from_digest(digest, session)
            fso.delete()
            session.commit()
Exemple #10
0
    def add_ranking_score_details():
        """Add a field with the score details to send to RWS

        Please rescore solutions.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE submissions "
                            "ADD COLUMN ranking_score_details VARCHAR;")
Exemple #11
0
    def change_token_constraints():
        """Fix token constraints to avoid ambiguos corner cases.

        Set some token_* fields to != None or to != zero since these
        values would cause a "behavior" (from the user-perspective)
        that is identical to other, more "reasonable" and natural
        value combinations.

        """
        with SessionGen(commit=True) as session:
            for table in ["contests", "tasks"]:
                session.execute("""
UPDATE %s
SET token_initial = token_max
WHERE token_initial > token_max;
""" % table)
                session.execute("""
UPDATE %s
SET (token_initial, token_max, token_total) = (NULL, NULL, NULL)
WHERE token_max = 0 OR token_total = 0;
""" % table)
                session.execute("""
UPDATE %s
SET token_min_interval = 0
WHERE token_min_interval IS NULL;
""" % table)
                session.execute("""
UPDATE %s
SET (token_gen_time, token_gen_number) = (1, 0)
WHERE token_gen_time IS NULL OR token_gen_number IS NULL;
""" % table)
            session.execute("""
ALTER TABLE contests
ADD CONSTRAINT contests_check CHECK (token_initial <= token_max),
DROP CONSTRAINT contests_token_max_check,
DROP CONSTRAINT contests_token_total_check,
DROP CONSTRAINT contests_token_gen_time_check,
ADD CONSTRAINT contests_token_max_check CHECK (token_max > 0),
ADD CONSTRAINT contests_token_total_check CHECK (token_total > 0),
ADD CONSTRAINT contests_token_gen_time_check CHECK (token_gen_time >= 0),
ALTER COLUMN token_min_interval SET NOT NULL,
ALTER COLUMN token_gen_time SET NOT NULL,
ALTER COLUMN token_gen_number SET NOT NULL;
""")
            session.execute("""
ALTER TABLE tasks
ADD CONSTRAINT tasks_check CHECK (token_initial <= token_max),
DROP CONSTRAINT tasks_token_max_check,
DROP CONSTRAINT tasks_token_total_check,
DROP CONSTRAINT tasks_token_gen_time_check,
ADD CONSTRAINT tasks_token_max_check CHECK (token_max > 0),
ADD CONSTRAINT tasks_token_total_check CHECK (token_total > 0),
ADD CONSTRAINT tasks_token_gen_time_check CHECK (token_gen_time >= 0),
ALTER COLUMN token_min_interval SET NOT NULL,
ALTER COLUMN token_gen_time SET NOT NULL,
ALTER COLUMN token_gen_number SET NOT NULL;
""")
Exemple #12
0
    def change_scoretype_names():
        """Remove the ScoreType prefix from every score type name.

        """
        with SessionGen(commit=True) as session:
            for score_type in ["Sum", "Relative", "GroupMin", "GroupMul"]:
                session.execute("UPDATE tasks SET score_type = '%s' "
                                "WHERE score_type = 'ScoreType%s';" %
                                (score_type, score_type))
Exemple #13
0
    def change_tasktype_names():
        """Remove the TaskType prefix from every task type name.

        """
        with SessionGen(commit=True) as session:
            session.execute("UPDATE tasks SET task_type = 'Batch' "
                            "WHERE task_type = 'TaskTypeBatch';")
            session.execute("UPDATE tasks SET task_type = 'OutputOnly' "
                            "WHERE task_type = 'TaskTypeOutputOnly';")
Exemple #14
0
def task_score(user, task):
    """Return the score of a user on a task.

    user (User): the user for which to compute the score.
    task (Task): the task for which to compute the score.

    return (float, bool): the score of user on task, and True if the
                          score could change because of a submission
                          yet to score.

    """
    def waits_for_score(submission):
        """Return if submission could be scored but it currently is
        not.

        submission (Submission): the submission to check.

        """
        return submission.compilation_outcome != "fail" and \
               not submission.scored()

    # The score of the last submission (if valid, otherwise 0.0).
    last_score = 0.0
    # The maximum score amongst the tokened submissions (invalid
    # scores count as 0.0).
    max_tokened_score = 0.0
    # If the score could change due to submission still being compiled
    # / evaluated / scored.
    partial = False

    with SessionGen(commit=False) as session:
        submissions = session.query(Submission).\
            filter(Submission.user == user).\
            filter(Submission.task == task).\
            order_by(Submission.timestamp).all()

        if submissions == []:
            return 0.0, False

        # Last score: if the last submission is scored we use that,
        # otherwise we use 0.0 (and mark that the score is partial
        # when the last submission could be scored).
        if submissions[-1].scored():
            last_score = submissions[-1].score
        elif waits_for_score(submissions[-1]):
            partial = True

        for submission in submissions:
            if submission.token is not None:
                if submission.scored():
                    max_tokened_score = max(max_tokened_score,
                                            submission.score)
                elif waits_for_score(submission):
                    partial = True

    return max(last_score, max_tokened_score), partial
Exemple #15
0
    def invalidate_submission(self,
                              submission_id=None,
                              user_id=None,
                              task_id=None):
        """Request for invalidating some scores.

        Invalidate the scores of the Submission whose ID is
        submission_id or, if None, of those whose user is user_id
        and/or whose task is task_id or, if both None, of those that
        belong to the contest this service is running for.

        submission_id (int): id of the submission to invalidate, or
                             None.
        user_id (int): id of the user to invalidate, or None.
        task_id (int): id of the task to invalidate, or None.

        """
        logger.info("Invalidation request received.")

        # Validate arguments
        # TODO Check that all these objects belong to this contest.

        with SessionGen(commit=True) as session:
            submissions = get_submissions(
                # Give contest_id only if all others are None.
                self.contest_id
                if {user_id, task_id, submission_id} == {None} else None,
                user_id,
                task_id,
                submission_id,
                session)

            logger.info("Submissions to invalidate scores for: %d." %
                        len(submissions))
            if len(submissions) == 0:
                return

            new_submissions_to_score = set()

            for submission in submissions:
                # If the submission is not evaluated, it does not have
                # a score to invalidate, and, when evaluated,
                # ScoringService will be prompted to score it. So in
                # that case we do not have to do anything.
                if submission.evaluated():
                    submission.invalidate_score()
                    new_submissions_to_score.add(submission.id)

        old_s = len(self.submissions_to_score)
        old_t = len(self.submissions_to_token)
        self.submissions_to_score |= new_submissions_to_score
        if old_s + old_t == 0:
            self.add_timeout(self.score_old_submissions,
                             None,
                             0.5,
                             immediately=False)
Exemple #16
0
def is_contest_id(contest_id):
    """Return if there is a contest with the given id in the database.

    contest_id (int): the id to query.
    return (boolean): True if there is such a contest.

    """
    with SessionGen(commit=False) as session:
        contest = session.query(Contest).filter_by(id=contest_id).first()
        return contest is not None
Exemple #17
0
def get_submissions(contest_id,
                    submission_id=None,
                    user_id=None,
                    task_id=None):
    """Return a list of submission_ids restricted with the given
    information.

    We allow at most one of the parameters to be non-None. If all
    parameters are, we return all submissions for the given contest.

    contest_id (int): the id of the contest.

    submission_id (int): id of the submission to invalidate, or None.
    user_id (int): id of the user we want to invalidate, or None.
    task_id (int): id of the task we want to invalidate, or None.
    level (string): 'compilation' or 'evaluation'

    """
    if [x is not None
            for x in [submission_id, user_id, task_id]].count(True) > 1:
        err_msg = "Too many arguments for invalidate_submission."
        logger.warning(err_msg)
        raise ValueError(err_msg)

    submission_ids = []
    if submission_id is not None:
        submission_ids = [submission_id]
    elif user_id is not None:
        with SessionGen(commit=False) as session:
            user = User.get_from_id(user_id, session)
            submission_ids = [x.id for x in user.submissions]
    elif task_id is not None:
        with SessionGen(commit=False) as session:
            submissions = session.query(Submission)\
                .join(Task).filter(Task.id == task_id)
            submission_ids = [x.id for x in submissions]
    else:
        with SessionGen(commit=False) as session:
            contest = session.query(Contest).\
                filter_by(id=contest_id).first()
            submission_ids = [x.id for x in contest.get_submissions()]

    return submission_ids
Exemple #18
0
    def describe(self, digest):
        """See FileCacherBackend.describe().

        """
        with SessionGen() as session:
            fso = FSObject.get_from_digest(digest, session)
            if fso is not None:
                return fso.description
            else:
                return None
Exemple #19
0
    def drop_ranking_view():
        """Remove the useless tables.

        Ranking views and the accessory scores tables were intended to
        be used, but this is not true anymore.

        """
        with SessionGen(commit=True) as session:
            session.execute("DROP TABLE scores;")
            session.execute("DROP TABLE rankingviews;")
Exemple #20
0
    def support_output_only():
        """Increase support for output only tasks

        By allowing NULL time and memory limits

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE tasks "
                            "ALTER COLUMN time_limit DROP NOT NULL,"
                            "ALTER COLUMN memory_limit DROP NOT NULL;")
Exemple #21
0
    def get_size(self, digest):
        """See FileCacherBackend.get_size().

        """
        with SessionGen() as session:
            fso = FSObject.get_from_digest(digest, session)
            if fso is not None:
                with fso.get_lobject(session, mode='rb') as lobject:
                    return lobject.seek(0, os.SEEK_END)
            else:
                return None
Exemple #22
0
    def make_contest_description_not_null():
        """Make the Contest.description field NOT NULL.

        """
        with SessionGen(commit=True) as session:
            session.execute("""\
UPDATE contests
SET description = '' WHERE description IS NULL;""")
            session.execute("""\
ALTER TABLE contests
ALTER COLUMN description SET NOT NULL;""")
Exemple #23
0
    def constraints_on_tokens():
        """Better constraints for token information.

        We allow token_initial to be NULL, which means that the tokens
        are disabled for that contest/task. Moreover, all information
        are required to be non-negative (or positive when
        appropriate).

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE contests "
                            "ALTER COLUMN token_initial "
                            "DROP NOT NULL;")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_initial_check "
                            "CHECK (token_initial >= 0);")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_max_check "
                            "CHECK (token_max >= 0);")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_total_check "
                            "CHECK (token_total >= 0);")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_min_interval_check "
                            "CHECK (token_min_interval >= 0);")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_gen_time_check "
                            "CHECK (token_gen_time > 0);")
            session.execute("ALTER TABLE contests "
                            "ADD CONSTRAINT contests_token_gen_number_check "
                            "CHECK (token_gen_number >= 0);")

            session.execute("ALTER TABLE tasks "
                            "ALTER COLUMN token_initial "
                            "DROP NOT NULL;")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_initial_check "
                            "CHECK (token_initial >= 0);")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_max_check "
                            "CHECK (token_max >= 0);")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_total_check "
                            "CHECK (token_total >= 0);")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_min_interval_check "
                            "CHECK (token_min_interval >= 0);")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_gen_time_check "
                            "CHECK (token_gen_time > 0);")
            session.execute("ALTER TABLE tasks "
                            "ADD CONSTRAINT tasks_token_gen_number_check "
                            "CHECK (token_gen_number >= 0);")
Exemple #24
0
    def add_ignore_on_questions():
        """Possibility to ignore users' questions.

        We simply add a field "ignored" in the questions table.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE questions "
                            "ADD COLUMN ignored BOOLEAN;")
            session.execute("UPDATE questions SET ignored = False;")
            session.execute("ALTER TABLE questions "
                            "ALTER COLUMN ignored SET NOT NULL;")
Exemple #25
0
    def add_extra_time():
        """Add extra time for the users

        Defaults to zero.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE users "
                            "ADD COLUMN extra_time INTERVAL;")
            session.execute("UPDATE users " "SET extra_time = '0 seconds';")
            session.execute("ALTER TABLE users "
                            "ALTER COLUMN extra_time SET NOT NULL;")
Exemple #26
0
    def add_timezones():
        """Add support for per-contest and per-user timezones

        By adding the Contest.timezone and User.timezone fields.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE contests "
                            "ADD COLUMN timezone VARCHAR;")
            session.execute("ALTER TABLE users "
                            "ALTER timezone DROP NOT NULL,"
                            "ALTER timezone TYPE VARCHAR USING NULL;")
Exemple #27
0
    def add_languages():
        """Add a list of languages to each user

        Defaults to empty list.

        """
        with SessionGen(commit=True) as session:
            session.execute("ALTER TABLE users "
                            "ADD COLUMN languages VARCHAR[];")
            session.execute("UPDATE users " "SET languages = '{}';")
            session.execute("ALTER TABLE users "
                            "ALTER COLUMN languages SET NOT NULL;")
Exemple #28
0
def add_user(contest_id, first_name, last_name, username, password, ip_address,
             email, hidden):
    with SessionGen(commit=True) as session:
        contest = Contest.get_from_id(contest_id, session)
        user = User(first_name=first_name,
                    last_name=last_name,
                    username=username,
                    password=password,
                    email=email,
                    ip=ip_address,
                    hidden=hidden,
                    contest=contest)
        session.add(user)
Exemple #29
0
def default_argument_parser(description, cls, ask_contest=None):
    """Default argument parser for services - in two versions: needing
    a contest_id, or not.

    description (string): description of the service.
    cls (class): service's class.
    ask_contest (function): None if the service does not require a
                            contest, otherwise a function that returns
                            a contest_id (after asking the admins?)

    return (object): an instance of a service.

    """
    parser = ArgumentParser(description=description)
    parser.add_argument("shard", nargs="?", type=int, default=-1)

    # We need to allow using the switch "-c" also for services that do
    # not need the contest_id because RS needs to be able to restart
    # everything without knowing which is which.
    contest_id_help = "id of the contest to automatically load"
    if ask_contest is None:
        contest_id_help += " (ignored)"
    parser.add_argument("-c",
                        "--contest-id",
                        help=contest_id_help,
                        nargs="?",
                        type=int)
    args = parser.parse_args()

    # If the shard is -1 (i.e., unspecified) we find it basing on the
    # local IP addresses
    if args.shard == -1:
        addrs = find_local_addresses()
        args.shard = get_shard_from_addresses(cls.__name__, addrs)

    if ask_contest is not None:
        if args.contest_id is not None:
            # Test if there is a contest with the given contest id.
            from cms.db.SQLAlchemyAll import Contest, SessionGen
            with SessionGen(commit=False) as session:
                contest = session.query(Contest).\
                          filter_by(id=args.contest_id).first()
                if contest is None:
                    print >> sys.stderr, "There is no contest " \
                          "with the specified id. Please try again."
                    sys.exit(1)
            return cls(args.shard, args.contest_id)
        else:
            return cls(args.shard, ask_contest())
    else:
        return cls(args.shard)
Exemple #30
0
    def search_jobs_not_done(self):
        """Look in the database for submissions that have not been
        scored for no good reasons. Put the missing job in the queue.

        """
        # Do this only if we are not still loading old submission
        # (from the start of the service).
        if self.scoring_old_submission:
            return True

        with SessionGen(commit=False) as session:
            new_submission_ids_to_score = set([])
            new_submission_ids_to_token = set([])
            contest = session.query(Contest).\
                      filter_by(id=self.contest_id).first()
            for submission in contest.get_submissions():
                for dataset in get_autojudge_datasets(submission.task):
                    # If a submission result does not yet exist, then we don't
                    # need to score it.
                    r = SubmissionResult.get_from_id(
                        (submission.id, dataset.id),
                        session)
                    if r is None:
                        continue

                    x = (r.submission_id, r.dataset_id)
                    if r is not None and (r.evaluated()
                        or r.compilation_outcome == "fail") \
                            and x not in self.submission_ids_scored:
                        new_submission_ids_to_score.add(x)
                    if r.submission.tokened() and r.submission_id not in \
                            self.submission_ids_tokened:
                        new_submission_ids_to_token.add(
                            (r.submission_id,
                             make_timestamp(r.submission.token.timestamp)))

        new_s = len(new_submission_ids_to_score)
        old_s = len(self.submission_ids_to_score)
        new_t = len(new_submission_ids_to_token)
        old_t = len(self.submission_ids_to_token)
        logger.info("Submissions found to score/token: %d, %d." %
                    (new_s, new_t))
        if new_s + new_t > 0:
            self.submission_ids_to_score |= new_submission_ids_to_score
            self.submission_ids_to_token |= new_submission_ids_to_token
            if old_s + old_t == 0:
                self.add_timeout(self.score_old_submissions, None,
                                 0.5, immediately=False)

        # Run forever.
        return True