コード例 #1
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def test_006(self):
        """Send a ~100B random binary file to the storage through
        FileCacher as a string. FC should cache the content locally.

        """
        self.content = "".join(
            chr(random.randint(0, 255)) for unused_i in xrange(100))

        logger.info("  I am sending the ~100B binary file to FileCacher")
        try:
            data = self.file_cacher.put_file_content(self.content,
                                                     u"Test #005")
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return

        if not os.path.exists(os.path.join(self.cache_base_path, data)):
            self.test_end(False, "File not stored in local cache.")
        elif open(os.path.join(self.cache_base_path, data),
                  "rb").read() != self.content:
            self.test_end(
                False, "Local cache's content differ "
                "from original file.")
        else:
            self.cache_path = os.path.join(self.cache_base_path, data)
            self.digest = data
            self.test_end(True, "Data sent and cached without error.")
コード例 #2
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def test_008(self):
        """Put a ~100MB file into the storage (using a specially
        crafted file-like object).

        """
        logger.info("  I am sending the ~100MB binary file to FileCacher")
        rand_file = RandomFile(100000000)
        try:
            data = self.file_cacher.put_file_from_fobj(rand_file, u"Test #007")
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return
        if rand_file.dim != 0:
            self.test_end(False, "The input file wasn't read completely.")
        my_digest = rand_file.digest
        rand_file.close()

        if not os.path.exists(os.path.join(self.cache_base_path, data)):
            self.test_end(False, "File not stored in local cache.")
        elif my_digest != data:
            self.test_end(False, "File received with wrong hash.")
        else:
            self.cache_path = os.path.join(self.cache_base_path, data)
            self.digest = data
            self.test_end(True, "Data sent and cached without error.")
コード例 #3
0
ファイル: TestFileCacher.py プロジェクト: Ben0mega/cms
    def prepare(self):
        """Initialization for the test code - make sure that the cache
        is empty before testing.

        """
        logger.info("Please delete directory %s before." %
                    self.cache_base_path)
コード例 #4
0
    def get_params_for_user(self, user_dict):
        """Given the dictionary of information of a user (extracted
        from contest.yaml), it fills another dictionary with the
        parameters required by User.import_from_dict().

        """
        params = {}
        params["username"] = user_dict["username"]

        logger.info("Loading parameters for user %s." % params['username'])

        if self.modif == 'test':
            params["password"] = '******'
            params["ip"] = '0.0.0.0'
        else:
            params["password"] = user_dict["password"]
            params["ip"] = user_dict.get("ip", "0.0.0.0")
        name = user_dict.get("nome", "")
        surname = user_dict.get("cognome", user_dict["username"])
        params["first_name"] = name
        params["last_name"] = surname
        params["hidden"] = "True" == user_dict.get("fake", "False")

        params["timezone"] = 0.0
        params["messages"] = []
        params["questions"] = []
        params["submissions"] = []

        logger.info("User parameters loaded.")

        return params
コード例 #5
0
ファイル: TestFileCacher.py プロジェクト: Ben0mega/cms
    def test_006(self):
        """Send a ~100B random binary file to the storage through
        FileCacher as a string. FC should cache the content locally.

        """
        self.content = "".join(chr(random.randint(0, 255))
                               for unused_i in xrange(100))

        logger.info("  I am sending the ~100B binary file to FileCacher")
        try:
            data = self.file_cacher.put_file_content(self.content,
                                                     u"Test #005")
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return

        if not os.path.exists(os.path.join(self.cache_base_path, data)):
            self.test_end(False, "File not stored in local cache.")
        elif open(os.path.join(self.cache_base_path, data),
                  "rb").read() != self.content:
            self.test_end(False, "Local cache's content differ "
                          "from original file.")
        else:
            self.cache_path = os.path.join(self.cache_base_path, data)
            self.digest = data
            self.test_end(True, "Data sent and cached without error.")
コード例 #6
0
ファイル: TestFileCacher.py プロジェクト: Ben0mega/cms
    def test_003(self):
        """Get file from FileCacher.

        """
        logger.info("  I am retrieving the file from FileCacher " +
                    "after deleting the cache.")
        os.unlink(self.cache_path)
        try:
            data = self.file_cacher.get_file(self.digest)
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return

        received = data.read()
        data.close()
        if received != self.content:
            self.test_end(False, "Content differ.")
        elif not os.path.exists(self.cache_path):
            self.test_end(False, "File not stored in local cache.")
        elif open(self.cache_path).read() != self.content:
            self.test_end(False, "Local cache's content differ " +
                          "from original file.")
        else:
            self.test_end(True, "Content object received " +
                          "and cached correctly.")
コード例 #7
0
ファイル: YamlLoader.py プロジェクト: cbolk/cms
    def get_user(self, username):
        """See docstring in class Loader.

        """
        logger.info("Loading parameters for user %s." % username)
        conf = self.users_conf[username]
        assert username == conf['username']

        args = {}

        load(conf, args, "username")

        load(conf, args, "password")
        load(conf, args, "ip")

        load(conf, args, ["first_name", "nome"])
        load(conf, args, ["last_name", "cognome"])

        if "first_name" not in args:
            args["first_name"] = ""
        if "last_name" not in args:
            args["last_name"] = args["username"]

        load(conf, args, ["hidden", "fake"], conv=lambda a: a == "True")

        logger.info("User parameters loaded.")

        return User(**args)
コード例 #8
0
ファイル: TestFileCacher.py プロジェクト: Ben0mega/cms
    def test_009(self):
        """Get the ~100MB file from FileCacher.

        """
        logger.info("  I am retrieving the ~100MB file from FileCacher " +
                    "after deleting the cache.")
        os.unlink(self.cache_path)
        hash_file = HashingFile()
        try:
            self.file_cacher.get_file_to_fobj(self.digest, hash_file)
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return
        my_digest = hash_file.digest
        hash_file.close()

        try:
            if self.digest != my_digest:
                self.test_end(False, "Content differs.")
            elif not os.path.exists(self.cache_path):
                self.test_end(False, "File not stored in local cache.")
            else:
                self.test_end(True, "Content object received " +
                              "and cached correctly.")
        finally:
            self.file_cacher.delete(self.digest)
コード例 #9
0
ファイル: Checker.py プロジェクト: sekouperry/cms
    def echo_callback(self, data, error=None):
        """Callback for check.

        """
        current = time.time()
        logger.debug("Checker.echo_callback")
        if error is not None:
            return
        try:
            service, time_ = data.split()
            time_ = float(time_)
            name, shard = service.split(",")
            shard = int(shard)
            service = ServiceCoord(name, shard)
            if service not in self.waiting_for or current - time_ > 10:
                logger.warning("Got late reply (%5.3lf s) from %s." %
                               (current - time_, service))
            else:
                if time_ - self.waiting_for[service] > 0.001:
                    logger.warning("Someone cheated on the timestamp?!")
                logger.info("Got reply (%5.3lf s) from %s." %
                            (current - time_, service))
                del self.waiting_for[service]
        except KeyError:
            logger.error("Echo answer mis-shapen.")
