Skip to content

Commit

Permalink
Merge pull request pc2ccs#1000 from johnbrvc/i999_execute_grace_period
Browse files Browse the repository at this point in the history
Two approvals.  Code has low impact on the system.  Tested with multiple contests.
  • Loading branch information
johnbrvc authored Aug 27, 2024
2 parents b76eea2 + 43c0f16 commit fcdc36f
Show file tree
Hide file tree
Showing 11 changed files with 449 additions and 98 deletions.
52 changes: 31 additions & 21 deletions src/edu/csus/ecs/pc2/core/execute/Executable.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,6 @@ public class Executable extends Plugin implements IExecutable, IExecutableNotify

private static final long NANOSECS_PER_MILLISEC = 1_000_000;

/**
* Sandbox constants
*/
public static final long SANDBOX_EXTRA_KILLTIME_MS = 5000;

/**
* Return codes from sandbox
*/
Expand Down Expand Up @@ -1829,8 +1824,29 @@ protected boolean executeProgram(int dataSetNumber) {
log.log(Log.INFO, "Executing run " + run.getNumber() + " from " + run.getSubmitter().getTripletKey() + " test set " + testSetNumber);
}

log.info("Constructing ExecuteTimer...");
executionTimer = new ExecuteTimer(log, problem.getTimeOutInSeconds(), executorId, isUsingGUI() ? executionMonitor : null);

//determine whether the Problem is configured to use a sandbox
usingSandbox = isUsingSandbox();

//set the TLE kill task delay and ExecuteTimer delay to the number of seconds allowed by the problem
int delaySecs = problem.getTimeOutInSeconds();

if(usingSandbox) {
ContestInformation contestInfo = contest.getContestInformation();

//add ample extra time for interactive problems due to overhead the Primary may have in logging; also
//interactive validators may spend time too.
if(problem.isInteractive()) {
delaySecs = delaySecs * contestInfo.getSandboxInteractiveGraceMultiplier();
log.info ("multiplying time limit by " + contestInfo.getSandboxInteractiveGraceMultiplier() + " for interactive problem: " +
problem.getTimeOutInSeconds() + "secs -> " + delaySecs);
} else {
log.info ("adding " + contestInfo.getSandboxGraceTimeSecs() + " sec delay to TLE-Timer for sandbox");
delaySecs += contestInfo.getSandboxGraceTimeSecs();
}
}
log.info("Constructing ExecuteTimer of " + delaySecs + " seconds...");
executionTimer = new ExecuteTimer(log, delaySecs, executorId, isUsingGUI() ? executionMonitor : null);
log.info("Created new ExecuteTimer: " + executionTimer.toString());

