Search in sources :

Example 11 with Win32Exception

use of jnc.platform.win32.Win32Exception in project judge by zjnu-acm.

the class JudgeRunnerImpl method run.

@Override
public RunResult run(RunRecord runRecord, Path workDirectory, JudgeData judgeData, Validator validator, boolean cleanDirectory) {
    Objects.requireNonNull(runRecord);
    Objects.requireNonNull(workDirectory);
    try {
        RunResult.Builder builder = RunResult.builder();
        String source = runRecord.getSource();
        if (!StringUtils.hasLength(source)) {
            return builder.type(Status.COMPILATION_ERROR).compileInfo("empty source file").build();
        }
        final String main = "Main";
        Files.createDirectories(workDirectory);
        Language language = runRecord.getLanguage();
        // 源码码文件
        Path sourceFile = workDirectory.resolve(main + "." + language.getSourceExtension());
        Files.write(sourceFile, source.getBytes(Platform.getCharset()));
        String compileCommand = language.getCompileCommand();
        log.debug("Compile Command: {}", compileCommand);
        if (StringUtils.hasText(compileCommand)) {
            // create compiling process
            // VC++ will output compiling info to stdout
            // G++ will output compiling info to stderr
            Path compileInfo = workDirectory.resolve("compileInfo.txt");
            @SuppressWarnings("null") Process process = ProcessCreationHelper.execute(new ProcessBuilder(compileCommand.split("\\s+")).directory(workDirectory.toFile()).redirectInput(ProcessBuilder.Redirect.from(NULL_FILE)).redirectOutput(compileInfo.toFile()).redirectErrorStream(true)::start);
            try {
                process.waitFor(1, TimeUnit.MINUTES);
            } catch (InterruptedException ex) {
                process.destroy();
                throw new InterruptedIOException();
            }
            // export compiling information
            String errorInfo;
            if (process.isAlive()) {
                process.destroyForcibly();
                try {
                    process.waitFor();
                } catch (InterruptedException ex) {
                    throw new InterruptedIOException();
                }
                errorInfo = "Compile timeout\nOutput:\n" + collectLines(compileInfo);
            } else {
                errorInfo = collectLines(compileInfo);
            }
            builder.compileInfo(errorInfo);
            log.debug("errorInfo = {}", errorInfo);
            // The executable file after compiling
            Path executable = workDirectory.resolve(main + "." + language.getExecutableExtension());
            log.debug("executable = {}", executable);
            boolean compilePassed = Files.exists(executable);
            if (!compilePassed) {
                return builder.type(Status.COMPILATION_ERROR).build();
            }
        }
        int caseNum = judgeData.getCaseCount();
        ArrayList<String> details = new ArrayList<>(caseNum << 2);
        String command = language.getExecuteCommand();
        // executable command should be absolute
        command = StringUtils.hasText(command) ? command : workDirectory.toAbsolutePath().resolve("Main." + language.getExecutableExtension()).toString();
        long extTime = language.getExtTime();
        long castTimeLimit = runRecord.getTimeLimit() * language.getTimeFactor() + extTime;
        // 内存附加
        long extraMemory = language.getExtMemory();
        long caseMemoryLimit = (runRecord.getMemoryLimit() + extraMemory) * 1024;
        Option[] opts = new Option[caseNum];
        for (int cas = 0; cas < caseNum; cas++) {
            Path[] entry = judgeData.get(cas);
            Path in = entry[0];
            Path standard = entry[1];
            Path progOutput = workDirectory.resolve(standard.getFileName());
            opts[cas] = Option.builder().timeLimit(// time limit
            castTimeLimit).memoryLimit(// memory in bytes
            caseMemoryLimit).outputLimit(// 16M
            16 * 1024 * 1024).command(command).workDirectory(workDirectory).inputFile(in).outputFile(progOutput).standardOutput(standard).errFile(NULL_FILE.toPath()).build();
        }
        String scorePerCase = new DecimalFormat("0.#").format(100.0 / caseNum);
        final ExecuteResult[] ers;
        try {
            ers = judgeBridge.judge(opts, false, validator);
        } catch (NotExecutableException ex) {
            // original command
            if (!StringUtils.hasText(language.getExecuteCommand())) {
                String msg = "fail to execute the binary file";
                Win32Exception cause = ex.getCause();
                if (cause != null) {
                    msg = msg + ": " + cause.getMessage();
                }
                return builder.type(Status.COMPILATION_ERROR).detail(msg).build();
            }
            throw ex.getCause();
        }
        long time = 0;
        long memory = 0;
        // final case whose result is accepted.
        int accept = 0;
        for (ExecuteResult er : ers) {
            long tim1 = Math.max(0, er.getTime() - extTime);
            long mem1 = Math.max(0, er.getMemory() / 1024 - extraMemory);
            String message = er.getMessage();
            boolean success = er.isSuccess();
            time = Math.max(time, tim1);
            memory = Math.max(memory, mem1);
            log.debug("message = {}, time = {}, memory = {}", message, time, memory);
            details.add(String.valueOf(er.getCode().getResult()));
            details.add(success ? scorePerCase : "0");
            details.add(String.valueOf(tim1));
            details.add(String.valueOf(mem1));
            if (success) {
                ++accept;
            }
        }
        log.debug("{}", details);
        int score = accept >= 0 ? (int) Math.round(accept * 100.0 / caseNum) : accept;
        if (score == 0 && accept != 0) {
            ++score;
        } else if (score == 100 && accept != caseNum) {
            --score;
        }
        String msg = details.stream().map(String::valueOf).collect(Collectors.joining(","));
        return builder.score(score).time(time).memory(memory).detail(msg).build();
    } catch (IOException ex) {
        throw new UncheckedIOException(ex);
    } finally {
        if (cleanDirectory) {
            delete(workDirectory);
        }
    }
}
Also used : InterruptedIOException(java.io.InterruptedIOException) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) UncheckedIOException(java.io.UncheckedIOException) Language(cn.edu.zjnu.acm.judge.domain.Language) ExecuteResult(cn.edu.zjnu.acm.judge.core.ExecuteResult) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) Path(java.nio.file.Path) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) Win32Exception(jnc.platform.win32.Win32Exception) NotExecutableException(cn.edu.zjnu.acm.judge.core.NotExecutableException) Option(cn.edu.zjnu.acm.judge.core.Option)

