mdtest/src/parse_options.c

477 lines
23 KiB
C
Raw Normal View History

/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
2011-06-17 23:20:43 +04:00
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* Parse commandline functions.
2011-06-17 23:20:43 +04:00
*
\******************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
2011-06-17 23:20:43 +04:00
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
2011-06-17 23:20:43 +04:00
#include <string.h>
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#include "utilities.h"
#include "ior.h"
#include "aiori.h"
#include "parse_options.h"
#include "option.h"
#include "aiori.h"
2011-06-17 23:20:43 +04:00
IOR_param_t initialTestParams;
option_help * createGlobalOptions(IOR_param_t * params);
2012-01-09 06:41:30 +04:00
static IOR_param_t * parameters;
static options_all_t * global_options;
2012-01-09 06:41:30 +04:00
2011-06-17 23:20:43 +04:00
/*
* Check and correct all settings of each test in queue for correctness.
*/
static void CheckRunSettings(IOR_test_t *tests)
{
IOR_test_t *ptr;
IOR_param_t *params;
for (ptr = tests; ptr != NULL; ptr = ptr->next) {
params = &ptr->params;
/* If no write/read/check action requested, set both write and read */
if (params->writeFile == FALSE
&& params->readFile == FALSE
&& params->checkWrite == FALSE
&& params->checkRead == FALSE) {
params->readFile = TRUE;
params->writeFile = TRUE;
}
if(params->dualMount && !params->filePerProc) {
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "Dual Mount can only be used with File Per Process");
}
2011-06-17 23:20:43 +04:00
}
2011-11-12 03:11:28 +04:00
}
2011-06-17 23:20:43 +04:00
/*
* Set flags from commandline string/value pairs.
*/
void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_options)
2011-06-17 23:20:43 +04:00
{
char option[MAX_STR];
char value[MAX_STR];
int rc;
int initialized;
rc = sscanf(line, " %[^=# \t\r\n] = %[^# \t\r\n] ", option, value);
if (rc != 2 && rank == 0) {
fprintf(out_logfile, "Syntax error in configuration options: %s\n",
line);
MPI_CHECK(MPI_Initialized(&initialized), "MPI_Initialized() error");
if (initialized)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
else
exit(-1);
}
if (strcasecmp(option, "api") == 0) {
params->api = strdup(value);
params->backend = aiori_select(params->api);
if (params->backend == NULL){
fprintf(out_logfile, "Could not load backend API %s\n", params->api);
exit(-1);
}
2018-07-08 15:07:32 +03:00
} else if (strcasecmp(option, "summaryFile") == 0) {
if (rank == 0){
out_resultfile = fopen(value, "w");
if (out_resultfile == NULL){
FAIL("Cannot open output file for writes!");
}
printf("Writing output to %s\n", value);
2018-07-08 15:07:32 +03:00
}
} else if (strcasecmp(option, "summaryFormat") == 0) {
if(strcasecmp(value, "default") == 0){
2018-07-08 15:07:32 +03:00
outputFormat = OUTPUT_DEFAULT;
}else if(strcasecmp(value, "JSON") == 0){
2018-07-08 15:07:32 +03:00
outputFormat = OUTPUT_JSON;
}else if(strcasecmp(value, "CSV") == 0){
2018-07-08 15:07:32 +03:00
outputFormat = OUTPUT_CSV;
}else{
FAIL("Unknown summaryFormat");
}
2012-01-14 02:05:13 +04:00
} else if (strcasecmp(option, "refnum") == 0) {
params->referenceNumber = atoi(value);
} else if (strcasecmp(option, "debug") == 0) {
params->debug = strdup(value);
} else if (strcasecmp(option, "platform") == 0) {
params->platform = strdup(value);
} else if (strcasecmp(option, "testfile") == 0) {
params->testFileName = strdup(value);
} else if (strcasecmp(option, "dualmount") == 0){
params->dualMount = atoi(value);
} else if (strcasecmp(option, "deadlineforstonewalling") == 0) {
params->deadlineForStonewalling = atoi(value);
} else if (strcasecmp(option, "stoneWallingWearOut") == 0) {
params->stoneWallingWearOut = atoi(value);
} else if (strcasecmp(option, "stoneWallingWearOutIterations") == 0) {
params->stoneWallingWearOutIterations = atoll(value);
} else if (strcasecmp(option, "stoneWallingStatusFile") == 0) {
params->stoneWallingStatusFile = strdup(value);
} else if (strcasecmp(option, "maxtimeduration") == 0) {
params->maxTimeDuration = atoi(value);
} else if (strcasecmp(option, "outlierthreshold") == 0) {
params->outlierThreshold = atoi(value);
Fix #181. On systems where numTasks is not evenly divisible by 'tasksPerNode' we were seeing some nodes reading multiple files while others read none after reordering. Commonly all nodes have the same number of tasks but there is nothing requiring that to be the case. Imagine having 64 tasks running against 4 nodes which can run 20 tasks each. Here you get three groups of 20 and one group of 4. On this sytem nodes running in the group of 4 were previously getting tasksPerNode of 4 which meant they reordered tasks differently than the nodes which got tasksPerNode of 20. The key to fixing this is ensuring that every node reorders tasks the same way, which means ensuring they all use the same input values. Obviously on systems where the number of tasks per node is inconsistent the reordering will also be inconsistent (some tasks may end up on the same node, or not as far separated as desired, etc.) but at least this way you'll always end up with a 1:1 reordering. - Renamed nodes/nodeCount to numNodes - Renamed tasksPerNode to numTasksOnNode0 - Ensured that numTasksOnNode0 will always have the same value regardless of which node you're on - Removed inconsistently used globals numTasksWorld and tasksPerNode and replaced with per-test params equivalents - Added utility functions for setting these values: - numNodes -> GetNumNodes - numTasks -> GetNumTasks - numTasksOnNode0 -> GetNumNodesOnTask0 - Improved MPI_VERSION < 3 logic for GetNumNodes so it works when numTasks is not evenly divisible by numTasksOnNode0 - Left 'nodes' and 'tasksPerNode' in output alone to not break compatibility - Allowed command-line params to override numTasks, numNodes, and numTasksOnNode0 but default to using the MPI-calculated values
2019-08-31 01:45:03 +03:00
} else if (strcasecmp(option, "numnodes") == 0) {
params->numNodes = atoi(value);
} else if (strcasecmp(option, "numtasks") == 0) {
params->numTasks = atoi(value);
} else if (strcasecmp(option, "numtasksonnode0") == 0) {
params->numTasksOnNode0 = atoi(value);
} else if (strcasecmp(option, "repetitions") == 0) {
params->repetitions = atoi(value);
} else if (strcasecmp(option, "intertestdelay") == 0) {
params->interTestDelay = atoi(value);
} else if (strcasecmp(option, "interiodelay") == 0) {
params->interIODelay = atoi(value);
} else if (strcasecmp(option, "readfile") == 0) {
params->readFile = atoi(value);
} else if (strcasecmp(option, "writefile") == 0) {
params->writeFile = atoi(value);
} else if (strcasecmp(option, "fileperproc") == 0) {
params->filePerProc = atoi(value);
} else if (strcasecmp(option, "taskpernodeoffset") == 0) {
params->taskPerNodeOffset = atoi(value);
} else if (strcasecmp(option, "reordertasksconstant") == 0) {
params->reorderTasks = atoi(value);
} else if (strcasecmp(option, "reordertasksrandom") == 0) {
params->reorderTasksRandom = atoi(value);
} else if (strcasecmp(option, "reordertasksrandomSeed") == 0) {
params->reorderTasksRandomSeed = atoi(value);
} else if (strcasecmp(option, "reordertasks") == 0) {
/* Backwards compatibility for the "reorderTasks" option.
MUST follow the other longer reordertasks checks. */
params->reorderTasks = atoi(value);
} else if (strcasecmp(option, "checkwrite") == 0) {
params->checkWrite = atoi(value);
} else if (strcasecmp(option, "checkread") == 0) {
params->checkRead = atoi(value);
} else if (strcasecmp(option, "keepfile") == 0) {
params->keepFile = atoi(value);
} else if (strcasecmp(option, "keepfilewitherror") == 0) {
params->keepFileWithError = atoi(value);
} else if (strcasecmp(option, "multiFile") == 0) {
params->multiFile = atoi(value);
} else if (strcasecmp(option, "warningAsErrors") == 0) {
params->warningAsErrors = atoi(value);
} else if (strcasecmp(option, "segmentcount") == 0) {
params->segmentCount = string_to_bytes(value);
} else if (strcasecmp(option, "blocksize") == 0) {
params->blockSize = string_to_bytes(value);
} else if (strcasecmp(option, "transfersize") == 0) {
params->transferSize = string_to_bytes(value);
} else if (strcasecmp(option, "singlexferattempt") == 0) {
params->singleXferAttempt = atoi(value);
} else if (strcasecmp(option, "intraTestBarriers") == 0) {
params->intraTestBarriers = atoi(value);
} else if (strcasecmp(option, "verbose") == 0) {
params->verbose = atoi(value);
} else if (strcasecmp(option, "settimestampsignature") == 0) {
params->setTimeStampSignature = atoi(value);
} else if (strcasecmp(option, "storefileoffset") == 0) {
params->storeFileOffset = atoi(value);
} else if (strcasecmp(option, "uniqueDir") == 0) {
params->uniqueDir = atoi(value);
} else if (strcasecmp(option, "useexistingtestfile") == 0) {
params->useExistingTestFile = atoi(value);
} else if (strcasecmp(option, "fsyncperwrite") == 0) {
params->fsyncPerWrite = atoi(value);
} else if (strcasecmp(option, "fsync") == 0) {
params->fsync = atoi(value);
} else if (strcasecmp(option, "randomoffset") == 0) {
params->randomOffset = atoi(value);
} else if (strcasecmp(option, "memoryPerTask") == 0) {
params->memoryPerTask = string_to_bytes(value);
2012-01-09 06:41:30 +04:00
params->memoryPerNode = 0;
} else if (strcasecmp(option, "memoryPerNode") == 0) {
params->memoryPerNode = NodeMemoryStringToBytes(value);
params->memoryPerTask = 0;
} else if (strcasecmp(option, "summaryalways") == 0) {
params->summary_every_test = atoi(value);
} else {
// backward compatibility for now
if (strcasecmp(option, "useo_direct") == 0) {
strcpy(option, "--posix.odirect");
}
int parsing_error = option_parse_key_value(option, value, module_options);
if(parsing_error){
if (rank == 0)
fprintf(out_logfile, "Unrecognized parameter \"%s\"\n",
option);
MPI_CHECK(MPI_Initialized(&initialized), "MPI_Initialized() error");
if (initialized)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error");
else
exit(-1);
}
}
2011-11-12 03:11:28 +04:00
}
2011-06-17 23:20:43 +04:00
2011-06-17 23:20:43 +04:00
/*
* Parse a single line, which may contain multiple comma-seperated directives
*/
void ParseLine(char *line, IOR_param_t * test, options_all_t * module_options)
2011-06-17 23:20:43 +04:00
{
char *start, *end;
2011-06-17 23:20:43 +04:00
char * newline = strdup(line);
start = newline;
do {
2019-04-19 12:20:04 +03:00
end = strchr(start, '#');
if (end != NULL){
2019-04-19 12:20:04 +03:00
*end = '\0';
end = NULL; // stop parsing after comment
}
end = strchr(start, ',');
if (end != NULL){
*end = '\0';
}
if(strlen(start) < 3){
fprintf(out_logfile, "Invalid option substring string: \"%s\" in \"%s\"\n", start, line);
exit(1);
}
DecodeDirective(start, test, module_options);
start = end + 1;
} while (end != NULL);
free(newline);
2011-11-12 03:11:28 +04:00
}
2011-06-17 23:20:43 +04:00
2019-05-16 14:56:56 +03:00
static void decodeDirectiveWrapper(char *line){
ParseLine(line, parameters, global_options);
}
2011-06-17 23:20:43 +04:00
/*
* Determines if the string "haystack" contains only the string "needle", and
* possibly whitespace before and after needle. Function is case insensitive.
*/
int contains_only(char *haystack, char *needle)
2011-06-17 23:20:43 +04:00
{
char *ptr, *end;
2011-06-17 23:20:43 +04:00
end = haystack + strlen(haystack);
/* skip over leading shitspace */
for (ptr = haystack; ptr < end; ptr++) {
if (!isspace(*ptr))
break;
}
/* check for "needle" */
if (strncasecmp(ptr, needle, strlen(needle)) != 0)
return 0;
2020-07-03 10:09:40 +03:00
/* make sure the rest of the line is only whitespace as well */
for (ptr += strlen(needle); ptr < end; ptr++) {
if (!isspace(*ptr))
return 0;
}
return 1;
2011-11-12 03:11:28 +04:00
}
2011-06-17 23:20:43 +04:00
/*
* Read the configuration script, allocating and filling in the structure of
* global parameters.
*/
IOR_test_t *ReadConfigScript(char *scriptName)
2011-06-17 23:20:43 +04:00
{
int test_num = 0;
int runflag = 0;
char linebuf[MAX_STR];
char empty[MAX_STR];
char *ptr;
FILE *file;
IOR_test_t *head = NULL;
IOR_test_t *tail = NULL;
option_help ** option_p = & global_options->modules[0].options;
/* Initialize the first test */
head = CreateTest(& initialTestParams, test_num++);
tail = head;
*option_p = createGlobalOptions(& ((IOR_test_t*) head)->params); /* The current options */
/* open the script */
file = fopen(scriptName, "r");
if (file == NULL)
ERR("fopen() failed");
/* search for the "IOR START" line */
while (fgets(linebuf, MAX_STR, file) != NULL) {
if (contains_only(linebuf, "ior start")) {
break;
}
2011-06-17 23:20:43 +04:00
}
/* Iterate over a block of IOR commands */
while (fgets(linebuf, MAX_STR, file) != NULL) {
/* skip over leading whitespace */
ptr = linebuf;
while (isspace(*ptr))
ptr++;
/* skip empty lines */
if (sscanf(ptr, "%s", empty) == -1)
continue;
/* skip lines containing only comments */
if (sscanf(ptr, " #%s", empty) == 1)
continue;
if (contains_only(ptr, "ior stop")) {
break;
} else if (contains_only(ptr, "run")) {
if (runflag) {
/* previous line was a "run" as well
create duplicate test */
tail->next = CreateTest(&tail->params, test_num++);
2018-08-29 19:49:41 +03:00
AllocResults(tail);
((IOR_test_t*) tail)->params.backend_options = airoi_update_module_options(((IOR_test_t*) tail)->params.backend, global_options);
tail = tail->next;
*option_p = createGlobalOptions(& ((IOR_test_t*) tail->next)->params);
}
runflag = 1;
} else if (runflag) {
/* If this directive was preceded by a "run" line, then
create and initialize a new test structure */
runflag = 0;
tail->next = CreateTest(&tail->params, test_num++);
*option_p = createGlobalOptions(& ((IOR_test_t*) tail->next)->params);
2018-08-29 19:49:41 +03:00
AllocResults(tail);
((IOR_test_t*) tail)->params.backend_options = airoi_update_module_options(((IOR_test_t*) tail)->params.backend, global_options);
tail = tail->next;
ParseLine(ptr, &tail->params, global_options);
} else {
ParseLine(ptr, &tail->params, global_options);
}
2011-06-17 23:20:43 +04:00
}
/* close the script */
if (fclose(file) != 0)
ERR("fclose() of script file failed");
AllocResults(tail); /* copy the actual module options into the test */
((IOR_test_t*) tail)->params.backend_options = airoi_update_module_options(((IOR_test_t*) tail)->params.backend, global_options);
2011-06-17 23:20:43 +04:00
return head;
2011-11-12 03:11:28 +04:00
}
2011-06-17 23:20:43 +04:00
option_help * createGlobalOptions(IOR_param_t * params){
char APIs[1024];
char APIs_legacy[1024];
aiori_supported_apis(APIs, APIs_legacy, IOR);
char apiStr[1024];
sprintf(apiStr, "API for I/O [%s]", APIs);
option_help o [] = {
{'a', NULL, apiStr, OPTION_OPTIONAL_ARGUMENT, 's', & params->api},
{'A', NULL, "refNum -- user supplied reference number to include in the summary", OPTION_OPTIONAL_ARGUMENT, 'd', & params->referenceNumber},
{'b', NULL, "blockSize -- contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'l', & params->blockSize},
{'c', "collective", "Use collective I/O", OPTION_FLAG, 'd', & params->collective},
{'C', NULL, "reorderTasks -- changes task ordering for readback (useful to avoid client cache)", OPTION_FLAG, 'd', & params->reorderTasks},
{'d', NULL, "interTestDelay -- delay between reps in seconds", OPTION_OPTIONAL_ARGUMENT, 'd', & params->interTestDelay},
{'D', NULL, "deadlineForStonewalling -- seconds before stopping write or read phase", OPTION_OPTIONAL_ARGUMENT, 'd', & params->deadlineForStonewalling},
2020-07-03 10:09:40 +03:00
{.help=" -O stoneWallingWearOut=1 -- once the stonewalling timeout is over, all process finish to access the amount of data", .arg = OPTION_OPTIONAL_ARGUMENT},
{.help=" -O stoneWallingWearOutIterations=N -- stop after processing this number of iterations, needed for reading data back written with stoneWallingWearOut", .arg = OPTION_OPTIONAL_ARGUMENT},
{.help=" -O stoneWallingStatusFile=FILE -- this file keeps the number of iterations from stonewalling during write and allows to use them for read", .arg = OPTION_OPTIONAL_ARGUMENT},
2019-09-01 17:29:12 +03:00
{'e', NULL, "fsync -- perform a fsync() operation at the end of each read/write phase", OPTION_FLAG, 'd', & params->fsync},
{'E', NULL, "useExistingTestFile -- do not remove test file before write access", OPTION_FLAG, 'd', & params->useExistingTestFile},
{'f', NULL, "scriptFile -- test script name", OPTION_OPTIONAL_ARGUMENT, 's', & params->testscripts},
{'F', NULL, "filePerProc -- file-per-process", OPTION_FLAG, 'd', & params->filePerProc},
{'g', NULL, "intraTestBarriers -- use barriers between open, write/read, and close", OPTION_FLAG, 'd', & params->intraTestBarriers},
/* This option toggles between Incompressible Seed and Time stamp sig based on -l,
* so we'll toss the value in both for now, and sort it out in initialization
* after all the arguments are in and we know which it keep.
*/
{'G', NULL, "setTimeStampSignature -- set value for time stamp signature/random seed", OPTION_OPTIONAL_ARGUMENT, 'd', & params->setTimeStampSignature},
{'i', NULL, "repetitions -- number of repetitions of test", OPTION_OPTIONAL_ARGUMENT, 'd', & params->repetitions},
{'j', NULL, "outlierThreshold -- warn on outlier N seconds from mean", OPTION_OPTIONAL_ARGUMENT, 'd', & params->outlierThreshold},
{'k', NULL, "keepFile -- don't remove the test file(s) on program exit", OPTION_FLAG, 'd', & params->keepFile},
{'K', NULL, "keepFileWithError -- keep error-filled file(s) after data-checking", OPTION_FLAG, 'd', & params->keepFileWithError},
{'l', NULL, "datapacket type-- type of packet that will be created [offset|incompressible|timestamp|o|i|t]", OPTION_OPTIONAL_ARGUMENT, 's', & params->buffer_type},
{'m', NULL, "multiFile -- use number of reps (-i) for multiple file count", OPTION_FLAG, 'd', & params->multiFile},
{'M', NULL, "memoryPerNode -- hog memory on the node (e.g.: 2g, 75%)", OPTION_OPTIONAL_ARGUMENT, 's', & params->memoryPerNodeStr},
Fix #181. On systems where numTasks is not evenly divisible by 'tasksPerNode' we were seeing some nodes reading multiple files while others read none after reordering. Commonly all nodes have the same number of tasks but there is nothing requiring that to be the case. Imagine having 64 tasks running against 4 nodes which can run 20 tasks each. Here you get three groups of 20 and one group of 4. On this sytem nodes running in the group of 4 were previously getting tasksPerNode of 4 which meant they reordered tasks differently than the nodes which got tasksPerNode of 20. The key to fixing this is ensuring that every node reorders tasks the same way, which means ensuring they all use the same input values. Obviously on systems where the number of tasks per node is inconsistent the reordering will also be inconsistent (some tasks may end up on the same node, or not as far separated as desired, etc.) but at least this way you'll always end up with a 1:1 reordering. - Renamed nodes/nodeCount to numNodes - Renamed tasksPerNode to numTasksOnNode0 - Ensured that numTasksOnNode0 will always have the same value regardless of which node you're on - Removed inconsistently used globals numTasksWorld and tasksPerNode and replaced with per-test params equivalents - Added utility functions for setting these values: - numNodes -> GetNumNodes - numTasks -> GetNumTasks - numTasksOnNode0 -> GetNumNodesOnTask0 - Improved MPI_VERSION < 3 logic for GetNumNodes so it works when numTasks is not evenly divisible by numTasksOnNode0 - Left 'nodes' and 'tasksPerNode' in output alone to not break compatibility - Allowed command-line params to override numTasks, numNodes, and numTasksOnNode0 but default to using the MPI-calculated values
2019-08-31 01:45:03 +03:00
{'N', NULL, "numTasks -- number of tasks that are participating in the test (overrides MPI)", OPTION_OPTIONAL_ARGUMENT, 'd', & params->numTasks},
{'o', NULL, "testFile -- full name for test", OPTION_OPTIONAL_ARGUMENT, 's', & params->testFileName},
{'O', NULL, "string of IOR directives (e.g. -O checkRead=1,lustreStripeCount=32)", OPTION_OPTIONAL_ARGUMENT, 'p', & decodeDirectiveWrapper},
{'Q', NULL, "taskPerNodeOffset for read tests use with -C & -Z options (-C constant N, -Z at least N)", OPTION_OPTIONAL_ARGUMENT, 'd', & params->taskPerNodeOffset},
{'r', NULL, "readFile -- read existing file", OPTION_FLAG, 'd', & params->readFile},
{'R', NULL, "checkRead -- verify that the output of read matches the expected signature (used with -G)", OPTION_FLAG, 'd', & params->checkRead},
{'s', NULL, "segmentCount -- number of segments", OPTION_OPTIONAL_ARGUMENT, 'd', & params->segmentCount},
{'t', NULL, "transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'l', & params->transferSize},
{'T', NULL, "maxTimeDuration -- max time in minutes executing repeated test; it aborts only between iterations and not within a test!", OPTION_OPTIONAL_ARGUMENT, 'd', & params->maxTimeDuration},
{'u', NULL, "uniqueDir -- use unique directory name for each file-per-process", OPTION_FLAG, 'd', & params->uniqueDir},
{'v', NULL, "verbose -- output information (repeating flag increases level)", OPTION_FLAG, 'd', & params->verbose},
{'w', NULL, "writeFile -- write file", OPTION_FLAG, 'd', & params->writeFile},
{'W', NULL, "checkWrite -- check read after write", OPTION_FLAG, 'd', & params->checkWrite},
{'x', NULL, "singleXferAttempt -- do not retry transfer if incomplete", OPTION_FLAG, 'd', & params->singleXferAttempt},
{'X', NULL, "reorderTasksRandomSeed -- random seed for -Z option", OPTION_OPTIONAL_ARGUMENT, 'd', & params->reorderTasksRandomSeed},
{'y', NULL, "dualMount -- use dual mount points for a filesystem", OPTION_FLAG, 'd', & params->dualMount},
{'Y', NULL, "fsyncPerWrite -- perform sync operation after every write operation", OPTION_FLAG, 'd', & params->fsyncPerWrite},
{'z', NULL, "randomOffset -- access is to random, not sequential, offsets within a file", OPTION_FLAG, 'd', & params->randomOffset},
{'Z', NULL, "reorderTasksRandom -- changes task ordering to random ordering for readback", OPTION_FLAG, 'd', & params->reorderTasksRandom},
{0, "warningAsErrors", "Any warning should lead to an error.", OPTION_FLAG, 'd', & params->warningAsErrors},
{.help=" -O summaryFile=FILE -- store result data into this file", .arg = OPTION_OPTIONAL_ARGUMENT},
2020-07-03 10:09:40 +03:00
{.help=" -O summaryFormat=[default,JSON,CSV] -- use the format for outputting the summary", .arg = OPTION_OPTIONAL_ARGUMENT},
{0, "dryRun", "do not perform any I/Os just run evtl. inputs print dummy output", OPTION_FLAG, 'd', & params->dryRun},
LAST_OPTION,
};
option_help * options = malloc(sizeof(o));
memcpy(options, & o, sizeof(o));
return options;
}
2011-06-17 23:20:43 +04:00
/*
* Parse Commandline.
*/
IOR_test_t *ParseCommandLine(int argc, char **argv)
2011-06-17 23:20:43 +04:00
{
init_IOR_Param_t(& initialTestParams);
IOR_test_t *tests = NULL;
initialTestParams.platform = GetPlatformName();
option_help * options = createGlobalOptions( & initialTestParams);
parameters = & initialTestParams;
global_options = airoi_create_all_module_options(options);
option_parse(argc, argv, global_options);
updateParsedOptions(& initialTestParams, global_options);
if (initialTestParams.testscripts){
tests = ReadConfigScript(initialTestParams.testscripts);
}else{
tests = CreateTest(&initialTestParams, 0);
AllocResults(tests);
}
2011-06-17 23:20:43 +04:00
CheckRunSettings(tests);
return (tests);
2011-11-12 03:11:28 +04:00
}