if (problem.getDataFileName() != null) {
Expand Down Expand Up @@ -1961,9 +1977,6 @@ protected boolean executeProgram(int dataSetNumber) {

}

//determine whether the Problem is configured to use a sandbox
usingSandbox = isUsingSandbox();

// we do not do sandboxes or interactive for test runs
if(!isTestRunOnly()) {
if(usingSandbox) {
Expand Down Expand Up @@ -2055,7 +2068,7 @@ protected boolean executeProgram(int dataSetNumber) {

//We do NOT disable the ExecutionTimer here for sandbox mode as the original comment suggests.
// The reason is, we use the ExecutionTimer as a watchdog in the event that the sandbox script hangs for some reason.
// We do bump the time up limit up a bit, though, so it doesn't prematurely terminate the run. JB 05/03/2023
// We do bump the time up limit up a bit (see delaySecs above), though, so it doesn't prematurely terminate the run. JB 05/03/2023
//
//if a sandbox is being used, disable both the ExecutionTimer's actionPerformed() ability to stop the process
// as well as the TimerTask's ability to stop the process
Expand Down Expand Up @@ -2119,19 +2132,15 @@ public void run() {
}
};

//set the TLE kill task delay to the number of milliseconds allowed by the problem
long delay = problem.getTimeOutInSeconds() * 1000 ;

if(usingSandbox) {
log.info ("adding " + SANDBOX_EXTRA_KILLTIME_MS + " msec delay to TLE-Timer for sandbox");
delay += SANDBOX_EXTRA_KILLTIME_MS;
}
// this is how long the timers are set for. If running in a sandbox, TLE is handled by the sandbox,
// and this time represents wall time pc2 will wait. If not in a sandbox, this is the problem time limit.
long delayMs = delaySecs * 1000;

//schedule the TLE kill task with the Timer -- but only for judged runs (i.e., non-team runs)
// and only when we're not using a sandbox (which will handle time limit within the sandbox)
if (autoStop) {
log.info ("scheduling kill task with TLE-Timer with " + delay + " msec delay");
timeLimitKillTimer.schedule(task, delay);
log.info ("scheduling kill task with TLE-Timer with " + delayMs + " msec delay");
timeLimitKillTimer.schedule(task, delayMs);
}

// TODO: Future investigation: The IOCollectors are probably not needed for interactive problems since
Expand Down Expand Up @@ -2240,7 +2249,8 @@ public void run() {
executionData.setExecuteExitValue(exitCode);
executionData.setExecuteTimeMS(getExecutionTimeInMSecs());

boolean runTimeLimitWasExceeded = getExecutionTimeInMSecs() > problem.getTimeOutInSeconds()*1000 ;
//delaySecs represents wall time for sandbox submissions, and cpu time for non-sandbox submissions.
boolean runTimeLimitWasExceeded = getExecutionTimeInMSecs() > delayMs ;
executionData.setRunTimeLimitExceeded(runTimeLimitWasExceeded);

/**
Expand Down
53 changes: 53 additions & 0 deletions src/edu/csus/ecs/pc2/core/list/AlphaNumericComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (C) 1989-2024 PC2 Development Team: John Clevenger, Douglas Lane, Samir Ashoo, and Troy Boudreau.
package edu.csus.ecs.pc2.core.list;

import java.io.Serializable;
import java.util.Comparator;

/**
* Compare the two strings as numbers
* <P>
* Compare things that may be words or numbers
*
* @author John Buck
*/

// $HeadURL$
// $Id$

public class AlphaNumericComparator implements Comparator<String>, Serializable {

private static final long serialVersionUID = 1L;

@Override
public int compare(String ValOne, String ValTwo) {
boolean b1Alpha = false;
boolean b2Alpha = false;
int cmpVal1 = 0;
int cmpVal2 = 0;

try {
cmpVal1 = Integer.parseInt(ValOne);
} catch(Exception exception) {
b1Alpha = true;
}
try {
cmpVal2 = Integer.parseInt(ValTwo);
} catch(Exception exception) {
b2Alpha = true;
}
if(b1Alpha) {
// If both are alpha, then just compare the strings.
if(b2Alpha) {
return(ValOne.compareToIgnoreCase(ValTwo));
}
// ValTwo is a number, and it comes before the alpha
return(1);
}
if(b2Alpha) {
// ValOne is a number, it comes before the alpha string
return(-1);
}
return(cmpVal1 - cmpVal2);
}
}
64 changes: 64 additions & 0 deletions src/edu/csus/ecs/pc2/core/list/LabelToDoubleComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (C) 1989-2024 PC2 Development Team: John Clevenger, Douglas Lane, Samir Ashoo, and Troy Boudreau.
package edu.csus.ecs.pc2.core.list;

import java.io.Serializable;
import java.util.Comparator;

import javax.swing.JLabel;

/**
* Compare the two strings as numbers
* <P>
* Simply convert to integers and compare
*
* @version $Id$
* @author John Buck
*/

// $HeadURL$
// $Id$

public class LabelToDoubleComparator implements Comparator<JLabel>, Serializable {

private static final long serialVersionUID = 1L;

@Override
public int compare(JLabel LabOne, JLabel LabTwo) {
String valOne = LabOne.getText();
String valTwo = LabTwo.getText();
boolean b1Alpha = false;
boolean b2Alpha = false;
double cmpVal1 = 0;
double cmpVal2 = 0;

try {
cmpVal1 = Double.parseDouble(valOne);
} catch(Exception exception) {
b1Alpha = true;
}
try {
cmpVal2 = Double.parseDouble(valTwo);
} catch(Exception exception) {
b2Alpha = true;
}
if(b1Alpha) {
// If both are alpha, then just compare the strings.
if(b2Alpha) {
return(valOne.compareToIgnoreCase(valTwo));
}
// ValTwo is a number, and it comes before the alpha
return(1);
}
if(b2Alpha) {
// ValOne is a number, it comes before the alpha string
return(-1);
}
double dResult = cmpVal1 - cmpVal2;
if(dResult < 0) {
return(-1);
} else if(dResult > 0) {
return(1);
}
return(0);
}
}
38 changes: 0 additions & 38 deletions src/edu/csus/ecs/pc2/core/list/StringToDoubleComparator.java

This file was deleted.

27 changes: 27 additions & 0 deletions src/edu/csus/ecs/pc2/core/model/ContestInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public class ContestInformation implements Serializable{
*/
public static final int DEFAULT_FREEZE_MINUTES = 60;

/**
* Default Sandbox grace time constants
*/
public static final int SANDBOX_GRACE_TIME_SECS = 1;
public static final int SANDBOX_INTERACTIVE_MULTIPLIER = 3;

private String contestTitle = "Programming Contest";

private String contestURL;
Expand Down Expand Up @@ -97,6 +103,11 @@ public class ContestInformation implements Serializable{
private String teamScoreboardDisplayFormat = ScoreboardVariableReplacer.TEAM_NAME;

/**
* Grace time constants to adjust Executable timers
*/
private int sandboxGraceTimeSecs = SANDBOX_GRACE_TIME_SECS;
private int sandboxInteractiveGraceMultiplier = SANDBOX_INTERACTIVE_MULTIPLIER;
/*
* String to append to the execute folder for judged runs. May contain substitution strings.
*/
private String executeFolder = "";
Expand Down Expand Up @@ -870,4 +881,20 @@ public void setLoadSampleJudgesData(boolean loadSampleJudgesData) {
this.loadSampleJudgesData = loadSampleJudgesData;
}

public int getSandboxGraceTimeSecs() {
return(sandboxGraceTimeSecs);
}

public void setSandboxGraceTimeSecs(int nSecs) {
sandboxGraceTimeSecs = nSecs;
}

public int getSandboxInteractiveGraceMultiplier() {
return(sandboxInteractiveGraceMultiplier);
}

public void setSandboxInteractiveGraceMultiplier(int nSecs) {
sandboxInteractiveGraceMultiplier = nSecs;
}

}
6 changes: 5 additions & 1 deletion src/edu/csus/ecs/pc2/core/model/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,9 @@ public String toString() {
if (filteringGroups) {
filterInfo += " groups(s)";
}
if (filteringCustom) {
filterInfo += " custom";
}

return filterInfo;
} else {
Expand Down Expand Up @@ -1373,7 +1376,8 @@ public boolean isFilterOn() {
|| filteringJudgements || filteringLanguages || filteringElapsedTime || filteringRunStates
|| filteringPermissions
|| thisSiteOnly
|| filteringGroups;
|| filteringGroups
|| filteringCustom;
} else {
return false;
}
Expand Down
34 changes: 34 additions & 0 deletions src/edu/csus/ecs/pc2/imports/ccs/ContestSnakeYAMLLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,28 @@ private void setMemoryLimitMB(IInternalContest contest, int memoryLimitMB) {
contest.updateContestInformation(contestInformation);
}

private int getSandboxGraceTimeSecs(IInternalContest contest) {
ContestInformation contestInformation = contest.getContestInformation();
return(contestInformation.getSandboxGraceTimeSecs());
}

private void setSandboxGraceTimeSecs(IInternalContest contest, int graceTime) {
ContestInformation contestInformation = contest.getContestInformation();
contestInformation.setSandboxGraceTimeSecs(graceTime);;
contest.updateContestInformation(contestInformation);
}

private int getSandboxInteractiveTimeMultiplier(IInternalContest contest) {
ContestInformation contestInformation = contest.getContestInformation();
return(contestInformation.getSandboxInteractiveGraceMultiplier());
}

private void setSandboxInteractiveTimeMultiplier(IInternalContest contest, int mult) {
ContestInformation contestInformation = contest.getContestInformation();
contestInformation.setSandboxInteractiveGraceMultiplier(mult);
contest.updateContestInformation(contestInformation);
}


private void setCcsTestMode(IInternalContest contest, boolean ccsTestMode) {
ContestInformation contestInformation = contest.getContestInformation();
Expand Down Expand Up @@ -504,6 +526,18 @@ public IInternalContest fromYaml(IInternalContest contest, String[] yamlLines, S
setMemoryLimitMB(contest, globalMemoryLimit);
}

int currentSandboxGraceTime = getSandboxGraceTimeSecs(contest);
Integer sandboxGraceTime = fetchIntValue(content, SANDBOX_GRACE_TIME, currentSandboxGraceTime);
if(currentSandboxGraceTime != sandboxGraceTime) {
setSandboxGraceTimeSecs(contest, sandboxGraceTime);
}

int currentSandboxIntMult = getSandboxInteractiveTimeMultiplier(contest);
Integer sandboxIntMult = fetchIntValue(content, SANDBOX_INTERACTIVE_GRACE_MULTIPLIER, currentSandboxIntMult);
if(currentSandboxIntMult != sandboxIntMult) {
setSandboxInteractiveTimeMultiplier(contest, sandboxIntMult);
}

for (String line : yamlLines) {
if (line.startsWith(CLICS_CONTEST_NAME + DELIMIT) || line.startsWith(CONTEST_NAME_KEY + DELIMIT)) {
setTitle(contest, unquoteAll(line.substring(line.indexOf(DELIMIT) + 1).trim()));
Expand Down
4 changes: 4 additions & 0 deletions src/edu/csus/ecs/pc2/imports/ccs/IContestLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ public interface IContestLoader {

String LOAD_ACCOUNTS_FILE_KEY = "load-accounts-file";

String SANDBOX_GRACE_TIME = "sandbox-grace-time-secs";

String SANDBOX_INTERACTIVE_GRACE_MULTIPLIER = "sandbox-interactive-time-multiplier";

/**
*
* @see ScoreboardVariableReplacer#substituteDisplayNameVariables(String, IInternalContest, edu.csus.ecs.pc2.core.model.Account)
Expand Down
2 changes: 1 addition & 1 deletion src/edu/csus/ecs/pc2/list/SubmissionSolutionList.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static List<String> getAllDirectoryEntries(String directory) {
* @return the acronym, or null if the folder is non-standard
*/
public String getAcronymForSubmissionDirectory(String dir) {
if(submissionDirectoryToAcronym.containsKey(dir)) {
if(dir != null && submissionDirectoryToAcronym.containsKey(dir)) {
return submissionDirectoryToAcronym.get(dir);
}
return null;
Expand Down
Loading

0 comments on commit fcdc36f

Please sign in to comment.