コード例 #10
0
    def release_worker(self, shard):
        """To be called by ES when it receives a notification that a
        job finished.

        Note: if the worker is scheduled to be disabled, then we
        disable it, and notify the ES to discard the outcome obtained
        by the worker.

        shard (int): the worker to release.

        returns (bool): if the result is to be ignored.

        """
        if self._job[shard] == WorkerPool.WORKER_INACTIVE:
            err_msg = "Trying to release worker while it's inactive."
            logger.error(err_msg)
            raise ValueError(err_msg)
        ret = self._ignore[shard]
        self._start_time[shard] = None
        self._side_data[shard] = None
        self._ignore[shard] = False
        if self._schedule_disabling[shard]:
            self._job[shard] = WorkerPool.WORKER_DISABLED
            self._schedule_disabling[shard] = False
            logger.info("Worker %s released and disabled." % shard)
        else:
            self._job[shard] = WorkerPool.WORKER_INACTIVE
            logger.debug("Worker %s released." % shard)
        return ret
コード例 #11
0
    def search_jobs_not_done(self):
        """Look in the database for submissions that have not been
        compiled or evaluated for no good reasons. Put the missing job
        in the queue.

        """
        new_jobs = 0
        with SessionGen(commit=False) as session:
            contest = session.query(Contest).\
                      filter_by(id=self.contest_id).first()

            # Only adding submission not compiled/evaluated that have
            # not yet reached the limit of tries.
            for submission in contest.get_submissions():
                if to_compile(submission):
                    if self.push_in_queue(
                        (EvaluationService.JOB_TYPE_COMPILATION,
                         submission.id),
                        EvaluationService.JOB_PRIORITY_HIGH,
                        submission.timestamp):
                        new_jobs += 1
                elif to_evaluate(submission):
                    if self.push_in_queue(
                        (EvaluationService.JOB_TYPE_EVALUATION,
                         submission.id),
                        EvaluationService.JOB_PRIORITY_MEDIUM,
                        submission.timestamp):
                        new_jobs += 1

        if new_jobs > 0:
            logger.info("Found %s submissions with jobs to do." % new_jobs)

        # Run forever.
        return True
コード例 #12
0
ファイル: Worker.py プロジェクト: Mloc/cms
    def execute_job(self, job_dict):
        job = Job.import_from_dict_with_type(job_dict)

        if self.work_lock.acquire(False):

            try:
                logger.operation = "job '%s'" % (job.info)
                logger.info("Request received")
                job.shard = self.shard

                self.task_type = get_task_type(job, self.file_cacher)
                self.task_type.execute_job()
                logger.info("Request finished.")

                return job.export_to_dict()

            except:
                err_msg = "Worker failed on operation `%s'" % logger.operation
                logger.error("%s\n%s" % (err_msg, traceback.format_exc()))
                raise JobException(err_msg)

            finally:
                self.task_type = None
                self.session = None
                logger.operation = ""
                self.work_lock.release()

        else:
            err_msg = "Request '%s' received, " \
                "but declined because of acquired lock" % \
                (job.info)
            logger.warning(err_msg)
            raise JobException(err_msg)
コード例 #13
0
    def submit(self, timestamp, username, password, t_id, t_short,
               files, language):
        """Execute the request for a submission.

        timestamp (int): seconds from the start.
        username (string): username issuing the submission.
        password (string): password of username.
        t_id (string): id of the task.
        t_short (string): short name of the task.
        files ([dict]): list of dictionaries with keys 'filename' and
                        'digest'.
        language (string): the extension the files should have.

        """
        logger.info("%s - Submitting for %s on task %s."
                    % (to_time(timestamp), username, t_short))

        submit_files = []
        for f in files:
            filename_to_send = f["filename"]
            if language != None:
                filename_to_send = f["filename"].replace("%%l", language)
            submit_files.append([ f["filename"],
                    filename_to_send,
                    os.path.join(self.import_source, "files", f["digest"])
                    ])

        browser = Browser()
        browser.set_handle_robots(False)
        step(LoginRequest(browser, username, password,
                          base_url=self.cws_address))
        step(SubmitMultifileRequest(browser,
                           (int(t_id), t_short),
                           files=files,
                           base_url=self.cws_address))
コード例 #14
0
ファイル: ScoringService.py プロジェクト: volpino/cms
    def dispatch_operations(self):
        """Look at the operations still to do in the queue and tries
        to dispatch them

        """
        pending = len(self.operation_queue)
        if pending > 0:
            logger.info("%s operations still pending." % pending)

        failed_rankings = set([])
        new_queue = []
        for method, args in self.operation_queue:
            if args[0] in failed_rankings:
                new_queue.append((method, args))
                continue
            try:
                method(*args)
            except:
                logger.info("Ranking %s not connected or generic error." %
                            args[0][0])
                new_queue.append((method, args))
                failed_rankings.add(args[0])
        self.operation_queue = new_queue

        # We want this to run forever.
        return True
コード例 #15
0
ファイル: Checker.py プロジェクト: strogo/cms-1
    def echo_callback(self, data, error=None):
        """Callback for check.

        """
        current = time.time()
        logger.debug("Checker.echo_callback")
        if error is not None:
            return
        try:
            service, time_ = data.split()
            time_ = float(time_)
            name, shard = service.split(",")
            shard = int(shard)
            service = ServiceCoord(name, shard)
            if service not in self.waiting_for or current - time_ > 10:
                logger.warning("Got late reply (%5.3lf s) from %s."
                            % (current - time_, service))
            else:
                if time_ - self.waiting_for[service] > 0.001:
                    logger.warning("Someone cheated on the timestamp?!")
                logger.info("Got reply (%5.3lf s) from %s."
                            % (current - time_, service))
                del self.waiting_for[service]
        except KeyError:
            logger.error("Echo answer mis-shapen.")
コード例 #16
0
ファイル: ScoringService.py プロジェクト: beyondai/cms
    def submission_tokened(self, submission_id):
        """This RPC inform ScoringService that the user has played the
        token on a submission.

        submission_id (int): the id of the submission that changed.
        timestamp (int): the time of the token.

        """
        with SessionGen(commit=False) as session:
            submission = Submission.get_from_id(submission_id, session)

            if submission is None:
                logger.error("[submission_tokened] Received token request for "
                             "unexistent submission id %s." % submission_id)
                raise KeyError

            if submission.user.hidden:
                logger.info("[submission_tokened] Token for submission %d "
                            "not sent because user is hidden." % submission_id)
                return

            # Mark submission as tokened.
            self.submissions_tokened.add(submission_id)

            # Update RWS.
            self.rankings_send_token(submission)
コード例 #17
0
    def import_contest(self, path):
        """Import a contest into the system, returning a dictionary
        that can be passed to Contest.import_from_dict().

        """
        params, tasks, users = self.get_params_for_contest(path)
        for i, task in enumerate(tasks):
            task_params = self.get_params_for_task(os.path.join(path, task),
                                                   num=i)
            params["tasks"].append(task_params)
        if self.user_number is None:
            for user in users:
                user_params = self.get_params_for_user(user)
                params["users"].append(user_params)
        else:
            logger.info("Generating %s random users." % self.user_number)
            for i in xrange(self.user_number):
                user = User("User %d" % (i),
                            "Last name %d" % (i),
                            "user%03d" % (i))
                if self.modif == 'test':
                    user.password = '******'
                params["users"].append(user.export_to_dict())

        return params
