@@ -85,9 +85,11 @@ def __init__(
8585 task_type_parameters : object = None ,
8686 language : str | None = None ,
8787 multithreaded_sandbox : bool = False ,
88+ archive_sandbox : bool = False ,
8889 shard : int | None = None ,
8990 keep_sandbox : bool = False ,
9091 sandboxes : list [str ] | None = None ,
92+ sandbox_digests : dict [str , str ] | None = None ,
9193 info : str | None = None ,
9294 success : bool | None = None ,
9395 text : list [str ] | None = None ,
@@ -104,12 +106,15 @@ def __init__(
104106 language: the language of the submission / user test.
105107 multithreaded_sandbox: whether the sandbox should
106108 allow multithreading.
109+ archive_sandbox: whether the sandbox is to be archived.
107110 shard: the shard of the Worker completing this job.
108111 keep_sandbox: whether to forcefully keep the sandbox,
109112 even if other conditions (the config, the sandbox status)
110113 don't warrant it.
111114 sandboxes: the paths of the sandboxes used in
112115 the Worker during the execution of the job.
116+ sandbox_digests: the digests of the sandbox archives used to
117+ debug solutions. (map of sandbox path -> archive digest)
113118 info: a human readable description of the job.
114119 success: whether the job succeeded.
115120 text: description of the outcome of the job,
@@ -125,6 +130,8 @@ def __init__(
125130 task_type = ""
126131 if sandboxes is None :
127132 sandboxes = []
133+ if sandbox_digests is None :
134+ sandbox_digests = {}
128135 if info is None :
129136 info = ""
130137 if files is None :
@@ -139,9 +146,11 @@ def __init__(
139146 self .task_type_parameters = task_type_parameters
140147 self .language = language
141148 self .multithreaded_sandbox = multithreaded_sandbox
149+ self .archive_sandbox = archive_sandbox
142150 self .shard = shard
143151 self .keep_sandbox = keep_sandbox
144152 self .sandboxes = sandboxes
153+ self .sandbox_digests = sandbox_digests
145154 self .info = info
146155
147156 self .success = success
@@ -161,9 +170,11 @@ def export_to_dict(self) -> dict:
161170 'task_type_parameters' : self .task_type_parameters ,
162171 'language' : self .language ,
163172 'multithreaded_sandbox' : self .multithreaded_sandbox ,
173+ 'archive_sandbox' : self .archive_sandbox ,
164174 'shard' : self .shard ,
165175 'keep_sandbox' : self .keep_sandbox ,
166176 'sandboxes' : self .sandboxes ,
177+ 'sandbox_digests' : self .sandbox_digests ,
167178 'info' : self .info ,
168179 'success' : self .success ,
169180 'text' : self .text ,
@@ -253,6 +264,26 @@ def from_operation(
253264 job = EvaluationJob .from_user_test (operation , object_ , dataset )
254265 return job
255266
267+ def get_sandbox_digest_list (self ) -> list [str ] | None :
268+ """
269+ Convert self.sandbox_digests into a list, where each index matches the
270+ corresponding index in self.sandboxes.
271+ """
272+ if not self .sandbox_digests :
273+ return None
274+ res : list [str | None ] = [None ] * len (self .sandboxes )
275+ for k ,v in self .sandbox_digests .items ():
276+ if k in self .sandboxes :
277+ index = self .sandboxes .index (k )
278+ res [index ] = v
279+ else :
280+ logger .warning ("Have digest for unknown sandbox %s" , k )
281+ if None in res :
282+ ind = res .index (None )
283+ logger .warning ("Sandbox %s was not archived" , self .sandboxes [ind ])
284+ return None
285+ return res
286+
256287
257288class CompilationJob (Job ):
258289 """Job representing a compilation.
@@ -274,9 +305,11 @@ def __init__(
274305 shard : int | None = None ,
275306 keep_sandbox : bool = False ,
276307 sandboxes : list [str ] | None = None ,
308+ sandbox_digests : dict [str , str ] | None = None ,
277309 info : str | None = None ,
278310 language : str | None = None ,
279311 multithreaded_sandbox : bool = False ,
312+ archive_sandbox : bool = False ,
280313 files : dict [str , File ] | None = None ,
281314 managers : dict [str , Manager ] | None = None ,
282315 success : bool | None = None ,
@@ -296,9 +329,9 @@ def __init__(
296329 """
297330
298331 Job .__init__ (self , operation , task_type , task_type_parameters ,
299- language , multithreaded_sandbox ,
300- shard , keep_sandbox , sandboxes , info , success , text ,
301- files , managers , executables )
332+ language , multithreaded_sandbox , archive_sandbox ,
333+ shard , keep_sandbox , sandboxes , sandbox_digests , info , success ,
334+ text , files , managers , executables )
302335 self .compilation_success = compilation_success
303336 self .plus = plus
304337
@@ -341,6 +374,7 @@ def from_submission(
341374 task_type_parameters = dataset .task_type_parameters ,
342375 language = submission .language ,
343376 multithreaded_sandbox = multithreaded ,
377+ archive_sandbox = operation .archive_sandbox ,
344378 files = dict (submission .files ),
345379 managers = dict (dataset .managers ),
346380 info = "compile submission %d" % (submission .id )
@@ -367,7 +401,8 @@ def to_submission(self, sr: SubmissionResult):
367401 self .plus .get ('execution_wall_clock_time' )
368402 sr .compilation_memory = self .plus .get ('execution_memory' )
369403 sr .compilation_shard = self .shard
370- sr .compilation_sandbox = ":" .join (self .sandboxes )
404+ sr .compilation_sandbox_paths = self .sandboxes
405+ sr .compilation_sandbox_digests = self .get_sandbox_digest_list ()
371406 for executable in self .executables .values ():
372407 sr .executables .set (executable )
373408
@@ -431,6 +466,7 @@ def from_user_test(
431466 task_type_parameters = dataset .task_type_parameters ,
432467 language = user_test .language ,
433468 multithreaded_sandbox = multithreaded ,
469+ archive_sandbox = operation .archive_sandbox ,
434470 files = dict (user_test .files ),
435471 managers = managers ,
436472 info = "compile user test %d" % (user_test .id )
@@ -457,7 +493,8 @@ def to_user_test(self, ur: UserTestResult):
457493 self .plus .get ('execution_wall_clock_time' )
458494 ur .compilation_memory = self .plus .get ('execution_memory' )
459495 ur .compilation_shard = self .shard
460- ur .compilation_sandbox = ":" .join (self .sandboxes )
496+ ur .compilation_sandbox_paths = self .sandboxes
497+ ur .compilation_sandbox_digests = self .get_sandbox_digest_list ()
461498 for executable in self .executables .values ():
462499 u_executable = UserTestExecutable (
463500 executable .filename , executable .digest )
@@ -485,9 +522,11 @@ def __init__(
485522 shard : int | None = None ,
486523 keep_sandbox : bool = False ,
487524 sandboxes : list [str ] | None = None ,
525+ sandbox_digests : dict [str , str ] | None = None ,
488526 info : str | None = None ,
489527 language : str | None = None ,
490528 multithreaded_sandbox : bool = False ,
529+ archive_sandbox : bool = False ,
491530 files : dict [str , File ] | None = None ,
492531 managers : dict [str , Manager ] | None = None ,
493532 executables : dict [str , Executable ] | None = None ,
@@ -526,9 +565,9 @@ def __init__(
526565
527566 """
528567 Job .__init__ (self , operation , task_type , task_type_parameters ,
529- language , multithreaded_sandbox ,
530- shard , keep_sandbox , sandboxes , info , success , text ,
531- files , managers , executables )
568+ language , multithreaded_sandbox , archive_sandbox ,
569+ shard , keep_sandbox , sandboxes , sandbox_digests , info , success ,
570+ text , files , managers , executables )
532571 self .input = input
533572 self .output = output
534573 self .time_limit = time_limit
@@ -592,6 +631,7 @@ def from_submission(
592631 task_type_parameters = dataset .task_type_parameters ,
593632 language = submission .language ,
594633 multithreaded_sandbox = multithreaded ,
634+ archive_sandbox = operation .archive_sandbox ,
595635 files = dict (submission .files ),
596636 managers = dict (dataset .managers ),
597637 executables = dict (submission_result .executables ),
@@ -619,7 +659,8 @@ def to_submission(self, sr: SubmissionResult):
619659 'execution_wall_clock_time' ),
620660 execution_memory = self .plus .get ('execution_memory' ),
621661 evaluation_shard = self .shard ,
622- evaluation_sandbox = ":" .join (self .sandboxes ),
662+ evaluation_sandbox_paths = self .sandboxes ,
663+ evaluation_sandbox_digests = self .get_sandbox_digest_list (),
623664 testcase = sr .dataset .testcases [self .operation .testcase_codename ])]
624665
625666 @staticmethod
@@ -674,6 +715,7 @@ def from_user_test(
674715 task_type_parameters = dataset .task_type_parameters ,
675716 language = user_test .language ,
676717 multithreaded_sandbox = multithreaded ,
718+ archive_sandbox = operation .archive_sandbox ,
677719 files = dict (user_test .files ),
678720 managers = managers ,
679721 executables = dict (user_test_result .executables ),
@@ -704,7 +746,8 @@ def to_user_test(self, ur: UserTestResult):
704746 self .plus .get ('execution_wall_clock_time' )
705747 ur .execution_memory = self .plus .get ('execution_memory' )
706748 ur .evaluation_shard = self .shard
707- ur .evaluation_sandbox = ":" .join (self .sandboxes )
749+ ur .evaluation_sandbox_paths = self .sandboxes
750+ ur .evaluation_sandbox_digests = self .get_sandbox_digest_list ()
708751 ur .output = self .user_output
709752
710753
0 commit comments