Skip to content

Commit

Permalink
Merge pull request #316 from blackav/315-implement-support-for-extend…
Browse files Browse the repository at this point in the history
…ed-compilation-status

315 implement support for extended compilation status
  • Loading branch information
blackav authored Apr 28, 2024
2 parents fcbdce8 + 6944a15 commit 8af6333
Show file tree
Hide file tree
Showing 32 changed files with 893 additions and 72 deletions.
6 changes: 4 additions & 2 deletions bin/ej-batch.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* -*- c -*- */

/* Copyright (C) 2010-2023 Alexander Chernov <[email protected]> */
/* Copyright (C) 2010-2024 Alexander Chernov <[email protected]> */

/*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -701,7 +701,9 @@ process_compile_packet(
0 /* inp_size*/,
NULL /* ure */,
NULL /* src_text*/,
0 /* src_size */);
0 /* src_size */,
NULL /* prop_text */,
0 /* prop_size */);
if (r < 0) abort();

return 0;
Expand Down
135 changes: 118 additions & 17 deletions bin/ej-compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ struct testinfo_subst_handler_compile
static int *lang_id_map = NULL;
static int lang_id_map_size = 0;

static const unsigned char PROP_SUFFIX[] = ".json";

static unsigned char *
subst_get_variable(
const void *vp,
Expand Down Expand Up @@ -236,7 +238,7 @@ invoke_style_checker(
}

// non-recursive
static int
static __attribute__((unused)) int
copy_all_files(
FILE *log_f,
const unsigned char *src_dir,
Expand Down Expand Up @@ -453,13 +455,15 @@ invoke_compiler(
const unsigned char *working_dir,
const unsigned char *log_path,
const testinfo_t *tinf,
int *p_prepended_size)
int *p_prepended_size,
const unsigned char *status_file)
{
const struct section_global_data *global = serve_state.global;
tpTask tsk = 0;

if (req->extra_src_dir && req->extra_src_dir[0]) {
int r = copy_all_files(log_f, req->extra_src_dir, working_dir);
int r = copy_directory_recursively(log_f, req->extra_src_dir, working_dir);
//int r = copy_all_files(log_f, req->extra_src_dir, working_dir);
if (r < 0) {
err("failed to copy extra_src_dir from %s to %s",
req->extra_src_dir, working_dir);
Expand Down Expand Up @@ -506,6 +510,9 @@ invoke_compiler(
task_AddArg(tsk, input_file);
task_AddArg(tsk, output_file);
}
if (status_file && req->enable_run_props > 0) {
task_AddArg(tsk, status_file);
}
task_SetPathAsArg0(tsk);
task_EnableProcessGroup(tsk);
if (VALID_SIZE(req->max_vm_size)) {
Expand Down Expand Up @@ -546,6 +553,9 @@ invoke_compiler(
}
task_SetLanguageName(tsk, lang->short_name);
}
if (req->enable_run_props > 0) {
task_EnableSubdirMode(tsk);
}

if (req->env_num > 0) {
for (int i = 0; i < req->env_num; i++)
Expand All @@ -558,6 +568,9 @@ invoke_compiler(
if (req->vcs_mode) {
task_PutEnv(tsk, "EJUDGE_VCS_MODE=1");
}
if (req->enable_run_props > 0) {
task_PutEnv(tsk, "EJUDGE_EXE_PROPERTIES=1");
}
task_SetWorkingDir(tsk, working_dir);
task_SetRedir(tsk, 0, TSR_FILE, "/dev/null", TSK_READ);
if (tinf && tinf->compiler_must_fail > 0) {
Expand Down Expand Up @@ -768,17 +781,32 @@ handle_packet(
const unsigned char *log_work_path, // the path to the log file (open in APPEND mode)
unsigned char *exe_work_name, // OUTPUT: the name of the executable
int *p_override_exe,
int *p_exe_copied)
int *p_exe_copied,
const unsigned char *json_work_path) // extended status working path
{
struct ZipData *zf = NULL;
int prepended_size = 0;
unsigned char build_dir[PATH_MAX];
__attribute__((unused)) int _;
const unsigned char *build_dir_ptr = working_dir;
unsigned char exe_rel_path[PATH_MAX];

if (req->enable_run_props > 0) {
_ = snprintf(build_dir, sizeof(build_dir), "%s/build", working_dir);
if (mkdir(build_dir, 0700) < 0 && errno != EEXIST) {
fprintf(log_f, "cannot create build directory: %s\n", os_ErrorMsg());
rpl->status = RUN_CHECK_FAILED;
goto cleanup;
}
build_dir_ptr = build_dir;
}

if (req->output_only) {
if (req->style_checker && req->style_checker[0]) {
unsigned char src_work_name[PATH_MAX];
snprintf(src_work_name, sizeof(src_work_name), "%llx", random_u64());
unsigned char src_work_path[PATH_MAX];
snprintf(src_work_path, sizeof(src_work_path), "%s/%s", working_dir, src_work_name);
snprintf(src_work_path, sizeof(src_work_path), "%s/%s", build_dir_ptr, src_work_name);

if (src_buf) {
if (generic_write_file(src_buf, src_len, 0, NULL, src_work_path, "") < 0) {
Expand All @@ -794,7 +822,7 @@ handle_packet(
}
}

int r = invoke_style_checker(log_f, cs, lang, req, src_work_name, working_dir, log_work_path, NULL);
int r = invoke_style_checker(log_f, cs, lang, req, src_work_name, build_dir_ptr, log_work_path, NULL);
if (r != RUN_OK) {
rpl->status = r;
goto cleanup;
Expand Down Expand Up @@ -869,7 +897,7 @@ handle_packet(
unsigned char src_work_name[PATH_MAX];
snprintf(src_work_name, sizeof(src_work_name), "%llx%s", random_u64(), lang->src_sfx);
unsigned char src_work_path[PATH_MAX];
snprintf(src_work_path, sizeof(src_work_path), "%s/%s", working_dir, src_work_name);
snprintf(src_work_path, sizeof(src_work_path), "%s/%s", build_dir_ptr, src_work_name);

if (src_buf) {
if (generic_write_file(src_buf, src_len, 0, NULL, src_work_path, "") < 0) {
Expand All @@ -893,7 +921,12 @@ handle_packet(
if (!req->multi_header) {
snprintf(exe_work_name, PATH_MAX, "%llx%s", random_u64(), lang->exe_sfx);
unsigned char exe_work_path[PATH_MAX];
snprintf(exe_work_path, sizeof(exe_work_path), "%s/%s", working_dir, exe_work_name);
snprintf(exe_work_path, sizeof(exe_work_path), "%s/%s", build_dir_ptr, exe_work_name);
if (req->enable_run_props > 0) {
snprintf(exe_rel_path, sizeof(exe_rel_path), "../%s", exe_work_name);
} else {
snprintf(exe_rel_path, sizeof(exe_rel_path), "%s", exe_work_name);
}

/*
if (req->style_checker && req->style_checker[0]) {
Expand All @@ -911,14 +944,14 @@ handle_packet(
*/

if (req->style_check_only <= 0) {
int r = invoke_compiler(log_f, cs, lang, req, src_work_name, exe_work_name, working_dir, log_work_path, NULL, &prepended_size);
int r = invoke_compiler(log_f, cs, lang, req, src_work_name, exe_rel_path, build_dir_ptr, log_work_path, NULL, &prepended_size, json_work_path);
rpl->status = r;
if (r != RUN_OK) goto cleanup;
rpl->prepended_size = prepended_size;
}

if (req->vcs_mode <= 0 && req->style_checker && req->style_checker[0]) {
int r = invoke_style_checker(log_f, cs, lang, req, src_work_name, working_dir, log_work_path, NULL);
int r = invoke_style_checker(log_f, cs, lang, req, src_work_name, build_dir_ptr, log_work_path, NULL);
rpl->status = r;
if (r == RUN_OK && req->style_check_only > 0) *p_override_exe = 1;
}
Expand All @@ -929,7 +962,7 @@ handle_packet(
// multi-header mode
snprintf(exe_work_name, PATH_MAX, "%llx%s", random_u64(), lang->exe_sfx);
unsigned char exe_work_path[PATH_MAX];
snprintf(exe_work_path, sizeof(exe_work_path), "%s/%s", working_dir, exe_work_name);
snprintf(exe_work_path, sizeof(exe_work_path), "%s/%s", build_dir_ptr, exe_work_name);
zf = ej_libzip_open(log_f, exe_work_path, O_CREAT | O_TRUNC | O_WRONLY);
if (!zf) {
fprintf(log_f, "cannot create zip archive '%s'\n", exe_work_path);
Expand Down Expand Up @@ -1114,7 +1147,7 @@ handle_packet(
unsigned char test_src_name[PATH_MAX];
snprintf(test_src_name, sizeof(test_src_name), "%llx%s", random_u64(), lang->src_sfx);
unsigned char test_src_path[PATH_MAX];
snprintf(test_src_path, sizeof(test_src_path), "%s/%s", working_dir, test_src_name);
snprintf(test_src_path, sizeof(test_src_path), "%s/%s", build_dir_ptr, test_src_name);
if (generic_write_file(full_s, full_z, 0, NULL, test_src_path, NULL) < 0) {
fprintf(log_f, "failed to write full source file '%s'\n", test_src_path);
testinfo_free(tinf);
Expand All @@ -1130,7 +1163,16 @@ handle_packet(
// FIXME: random exe name?
snprintf(test_exe_name, sizeof(test_exe_name), "%06d_%03d%s", req->run_id, serial, lang->exe_sfx);
unsigned char test_exe_path[PATH_MAX];
snprintf(test_exe_path, sizeof(test_exe_path), "%s/%s", working_dir, test_exe_name);
snprintf(test_exe_path, sizeof(test_exe_path), "%s/%s", build_dir_ptr, test_exe_name);
unsigned char test_json_name[PATH_MAX];
unsigned char test_json_path[PATH_MAX];
test_json_name[0] = 0;
test_json_path[0] = 0;
if (req->enable_run_props > 0) {
__attribute__((unused)) int _;
_ = snprintf(test_json_name, sizeof(test_json_name), "%06d_%03d%s", req->run_id, serial, PROP_SUFFIX);
_ = snprintf(test_json_path, sizeof(test_json_path), "%s/%s", working_dir, test_json_name);
}

int cur_status = RUN_OK;
/*
Expand All @@ -1152,7 +1194,7 @@ handle_packet(
if (cur_status == RUN_OK) {
fprintf(log_f, "=== compilation for test %d ===\n", serial);
fflush(log_f);
cur_status = invoke_compiler(log_f, cs, lang, req, test_src_name, test_exe_name, working_dir, log_work_path, tinf, &prepended_size);
cur_status = invoke_compiler(log_f, cs, lang, req, test_src_name, test_exe_name, build_dir_ptr, log_work_path, tinf, &prepended_size, test_json_path);
// valid statuses: RUN_OK, RUN_COMPILE_ERR, RUN_CHECK_FAILED
if (cur_status == RUN_CHECK_FAILED) {
status = RUN_CHECK_FAILED;
Expand Down Expand Up @@ -1201,7 +1243,7 @@ handle_packet(
fprintf(log_f, "failed to write full source file '%s'\n", test_src_path);
status = RUN_CHECK_FAILED;
} else {
cur_status = invoke_compiler(log_f, cs, lang, req, test_src_name, test_exe_name, working_dir, log_work_path, tinf, &prepended_size);
cur_status = invoke_compiler(log_f, cs, lang, req, test_src_name, test_exe_name, build_dir_ptr, log_work_path, tinf, &prepended_size, test_json_path);

if (cur_status == RUN_CHECK_FAILED) {
status = RUN_CHECK_FAILED;
Expand All @@ -1223,6 +1265,17 @@ handle_packet(
fprintf(log_f, "output file '%s' is not executable: %s\n", test_exe_path, strerror(errno));
status = RUN_CHECK_FAILED;
} else {
struct stat stb;
if (req->enable_run_props > 0 && lstat(test_json_path, &stb) >= 0
&& S_ISREG(stb.st_mode) && stb.st_size > 0) {
if (zf->ops->add_file(zf, test_json_name, test_json_path) < 0) {
fprintf(log_f, "cannot add file '%s' to zip archive\n", test_json_path);
status = RUN_CHECK_FAILED;
}
rpl->has_run_props = 1;
strcpy(rpl->prop_sfx, PROP_SUFFIX);
}

if (zf->ops->add_file(zf, test_exe_name, test_exe_path) < 0) {
fprintf(log_f, "cannot add file '%s' to zip archive\n", test_exe_path);
status = RUN_CHECK_FAILED;
Expand Down Expand Up @@ -1262,6 +1315,17 @@ handle_packet(
fprintf(log_f, "%s\n", tinf->comment);
}
} else {
struct stat stb;
if (req->enable_run_props > 0 && lstat(test_json_path, &stb) >= 0
&& S_ISREG(stb.st_mode) && stb.st_size > 0) {
if (zf->ops->add_file(zf, test_json_name, test_json_path) < 0) {
fprintf(log_f, "cannot add file '%s' to zip archive\n", test_json_path);
status = RUN_CHECK_FAILED;
}
strcpy(rpl->prop_sfx, PROP_SUFFIX);
rpl->has_run_props = 1;
}

if (zf->ops->add_file(zf, test_exe_name, test_exe_path) < 0) {
fprintf(log_f, "cannot add file '%s' to zip archive\n", test_exe_path);
status = RUN_CHECK_FAILED;
Expand All @@ -1275,7 +1339,7 @@ handle_packet(
fflush(log_f);

style_already_checked = 1;
cur_status = invoke_style_checker(log_f, cs, lang, req, test_src_name, working_dir, log_work_path, tinf);
cur_status = invoke_style_checker(log_f, cs, lang, req, test_src_name, build_dir_ptr, log_work_path, tinf);
// valid statuses: RUN_OK, RUN_STYLE_ERR, RUN_CHECK_FAILED
if (cur_status == RUN_CHECK_FAILED) {
status = RUN_CHECK_FAILED;
Expand Down Expand Up @@ -1804,6 +1868,24 @@ new_loop(int parallel_mode, const unsigned char *global_log_path)
snprintf(log_path, sizeof(log_path), "%s/%s.txt", report_dir, run_name);
unlink(log_path);

unsigned char json_path[PATH_MAX];
unsigned char json_work_name[PATH_MAX];
unsigned char json_work_path[PATH_MAX];
unsigned char json_rel_path[PATH_MAX];
json_path[0] = 0;
json_work_name[0] = 0;
json_work_path[0] = 0;
json_rel_path[0] = 0;
if (req->enable_run_props > 0) {
__attribute__((unused)) int _;
_ = snprintf(json_path, sizeof(json_path), "%s/%s%s", report_dir, run_name, PROP_SUFFIX);
unlink(json_path);
_ = snprintf(json_work_name, sizeof(json_work_name), "%s%s", run_name, PROP_SUFFIX);
_ = snprintf(json_work_path, sizeof(json_work_path), "%s/%s", full_working_dir, json_work_name);
unlink(json_work_path);
_ = snprintf(json_rel_path, sizeof(json_rel_path), "../%s", json_work_name);
}

unsigned char exe_work_name[PATH_MAX];
exe_work_name[0] = 0;

Expand Down Expand Up @@ -1872,7 +1954,8 @@ new_loop(int parallel_mode, const unsigned char *global_log_path)
log_work_path,
exe_work_name,
&override_exe,
&exe_copied);
&exe_copied,
json_rel_path);

free(src_buf); src_buf = NULL; src_len = 0;

Expand Down Expand Up @@ -1942,6 +2025,24 @@ new_loop(int parallel_mode, const unsigned char *global_log_path)

fclose(log_f); log_f = NULL;

if (req->enable_run_props > 0) {
struct stat stb;
if (lstat(json_work_path, &stb) >= 0 && S_ISREG(stb.st_mode) && stb.st_size > 0) {
rpl.has_run_props = 1;
strcpy(rpl.prop_sfx, PROP_SUFFIX);
if (agent) {
r = agent->ops->put_output_2(agent,
contest_server_id,
rpl.contest_id,
run_name,
PROP_SUFFIX,
json_work_path);
} else {
r = generic_copy_file(0, NULL, json_work_path, "", 0, NULL, json_path, "");
}
}
}

if (agent) {
r = agent->ops->put_output_2(agent,
contest_server_id,
Expand Down
5 changes: 3 additions & 2 deletions bin/ej-run.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* -*- c -*- */

/* Copyright (C) 2000-2023 Alexander Chernov <[email protected]> */
/* Copyright (C) 2000-2024 Alexander Chernov <[email protected]> */

/*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -354,7 +354,8 @@ do_loop(void)
0 /* user_input_mode*/,
NULL /* inp_data */,
0 /* inp_size*/,
NULL /* src_path */);
NULL /* src_path */,
NULL /* run_props */);
//if (cr_serialize_unlock(&serve_state) < 0) return -1;

if (tst == &tn) {
Expand Down
Loading

0 comments on commit 8af6333

Please sign in to comment.