Beispiel #1
0
int
main (int argc, char **argv)
{
  int i, pid, children = 0, retval = 0;
  long starttime, stoptime, runtime;

  /* Variables that indicate which options have been selected.  */
  int do_dryrun = 0;
  int do_timeout = 0;
  int do_cpu = 0;               /* Default to 1 fork. */
  long long do_cpu_forks = 1;
  int do_io = 0;                /* Default to 1 fork. */
  long long do_io_forks = 1;
  int do_vm = 0;                /* Default to 1 fork, 1 chunk of 256MB.  */
  long long do_vm_forks = 1;
  long long do_vm_chunks = 1;
  long long do_vm_bytes = 256 * 1024 * 1024;
  int do_hdd = 0;               /* Default to 1 fork, clean, 1 file of 1GB.  */
  long long do_hdd_forks = 1;
  int do_hdd_clean = 0;
  long long do_hdd_files = 1;
  long long do_hdd_bytes = 1024 * 1024 * 1024;

  /* Record our start time.  */
  if ((starttime = time (NULL)) == -1)
    {
      err (stderr, "failed to acquire current time\n");
      exit (1);
    }

  /* SuSv3 does not define any error conditions for this function.  */
  global_progname = basename (argv[0]);

  /* For portability, parse command line options without getopt_long.  */
  for (i = 1; i < argc; i++)
    {
      char *arg = argv[i];

      if (strcmp (arg, "--help") == 0 || strcmp (arg, "-?") == 0)
        {
          usage (0);
        }
      else if (strcmp (arg, "--version") == 0)
        {
          version (0);
        }
      else if (strcmp (arg, "--verbose") == 0 || strcmp (arg, "-v") == 0)
        {
          global_debug = 3;
        }
      else if (strcmp (arg, "--quiet") == 0 || strcmp (arg, "-q") == 0)
        {
          global_debug = 0;
        }
      else if (strcmp (arg, "--dry-run") == 0 || strcmp (arg, "-n") == 0)
        {
          do_dryrun = 1;
        }
      else if (strcmp (arg, "--no-retry") == 0)
        {
          global_ignore = 0;
          dbg (stdout, "turning off ignore of non-critical errors");
        }
      else if (strcmp (arg, "--retry-delay") == 0)
        {
          assert_arg ("--retry-delay");
          global_retry = atoll (arg);
          dbg (stdout, "setting retry delay to %dus\n", global_retry);
        }
      else if (strcmp (arg, "--backoff") == 0)
        {
          assert_arg ("--backoff");
          global_backoff = atoll (arg);
          if (global_backoff < 0)
            {
              err (stderr, "invalid backoff factor: %i\n", global_backoff);
              exit (1);
            }
          dbg (stdout, "setting backoff coeffient to %dus\n", global_backoff);
        }
      else if (strcmp (arg, "--timeout") == 0 || strcmp (arg, "-t") == 0)
        {
          do_timeout = 1;
          assert_arg ("--timeout");
          global_timeout = atoll_s (arg);
          dbg (stdout, "setting timeout to %ds\n", global_timeout);
        }
      else if (strcmp (arg, "--cpu") == 0 || strcmp (arg, "-c") == 0)
        {
          do_cpu = 1;
          assert_arg ("--cpu");
          do_cpu_forks = atoll_b (arg);
        }
      else if (strcmp (arg, "--io") == 0 || strcmp (arg, "-i") == 0)
        {
          do_io = 1;
          assert_arg ("--io");
          do_io_forks = atoll_b (arg);
        }
      else if (strcmp (arg, "--vm") == 0 || strcmp (arg, "-m") == 0)
        {
          do_vm = 1;
          assert_arg ("--vm");
          do_vm_forks = atoll_b (arg);
        }
      else if (strcmp (arg, "--vm-chunks") == 0)
        {
          assert_arg ("--vm-chunks");
          do_vm_chunks = atoll_b (arg);
        }
      else if (strcmp (arg, "--vm-bytes") == 0)
        {
          assert_arg ("--vm-bytes");
          do_vm_bytes = atoll_b (arg);
        }
      else if (strcmp (arg, "--vm-hang") == 0)
        {
          global_vmhang = 1;
        }
      else if (strcmp (arg, "--hdd") == 0 || strcmp (arg, "-d") == 0)
        {
          do_hdd = 1;
          assert_arg ("--hdd");
          do_hdd_forks = atoll_b (arg);
        }
      else if (strcmp (arg, "--hdd-noclean") == 0)
        {
          do_hdd_clean = 2;
        }
      else if (strcmp (arg, "--hdd-files") == 0)
        {
          assert_arg ("--hdd-files");
          do_hdd_files = atoll_b (arg);
        }
      else if (strcmp (arg, "--hdd-bytes") == 0)
        {
          assert_arg ("--hdd-bytes");
          do_hdd_bytes = atoll_b (arg);
        }
      else
        {
          err (stderr, "unrecognized option: %s\n", arg);
          exit (1);
        }
    }

  /* Hog CPU option.  */
  if (do_cpu)
    {
      out (stdout, "dispatching %lli hogcpu forks\n", do_cpu_forks);

      switch (pid = fork ())
        {
        case 0:                /* child */
          if (do_dryrun)
            exit (0);
          exit (hogcpu (do_cpu_forks));
        case -1:               /* error */
          err (stderr, "hogcpu dispatcher fork failed\n");
          exit (1);
        default:               /* parent */
          children++;
          dbg (stdout, "--> hogcpu dispatcher forked (%i)\n", pid);
        }
    }

  /* Hog I/O option.  */
  if (do_io)
    {
      out (stdout, "dispatching %lli hogio forks\n", do_io_forks);

      switch (pid = fork ())
        {
        case 0:                /* child */
          if (do_dryrun)
            exit (0);
          exit (hogio (do_io_forks));
        case -1:               /* error */
          err (stderr, "hogio dispatcher fork failed\n");
          exit (1);
        default:               /* parent */
          children++;
          dbg (stdout, "--> hogio dispatcher forked (%i)\n", pid);
        }
    }

  /* Hog VM option.  */
  if (do_vm)
    {
      out (stdout,
           "dispatching %lli hogvm forks, each %lli chunks of %lli bytes\n",
           do_vm_forks, do_vm_chunks, do_vm_bytes);

      switch (pid = fork ())
        {
        case 0:                /* child */
          if (do_dryrun)
            exit (0);
          exit (hogvm (do_vm_forks, do_vm_chunks, do_vm_bytes));
        case -1:               /* error */
          err (stderr, "hogvm dispatcher fork failed\n");
          exit (1);
        default:               /* parent */
          children++;
          dbg (stdout, "--> hogvm dispatcher forked (%i)\n", pid);
        }
    }

  /* Hog HDD option.  */
  if (do_hdd)
    {
      out (stdout, "dispatching %lli hoghdd forks, each %lli files of "
           "%lli bytes\n", do_hdd_forks, do_hdd_files, do_hdd_bytes);

      switch (pid = fork ())
        {
        case 0:                /* child */
          if (do_dryrun)
            exit (0);
          exit (hoghdd
                (do_hdd_forks, do_hdd_clean, do_hdd_files, do_hdd_bytes));
        case -1:               /* error */
          err (stderr, "hoghdd dispatcher fork failed\n");
          exit (1);
        default:               /* parent */
          children++;
          dbg (stdout, "--> hoghdd dispatcher forked (%i)\n", pid);
        }
    }

  /* We have no work to do, so bail out.  */
  if (children == 0)
    usage (0);

  /* Wait for our children to exit.  */
  while (children)
    {
      int status, ret;

      if ((pid = wait (&status)) > 0)
        {
          if ((WIFEXITED (status)) != 0)
            {
              if ((ret = WEXITSTATUS (status)) != 0)
                {
                  err (stderr, "dispatcher %i returned error %i\n", pid, ret);
                  retval += ret;
                }
              else
                {
                  dbg (stdout, "<-- dispatcher return (%i)\n", pid);
                }
            }
          else
            {
              err (stderr, "dispatcher did not exit normally\n");
              ++retval;
            }

          --children;
        }
      else
        {
          dbg (stdout, "wait() returned error: %s\n", strerror (errno));
          err (stderr, "detected missing dispatcher children\n");
          ++retval;
          break;
        }
    }

  /* Record our stop time.  */
  if ((stoptime = time (NULL)) == -1)
    {
      err (stderr, "failed to acquire current time\n");
      exit (1);
    }

  /* Calculate our runtime.  */
  runtime = stoptime - starttime;

  /* Print final status message.  */
  if (retval)
    {
      err (stderr, "failed run completed in %lis\n", runtime);
    }
  else
    {
      out (stdout, "successful run completed in %lis\n", runtime);
    }

  exit (retval);
}
Beispiel #2
0
int
main (int argc, char **argv)
{
  int i, pid, children = 0, retval = 0;
  long starttime, stoptime, runtime, forks;

  /* Variables that indicate which options have been selected.  */
  int do_dryrun = 0;
  long long do_backoff = 3000;
  long long do_timeout = 0;
  long long do_cpu = 0;
  long long do_io = 0;
  long long do_vm = 0;
  long long do_vm_bytes = 256 * 1024 * 1024;
  long long do_vm_stride = 4096;
  long long do_vm_hang = -1;
  int do_vm_keep = 0;
  long long do_hdd = 0;
  int do_hdd_clean = 2;
  long long do_hdd_bytes = 1024 * 1024 * 1024;

  /* Record our start time.  */
  if ((starttime = time (NULL)) == -1)
    {
      err (stderr, "failed to acquire current time: %s\n", strerror (errno));
      exit (1);
    }

  /* SuSv3 does not define any error conditions for this function.  */
  global_progname = basename (argv[0]);

  /* For portability, parse command line options without getopt_long.  */
  for (i = 1; i < argc; i++)
    {
      char *arg = argv[i];

      if (strcmp (arg, "--help") == 0 || strcmp (arg, "-?") == 0)
        {
          usage (0);
        }
      else if (strcmp (arg, "--version") == 0)
        {
          version (0);
        }
      else if (strcmp (arg, "--verbose") == 0 || strcmp (arg, "-v") == 0)
        {
          global_debug = 3;
        }
      else if (strcmp (arg, "--quiet") == 0 || strcmp (arg, "-q") == 0)
        {
          global_debug = 0;
        }
      else if (strcmp (arg, "--dry-run") == 0 || strcmp (arg, "-n") == 0)
        {
          do_dryrun = 1;
        }
      else if (strcmp (arg, "--backoff") == 0)
        {
          assert_arg ("--backoff");
          if (sscanf (arg, "%lli", &do_backoff) != 1)
            {
              err (stderr, "invalid number: %s\n", arg);
              exit (1);
            }
          if (do_backoff < 0)
            {
              err (stderr, "invalid backoff factor: %lli\n", do_backoff);
              exit (1);
            }
          dbg (stdout, "setting backoff coeffient to %llius\n", do_backoff);
        }
      else if (strcmp (arg, "--timeout") == 0 || strcmp (arg, "-t") == 0)
        {
          assert_arg ("--timeout");
          do_timeout = atoll_s (arg);
          if (do_timeout <= 0)
            {
              err (stderr, "invalid timeout value: %llis\n", do_timeout);
              exit (1);
            }
        }
      else if (strcmp (arg, "--cpu") == 0 || strcmp (arg, "-c") == 0)
        {
          assert_arg ("--cpu");
          do_cpu = atoll_b (arg);
          if (do_cpu <= 0)
            {
              err (stderr, "invalid number of cpu hogs: %lli\n", do_cpu);
              exit (1);
            }
        }
      else if (strcmp (arg, "--io") == 0 || strcmp (arg, "-i") == 0)
        {
          assert_arg ("--io");
          do_io = atoll_b (arg);
          if (do_io <= 0)
            {
              err (stderr, "invalid number of io hogs: %lli\n", do_io);
              exit (1);
            }
        }
      else if (strcmp (arg, "--vm") == 0 || strcmp (arg, "-m") == 0)
        {
          assert_arg ("--vm");
          do_vm = atoll_b (arg);
          if (do_vm <= 0)
            {
              err (stderr, "invalid number of vm hogs: %lli\n", do_vm);
              exit (1);
            }
        }
      else if (strcmp (arg, "--vm-bytes") == 0)
        {
          assert_arg ("--vm-bytes");
          do_vm_bytes = atoll_b (arg);
          if (do_vm_bytes <= 0)
            {
              err (stderr, "invalid vm byte value: %lli\n", do_vm_bytes);
              exit (1);
            }
        }
      else if (strcmp (arg, "--vm-stride") == 0)
        {
          assert_arg ("--vm-stride");
          do_vm_stride = atoll_b (arg);
          if (do_vm_stride <= 0)
            {
              err (stderr, "invalid stride value: %lli\n", do_vm_stride);
              exit (1);
            }
        }
      else if (strcmp (arg, "--vm-hang") == 0)
        {
          assert_arg ("--vm-hang");
          do_vm_hang = atoll_b (arg);
          if (do_vm_hang < 0)
            {
              err (stderr, "invalid value: %lli\n", do_vm_hang);
              exit (1);
            }
        }
      else if (strcmp (arg, "--vm-keep") == 0)
        {
          do_vm_keep = 1;
        }
      else if (strcmp (arg, "--hdd") == 0 || strcmp (arg, "-d") == 0)
        {
          assert_arg ("--hdd");
          do_hdd = atoll_b (arg);
          if (do_hdd <= 0)
            {
              err (stderr, "invalid number of hdd hogs: %lli\n", do_hdd);
              exit (1);
            }
        }
      else if (strcmp (arg, "--hdd-noclean") == 0)
        {
          do_hdd_clean = 0;
        }
      else if (strcmp (arg, "--hdd-bytes") == 0)
        {
          assert_arg ("--hdd-bytes");
          do_hdd_bytes = atoll_b (arg);
          if (do_hdd_bytes <= 0)
            {
              err (stderr, "invalid hdd byte value: %lli\n", do_hdd_bytes);
              exit (1);
            }
        }
      else
        {
          err (stderr, "unrecognized option: %s\n", arg);
          exit (1);
        }
    }

  /* Print startup message if we have work to do, bail otherwise.  */
  if (do_cpu + do_io + do_vm + do_hdd)
    {
      out (stdout, "dispatching hogs: %lli cpu, %lli io, %lli vm, %lli hdd\n",
           do_cpu, do_io, do_vm, do_hdd);
    }
  else
    usage (0);

  /* Round robin dispatch our worker processes.  */
  while ((forks = (do_cpu + do_io + do_vm + do_hdd)))
    {
      long long backoff, timeout = 0;

      /* Calculate the backoff value so we get good fork throughput.  */
      backoff = do_backoff * forks;
      dbg (stdout, "using backoff sleep of %llius\n", backoff);

      /* If we are supposed to respect a timeout, calculate it.  */
      if (do_timeout)
        {
          long long currenttime;

          /* Acquire current time.  */
          if ((currenttime = time (NULL)) == -1)
            {
              perror ("error acquiring current time");
              exit (1);
            }

          /* Calculate timeout based on current time.  */
          timeout = do_timeout - (currenttime - starttime);

          if (timeout > 0)
            {
              dbg (stdout, "setting timeout to %llis\n", timeout);
            }
          else
            {
              wrn (stderr, "used up time before all workers dispatched\n");
              break;
            }
        }

      if (do_cpu)
        {
          switch (pid = fork ())
            {
            case 0:            /* child */
              alarm (timeout);
              usleep (backoff);
              if (do_dryrun)
                exit (0);
              exit (hogcpu ());
            case -1:           /* error */
              err (stderr, "fork failed: %s\n", strerror (errno));
              break;
            default:           /* parent */
              dbg (stdout, "--> hogcpu worker %lli [%i] forked\n",
                   do_cpu, pid);
              ++children;
            }
          --do_cpu;
        }

      if (do_io)
        {
          switch (pid = fork ())
            {
            case 0:            /* child */
              alarm (timeout);
              usleep (backoff);
              if (do_dryrun)
                exit (0);
              exit (hogio ());
            case -1:           /* error */
              err (stderr, "fork failed: %s\n", strerror (errno));
              break;
            default:           /* parent */
              dbg (stdout, "--> hogio worker %lli [%i] forked\n", do_io, pid);
              ++children;
            }
          --do_io;
        }

      if (do_vm)
        {
          switch (pid = fork ())
            {
            case 0:            /* child */
              alarm (timeout);
              usleep (backoff);
              if (do_dryrun)
                exit (0);
              exit (hogvm
                    (do_vm_bytes, do_vm_stride, do_vm_hang, do_vm_keep));
            case -1:           /* error */
              err (stderr, "fork failed: %s\n", strerror (errno));
              break;
            default:           /* parent */
              dbg (stdout, "--> hogvm worker %lli [%i] forked\n", do_vm, pid);
              ++children;
            }
          --do_vm;
        }

      if (do_hdd)
        {
          switch (pid = fork ())
            {
            case 0:            /* child */
              alarm (timeout);
              usleep (backoff);
              if (do_dryrun)
                exit (0);
              exit (hoghdd (do_hdd_bytes, do_hdd_clean));
            case -1:           /* error */
              err (stderr, "fork failed: %s\n", strerror (errno));
              break;
            default:           /* parent */
              dbg (stdout, "--> hoghdd worker %lli [%i] forked\n",
                   do_hdd, pid);
              ++children;
            }
          --do_hdd;
        }
    }

  /* Wait for our children to exit.  */
  while (children)
    {
      int status, ret;

      if ((pid = wait (&status)) > 0)
        {
          --children;

          if (WIFEXITED (status))
            {
              if ((ret = WEXITSTATUS (status)) == 0)
                {
                  dbg (stdout, "<-- worker %i returned normally\n", pid);
                }
              else
                {
                  err (stderr, "<-- worker %i returned error %i\n", pid, ret);
                  ++retval;
                  wrn (stderr, "now reaping child worker processes\n");
                  if (signal (SIGUSR1, SIG_IGN) == SIG_ERR)
                    err (stderr, "handler error: %s\n", strerror (errno));
                  if (kill (-1 * getpid (), SIGUSR1) == -1)
                    err (stderr, "kill error: %s\n", strerror (errno));
                }
            }
          else if (WIFSIGNALED (status))
            {
              if ((ret = WTERMSIG (status)) == SIGALRM)
                {
                  dbg (stdout, "<-- worker %i signalled normally\n", pid);
                }
              else if ((ret = WTERMSIG (status)) == SIGUSR1)
                {
                  dbg (stdout, "<-- worker %i reaped\n", pid);
                }
              else
                {
                  err (stderr, "<-- worker %i got signal %i\n", pid, ret);
                  ++retval;
                  wrn (stderr, "now reaping child worker processes\n");
                  if (signal (SIGUSR1, SIG_IGN) == SIG_ERR)
                    err (stderr, "handler error: %s\n", strerror (errno));
                  if (kill (-1 * getpid (), SIGUSR1) == -1)
                    err (stderr, "kill error: %s\n", strerror (errno));
                }
            }
          else
            {
              err (stderr, "<-- worker %i exited abnormally\n", pid);
              ++retval;
            }
        }
      else
        {
          err (stderr, "error waiting for worker: %s\n", strerror (errno));
          ++retval;
          break;
        }
    }

  /* Record our stop time.  */
  if ((stoptime = time (NULL)) == -1)
    {
      err (stderr, "failed to acquire current time\n");
      exit (1);
    }

  /* Calculate our runtime.  */
  runtime = stoptime - starttime;

  /* Print final status message.  */
  if (retval)
    {
      err (stderr, "failed run completed in %lis\n", runtime);
    }
  else
    {
      out (stdout, "successful run completed in %lis\n", runtime);
    }

  exit (retval);
}