def test_new_input_file(self): input_id = 'input_id' task = 'simple_task' attempt = 42 path = StorageManager.new_input_file(input_id, task, attempt) self.assertIn("input", path) self.assertTrue(path.find(input_id) >= 0) self.assertTrue(path.find(task) >= 0) self.assertTrue(path.find(str(attempt)) >= 0)
def get_input(task_name, attempt): """ Fetch an input from the queue and properly rename it :param task_name: Name of the task :param attempt: Number of the attempt for the user :return: A pair, the first element is the id of the input file, the second the path """ if ContestManager.input_queue[task_name].empty(): Logger.warning("TASK", "Empty queue for task %s!" % task_name) input = ContestManager.input_queue[task_name].get() path = StorageManager.new_input_file(input["id"], task_name, attempt) StorageManager.rename_file(input["path"], path) return input["id"], path
def worker(task_name): """ Method that stays in the background and generates inputs """ task = ContestManager.tasks[task_name] queue = ContestManager.input_queue[task_name] while True: try: id = Database.gen_id() path = StorageManager.new_input_file(id, task_name, "invalid") seed = int(sha256(id.encode()).hexdigest(), 16) % (2**31) stdout = os.open( StorageManager.get_absolute_path(path), os.O_WRONLY | os.O_CREAT, 0o644, ) try: start_time = time.monotonic() # generate the input and store the stdout into a file retcode = gevent.subprocess.call( [task["generator"], str(seed), "0"], stdout=stdout) if time.monotonic() > start_time + 1: Logger.warning( "TASK", "Generation of input %s for task %s took %f seconds" % (seed, task_name, time.monotonic() - start_time), ) finally: os.close(stdout) if retcode != 0: Logger.error( "TASK", "Error %d generating input %s (%d) for task %s" % (retcode, id, seed, task_name), ) # skip the input continue # if there is a validator in the task use it to check if the # generated input is valid if "validator" in task: stdin = os.open(StorageManager.get_absolute_path(path), os.O_RDONLY) try: start_time = time.monotonic() # execute the validator piping the input file to stdin retcode = gevent.subprocess.call( [task["validator"], "0"], stdin=stdin) if time.monotonic() > start_time + 1: Logger.warning( "TASK", "Validation of input %s for task %s took %f " "seconds" % (seed, task_name, time.monotonic() - start_time), ) finally: os.close(stdin) if retcode != 0: Logger.error( "TASK", "Error %d validating input %s (%d) for task %s" % (retcode, id, seed, task_name), ) # skip the input continue Logger.debug( "TASK", "Generated input %s (%d) for task %s" % (id, seed, task_name), ) # this method is blocking if the queue is full queue.put({"id": id, "path": path}) except: Logger.error( "TASK", "Exception while creating an input file: " + traceback.format_exc(), )