示例#1
0
/* Worker thread. */
static void *
start_thread (void *thread_data_vp)
{
  struct thread_data *thread_data = thread_data_vp;
  int quit = 0;
  int err;
  size_t i;
  guestfs_h *g;
  unsigned errors = 0;
  char id[64];

  for (;;) {
    CLEANUP_FREE char *log_file = NULL;
    CLEANUP_FCLOSE FILE *log_fp = NULL;

    /* Take the next process. */
    err = pthread_mutex_lock (&mutex);
    if (err != 0) {
      fprintf (stderr, "%s: pthread_mutex_lock: %s",
               guestfs_int_program_name, strerror (err));
      goto error;
    }

    i = n;
    if (i > 0) {
      printf ("%zu to go ...          \r", n);
      fflush (stdout);

      n--;
    }
    else
      quit = 1;

    err = pthread_mutex_unlock (&mutex);
    if (err != 0) {
      fprintf (stderr, "%s: pthread_mutex_unlock: %s",
               guestfs_int_program_name, strerror (err));
      goto error;
    }

    if (quit)                   /* Work finished. */
      break;

    g = guestfs_create ();
    if (g == NULL) {
      perror ("guestfs_create");
      errors++;
      if (!ignore_errors)
        goto error;
    }

    /* Only if using --log, set up a callback.  See examples/debug-logging.c */
    if (log_template != NULL) {
      size_t j, k;

      log_file = malloc (log_file_size + 1);
      if (log_file == NULL) abort ();
      for (j = 0, k = 0; j < strlen (log_template); ++j) {
        if (log_template[j] == '%') {
          snprintf (&log_file[k], log_file_size - k, "%zu", i);
          k += strlen (&log_file[k]);
        }
        else
          log_file[k++] = log_template[j];
      }
      log_file[k] = '\0';
      log_fp = fopen (log_file, "w");
      if (log_fp == NULL) {
        perror (log_file);
        abort ();
      }
      guestfs_set_event_callback (g, message_callback,
                                  event_bitmask, 0, log_fp);
    }

    snprintf (id, sizeof id, "%zu", i);
    guestfs_set_identifier (g, id);

    guestfs_set_trace (g, trace);
    guestfs_set_verbose (g, verbose);

    if (guestfs_add_drive_ro (g, "/dev/null") == -1) {
      errors++;
      if (!ignore_errors)
        goto error;
    }

    if (guestfs_launch (g) == -1) {
      errors++;
      if (!ignore_errors)
        goto error;
    }

    if (guestfs_shutdown (g) == -1) {
      errors++;
      if (!ignore_errors)
        goto error;
    }

    guestfs_close (g);
  }

  if (errors > 0) {
    fprintf (stderr, "%s: thread %d: %u errors were ignored\n",
             guestfs_int_program_name, thread_data->thread_num, errors);
    goto error;
  }

  thread_data->r = 0;
  return &thread_data->r;

 error:
  thread_data->r = -1;
  return &thread_data->r;
}
示例#2
0
/* Worker thread. */
static void *
worker_thread (void *thread_data_vp)
{
  struct thread_data *thread_data = thread_data_vp;

  thread_data->r = 0;

  if (thread_data->verbose)
    fprintf (stderr, "parallel: thread %zu starting\n",
             thread_data->thread_num);

  while (1) {
    size_t i;               /* The current domain we're working on. */
    FILE *fp;
    CLEANUP_FREE char *output = NULL;
    size_t output_len = 0;
    guestfs_h *g;
    int err;
    char id[64];

    /* Take the next domain from the list. */
    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu waiting to get work\n",
               thread_data->thread_num);

    err = pthread_mutex_lock (&take_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_lock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
    i = next_domain_to_take++;
    err = pthread_mutex_unlock (&take_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_unlock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }

    if (i >= nr_domains)        /* Work finished. */
      break;

    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu taking domain %zu\n",
               thread_data->thread_num, i);

    fp = open_memstream (&output, &output_len);
    if (fp == NULL) {
      perror ("open_memstream");
      thread_data->r = -1;
      return &thread_data->r;
    }

    /* Create a guestfs handle. */
    g = guestfs_create ();
    if (g == NULL) {
      perror ("guestfs_create");
      thread_data->r = -1;
      return &thread_data->r;
    }

    /* Set the handle identifier so we can tell threads apart. */
    snprintf (id, sizeof id, "thread_%zu_domain_%zu",
              thread_data->thread_num, i);
    guestfs_set_identifier (g, id);

    /* Copy some settings from the options guestfs handle. */
    guestfs_set_trace (g, thread_data->trace);
    guestfs_set_verbose (g, thread_data->verbose);

    /* Do work. */
    if (thread_data->work (g, i, fp) == -1) {
      thread_data->r = -1;

      if (thread_data->verbose)
        fprintf (stderr,
                 "parallel: thread %zu work function returned an error\n",
                 thread_data->thread_num);
    }

    fclose (fp);
    guestfs_close (g);

    /* Retire this domain.  We have to retire domains in order, which
     * may mean waiting for another thread to finish here.
     */
    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu waiting to retire domain %zu\n",
               thread_data->thread_num, i);

    err = pthread_mutex_lock (&retire_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_lock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
    while (next_domain_to_retire != i) {
      err = pthread_cond_wait (&retire_cond, &retire_mutex);
      if (err != 0) {
        thread_failure ("pthread_cond_wait", err);
        thread_data->r = -1;
        ignore_value (pthread_mutex_unlock (&retire_mutex));
        return &thread_data->r;
      }
    }

    if (thread_data->verbose)
      fprintf (stderr, "parallel: thread %zu retiring domain %zu\n",
               thread_data->thread_num, i);

    /* Retire domain. */
    printf ("%s", output);

    /* Update next_domain_to_retire and tell other threads. */
    next_domain_to_retire = i+1;
    pthread_cond_broadcast (&retire_cond);
    err = pthread_mutex_unlock (&retire_mutex);
    if (err != 0) {
      thread_failure ("pthread_mutex_unlock", err);
      thread_data->r = -1;
      return &thread_data->r;
    }
  }

  if (thread_data->verbose)
    fprintf (stderr, "parallel: thread %zu exiting (r = %d)\n",
             thread_data->thread_num, thread_data->r);

  return &thread_data->r;
}