@@ -22,7 +22,7 @@ class JudgeDaemon
2222{
2323 private static ?JudgeDaemon $ instance = null ;
2424
25- private array $ endpoints = [] ;
25+ private ? array $ endpoint = null ;
2626 private array $ domjudge_config = [];
2727 private string $ myhost ;
2828 private int $ verbose = LOG_INFO ;
@@ -35,8 +35,6 @@ class JudgeDaemon
3535 private ?string $ lastrequest = '' ;
3636 private float $ waittime = self ::INITIAL_WAITTIME_SEC ;
3737
38- private ?string $ endpointID = null ;
39-
4038 private array $ langexts = [];
4139
4240 private $ lockfile ;
@@ -221,10 +219,7 @@ private function initialize(): void
221219 error ("chroot validation check failed " );
222220 }
223221
224- foreach (array_keys ($ this ->endpoints ) as $ id ) {
225- $ this ->endpointID = $ id ;
226- $ this ->registerJudgehost ();
227- }
222+ $ this ->registerJudgehost ();
228223
229224 // Populate the DOMjudge configuration initially
230225 $ this ->djconfigRefresh ();
@@ -248,34 +243,21 @@ private function initialize(): void
248243
249244 private function loop (): void
250245 {
251- $ endpointIDs = array_keys ($ this ->endpoints );
252- $ currentEndpoint = 0 ;
253246 $ lastWorkdir = null ;
247+ $ workdirpath = JUDGEDIR . "/ $ this ->myhost /endpoint- " . $ this ->endpoint ['id ' ];
248+
254249 while (true ) {
255- // If all endpoints are waiting, sleep for a bit.
256- $ dosleep = true ;
257- foreach ($ this ->endpoints as $ id => $ endpoint ) {
258- if ($ endpoint ['errorred ' ]) {
259- $ this ->endpointID = $ id ;
260- $ this ->registerJudgehost ();
261- }
262- if (!$ endpoint ['waiting ' ]) {
263- $ dosleep = false ;
264- $ this ->waittime = self ::INITIAL_WAITTIME_SEC ;
265- break ;
266- }
250+ if ($ this ->endpoint ['errorred ' ]) {
251+ $ this ->registerJudgehost ();
267252 }
268- // Sleep only if everything is "waiting" and only if we're looking at the first endpoint again.
269- if ($ dosleep && $ currentEndpoint == 0 ) {
253+
254+ if ($ this -> endpoint [ ' waiting ' ] ) {
270255 dj_sleep ($ this ->waittime );
271256 $ this ->waittime = min ($ this ->waittime * 2 , self ::MAXIMAL_WAITTIME_SEC );
257+ } else {
258+ $ this ->waittime = self ::INITIAL_WAITTIME_SEC ;
272259 }
273260
274- // Cycle through endpoints.
275- $ currentEndpoint = ($ currentEndpoint + 1 ) % count ($ this ->endpoints );
276- $ this ->endpointID = $ endpointIDs [$ currentEndpoint ];
277- $ workdirpath = JUDGEDIR . "/ $ this ->myhost /endpoint- $ this ->endpointID " ;
278-
279261 // Check whether we have received an exit signal
280262 if (function_exists ('pcntl_signal_dispatch ' )) {
281263 pcntl_signal_dispatch ();
@@ -308,12 +290,12 @@ private function loop(): void
308290 exit ;
309291 }
310292
311- if ($ this ->endpoints [ $ this -> endpointID ] ['errorred ' ]) {
293+ if ($ this ->endpoint ['errorred ' ]) {
312294 continue ;
313295 }
314296
315297
316- if ($ this ->endpoints [ $ this -> endpointID ] ['waiting ' ] === false ) {
298+ if ($ this ->endpoint ['waiting ' ] === false ) {
317299 $ this ->checkDiskSpace ($ workdirpath );
318300 }
319301
@@ -330,13 +312,13 @@ private function loop(): void
330312
331313 // Nothing returned -> no open work for us.
332314 if (empty ($ row )) {
333- if (!$ this ->endpoints [ $ this -> endpointID ] ["waiting " ]) {
334- $ this ->endpoints [ $ this -> endpointID ] ["waiting " ] = true ;
315+ if (!$ this ->endpoint ["waiting " ]) {
316+ $ this ->endpoint ["waiting " ] = true ;
335317 if ($ lastWorkdir !== null ) {
336318 $ this ->cleanupJudging ($ lastWorkdir );
337319 $ lastWorkdir = null ;
338320 }
339- logmsg (LOG_INFO , "No submissions in queue (for endpoint $ this ->endpointID ), waiting... " );
321+ logmsg (LOG_INFO , "No submissions in queue (for endpoint " . $ this ->endpoint [ ' id ' ] . " ), waiting... " );
340322 $ judgehosts = $ this ->request ('judgehosts ' , 'GET ' );
341323 if ($ judgehosts !== null ) {
342324 $ judgehosts = dj_json_decode ($ judgehosts );
@@ -350,7 +332,7 @@ private function loop(): void
350332 }
351333
352334 // We have gotten a work packet.
353- $ this ->endpoints [ $ this -> endpointID ] ["waiting " ] = false ;
335+ $ this ->endpoint ["waiting " ] = false ;
354336
355337 // All tasks are guaranteed to be of the same type.
356338 // If $row is empty, we already continued.
@@ -542,16 +524,16 @@ private function handlePrefetchTask(array $row, ?string &$lastWorkdir, string $w
542524 private function handleTask (string $ type , array $ row , ?string &$ lastWorkdir , string $ workdirpath ): void
543525 {
544526 if ($ type == 'try_again ' ) {
545- if (!$ this ->endpoints [ $ this -> endpointID ] ['retrying ' ]) {
527+ if (!$ this ->endpoint ['retrying ' ]) {
546528 logmsg (LOG_INFO , "API indicated to retry fetching work (this might take a while to clean up). " );
547529 }
548- $ this ->endpoints [ $ this -> endpointID ] ['retrying ' ] = true ;
530+ $ this ->endpoint ['retrying ' ] = true ;
549531 return ;
550532 }
551- $ this ->endpoints [ $ this -> endpointID ] ['retrying ' ] = false ;
533+ $ this ->endpoint ['retrying ' ] = false ;
552534
553535 logmsg (LOG_INFO ,
554- "⇝ Received " . sizeof ($ row ) . " ' " . $ type . "' judge tasks (endpoint $ this ->endpointID ) " );
536+ "⇝ Received " . sizeof ($ row ) . " ' " . $ type . "' judge tasks (endpoint " . $ this ->endpoint [ ' id ' ] . " ) " );
555537
556538 if ($ type == 'prefetch ' ) {
557539 $ this ->handlePrefetchTask ($ row , $ lastWorkdir , $ workdirpath );
@@ -657,10 +639,12 @@ private function readCredentials(): void
657639 error ("Error parsing REST API credentials. Invalid format in line $ lineno. " );
658640 }
659641 [$ endpointID , $ resturl , $ restuser , $ restpass ] = $ items ;
660- if (array_key_exists ($ endpointID , $ this ->endpoints )) {
661- error ("Error parsing REST API credentials. Duplicate endpoint ID ' $ endpointID' in line $ lineno. " );
642+
643+ if ($ this ->endpoint !== null ) {
644+ error ("Error parsing REST API credentials. Multiple endpoints are not supported. " );
662645 }
663- $ this ->endpoints [$ endpointID ] = [
646+ $ this ->endpoint = [
647+ "id " => $ endpointID ,
664648 "url " => $ resturl ,
665649 "user " => $ restuser ,
666650 "pass " => $ restpass ,
@@ -670,7 +654,7 @@ private function readCredentials(): void
670654 "retrying " => false ,
671655 ];
672656 }
673- if (count ( $ this ->endpoints ) <= 0 ) {
657+ if ($ this ->endpoint === null ) {
674658 error ("Error parsing REST API credentials: no endpoints found. " );
675659 }
676660 }
@@ -687,11 +671,9 @@ private function setupCurlHandle(string $restuser, string $restpass): \CurlHandl
687671
688672 private function closeCurlHandles (): void
689673 {
690- foreach ($ this ->endpoints as $ id => $ endpoint ) {
691- if (!empty ($ endpoint ['ch ' ])) {
692- curl_close ($ endpoint ['ch ' ]);
693- unset($ this ->endpoints [$ id ]['ch ' ]);
694- }
674+ if (!empty ($ this ->endpoint ['ch ' ])) {
675+ curl_close ($ this ->endpoint ['ch ' ]);
676+ unset($ this ->endpoint ['ch ' ]);
695677 }
696678 }
697679
@@ -708,8 +690,8 @@ private function request(string $url, string $verb = 'GET', $data = '', bool $fa
708690 $ this ->lastrequest = $ url ;
709691 }
710692
711- $ requestUrl = $ this ->endpoints [ $ this -> endpointID ] ['url ' ] . "/ " . $ url ;
712- $ curl_handle = $ this ->endpoints [ $ this -> endpointID ] ['ch ' ];
693+ $ requestUrl = $ this ->endpoint ['url ' ] . "/ " . $ url ;
694+ $ curl_handle = $ this ->endpoint ['ch ' ];
713695 if ($ verb == 'GET ' ) {
714696 $ requestUrl .= '? ' . $ data ;
715697 }
@@ -778,15 +760,15 @@ private function request(string $url, string $verb = 'GET', $data = '', bool $fa
778760 error ($ errstr );
779761 } else {
780762 warning ($ errstr );
781- $ this ->endpoints [ $ this -> endpointID ] ['errorred ' ] = true ;
763+ $ this ->endpoint ['errorred ' ] = true ;
782764 return null ;
783765 }
784766 }
785767
786- if ($ this ->endpoints [ $ this -> endpointID ] ['errorred ' ]) {
787- $ this ->endpoints [ $ this -> endpointID ] ['errorred ' ] = false ;
788- $ this ->endpoints [ $ this -> endpointID ] ['waiting ' ] = false ;
789- logmsg (LOG_NOTICE , "Reconnected to endpoint $ this ->endpointID . " );
768+ if ($ this ->endpoint ['errorred ' ]) {
769+ $ this ->endpoint ['errorred ' ] = false ;
770+ $ this ->endpoint ['waiting ' ] = false ;
771+ logmsg (LOG_NOTICE , "Reconnected to endpoint " . $ this ->endpoint [ ' id ' ] . " . " );
790772 }
791773
792774 return $ response ;
@@ -1083,7 +1065,7 @@ private function fetchExecutableInternal(
10831065
10841066 private function registerJudgehost (): void
10851067 {
1086- $ endpoint = &$ this ->endpoints [ $ this -> endpointID ] ;
1068+ $ endpoint = &$ this ->endpoint ;
10871069
10881070 // Only try to register every 30s.
10891071 $ now = time ();
@@ -1093,11 +1075,11 @@ private function registerJudgehost(): void
10931075 }
10941076 $ endpoint ['last_attempt ' ] = $ now ;
10951077
1096- logmsg (LOG_NOTICE , "Registering judgehost on endpoint $ this ->endpointID : " . $ endpoint ['url ' ]);
1097- $ this ->endpoints [ $ this -> endpointID ] ['ch ' ] = $ this ->setupCurlHandle ($ endpoint ['user ' ], $ endpoint ['pass ' ]);
1078+ logmsg (LOG_NOTICE , "Registering judgehost on endpoint " . $ this ->endpoint [ ' id ' ] . " : " . $ endpoint ['url ' ]);
1079+ $ this ->endpoint ['ch ' ] = $ this ->setupCurlHandle ($ endpoint ['user ' ], $ endpoint ['pass ' ]);
10981080
10991081 // Create directory where to test submissions
1100- $ workdirpath = JUDGEDIR . "/ $ this ->myhost /endpoint- $ this ->endpointID " ;
1082+ $ workdirpath = JUDGEDIR . "/ $ this ->myhost /endpoint- " . $ this ->endpoint [ ' id ' ] ;
11011083 if (!$ this ->runCommandSafe (['mkdir ' , '-p ' , "$ workdirpath/testcase " ])) {
11021084 error ("Could not create $ workdirpath " );
11031085 }
@@ -1108,7 +1090,7 @@ private function registerJudgehost(): void
11081090 // they have and will not be finished. Give them back.
11091091 $ unfinished = $ this ->request ('judgehosts ' , 'POST ' , ['hostname ' => urlencode ($ this ->myhost )], false );
11101092 if ($ unfinished === null ) {
1111- logmsg (LOG_WARNING , "Registering judgehost on endpoint $ this ->endpointID failed. " );
1093+ logmsg (LOG_WARNING , "Registering judgehost on endpoint " . $ this ->endpoint [ ' id ' ] . " failed. " );
11121094 } else {
11131095 $ unfinished = dj_json_decode ($ unfinished );
11141096 foreach ($ unfinished as $ jud ) {
@@ -1683,8 +1665,8 @@ private function reportJudgingRun(array $judgeTask, array $new_judging_run, bool
16831665
16841666 // The child should use its own curl handle to avoid issues with sharing handles
16851667 // between processes.
1686- $ endpoint = $ this ->endpoints [ $ this -> endpointID ] ;
1687- $ this ->endpoints [ $ this -> endpointID ] ['ch ' ] = $ this ->setupCurlHandle ($ endpoint ['user ' ], $ endpoint ['pass ' ]);
1668+ $ endpoint = $ this ->endpoint ;
1669+ $ this ->endpoint ['ch ' ] = $ this ->setupCurlHandle ($ endpoint ['user ' ], $ endpoint ['pass ' ]);
16881670 }
16891671 } elseif ($ asynchronous ) {
16901672 logmsg (LOG_WARNING , "pcntl extension not available, reporting result for jt $ judgeTaskId synchronously. " );
0 commit comments