예제 #1
0
파일: nwrun.c 프로젝트: mezun7/ejudge
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);
    }
  }
}
예제 #2
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;
}
예제 #3
0
파일: nwrun.c 프로젝트: mezun7/ejudge
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);
}