static int process_default_testers(void) { int total = 0; int i, j, k; unsigned char *prob_flags = 0; struct section_tester_data *tp, *tq; struct section_problem_data *ts; struct section_tester_data tn; //temporary entry prob_flags = (unsigned char *) alloca(serve_state.max_prob + 1); /* scan all the 'any' testers */ for (i = 1; i <= serve_state.max_tester; i++) { tp = serve_state.testers[i]; if (!tp || !tp->any) continue; // check architecture uniqueness for (j = 1; j <= serve_state.max_tester; j++) { tq = serve_state.testers[j]; if (i == j || !tq || !tq->any) continue; if (strcmp(serve_state.testers[j]->arch, tp->arch) != 0) continue; err("default testers %d and %d has the same architecture '%s'", i, j, tp->arch); return -1; } // mark the problems with explicit testers for this architecture memset(prob_flags, 0, serve_state.max_prob + 1); for (j = 1; j <= serve_state.max_tester; j++) { tq = serve_state.testers[j]; if (!tq || tq->any) continue; if (strcmp(tp->arch, tq->arch) != 0) continue; // tq is specific tester with the same architecture ASSERT(tq->problem > 0 && tq->problem <= serve_state.max_prob); ASSERT(serve_state.probs[tq->problem]); prob_flags[tq->problem] = 1; } // scan all problems, which have no default tester for (k = 1; k <= serve_state.max_prob; k++) { ts = serve_state.probs[k]; if (!ts || prob_flags[k]) continue; if (ts->disable_testing) continue; if (ts->manual_checking) continue; // so at this point: tp - pointer to the default tester, // k is the problem number // ts - pointer to the problem which should be handled by the // default tester if (prepare_tester_refinement(&serve_state, &tn, i, k) < 0) return -1; if (create_tester_dirs(&tn) < 0) return -1; /* check working dirs */ if (make_writable(tn.check_dir) < 0) return -1; if (check_writable_dir(tn.check_dir) < 0) return -1; if (tn.prepare_cmd[0] && check_executable(tn.prepare_cmd) < 0) return -1; if (tn.start_cmd[0] && check_executable(tn.start_cmd) < 0) return -1; total++; sarray_free(tn.start_env); sarray_free(tn.super); } } return total; }
void sarray_free (struct sarray *array) { #ifdef OBJC_SPARSE3 size_t old_max_index = (array->capacity - 1)/INDEX_CAPACITY; struct sindex **old_indices; #else size_t old_max_index = (array->capacity - 1)/BUCKET_SIZE; struct sbucket **old_buckets; #endif size_t counter = 0; assert (array->ref_count != 0); /* Freed multiple times!!! */ if (--(array->ref_count) != 0) /* There exists copies of me */ return; #ifdef OBJC_SPARSE3 old_indices = array->indices; #else old_buckets = array->buckets; #endif if ((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0)) sarray_free (array->is_copy_of); /* Free all entries that do not point to empty_bucket */ for (counter = 0; counter <= old_max_index; counter++ ) { #ifdef OBJC_SPARSE3 struct sindex *idx = old_indices[counter]; if ((idx != array->empty_index) && (idx->version.version == array->version.version)) { int c2; for (c2 = 0; c2 < INDEX_SIZE; c2++) { struct sbucket *bkt = idx->buckets[c2]; if ((bkt != array->empty_bucket) && (bkt->version.version == array->version.version)) { sarray_free_garbage (bkt); nbuckets -= 1; } } sarray_free_garbage (idx); nindices -= 1; } #else /* OBJC_SPARSE2 */ struct sbucket *bkt = array->buckets[counter]; if ((bkt != array->empty_bucket) && (bkt->version.version == array->version.version)) { sarray_free_garbage (bkt); nbuckets -= 1; } #endif } #ifdef OBJC_SPARSE3 /* free empty_index */ if (array->empty_index->version.version == array->version.version) { sarray_free_garbage (array->empty_index); nindices -= 1; } #endif /* free empty_bucket */ if (array->empty_bucket->version.version == array->version.version) { sarray_free_garbage (array->empty_bucket); nbuckets -= 1; } idxsize -= (old_max_index + 1); narrays -= 1; #ifdef OBJC_SPARSE3 /* free bucket table */ sarray_free_garbage (array->indices); #else /* free bucket table */ sarray_free_garbage (array->buckets); #endif /* free array */ sarray_free_garbage (array); }
static int do_loop(void) { int r; path_t report_path; path_t full_report_path; path_t pkt_name; unsigned char exe_pkt_name[64]; unsigned char run_base[64]; path_t full_report_dir; path_t full_status_dir; path_t full_full_dir; char exe_name[64]; int tester_id; struct section_tester_data tn, *tst; int got_quit_packet = 0; struct run_reply_packet reply_pkt; void *reply_pkt_buf = 0; size_t reply_pkt_buf_size = 0; unsigned char errmsg[512]; const struct section_global_data *global = serve_state.global; const unsigned char *arch = 0; char *srp_b = 0; size_t srp_z = 0; struct super_run_in_packet *srp = NULL; struct super_run_in_global_packet *srgp = NULL; struct super_run_in_problem_packet *srpp = NULL; memset(&tn, 0, sizeof(tn)); //if (cr_serialize_init(&serve_state) < 0) return -1; interrupt_init(); interrupt_disable(); while (1) { interrupt_enable(); /* time window for immediate signal delivery */ interrupt_disable(); // terminate, if signaled if (interrupt_get_status()) break; if (interrupt_restart_requested()) { restart_flag = 1; } if (restart_flag) break; r = scan_dir(global->run_queue_dir, pkt_name, sizeof(pkt_name)); if (r < 0) return -1; if (!r) { if (got_quit_packet && managed_mode_flag) { return 0; } if (managed_mode_flag && global->inactivity_timeout > 0 && last_activity_time + global->inactivity_timeout < time(0)) { info("no activity for %d seconds, exiting",global->inactivity_timeout); return 0; } interrupt_enable(); os_Sleep(global->sleep_time); interrupt_disable(); continue; } last_activity_time = time(0); srp = super_run_in_packet_free(srp); xfree(srp_b); srp_b = NULL; srp_z = 0; r = generic_read_file(&srp_b, 0, &srp_z, SAFE | REMOVE, global->run_queue_dir, pkt_name, ""); if (r == 0) continue; if (r < 0) return -1; if (!strcmp(pkt_name, "QUIT")) { if (managed_mode_flag) { got_quit_packet = 1; info("got force quit run packet"); } else { restart_flag = 1; } xfree(srp_b); srp_b = NULL; srp_z = 0; continue; } fprintf(stderr, "packet: <<%.*s>>\n", (int) srp_z, srp_b); srp = super_run_in_packet_parse_cfg_str(pkt_name, srp_b, srp_z); //xfree(srp_b); srp_b = NULL; srp_z = 0; if (!srp) { err("failed to parse file %s", pkt_name); continue; } if (!(srgp = srp->global)) { err("packet %s has no global section", pkt_name); continue; } if (srgp->contest_id <= 0) { err("packet %s: undefined contest_id", pkt_name); continue; } if (managed_mode_flag && srgp->restart > 0) { got_quit_packet = 1; info("got force quit run packet"); continue; } if (srgp->restart > 0) { restart_flag = 1; continue; } /* if (req_pkt->contest_id == -1) { r = generic_write_file(req_buf, req_buf_size, SAFE, serve_state.global->run_queue_dir, pkt_name, ""); if (r < 0) return -1; info("force quit packet is ignored in unmanaged mode"); scan_dir_add_ignored(serve_state.global->run_queue_dir, pkt_name); continue; } */ if (!(srpp = srp->problem)) { err("packet %s: no [problem] section", pkt_name); continue; } /* if we are asked to do full testing, but don't want */ if ((global->skip_full_testing > 0 && !srgp->accepting_mode) || (global->skip_accept_testing > 0 && srgp->accepting_mode)) { r = generic_write_file(srp_b, srp_z, SAFE, global->run_queue_dir, pkt_name, ""); if (r < 0) return -1; info("skipping problem %s", srpp->short_name); scan_dir_add_ignored(global->run_queue_dir, pkt_name); continue; } /* if this problem is marked as "skip_testing" put the * packet back to the spool directory */ #if 0 if (cur_prob->skip_testing > 0) { r = generic_write_file(srp_b, srp_z, SAFE, global->run_queue_dir, pkt_name, ""); if (r < 0) return -1; info("skipping problem %s", cur_prob->short_name); scan_dir_add_ignored(global->run_queue_dir, pkt_name); continue; } #endif snprintf(run_base, sizeof(run_base), "%06d", srgp->run_id); report_path[0] = 0; full_report_path[0] = 0; if (srpp->type_val == PROB_TYPE_TESTS) { //cr_serialize_lock(&serve_state); run_inverse_testing(&serve_state, srp, &reply_pkt, pkt_name, global->run_exe_dir, report_path, sizeof(report_path), utf8_mode); //cr_serialize_unlock(&serve_state); } else { arch = srgp->arch; if (!arch) arch = ""; if (srpp->type_val > 0 && arch && !*arch) { // any tester will work for output-only problems arch = 0; } /* regular problem */ if (!(tester_id = find_tester(&serve_state, srpp->id, arch))){ snprintf(errmsg, sizeof(errmsg), "no tester found for %d, %s\n", srpp->id, srgp->arch); goto report_check_failed_and_continue; } info("fount tester %d for pair %d,%s", tester_id, srpp->id, srgp->arch); tst = serve_state.testers[tester_id]; if (tst->any) { info("tester %d is a default tester", tester_id); r = prepare_tester_refinement(&serve_state, &tn, tester_id, srpp->id); ASSERT(r >= 0); tst = &tn; } /* if this tester is marked as "skip_testing" put the * packet back to the spool directory */ if (tst->skip_testing > 0) { r = generic_write_file(srp_b, srp_z, SAFE, global->run_queue_dir, pkt_name, ""); if (r < 0) return -1; info("skipping tester <%s,%s>", srpp->short_name, tst->arch); scan_dir_add_ignored(global->run_queue_dir, pkt_name); if (tst == &tn) { sarray_free(tst->start_env); tst->start_env = 0; sarray_free(tst->super); tst->super = 0; } continue; } snprintf(exe_pkt_name, sizeof(exe_pkt_name), "%s%s", pkt_name, srgp->exe_sfx); snprintf(exe_name, sizeof(exe_name), "%s%s", run_base, srgp->exe_sfx); r = generic_copy_file(REMOVE, global->run_exe_dir, exe_pkt_name, "", 0, global->run_work_dir, exe_name, ""); if (r <= 0) { snprintf(errmsg, sizeof(errmsg), "failed to copy executable file %s/%s\n", global->run_exe_dir, exe_pkt_name); goto report_check_failed_and_continue; } /* start filling run_reply_packet */ memset(&reply_pkt, 0, sizeof(reply_pkt)); reply_pkt.judge_id = srgp->judge_id; reply_pkt.contest_id = srgp->contest_id; reply_pkt.run_id = srgp->run_id; reply_pkt.notify_flag = srgp->notify_flag; reply_pkt.user_status = -1; reply_pkt.user_tests_passed = -1; reply_pkt.user_score = -1; reply_pkt.ts1 = srgp->ts1; reply_pkt.ts1_us = srgp->ts1_us; reply_pkt.ts2 = srgp->ts2; reply_pkt.ts2_us = srgp->ts2_us; reply_pkt.ts3 = srgp->ts3; reply_pkt.ts3_us = srgp->ts3_us; reply_pkt.ts4 = srgp->ts4; reply_pkt.ts4_us = srgp->ts4_us; get_current_time(&reply_pkt.ts5, &reply_pkt.ts5_us); //if (cr_serialize_lock(&serve_state) < 0) return -1; run_tests(ejudge_config, &serve_state, tst, srp, &reply_pkt, srgp->accepting_mode, srpp->accept_partial, srgp->variant, exe_name, run_base, report_path, full_report_path, srgp->user_spelling, srpp->spelling, NULL /* mirror_dir */, utf8_mode); //if (cr_serialize_unlock(&serve_state) < 0) return -1; if (tst == &tn) { sarray_free(tst->start_env); tst->start_env = 0; sarray_free(tst->super); tst->super = 0; } } if (srgp->reply_report_dir && srgp->reply_report_dir[0]) { snprintf(full_report_dir, sizeof(full_report_dir), "%s", srgp->reply_report_dir); } else { snprintf(full_report_dir, sizeof(full_report_dir), "%s/%06d/report", global->run_dir, srgp->contest_id); } if (srgp->reply_spool_dir && srgp->reply_spool_dir[0]) { snprintf(full_status_dir, sizeof(full_status_dir), "%s", srgp->reply_spool_dir); } else { snprintf(full_status_dir, sizeof(full_status_dir), "%s/%06d/status", global->run_dir, srgp->contest_id); } if (srgp->reply_full_archive_dir && srgp->reply_full_archive_dir[0]) { snprintf(full_full_dir, sizeof(full_full_dir), "%s", srgp->reply_full_archive_dir); } else { snprintf(full_full_dir, sizeof(full_full_dir), "%s/%06d/output", global->run_dir, srgp->contest_id); } if (generic_copy_file(0, NULL, report_path, "", 0, full_report_dir, run_base, "") < 0) return -1; #if defined CONF_HAS_LIBZIP if (full_report_path[0] && generic_copy_file(0, NULL, full_report_path, "", 0, full_full_dir, run_base, ".zip") < 0) return -1; #else if (full_report_path[0] && generic_copy_file(0, NULL, full_report_path, "", 0, full_full_dir, run_base, "") < 0) return -1; #endif //run_reply_packet_dump(&reply_pkt); if (run_reply_packet_write(&reply_pkt, &reply_pkt_buf_size, &reply_pkt_buf) < 0) { /* FIXME: do something, if this is possible. * However, unability to generate a reply packet only * means that invalid data passed, which should be reported * immediately as internal error! */ abort(); } if (generic_write_file(reply_pkt_buf, reply_pkt_buf_size, SAFE, full_status_dir, run_base, "") < 0) { xfree(reply_pkt_buf); reply_pkt_buf = 0; return -1; } xfree(reply_pkt_buf); reply_pkt_buf = 0; clear_directory(global->run_work_dir); last_activity_time = time(0); continue; report_check_failed_and_continue:; memset(&reply_pkt, 0, sizeof(reply_pkt)); reply_pkt.judge_id = srgp->judge_id; reply_pkt.contest_id = srgp->contest_id; reply_pkt.run_id = srgp->run_id; reply_pkt.user_status = -1; reply_pkt.user_tests_passed = -1; reply_pkt.user_score = -1; reply_pkt.ts1 = srgp->ts1; reply_pkt.ts1_us = srgp->ts1_us; reply_pkt.ts2 = srgp->ts2; reply_pkt.ts2_us = srgp->ts2_us; reply_pkt.ts3 = srgp->ts3; reply_pkt.ts3_us = srgp->ts3_us; reply_pkt.ts4 = srgp->ts4; reply_pkt.ts4_us = srgp->ts4_us; get_current_time(&reply_pkt.ts5, &reply_pkt.ts5_us); reply_pkt.ts6 = reply_pkt.ts5; reply_pkt.ts6_us = reply_pkt.ts5_us; reply_pkt.ts7 = reply_pkt.ts5; reply_pkt.ts7_us = reply_pkt.ts5_us; reply_pkt.status = RUN_CHECK_FAILED; reply_pkt.failed_test = 0; reply_pkt.score = -1; if (run_reply_packet_write(&reply_pkt, &reply_pkt_buf_size, &reply_pkt_buf) < 0) { // oops :( abort(); } if (generic_write_file(errmsg, strlen(errmsg), 0, full_report_dir, run_base, "") < 0 || generic_write_file(reply_pkt_buf, reply_pkt_buf_size, SAFE, full_status_dir, run_base, "") < 0) { err("error writing check failed packet"); } clear_directory(global->run_work_dir); } srp = super_run_in_packet_free(srp); xfree(srp_b); srp_b = NULL; srp_z = 0; return 0; }