Aggregations

Win32Exception (com.sun.jna.platform.win32.Win32Exception)7 DebuggableException (com.github.mob41.organdebug.exceptions.DebuggableException)3 IOException (java.io.IOException)3 NotExecutableException (cn.edu.zjnu.acm.judge.core.NotExecutableException)2 Memory (com.sun.jna.Memory)2 File (java.io.File)2 ArrayList (java.util.ArrayList)2 Win32Exception (jnc.platform.win32.Win32Exception)2 JoranException (ch.qos.logback.core.joran.spi.JoranException)1 ExecuteResult (cn.edu.zjnu.acm.judge.core.ExecuteResult)1 Option (cn.edu.zjnu.acm.judge.core.Option)1 Language (cn.edu.zjnu.acm.judge.domain.Language)1 RunResult (cn.edu.zjnu.acm.judge.support.RunResult)1 UserModel (com.gitblit.models.UserModel)1 EXPLICIT_ACCESS (com.github.zhanhb.jnc.platform.win32.EXPLICIT_ACCESS)1 NO_MULTIPLE_TRUSTEE (com.github.zhanhb.jnc.platform.win32.MULTIPLE_TRUSTEE_OPERATION.NO_MULTIPLE_TRUSTEE)1 TRUSTEE (com.github.zhanhb.jnc.platform.win32.TRUSTEE)1 Win32Exception (com.github.zhanhb.jnc.platform.win32.Win32Exception)1 Pointer (com.sun.jna.Pointer)1 VS_FIXEDFILEINFO (com.sun.jna.platform.win32.VerRsrc.VS_FIXEDFILEINFO)1