static void do_loop(void) { unsigned char new_entry_name[EJ_PATH_MAX]; unsigned char out_entry_name[EJ_PATH_MAX]; unsigned char new_path[EJ_PATH_MAX]; unsigned char out_path[EJ_PATH_MAX]; int r; int serial = 0; while (1) { r = scan_dir(global->queue_dir, new_entry_name, sizeof(new_entry_name), 0); if (r < 0) { die("scan_dir failed on %s", global->queue_dir); /* FIXME: recover and continue */ } if (!r) { os_Sleep(global->sleep_time); continue; } snprintf(out_entry_name, sizeof(out_entry_name), "%s_%s", os_NodeName(), new_entry_name); snprintf(new_path, sizeof(new_path), "%s/dir/%s", global->queue_dir, new_entry_name); snprintf(out_path, sizeof(out_path), "%s/out/%s", global->queue_dir, out_entry_name); while (rename(new_path, out_path) < 0) { if (errno == ENOENT) { err("file %s is stolen?", new_path); out_path[0] = 0; os_Sleep(global->sleep_time); break; } if (errno == ENOTEMPTY || errno == EEXIST) { err("directory %s already exists", out_path); snprintf(out_entry_name, sizeof(out_entry_name), "%s_%d_%s", os_NodeName(), ++serial, new_entry_name); snprintf(out_path, sizeof(out_path), "%s/out/%s", global->queue_dir, out_entry_name); continue; } die("rename: %s -> %s failed: %s", new_path, out_path, strerror(errno)); } if (out_path[0]) { read_packet(out_path); remove_directory_recursively(out_path, 0); } } }
/** * NAME: os_SetLock * PURPOSE: set the lockfile with the specified name * ARGS: path - lock file path * perms - file permissions * left_open - 1, if the function should return the open file * 0, if the function should close the file * RETURN: >= 0 - ok, -1 - file is locked, -2 - other error * NOTE: function works reliably over NFS (Network Failure System) */ int os_SetLock(char const *path, int perms, int left_open) { char *dirname = os_DirName(path); char *hostname = os_NodeName(); char *uniq_name = 0; int fd = -1; int code = 0; int file_flag = 0; struct stat buf; /* 1. Create the unique file on the same filesystem */ uniq_name = xmalloc(strlen(dirname) + strlen(hostname) + 32); sprintf(uniq_name, "%s/LCK_%s_%d", dirname, hostname, (int) getpid()); if ((fd = open(uniq_name, O_WRONLY | O_CREAT, perms)) < 0) { code = -2; goto free_resources; } file_flag = 1; /* 2. Use link(2) to create a link to the lockfile */ /* do not use the return value of link call */ link(uniq_name, path); /* 3. Use stat(2) on the unique file to check that the link count is increased to 2 */ if (fstat(fd, &buf) < 0) { code = -2; goto free_resources; } if (buf.st_nlink != 2) { code = -1; goto free_resources; } /* at this point lock file is created */ if (left_open) { code = fd; fd = -1; } free_resources: if (file_flag) unlink(uniq_name); free(uniq_name); free(dirname); if (fd >= 0) close(fd); return code; }
static void read_packet(const unsigned char *dir_path) { unsigned char packet_conf_file[EJ_PATH_MAX]; FILE *f = 0; struct generic_section_config *packet_config = 0; struct nwrun_in_packet *packet = 0; unsigned char result_name[EJ_PATH_MAX]; unsigned char result_in_dir[EJ_PATH_MAX]; unsigned char result_dir_dir[EJ_PATH_MAX]; unsigned char contest_dir[EJ_PATH_MAX]; struct nwrun_out_packet result; unsigned char result_packet_path[EJ_PATH_MAX]; int clean_result_dir = 0; memset(&result, 0, sizeof(result)); snprintf(packet_conf_file,sizeof(packet_conf_file),"%s/packet.cfg",dir_path); packet_config = nwrun_in_packet_parse(packet_conf_file, &packet); if (!packet_config) goto cleanup; nwrun_in_packet_print(stderr, (const struct nwrun_in_packet *) packet_config); /* setup packet defaults */ if (packet->contest_id <= 0) { err("contest_id is not set"); goto cleanup; } if (packet->prob_id <= 0) { err("prob_id is not set"); goto cleanup; } if (packet->test_num <= 0) { err("test_num is not set"); goto cleanup; } if (packet->judge_id <= 0) { err("judge_id is not set"); goto cleanup; } if (!packet->program_name[0]) { err("program_name is not set"); goto cleanup; } if (!packet->test_file_name[0]) { err("test_file_name is not set"); goto cleanup; } if (!packet->input_file_name[0]) { snprintf(packet->input_file_name, sizeof(packet->input_file_name), "%s", DEFAULT_INPUT_FILE_NAME); } if (!packet->result_file_name[0]) { err("result_file_name is not set"); goto cleanup; } if (!packet->output_file_name[0]) { snprintf(packet->output_file_name, sizeof(packet->output_file_name), "%s", DEFAULT_OUTPUT_FILE_NAME); } if (!packet->error_file_name[0]) { snprintf(packet->error_file_name, sizeof(packet->error_file_name), "%s", DEFAULT_ERROR_FILE_NAME); } if (packet->max_output_file_size <= 0) { packet->max_output_file_size = DEFAULT_MAX_OUTPUT_FILE_SIZE; } if (packet->max_error_file_size <= 0) { packet->max_error_file_size = DEFAULT_MAX_ERROR_FILE_SIZE; } if (packet->time_limit_millis <= 0) { err("time_limit_millis is invalid (%d)", packet->time_limit_millis); goto cleanup; } /* create the output directory */ snprintf(result_name, sizeof(result_name), "%c%c%d%c%d%c%d%c%d%c%d", get_priority_code(packet->priority - 17), get_num_prefix(packet->contest_id), packet->contest_id, get_num_prefix(packet->run_id - 1), packet->run_id - 1, get_num_prefix(packet->prob_id), packet->prob_id, get_num_prefix(packet->test_num), packet->test_num, get_num_prefix(packet->judge_id), packet->judge_id); if (packet->use_contest_id_in_reply) { snprintf(contest_dir, sizeof(contest_dir), "%s/%06d", global->result_dir, packet->contest_id); if (make_all_dir(contest_dir, 0777) < 0) { goto cleanup; } snprintf(result_in_dir, sizeof(result_in_dir), "%s/in/%s_%s", contest_dir, os_NodeName(), result_name); snprintf(result_dir_dir, sizeof(result_dir_dir), "%s/dir/%s", contest_dir, result_name); } else { snprintf(result_in_dir, sizeof(result_in_dir), "%s/in/%s_%s", global->result_dir, os_NodeName(), result_name); snprintf(result_dir_dir, sizeof(result_dir_dir), "%s/dir/%s", global->result_dir, result_name); } if (make_dir(result_in_dir, 0777) < 0) { goto cleanup; } clean_result_dir = 1; // set default values snprintf(result.hostname, sizeof(result.hostname), "%s", os_NodeName()); result.contest_id = packet->contest_id; result.run_id = packet->run_id; result.prob_id = packet->prob_id; result.test_num = packet->test_num; result.judge_id = packet->judge_id; result.status = RUN_CHECK_FAILED; snprintf(result.comment, sizeof(result.comment), "Default status was not changed"); handle_packet(dir_path, packet, result_in_dir, &result); snprintf(result_packet_path, sizeof(result_packet_path), "%s/packet.cfg", result_in_dir); if (!(f = fopen(result_packet_path, "wb"))) { err("cannot open file %s: %s", result_packet_path, os_ErrorMsg()); goto cleanup; } nwrun_out_packet_print(f, &result); fclose(f); f = 0; nwrun_out_packet_print(stderr, &result); if (rename(result_in_dir, result_dir_dir) < 0) { err("rename: %s -> %s failed: %s", result_in_dir, result_dir_dir, os_ErrorMsg()); goto cleanup; } clean_result_dir = 0; cleanup: if (clean_result_dir) { remove_directory_recursively(result_in_dir, 0); } nwrun_in_packet_free(packet_config); if (f) fclose(f); }