コード例 #18
0
ファイル: TestFileCacher.py プロジェクト: Ben0mega/cms
    def test_008(self):
        """Put a ~100MB file into the storage (using a specially
        crafted file-like object).

        """
        logger.info("  I am sending the ~100MB binary file to FileCacher")
        rand_file = RandomFile(100000000)
        try:
            data = self.file_cacher.put_file_from_fobj(rand_file, u"Test #007")
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return
        if rand_file.dim != 0:
            self.test_end(False, "The input file wasn't read completely.")
        my_digest = rand_file.digest
        rand_file.close()

        if not os.path.exists(os.path.join(self.cache_base_path, data)):
            self.test_end(False, "File not stored in local cache.")
        elif my_digest != data:
            self.test_end(False, "File received with wrong hash.")
        else:
            self.cache_path = os.path.join(self.cache_base_path, data)
            self.digest = data
            self.test_end(True, "Data sent and cached without error.")
コード例 #19
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def prepare(self):
        """Initialization for the test code - make sure that the cache
        is empty before testing.

        """
        logger.info("Please delete directory %s before." %
                    self.cache_base_path)
コード例 #20
0
ファイル: ReplayContest.py プロジェクト: ronalchn/cms
    def submit(self, timestamp, username, password, t_id, t_short, files, language):
        """Execute the request for a submission.

        timestamp (int): seconds from the start.
        username (string): username issuing the submission.
        password (string): password of username.
        t_id (string): id of the task.
        t_short (string): short name of the task.
        files ([dict]): list of dictionaries with keys 'filename' and
                        'digest'.
        language (string): the extension the files should have.

        """
        logger.info("%s - Submitting for %s on task %s." % (to_time(timestamp), username, t_short))
        if len(files) != 1:
            logger.error("We cannot submit more than one file.")
            return

        # Copying submission files into a temporary directory with the
        # correct name. Otherwise, SubmissionRequest does not know how
        # to interpret the file (and which language are they in).
        temp_dir = tempfile.mkdtemp(dir=config.temp_dir)
        for file_ in files:
            temp_filename = os.path.join(temp_dir, file_["filename"].replace("%l", language))
            shutil.copy(os.path.join(self.import_source, "files", files[0]["digest"]), temp_filename)
            file_["filename"] = temp_filename

        filename = os.path.join(files[0]["filename"])
        browser = Browser()
        browser.set_handle_robots(False)
        step(LoginRequest(browser, username, password, base_url=self.cws_address))
        step(SubmitRequest(browser, (int(t_id), t_short), filename=filename, base_url=self.cws_address))
        shutil.rmtree(temp_dir)
コード例 #21
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def test_003(self):
        """Get file from FileCacher.

        """
        logger.info("  I am retrieving the file from FileCacher " +
                    "after deleting the cache.")
        os.unlink(self.cache_path)
        try:
            data = self.file_cacher.get_file(self.digest)
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return

        received = data.read()
        data.close()
        if received != self.content:
            self.test_end(False, "Content differ.")
        elif not os.path.exists(self.cache_path):
            self.test_end(False, "File not stored in local cache.")
        elif open(self.cache_path).read() != self.content:
            self.test_end(
                False, "Local cache's content differ " + "from original file.")
        else:
            self.test_end(True,
                          "Content object received " + "and cached correctly.")
コード例 #22
0
    def score_old_submissions(self):
        """The submissions in the submission_ids_to_score set are
        evaluated submissions that we can assign a score to, and this
        method scores a bunch of these at a time. This method keeps
        getting called while the set is non-empty. (Exactly the same
        happens for the submissions to token.)

        Note: doing this way (instead of putting everything in the
        __init__) prevent freezing the service at the beginning in the
        case of many old submissions.

        """
        self.scoring_old_submission = True
        to_score = len(self.submission_ids_to_score)
        to_token = len(self.submission_ids_to_token)
        to_score_now = to_score if to_score < 4 else 4
        to_token_now = to_token if to_token < 16 else 16
        logger.info("Old submission yet to score/token: %s/%s." %
                    (to_score, to_token))

        for unused_i in xrange(to_score_now):
            self.new_evaluation(self.submission_ids_to_score.pop())
        if to_score - to_score_now > 0:
            return True

        for unused_i in xrange(to_token_now):
            submission_id, timestamp = self.submission_ids_to_token.pop()
            self.submission_tokened(submission_id, timestamp)
        if to_token - to_token_now > 0:
            return True

        logger.info("Finished loading old submissions.")
        self.scoring_old_submission = False
        return False
コード例 #23
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def test_009(self):
        """Get the ~100MB file from FileCacher.

        """
        logger.info("  I am retrieving the ~100MB file from FileCacher " +
                    "after deleting the cache.")
        os.unlink(self.cache_path)
        hash_file = HashingFile()
        try:
            self.file_cacher.get_file_to_fobj(self.digest, hash_file)
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)
            return
        my_digest = hash_file.digest
        hash_file.close()

        try:
            if self.digest != my_digest:
                self.test_end(False, "Content differs.")
            elif not os.path.exists(self.cache_path):
                self.test_end(False, "File not stored in local cache.")
            else:
                self.test_end(
                    True, "Content object received " + "and cached correctly.")
        finally:
            self.file_cacher.delete(self.digest)
コード例 #24
0
ファイル: YamlLoader.py プロジェクト: schlos/cms
    def get_user(self, conf):

        """Produce a User object.

        Given an object of the first list returned by get_contest,
        construct a full User object and return it. Access the data on
        the filesystem if needed.

        return (User): the User object corresponding to the given dict.

        """

        logger.info("Loading parameters for user %s." % conf['username'])

        args = {}

        load(conf, args, "username")

        load(conf, args, "password")
        load(conf, args, "ip")

        load(conf, args, "nome", "first_name")
        load(conf, args, "cognome", "last_name")

        if "first_name" not in args:
            args["first_name"] = ""
        if "last_name" not in args:
            args["last_name"] = args["username"]

        load(conf, args, "fake", "hidden", lambda a: a == "True")

        logger.info("User parameters loaded.")

        return User(**args)
コード例 #25
0
    def token(self, timestamp, username, password, t_id, t_short,
              submission_num):
        """Execute the request for releasing test a submission.

        timestamp (int): seconds from the start.
        username (string): username issuing the submission.
        password (string): password of username.
        t_id (string): id of the task.
        t_short (string): short name of the task.
        submission_num (string): id of the submission to release test.

        """
        logger.info("%s - Playing token for %s on task %s" %
                    (to_time(timestamp), username, t_short))
        browser = Browser()
        browser.set_handle_robots(False)
        step(
            LoginRequest(browser,
                         username,
                         password,
                         base_url=self.cws_address))
        step(
            TokenRequest(browser, (int(t_id), t_short),
                         submission_num=submission_num,
                         base_url=self.cws_address))
