Пример #1
0
static bool
benchmark_codec_with_options (struct BenchmarkContext* context, SquashCodec* codec, SquashOptions* opts) {
  SquashBenchmarkResult result = { 0, 0.0, 0.0, 0.0, 0.0 };
  bool success = false;
  SquashStatus res = SQUASH_OK;
  const int level = squash_options_get_int (opts, codec, "level");

#if !defined(SQUASH_BENCHMARK_NO_FORK)
  char fifo_name[] = ".squash-benchmark-fifo-XXXXXX";

  assert (mkfifo (mktemp (fifo_name), 0600) == 0);

  if (fork () == 0) {
    int out_descriptor = open (fifo_name, O_WRONLY);
#else
    int descriptors[2];
    assert (pipe (descriptors) == 0);
    int out_descriptor = descriptors[1];
#endif
    FILE* compressed = squash_tmpfile ();
    FILE* decompressed = squash_tmpfile ();
    SquashTimer* timer = squash_timer_new ();
    int iterations = 0;

    if (level < 0) {
      fputs ("    compressing: ", stdout);
    } else {
      fprintf (stdout, "    level %d: ", level);
    }

    if (fseek (context->input, 0, SEEK_SET) != 0) {
      perror ("Unable to seek to beginning of input file");
      exit (-1);
    }

    for ( iterations = 0 ; squash_timer_get_elapsed_cpu (timer) < min_exec_time ; iterations++ ) {
      fseek (context->input, 0, SEEK_SET);
      fseek (compressed, 0, SEEK_SET);

      rewind (compressed);
      squash_timer_start (timer);
      res = squash_splice_with_options (codec, SQUASH_STREAM_COMPRESS, compressed, context->input, 0, opts);
      squash_timer_stop (timer);
      rewind (context->input);

      if (res != SQUASH_OK) {
	fprintf (stderr, "ERROR: %s (%d) squash_splice_with_options (%s, compress, %p, %p, 0, %p)\n", squash_status_to_string (res), res, squash_codec_get_name (codec), compressed, context->input, opts);
        break;
      }
    }

    if (res == SQUASH_OK) {
      result.compressed_size = ftell (compressed);
      result.compress_cpu = squash_timer_get_elapsed_cpu (timer) / iterations;
      result.compress_wall = squash_timer_get_elapsed_wall (timer) / iterations;
      squash_timer_reset (timer);

      if (result.compressed_size == 0) {
        fprintf (stdout, "failed (0 byte output, %s [%d]).\n", squash_status_to_string (res), res);
      } else {
        fprintf (stdout, "compressed (%.6fs CPU, %.6fs wall, %ld bytes)... ",
                 result.compress_cpu,
                 result.compress_wall,
                 result.compressed_size);

        for ( iterations = 0 ; squash_timer_get_elapsed_cpu (timer) < min_exec_time ; iterations++ ) {
          fseek (compressed, 0, SEEK_SET);
          fseek (decompressed, 0, SEEK_SET);

          squash_timer_start (timer);
	  res = squash_splice_with_options (codec, SQUASH_STREAM_DECOMPRESS, decompressed, compressed, 0, opts);
          squash_timer_stop (timer);
	  rewind (compressed);

          if (res != SQUASH_OK) {
            break;
          }
        }

        if (res != SQUASH_OK) {
          fprintf (stderr, "Failed (%s [%d]).\n", squash_status_to_string (res), res);
        } else {
          result.decompress_cpu = squash_timer_get_elapsed_cpu (timer) / iterations;
          result.decompress_wall = squash_timer_get_elapsed_wall (timer) / iterations;
          squash_timer_reset (timer);

          if (ftell (decompressed) != context->input_size) {
            /* Should never happen. */
            fprintf (stderr, "Failed (size mismatch; expected %ld, got %ld.\n", context->input_size, ftell (decompressed));
          } else {
            fprintf (stdout, "decompressed (%.6fs CPU, %.6fs wall).\n",
                     result.decompress_cpu,
                     result.decompress_wall);

            write (out_descriptor, &result, sizeof (SquashBenchmarkResult));
          }
        }
      }
    }

    squash_timer_free (timer);
    fclose (compressed);
    fclose (decompressed);

    close (out_descriptor);
#if !defined(SQUASH_BENCHMARK_NO_FORK)
    exit (0);
  } else {
    int in_descriptor = open (fifo_name, O_RDONLY);
#else
    int in_descriptor = descriptors[0];
#endif
    size_t bytes_read = read (in_descriptor, &result, sizeof (SquashBenchmarkResult));
    wait (NULL);
    if (bytes_read == sizeof (SquashBenchmarkResult)) {
      if (context->csv != NULL) {
        if (level >= 0) {
          fprintf (context->csv, "%s,%s,%s,%d,%ld,%f,%f,%f,%f\r\n",
                   context->input_name,
                   squash_plugin_get_name (squash_codec_get_plugin (codec)),
                   squash_codec_get_name (codec),
                   level,
                   result.compressed_size,
                   result.compress_cpu,
                   result.compress_wall,
                   result.decompress_cpu,
                   result.decompress_wall);
        } else {
          fprintf (context->csv, "%s,%s,%s,,%ld,%f,%f,%f,%f\r\n",
                   context->input_name,
                   squash_plugin_get_name (squash_codec_get_plugin (codec)),
                   squash_codec_get_name (codec),
                   result.compressed_size,
                   result.compress_cpu,
                   result.compress_wall,
                   result.decompress_cpu,
                   result.decompress_wall);
        }
      }

      success = true;
    }
    close (in_descriptor);
#if !defined(SQUASH_BENCHMARK_NO_FORK)
    unlink (fifo_name);
  }
#endif

  return success;
}
Пример #2
0
int main (int argc, char** argv) {
  SquashStatus res;
  SquashCodec* codec = NULL;
  SquashOptions* options = NULL;
  SquashStreamType direction = SQUASH_STREAM_COMPRESS;
  FILE* input = NULL;
  FILE* output = NULL;
  char* input_name = NULL;
  char* output_name = NULL;
  bool list_codecs = false;
  bool list_plugins = false;
  char** option_keys = NULL;
  char** option_values = NULL;
  bool keep = false;
  bool force = false;
  int opt;
  int optc = 0;
  char* tmp_string;
  int retval = EXIT_SUCCESS;
  struct parg_state ps;
  int optend;
  const struct parg_option squash_options[] = {
    {"keep", PARG_NOARG, NULL, 'k'},
    {"option", PARG_REQARG, NULL, 'o'},
    {"codec", PARG_REQARG, NULL, 'c'},
    {"list-codecs", PARG_NOARG, NULL, 'L'},
    {"list-plugins", PARG_NOARG, NULL, 'P'},
    {"force", PARG_NOARG, NULL, 'f'},
    {"decompress", PARG_NOARG, NULL, 'd'},
    {"version", PARG_NOARG, NULL, 'V'},
    {"help", PARG_NOARG, NULL, 'h'},
    {NULL, 0, NULL, 0}
  };

  option_keys = (char**) malloc (sizeof (char*));
  option_values = (char**) malloc (sizeof (char*));
  *option_keys = NULL;
  *option_values = NULL;

  optend = parg_reorder (argc, argv, "c:ko:123456789LPfdhb:V", squash_options);

  parg_init(&ps);

  while ( (opt = parg_getopt_long (&ps, optend, argv, "c:ko:123456789LPfdhb:V", squash_options, NULL)) != -1 ) {
    switch ( opt ) {
      case 'c':
        codec = squash_get_codec (ps.optarg);
        if ( codec == NULL ) {
          fprintf (stderr, "Unable to find codec '%s'\n", ps.optarg);
          retval = exit_failure ();
          goto cleanup;
        }
        break;
      case 'k':
        keep = true;
        break;
      case 'o':
        parse_option (&option_keys, &option_values, ps.optarg);
        break;
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        tmp_string = malloc (8);
        snprintf (tmp_string, 8, "level=%c", (char) opt);
        parse_option (&option_keys, &option_values, tmp_string);
        free (tmp_string);
        break;
      case 'L':
        list_codecs = true;
        break;
      case 'P':
        list_plugins = true;
        break;
      case 'f':
        force = true;
        break;
      case 'h':
        print_help_and_exit (argc, argv, EXIT_SUCCESS);
        break;
      case 'd':
        direction = SQUASH_STREAM_DECOMPRESS;
        break;
      case 'V':
        print_version_and_exit (argc, argv, EXIT_SUCCESS);
        break;
    }

    optc++;
  }

  if (list_plugins) {
    if (list_codecs)
      squash_foreach_plugin (list_plugins_and_codecs_foreach_cb, NULL);
    else
      squash_foreach_plugin (list_plugins_foreach_cb, NULL);

    goto cleanup;
  } else if (list_codecs) {
    squash_foreach_codec (list_codecs_foreach_cb, NULL);
    goto cleanup;
  }

  if ( ps.optind < argc ) {
    input_name = argv[ps.optind++];

    if ( (direction == SQUASH_STREAM_DECOMPRESS) && codec == NULL ) {
      char* extension;

      extension = strrchr (input_name, '.');
      if (extension != NULL)
        extension++;

      if (extension != NULL)
        codec = squash_get_codec_from_extension (extension);
    }
  } else {
    fprintf (stderr, "You must provide an input file name.\n");
    retval = exit_failure ();
    goto cleanup;
  }

  if ( ps.optind < argc ) {
    output_name = strdup (argv[ps.optind++]);

    if ( codec == NULL && direction == SQUASH_STREAM_COMPRESS ) {
      const char* extension = strrchr (output_name, '.');
      if (extension != NULL)
        extension++;

      if (extension != NULL)
        codec = squash_get_codec_from_extension (extension);
    }
  } else {
    if ( codec != NULL ) {
      const char* extension = squash_codec_get_extension (codec);
      if (extension != NULL) {
        if (strcmp (input_name, "-") == 0) {
          output_name = strdup ("-");
        } else {
          size_t extension_length = strlen (extension);
          size_t input_name_length = strlen (input_name);

          if ( (extension_length + 1) < input_name_length &&
               input_name[input_name_length - (1 + extension_length)] == '.' &&
               strcasecmp (extension, input_name + (input_name_length - (extension_length))) == 0 ) {
            output_name = squash_strndup (input_name, input_name_length - (1 + extension_length));
          }
        }
      }
    }
  }

  if ( ps.optind < argc ) {
    fprintf (stderr, "Too many arguments.\n");
  }

  if ( codec == NULL ) {
    fprintf (stderr, "Unable to determine codec.  Please pass -c \"codec\", or -L to see a list of available codecs.\n");
    retval = exit_failure ();
    goto cleanup;
  }

  if ( output_name == NULL ) {
    fprintf (stderr, "Unable to determine output file.\n");
    retval = exit_failure ();
    goto cleanup;
  }

  if ( strcmp (input_name, "-") == 0 ) {
    input = stdin;
  } else {
    input = fopen (input_name, "rb");
    if ( input == NULL ) {
      perror ("Unable to open input file");
      retval = exit_failure ();
      goto cleanup;
    }
  }

  if ( strcmp (output_name, "-") == 0 ) {
    output = stdout;
  } else {
    int output_fd = open (output_name,
#if !defined(_WIN32)
                          O_RDWR | O_CREAT | (force ? O_TRUNC : O_EXCL),
                          S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
#else
                          O_RDWR | O_CREAT | (force ? O_TRUNC : O_EXCL) | O_BINARY,
                          S_IREAD | S_IWRITE
#endif
    );
    if ( output_fd < 0 ) {
      perror ("Unable to open output file");
      retval = exit_failure ();
      goto cleanup;
    }
    output = fdopen (output_fd, "wb");
    if ( output == NULL ) {
      perror ("Unable to open output");
      retval = exit_failure ();
      goto cleanup;
    }
  }

  options = squash_options_newa (codec, (const char * const*) option_keys, (const char * const*) option_values);

  res = squash_splice_with_options (codec, direction, output, input, 0, options);

  if ( res != SQUASH_OK ) {
    fprintf (stderr, "Failed to %s: %s\n",
             (direction == SQUASH_STREAM_COMPRESS) ? "compress" : "decompress",
             squash_status_to_string (res));
    retval = exit_failure ();
    goto cleanup;
  }

  if ( !keep && input != stdin ) {
    fclose (input);
    if ( unlink (input_name) != 0 ) {
      perror ("Unable to remove input file");
    }
    input = NULL;
  }

 cleanup:

  if (input != stdin && input != NULL)
    fclose (stdin);

  if (output != stdout)
    fclose (stdout);

  if (option_keys != NULL) {
    for (opt = 0 ; option_keys[opt] != NULL ; opt++) {
      free(option_keys[opt]);
    }
    free (option_keys);
  }

  if (option_values != NULL) {
    for (opt = 0 ; option_values[opt] != NULL ; opt++) {
      free(option_values[opt]);
    }
    free (option_values);
  }

  free (output_name);

  return retval;
}