Exemplo n.º 1
0
Arquivo: run.c Projeto: NUOG/ejudge
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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
Arquivo: run.c Projeto: NUOG/ejudge
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;
}