コード例 #26
0
ファイル: EvaluationService.py プロジェクト: vishan/cms
    def user_test_compilation_ended(self, user_test):
        """Actions to be performed when we have a user test that has
        ended compilation. In particular: we queue evaluation if
        compilation was ok; we requeue compilation if it failed.

        user_test (UserTest): the user test.

        """
        # Compilation was ok, so we evaluate
        if user_test.compilation_outcome == "ok":
            self.push_in_queue(
                (EvaluationService.JOB_TYPE_TEST_EVALUATION, user_test.id),
                EvaluationService.JOB_PRIORITY_MEDIUM,
                user_test.timestamp,
            )
        # If instead user test failed compilation, we don't evaluatate
        elif user_test.compilation_outcome == "fail":
            logger.info("User test %d did not compile. Not going " "to evaluate." % user_test.id)
        # If compilation failed for our fault, we requeue or not
        elif user_test.compilation_outcome is None:
            if user_test.compilation_tries > EvaluationService.MAX_TEST_COMPILATION_TRIES:
                logger.error(
                    "Maximum tries reached for the "
                    "compilation of user test %d. I will "
                    "not try again." % (user_test.id)
                )
            else:
                # Note: lower priority (MEDIUM instead of HIGH) for
                # compilations that are probably failing again
                self.push_in_queue(
                    (EvaluationService.JOB_TYPE_TEST_COMPILATION, user_test.id),
                    EvaluationService.JOB_PRIORITY_MEDIUM,
                    user_test.timestamp,
                )
コード例 #27
0
    def get_params_for_user(self, user_dict):
        """Given the dictionary of information of a user (extracted
        from contest.yaml), it fills another dictionary with the
        parameters required by User.import_from_dict().

        """
        params = {}
        params["username"] = user_dict["username"]

        logger.info("Loading parameters for user %s." % params['username'])

        if self.modif == 'test':
            params["password"] = '******'
            params["ip"] = '0.0.0.0'
        else:
            params["password"] = user_dict["password"]
            params["ip"] = user_dict.get("ip", "0.0.0.0")
        name = user_dict.get("nome", "")
        surname = user_dict.get("cognome", user_dict["username"])
        params["first_name"] = name
        params["last_name"] = surname
        params["hidden"] = "True" == user_dict.get("fake", "False")

        params["timezone"] = 0.0
        params["messages"] = []
        params["questions"] = []
        params["submissions"] = []

        logger.info("User parameters loaded.")

        return params
コード例 #28
0
ファイル: Worker.py プロジェクト: kennyboy/cms
    def execute_job(self, job_dict):
        job = Job.import_from_dict_with_type(job_dict)

        if self.work_lock.acquire(False):

            try:
                logger.operation = "job '%s'" % (job.info)
                logger.info("Request received")
                job.shard = self.shard

                self.task_type = get_task_type(job, self.file_cacher)
                self.task_type.execute_job()
                logger.info("Request finished.")

                return job.export_to_dict()

            except:
                err_msg = "Worker failed on operation `%s'" % logger.operation
                logger.error("%s\n%s" % (err_msg, traceback.format_exc()))
                raise JobException(err_msg)

            finally:
                self.task_type = None
                self.session = None
                logger.operation = ""
                self.work_lock.release()

        else:
            err_msg = "Request '%s' received, " \
                "but declined because of acquired lock" % \
                (job.info)
            logger.warning(err_msg)
            raise JobException(err_msg)
コード例 #29
0
    def toggle_autorestart(self, service):
        """If the service is scheduled for autorestart, disable it,
        otherwise enable it.

        service (string): format: name,shard.

        return (bool/None): current status of will_restart.

        """
        # If the contest_id is not set, we cannot autorestart.
        if self.contest_id is None:
            return None

        # Decode name,shard
        try:
            idx = service.rindex(",")
        except ValueError:
            logger.error("Unable to decode service string.")
        name = service[:idx]
        try:
            shard = int(service[idx + 1:])
        except ValueError:
            logger.error("Unable to decode service shard.")
        service = ServiceCoord(name, shard)

        self._will_restart[service] = not self._will_restart[service]
        logger.info("Will restart %s,%s is now %s." %
                    (service.name, service.shard, self._will_restart[service]))

        return self._will_restart[service]
コード例 #30
0
ファイル: ScoringService.py プロジェクト: s546360316/cms
    def score_old_submissions(self):
        """The submissions in the submission_results_to_score set are
        evaluated submissions that we can assign a score to, and this
        method scores a bunch of these at a time. This method keeps
        getting called while the set is non-empty. (Exactly the same
        happens for the submissions to token.)

        Note: doing this way (instead of putting everything in the
        __init__) prevent freezing the service at the beginning in the
        case of many old submissions.

        """
        self.scoring_old_submission = True
        to_score = len(self.submission_results_to_score)
        to_token = len(self.submissions_to_token)
        to_score_now = to_score if to_score < 4 else 4
        to_token_now = to_token if to_token < 16 else 16
        logger.info("Old submission yet to score/token: %s/%s." %
                    (to_score, to_token))

        for unused_i in xrange(to_score_now):
            submission_id, dataset_id = self.submission_results_to_score.pop()
            self.new_evaluation(submission_id, dataset_id)
        if to_score - to_score_now > 0:
            return True

        for unused_i in xrange(to_token_now):
            submission_id = self.submissions_to_token.pop()
            self.submission_tokened(submission_id)
        if to_token - to_token_now > 0:
            return True

        logger.info("Finished loading old submissions.")
        self.scoring_old_submission = False
        return False
コード例 #31
0
ファイル: ScoringService.py プロジェクト: s546360316/cms
    def invalidate_submission(self,
                              submission_id=None,
                              dataset_id=None,
                              user_id=None,
                              task_id=None):
        """Request for invalidating some scores.

        Invalidate the scores of the SubmissionResults that:
        - belong to submission_id or, if None, to any submission of
          user_id and/or task_id or, if both None, to any submission
          of the contest this service is running for.
        - belong to dataset_id or, if None, to any dataset of task_id
          or, if None, to any dataset of any task of the contest this
          service is running for.

        submission_id (int): id of the submission to invalidate, or
                             None.
        dataset_id (int): id of the dataset 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:
            submission_results = get_submission_results(
                # Give contest_id only if all others are None.
                self.contest_id
                    if {user_id, task_id, submission_id, dataset_id} == {None}
                    else None,
                user_id, task_id, submission_id, dataset_id, session)

            logger.info("Submission results to invalidate scores for: %d." %
                        len(submission_results))
            if len(submission_results) == 0:
                return

            new_submission_results_to_score = set()

            for submission_result in submission_results:
                # 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_result.evaluated():
                    submission_result.invalidate_score()
                    new_submission_results_to_score.add(
                        (submission_result.submission_id,
                         submission_result.dataset_id))

        old_s = len(self.submission_results_to_score)
        old_t = len(self.submissions_to_token)
        self.submission_results_to_score |= new_submission_results_to_score
        if old_s + old_t == 0:
            self.add_timeout(self.score_old_submissions, None,
                             0.5, immediately=False)
コード例 #32
0
ファイル: SpoolExporter.py プロジェクト: invinciblejha/cms
    def export_submissions(self):
        """Export submissions' source files.

        """
        logger.info("Exporting submissions.")

        queue_file = codecs.open(os.path.join(self.spool_dir, "queue"), "w",
                                 encoding="utf-8")
        # FIXME - The enumeration of submission should be time-increasing
        for submission in self.contest.get_submissions():
            if submission.user.hidden:
                continue
            logger.info("Exporting submission %s." % submission.id)
            username = submission.user.username
            task = submission.task.name
            timestamp = submission.timestamp

            # Get source files to the spool directory.
            file_digest = submission.files["%s.%s" % (task, "%l")].digest
            upload_filename = os.path.join(
                self.upload_dir, username, "%s.%d.%s" %
                (task, timestamp, submission.language))
            self.file_cacher.get_file(file_digest, path=upload_filename)
            upload_filename = os.path.join(
                self.upload_dir, username, "%s.%s" %
                (task, submission.language))
            self.file_cacher.get_file(file_digest, path=upload_filename)
            print >> queue_file, "./upload/%s/%s.%d.%s" % \
                (username, task, timestamp, submission.language)

            # Write results file for the submission.
            if submission.evaluated():
                res_file = codecs.open(os.path.join(
                    self.spool_dir,
                    "%d.%s.%s.%s.res" % (timestamp, username,
                                         task, submission.language)),
                                       "w", encoding="utf-8")
                res2_file = codecs.open(os.path.join(
                    self.spool_dir,
                    "%s.%s.%s.res" % (username, task,
                                      submission.language)),
                                        "w", encoding="utf-8")
                total = 0.0
                for num, evaluation in enumerate(submission.evaluations):
                    outcome = float(evaluation.outcome)
                    total += outcome
                    line = "Executing on file n. %2d %s (%.4f)" % \
                        (num, evaluation.text, outcome)
                    print >> res_file, line
                    print >> res2_file, line
                line = "Score: %.6f" % total
                print >> res_file, line
                print >> res2_file, line
                res_file.close()
                res2_file.close()

        print >> queue_file
        queue_file.close()
コード例 #33
0
ファイル: ContestWebServer.py プロジェクト: volpino/cms
    def post(self):

        submission_id = self.get_argument("submission_id", "")

        # Decrypt submission_id.
        try:
            submission_id = decrypt_number(submission_id)
        except ValueError:
            # We reply with Forbidden if the given ID cannot be
            # decrypted.
            logger.warning(
                "User %s tried to play a token " "on an undecryptable submission_id." % self.current_user.username
            )
            raise tornado.web.HTTPError(403)

        # Find submission and check it is of the current user.
        submission = Submission.get_from_id(submission_id, self.sql_session)
        if submission is None or submission.user != self.current_user:
            logger.warning(
                "User %s tried to play a token " "on an unexisting submission_id." % self.current_user.username
            )
            raise tornado.web.HTTPError(404)

        # Don't trust the user, check again if (s)he can really play
        # the token.
        timestamp = int(time.time())
        if self.contest.tokens_available(self.current_user.username, submission.task.name, timestamp)[0] <= 0:
            logger.warning("User %s tried to play a token " "when it shouldn't." % self.current_user.username)
            # Add "no luck" notification
            self.application.service.add_notification(
                self.current_user.username,
                timestamp,
                self._("Token request discarded"),
                self._("Your request has been discarded because you have no " "tokens available."),
            )
            self.redirect("/tasks/%s" % encrypt_number(submission.task.id))
            return

        token = Token(timestamp, submission)
        self.sql_session.add(token)
        self.sql_session.commit()

        # Inform ScoringService and eventually the ranking that the
        # token has been played.
        self.application.service.scoring_service.submission_tokened(submission_id=submission_id, timestamp=timestamp)

        logger.info("Token played by user %s on task %s." % (self.current_user.username, submission.task.name))

        # Add "All ok" notification
        self.application.service.add_notification(
            self.current_user.username,
            timestamp,
            self._("Token request received"),
            self._("Your request has been received " "and applied to the submission."),
        )

        self.redirect("/tasks/%s" % encrypt_number(submission.task.id))
コード例 #34
0
ファイル: TaskType.py プロジェクト: volpino/cms
    def evaluation_step_before_run(
        self,
        sandbox,
        command,
        executables_to_get,
        files_to_get,
        time_limit=0,
        memory_limit=0,
        allow_path=None,
        stdin_redirect=None,
        stdout_redirect=None,
        wait=False,
    ):
        """First part of an evaluation step, until the running.

        return: exit code already translated if wait is True, the
                process if wait is False.

        """
        # Record the usage of the sandbox.
        self.sandbox_paths = ":".join([self.sandbox_paths, sandbox.path])

        # Copy all necessary files.
        for filename, digest in executables_to_get.iteritems():
            sandbox.create_file_from_storage(filename, digest, executable=True)
        for filename, digest in files_to_get.iteritems():
            sandbox.create_file_from_storage(filename, digest)

        if allow_path is None:
            allow_path = []

        # Set sandbox parameters suitable for evaluation.
        sandbox.chdir = sandbox.path
        sandbox.filter_syscalls = 2
        sandbox.timeout = time_limit
        sandbox.wallclock_timeout = 2 * time_limit
        sandbox.address_space = memory_limit * 1024
        sandbox.file_check = 1
        sandbox.allow_path = allow_path
        sandbox.stdin_file = stdin_redirect
        sandbox.stdout_file = stdout_redirect
        stdout_filename = os.path.join(sandbox.path, "stdout.txt")
        stderr_filename = os.path.join(sandbox.path, "stderr.txt")
        if sandbox.stdout_file is None:
            sandbox.stdout_file = stdout_filename
        sandbox.stderr_file = stderr_filename
        # These syscalls and paths are used by executables generated
        # by fpc.
        sandbox.allow_path += ["/proc/self/exe"]
        sandbox.allow_syscall += ["getrlimit", "rt_sigaction", "ugetrlimit"]
        # This one seems to be used for a C++ executable.
        sandbox.allow_path += ["/proc/meminfo"]

        # Actually run the evaluation command.
        logger.info("Starting evaluation step.")

        return sandbox.execute_without_std(command, wait=wait)
コード例 #35
0
ファイル: DumpUpdater.py プロジェクト: beyondai/cms
def main():
    parser = argparse.ArgumentParser(
        description="Updater of CMS contest dumps.")
    parser.add_argument(
        "-V", "--to-version", action="store", type=int, default=-1,
        help="Update to given version number")
    parser.add_argument(
        "path", help="location of the dump or of the 'contest.json' file")

    args = parser.parse_args()
    path = args.path

    to_version = args.to_version
    if to_version == -1:
        to_version = model_version

    if not path.endswith("contest.json"):
        path = os.path.join(path, "contest.json")

    if not os.path.exists(path):
        logger.critical(
            "The given path doesn't exist or doesn't contain a contest "
            "dump in a format CMS is able to understand.")
        return

    with io.open(path, 'rb') as fin:
        data = json.load(fin, encoding="utf-8")

    # If no "_version" field is found we assume it's a v1.0
    # export (before the new dump format was introduced).
    dump_version = data.get("_version", 0)

    if dump_version == to_version:
        logger.info(
            "The dump you're trying to update is already stored using "
            "the most recent format supported by this version of CMS.")
        return

    if dump_version > to_version:
        logger.critical(
            "The dump you're trying to update is stored using a format "
            "that's more recent than the one supported by this version "
            "of CMS. You probably need to update CMS to handle it.")
        return

    for version in range(dump_version, to_version):
        # Update from version to version+1
        updater = __import__(
            "cmscontrib.updaters.update_%d" % (version + 1),
            globals(), locals(), ["Updater"]).Updater(data)
        data = updater.run()
        data["_version"] = version + 1

    assert data["_version"] == to_version

    with io.open(path, 'wb') as fout:
        json.dump(data, fout, encoding="utf-8", indent=4, sort_keys=True)
コード例 #36
0
ファイル: ScoringService.py プロジェクト: bblackham/cms
    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
コード例 #37
0
ファイル: ScoringService.py プロジェクト: cbolk/cms
    def reinitialize(self):
        """Inform the service that something in the data of the
        contest has changed (users, tasks, the contest itself) and we
        need to do it over again. This should be almost like
        restarting the service.

        """
        logger.info("Reinitializing rankings.")
        self.rankings_initialize()
コード例 #38
0
    def export_submissions(self):
        """Export submissions' source files.

        """
        logger.info("Exporting submissions.")

        queue_file = codecs.open(os.path.join(self.spool_dir, "queue"),
                                 "w",
                                 encoding="utf-8")
        for submission in self.submissions:
            logger.info("Exporting submission %s." % submission.id)
            username = submission.user.username
            task = submission.task.name
            timestamp = submission.timestamp

            # Get source files to the spool directory.
            file_digest = submission.files["%s.%s" % (task, "%l")].digest
            upload_filename = os.path.join(
                self.upload_dir, username,
                "%s.%d.%s" % (task, timestamp, submission.language))
            self.file_cacher.get_file(file_digest, path=upload_filename)
            upload_filename = os.path.join(
                self.upload_dir, username,
                "%s.%s" % (task, submission.language))
            self.file_cacher.get_file(file_digest, path=upload_filename)
            print >> queue_file, "./upload/%s/%s.%d.%s" % \
                (username, task, timestamp, submission.language)

            # Write results file for the submission.
            if submission.evaluated():
                res_file = codecs.open(os.path.join(
                    self.spool_dir, "%d.%s.%s.%s.res" %
                    (timestamp, username, task, submission.language)),
                                       "w",
                                       encoding="utf-8")
                res2_file = codecs.open(os.path.join(
                    self.spool_dir,
                    "%s.%s.%s.res" % (username, task, submission.language)),
                                        "w",
                                        encoding="utf-8")
                total = 0.0
                for num, evaluation in enumerate(submission.evaluations):
                    outcome = float(evaluation.outcome)
                    total += outcome
                    line = "Executing on file n. %2d %s (%.4f)" % \
                        (num, evaluation.text, outcome)
                    print >> res_file, line
                    print >> res2_file, line
                line = "Score: %.6f" % total
                print >> res_file, line
                print >> res2_file, line
                res_file.close()
                res2_file.close()

        print >> queue_file
        queue_file.close()
コード例 #39
0
ファイル: ContestExporter.py プロジェクト: vishan/cms
    def do_export(self):
        """Run the actual export code.

        """
        logger.operation = "exporting contest %d" % self.contest_id
        logger.info("Starting export.")

        export_dir = self.export_target
        archive_info = get_archive_info(self.export_target)

        if archive_info["write_mode"] != "":
            # We are able to write to this archive.
            if os.path.exists(self.export_target):
                logger.critical("The specified file already exists, " "I won't overwrite it.")
                return False
            export_dir = os.path.join(tempfile.mkdtemp(), archive_info["basename"])

        logger.info("Creating dir structure.")
        try:
            os.mkdir(export_dir)
        except OSError:
            logger.critical("The specified directory already exists, " "I won't overwrite it.")
            return False

        files_dir = os.path.join(export_dir, "files")
        descr_dir = os.path.join(export_dir, "descriptions")
        os.mkdir(files_dir)
        os.mkdir(descr_dir)

        with SessionGen(commit=False) as session:

            contest = Contest.get_from_id(self.contest_id, session)

            # Export files.
            logger.info("Exporting files.")
            files = contest.enumerate_files(self.skip_submissions, self.skip_user_tests, light=self.light)
            for _file in files:
                if not self.safe_get_file(_file, os.path.join(files_dir, _file), os.path.join(descr_dir, _file)):
                    return False

            # Export the contest in JSON format.
            logger.info("Exporting the contest in JSON format.")
            with open(os.path.join(export_dir, "contest.json"), "w") as fout:
                json.dump(contest.export_to_dict(self.skip_submissions, self.skip_user_tests), fout, indent=4)

        # If the admin requested export to file, we do that.
        if archive_info["write_mode"] != "":
            archive = tarfile.open(self.export_target, archive_info["write_mode"])
            archive.add(export_dir, arcname=archive_info["basename"])
            archive.close()
            shutil.rmtree(export_dir)

        logger.info("Export finished.")
        logger.operation = ""

        return True
コード例 #40
0
ファイル: ScoringService.py プロジェクト: sekouperry/cms
    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)
コード例 #41
0
ファイル: EvaluationService.py プロジェクト: vishan/cms
    def acquire_worker(self, job, side_data=None):
        """Tries to assign a job to an available worker. If no workers
        are available then this returns None, otherwise this returns
        the chosen worker.

        job (job): the job to assign to a worker
        side_data (object): object to attach to the worker for later
                            use

        returns (int): None if no workers are available, the worker
                       assigned to the job otherwise
        """
        # We look for an available worker
        try:
            shard = self.find_worker(WorkerPool.WORKER_INACTIVE, require_connection=True, random_worker=True)
        except LookupError:
            return None

        # Then we fill the info for future memory
        self._job[shard] = job
        self._start_time[shard] = make_datetime()
        self._side_data[shard] = side_data
        logger.debug("Worker %s acquired." % shard)

        # And finally we ask the worker to do the job
        action, object_id = job
        timestamp = side_data[1]
        queue_time = self._start_time[shard] - timestamp
        logger.info(
            "Asking worker %s to %s submission/user test %d "
            " (%s after submission)." % (shard, action, object_id, queue_time)
        )

        with SessionGen(commit=False) as session:
            if action == EvaluationService.JOB_TYPE_COMPILATION:
                submission = Submission.get_from_id(object_id, session)
                job_ = CompilationJob.from_submission(submission)
            elif action == EvaluationService.JOB_TYPE_EVALUATION:
                submission = Submission.get_from_id(object_id, session)
                job_ = EvaluationJob.from_submission(submission)
            elif action == EvaluationService.JOB_TYPE_TEST_COMPILATION:
                user_test = UserTest.get_from_id(object_id, session)
                job_ = CompilationJob.from_user_test(user_test)
            elif action == EvaluationService.JOB_TYPE_TEST_EVALUATION:
                user_test = UserTest.get_from_id(object_id, session)
                job_ = EvaluationJob.from_user_test(user_test)
                job_.get_output = True
                job_.only_execution = True

            self._worker[shard].execute_job(
                job_dict=job_.export_to_dict(),
                callback=self._service.action_finished.im_func,
                plus=(action, object_id, side_data, shard),
            )

        return shard
コード例 #42
0
ファイル: Worker.py プロジェクト: cbolk/cms
    def ignore_job(self):
        """RPC that inform the worker that its result for the current
        action will be discarded. The worker will try to return as
        soon as possible even if this means that the result are
        inconsistent.

        """
        # We remember to quit as soon as possible.
        logger.info("Trying to interrupt job as requested.")
        self._ignore_job = True
コード例 #43
0
ファイル: TestFileCacher.py プロジェクト: shaunren/cms
    def test_005(self):
        """Get unexisting file from FileCacher.

        """
        logger.info("  I am retrieving an unexisting file from FileCacher.")
        try:
            self.file_cacher.get_file(self.digest)
        except Exception as error:
            self.test_end(True, "Correctly received an error: %r." % error)
        else:
            self.test_end(False, "Did not receive error.")
コード例 #44
0
ファイル: ScoringService.py プロジェクト: kennyboy/cms
    def reinitialize(self):
        """Inform the service that something in the data of the
        contest has changed (users, tasks, the contest itself) and we
        need to do it over again. This should be almost like
        restarting the service.

        """
        logger.info("Reinitializing rankings.")
        self._initialize_scorers()
        with self.operation_queue_lock:
            for ranking in self.rankings:
                self.initialize_queue.add(ranking)
コード例 #45
0
    def get_params_for_contest(self, path):
        """Given the path of a contest, extract the data from its
        contest.yaml file, and create a dictionary with the parameter
        required by Contest.import_from_dict().

        Returns that dictionary and the two pieces of data that must
        be processed with get_params_for_task and
        get_params_for_users.

        path (string): the input directory.

        return (dict): data of the contest.

        """
        path = os.path.realpath(path)
        name = os.path.split(path)[1]
        conf = yaml.load(
            codecs.open(os.path.join(path, "contest.yaml"), "r", "utf-8"))

        logger.info("Loading parameters for contest %s." % name)

        params = {}
        params["name"] = name
        assert name == conf["nome_breve"]
        params["description"] = conf["nome"]
        params["token_initial"] = conf.get("token_initial", None)
        params["token_max"] = conf.get("token_max", None)
        params["token_total"] = conf.get("token_total", None)
        params["token_min_interval"] = conf.get("token_min_interval", 0)
        params["token_gen_time"] = conf.get("token_gen_time", 0)
        params["token_gen_number"] = conf.get("token_gen_number", 0)
        if params["token_gen_time"] is None or \
               params["token_gen_number"] is None:
            params["token_gen_time"] = 1
            params["token_gen_number"] = 0
        if self.modif == 'zero_time':
            params["start"] = 0
            params["stop"] = 0
        elif self.modif == 'test':
            params["start"] = 0
            params["stop"] = 2000000000
        else:
            params["start"] = conf.get("inizio", 0)
            params["stop"] = conf.get("fine", 0)

        logger.info("Contest parameters loaded.")

        params["tasks"] = []
        params["users"] = []
        params["announcements"] = []

        return params, conf["problemi"], conf["utenti"]
コード例 #46
0
ファイル: Worker.py プロジェクト: kennyboy/cms
    def ignore_job(self):
        """RPC that inform the worker that its result for the current
        action will be discarded. The worker will try to return as
        soon as possible even if this means that the result are
        inconsistent.

        """
        # We inform the task_type to quit as soon as possible.
        logger.info("Trying to interrupt job as requested.")
        try:
            self.task_type.ignore_job = True
        except AttributeError:
            pass  # Job concluded right under our nose, that's ok too.
コード例 #47
0
ファイル: ScoringService.py プロジェクト: bblackham/cms
    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
コード例 #48
0
ファイル: ContestExporter.py プロジェクト: kennyboy/cms
    def dump_database(self, export_dir):
        """Dump the whole database. This is never used; however, this
        part is retained for historical reasons.

        """
        # Warning: this part depends on the specific database used.
        logger.info("Dumping SQL database.")
        (engine, connection) = config.database.split(':', 1)
        db_exportfile = os.path.join(export_dir, "database_dump.sql")

        # Export procedure for PostgreSQL.
        if engine == 'postgresql':
            db_regex = re.compile('//(\w*):(\w*)@(\w*)/(\w*)')
            db_match = db_regex.match(connection)
            if db_match is not None:
                username, password, host, database = db_match.groups()
                os.environ['PGPASSWORD'] = password
                export_res = os.system('pg_dump -h %s -U %s -w %s -x " \
                    "--attribute-inserts > %s' % (host, username, database,
                                                  db_exportfile))
                del os.environ['PGPASSWORD']
                if export_res != 0:
                    logger.critical("Database export failed.")
                    return False
            else:
                logger.critical("Cannot obtain parameters for "
                                "database connection.")
                return False

        # Export procedure for SQLite.
        elif engine == 'sqlite':
            db_regex = re.compile('///(.*)')
            db_match = db_regex.match(connection)
            if db_match is not None:
                dbfile, = db_match.groups()
                export_res = os.system('sqlite3 %s .dump > %s' %
                                       (dbfile, db_exportfile))
                if export_res != 0:
                    logger.critical("Database export failed.")
                    return False
            else:
                logger.critical("Cannot obtain parameters for "
                                "database connection.")
                return False

        else:
            logger.critical("Database engine not supported. :-(")
            return False

        return True
コード例 #49
0
ファイル: ScoringService.py プロジェクト: sekouperry/cms
    def submission_tokened(self, submission_id):
        """This RPC inform ScoringService that the user has played the
        token on a submission.

        submission_id (int): the id of the submission that changed.
        timestamp (int): the time of the token.

        """
        with SessionGen(commit=False) as session:
            submission = Submission.get_from_id(submission_id, session)
            if submission is None:
                logger.error("[submission_tokened] Received token request for "
                             "unexistent submission id %s." % submission_id)
                raise KeyError
            elif submission.user.hidden:
                logger.info("[submission_tokened] Token for submission %d "
                            "not sent because user is hidden." % submission_id)
                return

            # Mark submission as tokened.
            self.submissions_tokened.add(submission_id)

            # Data to send to remote rankings.
            submission_put_data = {
                "user": encode_id(submission.user.username),
                "task": encode_id(submission.task.name),
                "time": int(make_timestamp(submission.timestamp))
            }
            subchange_id = "%s%st" % \
                (int(make_timestamp(submission.token.timestamp)),
                 submission_id)
            subchange_put_data = {
                "submission": encode_id(submission_id),
                "time": int(make_timestamp(submission.token.timestamp)),
                "token": True
            }

        # Adding operations to the queue.
        with self.operation_queue_lock:
            for ranking in self.rankings:
                self.submission_queue.setdefault(
                    ranking,
                    dict())[encode_id(submission_id)] = \
                    submission_put_data
                self.subchange_queue.setdefault(
                    ranking,
                    dict())[encode_id(subchange_id)] = \
                    subchange_put_data
コード例 #50
0
ファイル: Worker.py プロジェクト: kennyboy/cms
    def precache_files(self, contest_id):
        """RPC to ask the worker to precache of files in the contest.

        contest_id (int): the id of the contest

        """
        # Lock is not needed if the admins correctly placed cache and
        # temp directories in the same filesystem. This is what
        # usually happens since they are children of the same,
        # cms-created, directory.
        logger.info("Precaching files for contest %d." % contest_id)
        with SessionGen(commit=False) as session:
            contest = Contest.get_from_id(contest_id, session)
            for digest in contest.enumerate_files(skip_submissions=True):
                self.file_cacher.get_file(digest)
        logger.info("Precaching finished.")
コード例 #51
0
ファイル: TestFileCacher.py プロジェクト: pombredanne/cms-1
    def test_002(self):
        """Check the size of the file.

        """
        logger.info("  I am checking the size of the ~100B binary file")
        try:
            size = self.file_cacher.get_size(self.digest)
        except Exception as error:
            self.test_end(False, "Error received: %r." % error)

        if size == self.size:
            self.test_end(True, "The size is correct.")
        else:
            self.test_end(
                False,
                "The size is wrong: %d instead of %d" % (size, self.size))
コード例 #52
0
    def replay(self):
        """Start replaying the events in source on the CWS at the
        specified address.

        """
        with self.speed_lock:
            index = 0
            if self.start_from is not None:
                while index < len(self.events) \
                        and float(self.events[index][0]) < self.start_from:
                    index += 1
                self.start = time.time() - self.start_from
            else:
                self.start = time.time()

        while index < len(self.events):
            timestamp, username, password, task_id, task_name, type_, data \
                = self.events[index]
            to_wait = (timestamp / self.speed - (time.time() - self.start))
            while to_wait > .5:
                if 0 < to_wait % 10 <= .5:
                    logger.info("Next event in %d seconds." % int(to_wait))
                time.sleep(.5)
                to_wait = (timestamp / self.speed - (time.time() - self.start))
            if to_wait > 0:
                time.sleep(to_wait)

            if type_ == "s":  # Submit.
                files, language = data
                self.submit(timestamp=timestamp,
                            username=username,
                            password=password,
                            t_id=task_id,
                            t_short=task_name,
                            files=files,
                            language=language)
            elif type_ == "t":  # Token.
                self.token(timestamp=timestamp,
                           username=username,
                           password=password,
                           t_id=task_id,
                           t_short=task_name,
                           submission_num=data)
            else:
                logger.warning("Unexpected type `%s', ignoring." % type_)

            index += 1
コード例 #53
0
def evaluation_step_before_run(sandbox,
                               command,
                               time_limit=0,
                               memory_limit=0,
                               allow_path=None,
                               stdin_redirect=None,
                               stdout_redirect=None,
                               wait=False):
    """First part of an evaluation step, until the running.

    return: exit code already translated if wait is True, the
            process if wait is False.

    """
    # Set sandbox parameters suitable for evaluation.
    sandbox.chdir = sandbox.path
    sandbox.filter_syscalls = 2
    sandbox.timeout = time_limit
    sandbox.wallclock_timeout = 2 * time_limit
    sandbox.address_space = memory_limit * 1024
    sandbox.file_check = 1
    if allow_path is None:
        allow_path = []
    sandbox.allow_path = allow_path
    sandbox.stdin_file = stdin_redirect
    sandbox.stdout_file = stdout_redirect
    stdout_filename = os.path.join(sandbox.path, "stdout.txt")
    stderr_filename = os.path.join(sandbox.path, "stderr.txt")
    if sandbox.stdout_file is None:
        sandbox.stdout_file = stdout_filename
    sandbox.stderr_file = stderr_filename
    # These syscalls and paths are used by executables generated
    # by fpc.
    sandbox.allow_path += [
        "/proc/self/exe", "/etc/timezone", "/usr/share/zoneinfo/"
    ]
    sandbox.allow_syscall += [
        "getrlimit", "rt_sigaction", "ugetrlimit", "time"
    ]
    # This one seems to be used for a C++ executable.
    sandbox.allow_path += ["/proc/meminfo"]
    # This is used by freopen in Ubuntu 12.04.
    sandbox.allow_syscall += ["dup3"]

    # Actually run the evaluation command.
    logger.info("Starting execution step.")
    return sandbox.execute_without_std(command, wait=wait)
コード例 #54
0
ファイル: __init__.py プロジェクト: pombredanne/cms-1
        def _fetch_write_chunk(self):
            """Send a chunk of the file to the browser.

            """
            data = self.temp_file.read(FileCacher.CHUNK_SIZE)
            length = len(data)
            self.size += length / 1024.0 / 1024.0
            self.write(data)
            if length < FileCacher.CHUNK_SIZE:
                self.temp_file.close()
                os.unlink(self.temp_filename)
                duration = time.time() - self.start_time
                logger.info("%.3lf seconds for %.3lf MB, %.3lf MB/s" %
                            (duration, self.size, self.size / duration))
                self.finish()
                return False
            return True
コード例 #55
0
    def post(self):
        username = self.get_argument("username", "")
        password = self.get_argument("password", "")
        user = self.sql_session.query(User)\
            .filter(User.auth_type == "Password")\
            .filter(User.contest == self.contest)\
            .filter(User.username == username).first()

        filtered_user = filter_ascii(username)
        filtered_pass = filter_ascii(password)
        if user is None or user.password != password:
            logger.info("Login error: user=%s pass=%s remote_ip=%s." %
                        (filtered_user, filtered_pass, self.request.remote_ip))
            self.redirect("/?login_error=true")
            return

        self.try_user_login(user)
コード例 #56
0
    def invalidate_submission(self,
                              submission_id=None,
                              user_id=None,
                              task_id=None):
        """Request for invalidating the scores of some submissions.

        The scores to be cleared are the one regarding 1) a submission
        or 2) all submissions of a user or 3) all submissions of a
        task or 4) all submission (if all parameters are None).

        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.

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

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

        logger.info("Submissions to invalidate: %s" % len(submission_ids))
        if len(submission_ids) == 0:
            return

        new_submission_ids = []
        with SessionGen(commit=True) as session:
            for submission_id in submission_ids:
                submission = Submission.get_from_id(submission_id, session)
                # 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_submission_ids.append(submission_id)

        old_s = len(self.submission_ids_to_score)
        old_t = len(self.submission_ids_to_token)
        self.submission_ids_to_score |= new_submission_ids
        if old_s + old_t == 0:
            self.add_timeout(self.score_old_submissions,
                             None,
                             0.5,
                             immediately=False)
コード例 #57
0
    def submit(self, timestamp, username, password, t_id, t_short, files,
               language):
        """Execute the request for a submission.

        timestamp (int): seconds from the start.
        username (string): username issuing the submission.
        password (string): password of username.
        t_id (string): id of the task.
        t_short (string): short name of the task.
        files ([dict]): list of dictionaries with keys 'filename' and
                        'digest'.
        language (string): the extension the files should have.

        """
        logger.info("%s - Submitting for %s on task %s." %
                    (to_time(timestamp), username, t_short))
        if len(files) != 1:
            logger.error("We cannot submit more than one file.")
            return

        # Copying submission files into a temporary directory with the
        # correct name. Otherwise, SubmissionRequest does not know how
        # to interpret the file (and which language are they in).
        temp_dir = tempfile.mkdtemp(dir=config.temp_dir)
        for file_ in files:
            temp_filename = os.path.join(
                temp_dir, file_["filename"].replace("%l", language))
            shutil.copy(
                os.path.join(self.import_source, "files", files[0]["digest"]),
                temp_filename)
            file_["filename"] = temp_filename

        filename = os.path.join(files[0]["filename"])
        browser = Browser()
        browser.set_handle_robots(False)
        step(
            LoginRequest(browser,
                         username,
                         password,
                         base_url=self.cws_address))
        step(
            SubmitRequest(browser, (int(t_id), t_short),
                          filename=filename,
                          base_url=self.cws_address))
        shutil.rmtree(temp_dir)