xref: /onnv-gate/usr/src/cmd/filebench/common/parser_gram.y (revision 6750:bd49b8b8d6f3)
15184Sek110237 /*
25184Sek110237  * CDDL HEADER START
35184Sek110237  *
45184Sek110237  * The contents of this file are subject to the terms of the
55184Sek110237  * Common Development and Distribution License (the "License").
65184Sek110237  * You may not use this file except in compliance with the License.
75184Sek110237  *
85184Sek110237  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95184Sek110237  * or http://www.opensolaris.org/os/licensing.
105184Sek110237  * See the License for the specific language governing permissions
115184Sek110237  * and limitations under the License.
125184Sek110237  *
135184Sek110237  * When distributing Covered Code, include this CDDL HEADER in each
145184Sek110237  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155184Sek110237  * If applicable, add the following below this CDDL HEADER, with the
165184Sek110237  * fields enclosed by brackets "[]" replaced with your own identifying
175184Sek110237  * information: Portions Copyright [yyyy] [name of copyright owner]
185184Sek110237  *
195184Sek110237  * CDDL HEADER END
205184Sek110237  */
215184Sek110237 /*
226084Saw148015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235184Sek110237  * Use is subject to license terms.
246613Sek110237  *
256613Sek110237  * Portions Copyright 2008 Denis Cheng
265184Sek110237  */
275184Sek110237 
285184Sek110237 %{
295184Sek110237 #pragma ident	"%Z%%M%	%I%	%E% SMI"
305184Sek110237 %}
315184Sek110237 
325184Sek110237 %{
335184Sek110237 
345184Sek110237 #include <stdlib.h>
355184Sek110237 #include <stdio.h>
365184Sek110237 #include <string.h>
375184Sek110237 #include <signal.h>
385184Sek110237 #include <errno.h>
395184Sek110237 #include <sys/types.h>
405184Sek110237 #include <locale.h>
415184Sek110237 #include <sys/utsname.h>
425184Sek110237 #ifdef HAVE_STDINT_H
435184Sek110237 #include <stdint.h>
445184Sek110237 #endif
455184Sek110237 #include <fcntl.h>
465184Sek110237 #include <sys/mman.h>
475184Sek110237 #include <sys/wait.h>
485184Sek110237 #ifdef HAVE_LIBTECLA
495184Sek110237 #include <libtecla.h>
505184Sek110237 #endif
515184Sek110237 #include "parsertypes.h"
525184Sek110237 #include "filebench.h"
535184Sek110237 #include "utils.h"
545184Sek110237 #include "stats.h"
555184Sek110237 #include "vars.h"
565184Sek110237 #include "eventgen.h"
575184Sek110237 #ifdef HAVE_LIBTECLA
585184Sek110237 #include "auto_comp.h"
595184Sek110237 #endif
605184Sek110237 
615184Sek110237 int dofile = FS_FALSE;
625184Sek110237 static const char cmdname[] = "filebench";
635184Sek110237 static const char cmd_options[] = "pa:f:hi:s:m:";
645184Sek110237 static void usage(int);
655184Sek110237 
665184Sek110237 static cmd_t *cmd = NULL;		/* Command being processed */
675184Sek110237 #ifdef HAVE_LIBTECLA
685184Sek110237 static GetLine *gl;			/* GetLine resource object */
695184Sek110237 #endif
705184Sek110237 
715184Sek110237 char *execname;
725184Sek110237 char *fscriptname;
735184Sek110237 int noproc = 0;
745184Sek110237 var_t *var_list = NULL;
755184Sek110237 pidlist_t *pidlist = NULL;
765184Sek110237 char *cwd = NULL;
775184Sek110237 FILE *parentscript = NULL;
785673Saw148015 
795673Saw148015 static int filecreate_done = 0;
805673Saw148015 
815184Sek110237 /* yacc externals */
825184Sek110237 extern FILE *yyin;
835184Sek110237 extern int yydebug;
845184Sek110237 extern void yyerror(char *s);
855184Sek110237 
865184Sek110237 /* utilities */
875184Sek110237 static void terminate(void);
885184Sek110237 static cmd_t *alloc_cmd(void);
895184Sek110237 static attr_t *alloc_attr(void);
906550Saw148015 static attr_t *alloc_lvar_attr(var_t *var);
915184Sek110237 static attr_t *get_attr(cmd_t *cmd, int64_t name);
925184Sek110237 static attr_t *get_attr_integer(cmd_t *cmd, int64_t name);
935184Sek110237 static attr_t *get_attr_bool(cmd_t *cmd, int64_t name);
946550Saw148015 static void get_attr_lvars(cmd_t *cmd, flowop_t *flowop);
955184Sek110237 static var_t *alloc_var(void);
965184Sek110237 static var_t *get_var(cmd_t *cmd, int64_t name);
975184Sek110237 static list_t *alloc_list();
986212Saw148015 static probtabent_t *alloc_probtabent(void);
996550Saw148015 static void add_lvar_to_list(var_t *newlvar, var_t **lvar_list);
1005184Sek110237 
1015184Sek110237 /* Info Commands */
1025184Sek110237 static void parser_list(cmd_t *);
1036212Saw148015 static void parser_flowop_list(cmd_t *);
1045184Sek110237 
1055184Sek110237 /* Define Commands */
1065184Sek110237 static void parser_proc_define(cmd_t *);
1075184Sek110237 static void parser_thread_define(cmd_t *, procflow_t *, int instances);
1086212Saw148015 static void parser_flowop_define(cmd_t *, threadflow_t *, flowop_t **, int);
1095184Sek110237 static void parser_file_define(cmd_t *);
1105184Sek110237 static void parser_fileset_define(cmd_t *);
1116212Saw148015 static void parser_randvar_define(cmd_t *);
1126212Saw148015 static void parser_randvar_set(cmd_t *);
1136550Saw148015 static void parser_composite_flowop_define(cmd_t *);
1145184Sek110237 
1155184Sek110237 /* Create Commands */
1165184Sek110237 static void parser_proc_create(cmd_t *);
1175184Sek110237 static void parser_thread_create(cmd_t *);
1185184Sek110237 static void parser_flowop_create(cmd_t *);
1195184Sek110237 static void parser_fileset_create(cmd_t *);
1205184Sek110237 
1216212Saw148015 /* set commands */
1226212Saw148015 static void parser_set_integer(char *, fbint_t);
1236212Saw148015 static void parser_set_var(char *, char *);
1246212Saw148015 
1255184Sek110237 /* Shutdown Commands */
1265184Sek110237 static void parser_proc_shutdown(cmd_t *);
1275184Sek110237 static void parser_filebench_shutdown(cmd_t *cmd);
1285184Sek110237 
1295184Sek110237 /* Other Commands */
1305184Sek110237 static void parser_foreach_integer(cmd_t *cmd);
1315184Sek110237 static void parser_foreach_string(cmd_t *cmd);
1325184Sek110237 static void parser_sleep(cmd_t *cmd);
1335184Sek110237 static void parser_sleep_variable(cmd_t *cmd);
1345184Sek110237 static void parser_log(cmd_t *cmd);
1355184Sek110237 static void parser_statscmd(cmd_t *cmd);
1365184Sek110237 static void parser_statsdump(cmd_t *cmd);
1375184Sek110237 static void parser_statsxmldump(cmd_t *cmd);
1385184Sek110237 static void parser_echo(cmd_t *cmd);
1395184Sek110237 static void parser_usage(cmd_t *cmd);
1405184Sek110237 static void parser_vars(cmd_t *cmd);
1415184Sek110237 static void parser_printvars(cmd_t *cmd);
1425184Sek110237 static void parser_system(cmd_t *cmd);
1435184Sek110237 static void parser_statssnap(cmd_t *cmd);
1445184Sek110237 static void parser_directory(cmd_t *cmd);
1455184Sek110237 static void parser_eventgen(cmd_t *cmd);
1465184Sek110237 static void parser_run(cmd_t *cmd);
1475184Sek110237 static void parser_run_variable(cmd_t *cmd);
1485184Sek110237 static void parser_help(cmd_t *cmd);
1495184Sek110237 static void arg_parse(const char *command);
1505184Sek110237 static void parser_abort(int arg);
151*6750Sek110237 static void parser_version(cmd_t *cmd);
1525184Sek110237 
1535184Sek110237 %}
1545184Sek110237 
1555184Sek110237 %union {
1566212Saw148015 	int64_t		 ival;
1576212Saw148015 	uchar_t		 bval;
1586212Saw148015 	char *		 sval;
1596212Saw148015 	fs_u		 val;
1606212Saw148015 	avd_t		 avd;
1616212Saw148015 	cmd_t		*cmd;
1626212Saw148015 	attr_t		*attr;
1636212Saw148015 	list_t		*list;
1646212Saw148015 	probtabent_t	*rndtb;
1655184Sek110237 }
1665184Sek110237 
1675184Sek110237 %start commands
1685184Sek110237 
1695184Sek110237 %token FSC_LIST FSC_DEFINE FSC_EXEC FSC_QUIT FSC_DEBUG FSC_CREATE
1705184Sek110237 %token FSC_SLEEP FSC_STATS FSC_FOREACH FSC_SET FSC_SHUTDOWN FSC_LOG
1715184Sek110237 %token FSC_SYSTEM FSC_FLOWOP FSC_EVENTGEN FSC_ECHO FSC_LOAD FSC_RUN
172*6750Sek110237 %token FSC_USAGE FSC_HELP FSC_VARS FSC_VERSION
1735184Sek110237 %token FSV_STRING FSV_VAL_INT FSV_VAL_BOOLEAN FSV_VARIABLE FSV_WHITESTRING
1746212Saw148015 %token FSV_RANDUNI FSV_RANDTAB FSV_RANDVAR FSV_URAND FSV_RAND48
1755184Sek110237 %token FST_INT FST_BOOLEAN
1765184Sek110237 %token FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSE_ALL FSE_SNAP FSE_DUMP
1776212Saw148015 %token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP FSE_RAND FSE_MODE
1785184Sek110237 %token FSK_SEPLST FSK_OPENLST FSK_CLOSELST FSK_ASSIGN FSK_IN FSK_QUOTE
1795184Sek110237 %token FSK_DIRSEPLST
1805184Sek110237 %token FSA_SIZE FSA_PREALLOC FSA_PARALLOC FSA_PATH FSA_REUSE
1815184Sek110237 %token FSA_PROCESS FSA_MEMSIZE FSA_RATE FSA_CACHED
1825184Sek110237 %token FSA_IOSIZE FSA_FILE FSA_WSS FSA_NAME FSA_RANDOM FSA_INSTANCES
1835184Sek110237 %token FSA_DSYNC FSA_TARGET FSA_ITERS FSA_NICE FSA_VALUE FSA_BLOCKING
1845184Sek110237 %token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD
1856212Saw148015 %token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA FSA_DIRDEPTHRV
1866212Saw148015 %token FSA_DIRGAMMA FSA_USEISM FSA_TYPE FSA_RANDTABLE FSA_RANDSRC FSA_RANDROUND
1876212Saw148015 %token FSA_RANDSEED FSA_RANDGAMMA FSA_RANDMEAN FSA_RANDMIN
1886212Saw148015 %token FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC FSS_ROUND
1896550Saw148015 %token FSV_SET_LOCAL_VAR FSA_LVAR_ASSIGN
1906212Saw148015 %token FSA_ALLDONE FSA_FIRSTDONE FSA_TIMEOUT
1915184Sek110237 
1925184Sek110237 %type <ival> FSV_VAL_INT
1935184Sek110237 %type <bval> FSV_VAL_BOOLEAN
1945184Sek110237 %type <sval> FSV_STRING
1955184Sek110237 %type <sval> FSV_WHITESTRING
1965184Sek110237 %type <sval> FSV_VARIABLE
1976212Saw148015 %type <sval> FSV_RANDVAR
1985184Sek110237 %type <sval> FSK_ASSIGN
1996550Saw148015 %type <sval> FSV_SET_LOCAL_VAR
2005184Sek110237 
2015184Sek110237 %type <ival> FSC_LIST FSC_DEFINE FSC_SET FSC_LOAD FSC_RUN
202*6750Sek110237 %type <ival> FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSC_HELP FSC_VERSION
2035184Sek110237 
2045184Sek110237 %type <sval> name
2055184Sek110237 %type <ival> entity
2065184Sek110237 %type <val>  value
2075184Sek110237 
2086212Saw148015 %type <cmd> command inner_commands load_command run_command list_command
2096212Saw148015 %type <cmd> proc_define_command files_define_command randvar_define_command
2106550Saw148015 %type <cmd> fo_define_command debug_command create_command
2115184Sek110237 %type <cmd> sleep_command stats_command set_command shutdown_command
2125184Sek110237 %type <cmd> foreach_command log_command system_command flowop_command
2135184Sek110237 %type <cmd> eventgen_command quit_command flowop_list thread_list
2145184Sek110237 %type <cmd> thread echo_command usage_command help_command vars_command
215*6750Sek110237 %type <cmd> version_command
2165184Sek110237 
2176212Saw148015 %type <attr> files_attr_op files_attr_ops pt_attr_op pt_attr_ops
2186212Saw148015 %type <attr> fo_attr_op fo_attr_ops ev_attr_op ev_attr_ops
2196212Saw148015 %type <attr> randvar_attr_op randvar_attr_ops randvar_attr_typop
2206212Saw148015 %type <attr> randvar_attr_srcop attr_value attr_list_value
2216550Saw148015 %type <attr> comp_lvar_def comp_attr_op comp_attr_ops
2226212Saw148015 %type <list> integer_seplist string_seplist string_list var_string_list
2236212Saw148015 %type <list> var_string whitevar_string whitevar_string_list
2246212Saw148015 %type <ival> attrs_define_file attrs_define_thread attrs_flowop
2256550Saw148015 %type <ival> attrs_define_fileset attrs_define_proc attrs_eventgen attrs_define_comp
2266212Saw148015 %type <ival> files_attr_name pt_attr_name fo_attr_name ev_attr_name
2276212Saw148015 %type <ival> randvar_attr_name FSA_TYPE randtype_name randvar_attr_param
2286212Saw148015 %type <ival> randsrc_name FSA_RANDSRC randvar_attr_tsp
2296212Saw148015 %type <ival> FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC
2306212Saw148015 
2316212Saw148015 %type <rndtb>  probtabentry_list probtabentry
2326212Saw148015 %type <avd> var_int_val
2335184Sek110237 %%
2345184Sek110237 
2355184Sek110237 commands: commands command
2365184Sek110237 {
2375184Sek110237 	list_t *list = NULL;
2385184Sek110237 	list_t *list_end = NULL;
2395184Sek110237 
2405184Sek110237 	if ($2->cmd != NULL)
2415184Sek110237 		$2->cmd($2);
2425184Sek110237 
2435184Sek110237 	free($2);
2445184Sek110237 }
2455184Sek110237 | commands error
2465184Sek110237 {
2475184Sek110237 	if (dofile)
2485184Sek110237 		YYABORT;
2495184Sek110237 }
2505184Sek110237 |;
2515184Sek110237 
2525184Sek110237 inner_commands: command
2535184Sek110237 {
2545184Sek110237 	filebench_log(LOG_DEBUG_IMPL, "inner_command %zx", $1);
2555184Sek110237 	$$ = $1;
2565184Sek110237 }
2575184Sek110237 | inner_commands command
2585184Sek110237 {
2595184Sek110237 	cmd_t *list = NULL;
2605184Sek110237 	cmd_t *list_end = NULL;
2615184Sek110237 
2625184Sek110237 	/* Find end of list */
2635184Sek110237 	for (list = $1; list != NULL;
2645184Sek110237 	    list = list->cmd_next)
2655184Sek110237 		list_end = list;
2665184Sek110237 
2675184Sek110237 	list_end->cmd_next = $2;
2685184Sek110237 
2695184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
2705184Sek110237 	    "inner_commands adding cmd %zx to list %zx", $2, $1);
2715184Sek110237 
2725184Sek110237 	$$ = $1;
2735184Sek110237 };
2745184Sek110237 
2755184Sek110237 command:
2766212Saw148015   proc_define_command
2776212Saw148015 | files_define_command
2786212Saw148015 | randvar_define_command
2796550Saw148015 | fo_define_command
2805184Sek110237 | debug_command
2815184Sek110237 | eventgen_command
2825184Sek110237 | create_command
2835184Sek110237 | echo_command
2845184Sek110237 | usage_command
2855184Sek110237 | vars_command
2865184Sek110237 | foreach_command
2875184Sek110237 | help_command
2885184Sek110237 | list_command
2895184Sek110237 | load_command
2905184Sek110237 | log_command
2915184Sek110237 | run_command
2925184Sek110237 | set_command
2935184Sek110237 | shutdown_command
2945184Sek110237 | sleep_command
2955184Sek110237 | stats_command
2965184Sek110237 | system_command
297*6750Sek110237 | version_command
2985184Sek110237 | quit_command;
2995184Sek110237 
3005184Sek110237 foreach_command: FSC_FOREACH
3015184Sek110237 {
3025184Sek110237 	if (($$ = alloc_cmd()) == NULL)
3035184Sek110237 		YYERROR;
3045184Sek110237 	filebench_log(LOG_DEBUG_IMPL, "foreach_command %zx", $$);
3055184Sek110237 }
3065184Sek110237 | foreach_command FSV_VARIABLE FSK_IN integer_seplist FSK_OPENLST inner_commands FSK_CLOSELST
3075184Sek110237 {
3085184Sek110237 	cmd_t *cmd, *inner_cmd;
3095184Sek110237 	list_t *list;
3105184Sek110237 
3115184Sek110237 	$$ = $1;
3125184Sek110237 	$$->cmd_list = $6;
3135184Sek110237 	$$->cmd_tgt1 = $2;
3145184Sek110237 	$$->cmd_param_list = $4;
3155184Sek110237 	$$->cmd = parser_foreach_integer;
3165184Sek110237 
3175184Sek110237 	for (list = $$->cmd_param_list; list != NULL;
3185184Sek110237 	    list = list->list_next) {
3195184Sek110237 		for (inner_cmd = $$->cmd_list;
3205184Sek110237 		    inner_cmd != NULL;
3215184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
3225184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
3236286Saw148015 			    "packing foreach: %zx %s=%llu, cmd %zx",
3246212Saw148015 			    $$, $$->cmd_tgt1,
3256286Saw148015 			    (u_longlong_t)avd_get_int(list->list_integer),
3266286Saw148015 			    inner_cmd);
3275184Sek110237 		}
3285184Sek110237 	}
3295184Sek110237 }| foreach_command FSV_VARIABLE FSK_IN string_seplist FSK_OPENLST inner_commands FSK_CLOSELST
3305184Sek110237 {
3315184Sek110237 	cmd_t *cmd, *inner_cmd;
3325184Sek110237 	list_t *list;
3335184Sek110237 
3345184Sek110237 	$$ = $1;
3355184Sek110237 	$$->cmd_list = $6;
3365184Sek110237 	$$->cmd_tgt1 = $2;
3375184Sek110237 	$$->cmd_param_list = $4;
3385184Sek110237 	$$->cmd = parser_foreach_string;
3395184Sek110237 
3405184Sek110237 	for (list = $$->cmd_param_list; list != NULL;
3415184Sek110237 	    list = list->list_next) {
3425184Sek110237 		for (inner_cmd = $$->cmd_list;
3435184Sek110237 		    inner_cmd != NULL;
3445184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
3455184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
3465184Sek110237 			    "packing foreach: %zx %s=%s, cmd %zx",
3475184Sek110237 			    $$,
3485184Sek110237 			    $$->cmd_tgt1,
3495184Sek110237 			    *list->list_string, inner_cmd);
3505184Sek110237 		}
3515184Sek110237 	}
3525184Sek110237 };
3535184Sek110237 
3545184Sek110237 integer_seplist: FSV_VAL_INT
3555184Sek110237 {
3565184Sek110237 	if (($$ = alloc_list()) == NULL)
3575184Sek110237 		YYERROR;
3585184Sek110237 
3596212Saw148015 	$$->list_integer = avd_int_alloc($1);
3605184Sek110237 }
3615184Sek110237 | integer_seplist FSK_SEPLST FSV_VAL_INT
3625184Sek110237 {
3635184Sek110237 	list_t *list = NULL;
3645184Sek110237 	list_t *list_end = NULL;
3655184Sek110237 
3665184Sek110237 	if (($$ = alloc_list()) == NULL)
3675184Sek110237 		YYERROR;
3685184Sek110237 
3696212Saw148015 	$$->list_integer = avd_int_alloc($3);
3705184Sek110237 
3715184Sek110237 	/* Find end of list */
3725184Sek110237 	for (list = $1; list != NULL;
3735184Sek110237 	    list = list->list_next)
3745184Sek110237 		list_end = list;
3755184Sek110237 	list_end->list_next = $$;
3765184Sek110237 	$$ = $1;
3775184Sek110237 };
3785184Sek110237 
3795184Sek110237 string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
3805184Sek110237 {
3815184Sek110237 	if (($$ = alloc_list()) == NULL)
3825184Sek110237 		YYERROR;
3835184Sek110237 
3846212Saw148015 	$$->list_string = avd_str_alloc($2);
3855184Sek110237 }
3865184Sek110237 | string_seplist FSK_SEPLST FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
3875184Sek110237 {
3885184Sek110237 	list_t *list = NULL;
3895184Sek110237 	list_t *list_end = NULL;
3905184Sek110237 
3915184Sek110237 	if (($$ = alloc_list()) == NULL)
3925184Sek110237 			YYERROR;
3935184Sek110237 
3946212Saw148015 	$$->list_string = avd_str_alloc($4);
3955184Sek110237 
3965184Sek110237 	/* Find end of list */
3975184Sek110237 	for (list = $1; list != NULL;
3985184Sek110237 	    list = list->list_next)
3995184Sek110237 		list_end = list;
4005184Sek110237 	list_end->list_next = $$;
4015184Sek110237 	$$ = $1;
4025184Sek110237 };
4035184Sek110237 
4045184Sek110237 eventgen_command: FSC_EVENTGEN
4055184Sek110237 {
4065184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4075184Sek110237 		YYERROR;
4085184Sek110237 	$$->cmd = &parser_eventgen;
4095184Sek110237 }
4106212Saw148015 | eventgen_command ev_attr_ops
4115184Sek110237 {
4125184Sek110237 	$1->cmd_attr_list = $2;
4135184Sek110237 };
4145184Sek110237 
4155184Sek110237 system_command: FSC_SYSTEM whitevar_string_list
4165184Sek110237 {
4175184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4185184Sek110237 		YYERROR;
4195184Sek110237 
4205184Sek110237 	$$->cmd_param_list = $2;
4215184Sek110237 	$$->cmd = parser_system;
4225184Sek110237 };
4235184Sek110237 
4245184Sek110237 echo_command: FSC_ECHO whitevar_string_list
4255184Sek110237 {
4265184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4275184Sek110237 		YYERROR;
4285184Sek110237 
4295184Sek110237 	$$->cmd_param_list = $2;
4305184Sek110237 	$$->cmd = parser_echo;
4315184Sek110237 };
4325184Sek110237 
433*6750Sek110237 version_command: FSC_VERSION
434*6750Sek110237 {
435*6750Sek110237 	if (($$ = alloc_cmd()) == NULL)
436*6750Sek110237 		YYERROR;
437*6750Sek110237 	$$->cmd = parser_version;
438*6750Sek110237 };
439*6750Sek110237 
4405184Sek110237 usage_command: FSC_USAGE whitevar_string_list
4415184Sek110237 {
4425184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4435184Sek110237 		YYERROR;
4445184Sek110237 
4455184Sek110237 	$$->cmd_param_list = $2;
4465184Sek110237 	$$->cmd = parser_usage;
4475184Sek110237 };
4485184Sek110237 
4495184Sek110237 vars_command: FSC_VARS
4505184Sek110237 {
4515184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4525184Sek110237 		YYERROR;
4535184Sek110237 
4545184Sek110237 	$$->cmd = parser_printvars;
4555184Sek110237 };
4565184Sek110237 
4575184Sek110237 string_list: FSV_VARIABLE
4585184Sek110237 {
4595184Sek110237 	if (($$ = alloc_list()) == NULL)
4605184Sek110237 			YYERROR;
4616212Saw148015 	$$->list_string = avd_str_alloc($1);
4625184Sek110237 }
4635184Sek110237 | string_list FSK_SEPLST FSV_VARIABLE
4645184Sek110237 {
4655184Sek110237 	list_t *list = NULL;
4665184Sek110237 	list_t *list_end = NULL;
4675184Sek110237 
4685184Sek110237 	if (($$ = alloc_list()) == NULL)
4695184Sek110237 		YYERROR;
4705184Sek110237 
4716212Saw148015 	$$->list_string = avd_str_alloc($3);
4725184Sek110237 
4735184Sek110237 	/* Find end of list */
4745184Sek110237 	for (list = $1; list != NULL;
4755184Sek110237 	    list = list->list_next)
4765184Sek110237 		list_end = list;
4775184Sek110237 	list_end->list_next = $$;
4785184Sek110237 	$$ = $1;
4795184Sek110237 };
4805184Sek110237 
4815184Sek110237 var_string: FSV_VARIABLE
4825184Sek110237 {
4835184Sek110237 	if (($$ = alloc_list()) == NULL)
4845184Sek110237 			YYERROR;
4855184Sek110237 
4866212Saw148015 	$$->list_string = avd_str_alloc($1);
4875184Sek110237 }
4885184Sek110237 | FSV_STRING
4895184Sek110237 {
4905184Sek110237 	if (($$ = alloc_list()) == NULL)
4915184Sek110237 			YYERROR;
4925184Sek110237 
4936212Saw148015 	$$->list_string = avd_str_alloc($1);
4945184Sek110237 };
4955184Sek110237 
4965184Sek110237 var_string_list: var_string
4975184Sek110237 {
4985184Sek110237 	$$ = $1;
4995184Sek110237 }| var_string FSV_STRING
5005184Sek110237 {
5015184Sek110237 	list_t *list = NULL;
5025184Sek110237 	list_t *list_end = NULL;
5035184Sek110237 
5045184Sek110237 	/* Add string */
5055184Sek110237 	if (($$ = alloc_list()) == NULL)
5065184Sek110237 		YYERROR;
5075184Sek110237 
5086212Saw148015 	$$->list_string = avd_str_alloc($2);
5095184Sek110237 
5105184Sek110237 	/* Find end of list */
5115184Sek110237 	for (list = $1; list != NULL;
5125184Sek110237 	    list = list->list_next)
5135184Sek110237 		list_end = list;
5145184Sek110237 	list_end->list_next = $$;
5155184Sek110237 	$$ = $1;
5165184Sek110237 
5175184Sek110237 }| var_string FSV_VARIABLE
5185184Sek110237 {
5195184Sek110237 	list_t *list = NULL;
5205184Sek110237 	list_t *list_end = NULL;
5215184Sek110237 
5225184Sek110237 	/* Add variable */
5235184Sek110237 	if (($$ = alloc_list()) == NULL)
5245184Sek110237 		YYERROR;
5255184Sek110237 
5266212Saw148015 	$$->list_string = avd_str_alloc($2);
5275184Sek110237 
5285184Sek110237 	/* Find end of list */
5295184Sek110237 	for (list = $1; list != NULL;
5305184Sek110237 	    list = list->list_next)
5315184Sek110237 		list_end = list;
5325184Sek110237 	list_end->list_next = $$;
5335184Sek110237 	$$ = $1;
5345184Sek110237 } |var_string_list FSV_STRING
5355184Sek110237 {
5365184Sek110237 	list_t *list = NULL;
5375184Sek110237 	list_t *list_end = NULL;
5385184Sek110237 
5395184Sek110237 	/* Add string */
5405184Sek110237 	if (($$ = alloc_list()) == NULL)
5415184Sek110237 		YYERROR;
5425184Sek110237 
5436212Saw148015 	$$->list_string = avd_str_alloc($2);
5445184Sek110237 
5455184Sek110237 	/* Find end of list */
5465184Sek110237 	for (list = $1; list != NULL;
5475184Sek110237 	    list = list->list_next)
5485184Sek110237 		list_end = list;
5495184Sek110237 	list_end->list_next = $$;
5505184Sek110237 	$$ = $1;
5515184Sek110237 
5525184Sek110237 }| var_string_list FSV_VARIABLE
5535184Sek110237 {
5545184Sek110237 	list_t *list = NULL;
5555184Sek110237 	list_t *list_end = NULL;
5565184Sek110237 
5575184Sek110237 	/* Add variable */
5585184Sek110237 	if (($$ = alloc_list()) == NULL)
5595184Sek110237 		YYERROR;
5605184Sek110237 
5616212Saw148015 	$$->list_string = avd_str_alloc($2);
5625184Sek110237 
5635184Sek110237 	/* Find end of list */
5645184Sek110237 	for (list = $1; list != NULL;
5655184Sek110237 	    list = list->list_next)
5665184Sek110237 		list_end = list;
5675184Sek110237 	list_end->list_next = $$;
5685184Sek110237 	$$ = $1;
5695184Sek110237 };
5705184Sek110237 
5715184Sek110237 whitevar_string: FSK_QUOTE FSV_VARIABLE
5725184Sek110237 {
5735184Sek110237 	if (($$ = alloc_list()) == NULL)
5745184Sek110237 			YYERROR;
5755184Sek110237 
5766212Saw148015 	$$->list_string = avd_str_alloc($2);
5775184Sek110237 }
5785184Sek110237 | FSK_QUOTE FSV_WHITESTRING
5795184Sek110237 {
5805184Sek110237 	if (($$ = alloc_list()) == NULL)
5815184Sek110237 			YYERROR;
5825184Sek110237 
5836212Saw148015 	$$->list_string = avd_str_alloc($2);
5845184Sek110237 };
5855184Sek110237 
5865184Sek110237 whitevar_string_list: whitevar_string FSV_WHITESTRING
5875184Sek110237 {
5885184Sek110237 	list_t *list = NULL;
5895184Sek110237 	list_t *list_end = NULL;
5905184Sek110237 
5915184Sek110237 	/* Add string */
5925184Sek110237 	if (($$ = alloc_list()) == NULL)
5935184Sek110237 		YYERROR;
5945184Sek110237 
5956212Saw148015 	$$->list_string = avd_str_alloc($2);
5965184Sek110237 
5975184Sek110237 	/* Find end of list */
5985184Sek110237 	for (list = $1; list != NULL;
5995184Sek110237 	    list = list->list_next)
6005184Sek110237 		list_end = list;
6015184Sek110237 	list_end->list_next = $$;
6025184Sek110237 	$$ = $1;
6035184Sek110237 
6045184Sek110237 }| whitevar_string FSV_VARIABLE
6055184Sek110237 {
6065184Sek110237 	list_t *list = NULL;
6075184Sek110237 	list_t *list_end = NULL;
6085184Sek110237 
6095184Sek110237 	/* Add variable */
6105184Sek110237 	if (($$ = alloc_list()) == NULL)
6115184Sek110237 		YYERROR;
6125184Sek110237 
6136212Saw148015 	$$->list_string = avd_str_alloc($2);
6145184Sek110237 
6155184Sek110237 	/* Find end of list */
6165184Sek110237 	for (list = $1; list != NULL;
6175184Sek110237 	    list = list->list_next)
6185184Sek110237 		list_end = list;
6195184Sek110237 	list_end->list_next = $$;
6205184Sek110237 	$$ = $1;
6216212Saw148015 }| whitevar_string FSV_RANDVAR randvar_attr_tsp
6226212Saw148015 {
6236212Saw148015 	list_t *list = NULL;
6246212Saw148015 	list_t *list_end = NULL;
6256212Saw148015 
6266212Saw148015 	/* Add variable */
6276212Saw148015 	if (($$ = alloc_list()) == NULL)
6286212Saw148015 		YYERROR;
6296212Saw148015 
6306212Saw148015 	$$->list_string = avd_str_alloc($2);
6316212Saw148015 	$$->list_integer = avd_int_alloc($3);
6326212Saw148015 
6336212Saw148015 	/* Find end of list */
6346212Saw148015 	for (list = $1; list != NULL;
6356212Saw148015 	    list = list->list_next)
6366212Saw148015 		list_end = list;
6376212Saw148015 	list_end->list_next = $$;
6386212Saw148015 	$$ = $1;
6396212Saw148015 }| whitevar_string_list FSV_WHITESTRING
6405184Sek110237 {
6415184Sek110237 	list_t *list = NULL;
6425184Sek110237 	list_t *list_end = NULL;
6435184Sek110237 
6445184Sek110237 	/* Add string */
6455184Sek110237 	if (($$ = alloc_list()) == NULL)
6465184Sek110237 		YYERROR;
6475184Sek110237 
6486212Saw148015 	$$->list_string = avd_str_alloc($2);
6495184Sek110237 
6505184Sek110237 	/* Find end of list */
6515184Sek110237 	for (list = $1; list != NULL;
6525184Sek110237 	    list = list->list_next)
6535184Sek110237 		list_end = list;
6545184Sek110237 	list_end->list_next = $$;
6555184Sek110237 	$$ = $1;
6565184Sek110237 
6575184Sek110237 }| whitevar_string_list FSV_VARIABLE
6585184Sek110237 {
6595184Sek110237 	list_t *list = NULL;
6605184Sek110237 	list_t *list_end = NULL;
6615184Sek110237 
6625184Sek110237 	/* Add variable */
6635184Sek110237 	if (($$ = alloc_list()) == NULL)
6645184Sek110237 		YYERROR;
6655184Sek110237 
6666212Saw148015 	$$->list_string = avd_str_alloc($2);
6676212Saw148015 
6686212Saw148015 	/* Find end of list */
6696212Saw148015 	for (list = $1; list != NULL;
6706212Saw148015 	    list = list->list_next)
6716212Saw148015 		list_end = list;
6726212Saw148015 	list_end->list_next = $$;
6736212Saw148015 	$$ = $1;
6746212Saw148015 }| whitevar_string_list FSV_RANDVAR randvar_attr_tsp
6756212Saw148015 {
6766212Saw148015 	list_t *list = NULL;
6776212Saw148015 	list_t *list_end = NULL;
6786212Saw148015 
6796212Saw148015 	/* Add variable */
6806212Saw148015 	if (($$ = alloc_list()) == NULL)
6816212Saw148015 		YYERROR;
6826212Saw148015 
6836212Saw148015 	$$->list_string = avd_str_alloc($2);
6846212Saw148015 	$$->list_integer = avd_int_alloc($3);
6855184Sek110237 
6865184Sek110237 	/* Find end of list */
6875184Sek110237 	for (list = $1; list != NULL;
6885184Sek110237 	    list = list->list_next)
6895184Sek110237 		list_end = list;
6905184Sek110237 	list_end->list_next = $$;
6915184Sek110237 	$$ = $1;
6925184Sek110237 }| whitevar_string_list FSK_QUOTE
6935184Sek110237 {
6945184Sek110237 	$$ = $1;
6955184Sek110237 }| whitevar_string FSK_QUOTE
6965184Sek110237 {
6975184Sek110237 	$$ = $1;
6985184Sek110237 };
6995184Sek110237 
7005184Sek110237 list_command: FSC_LIST
7015184Sek110237 {
7025184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7035184Sek110237 		YYERROR;
7045184Sek110237 	$$->cmd = &parser_list;
7056212Saw148015 }
7066212Saw148015 | list_command FSC_FLOWOP
7076212Saw148015 {
7086212Saw148015 	$1->cmd = &parser_flowop_list;
7095184Sek110237 };
7105184Sek110237 
7115184Sek110237 log_command: FSC_LOG whitevar_string_list
7125184Sek110237 {
7135184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7145184Sek110237 		YYERROR;
7155184Sek110237 	$$->cmd = &parser_log;
7165184Sek110237 	$$->cmd_param_list = $2;
7175184Sek110237 };
7185184Sek110237 
7195184Sek110237 debug_command: FSC_DEBUG FSV_VAL_INT
7205184Sek110237 {
7215184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7225184Sek110237 		YYERROR;
7235184Sek110237 	$$->cmd = NULL;
7246391Saw148015 	filebench_shm->shm_debug_level = $2;
7256391Saw148015 	if (filebench_shm->shm_debug_level > 9)
7265184Sek110237 		yydebug = 1;
7275184Sek110237 };
7285184Sek110237 
7295184Sek110237 set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
7305184Sek110237 {
7315184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7325184Sek110237 		YYERROR;
7335184Sek110237 	var_assign_integer($2, $4);
7345184Sek110237 	if (parentscript) {
7355184Sek110237 		$$->cmd_tgt1 = $2;
7365184Sek110237 		parser_vars($$);
7375184Sek110237 	}
7385184Sek110237 	$$->cmd = NULL;
7395184Sek110237 }
7406212Saw148015 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_BOOLEAN
7416212Saw148015 {
7426212Saw148015 	if (($$ = alloc_cmd()) == NULL)
7436212Saw148015 		YYERROR;
7446212Saw148015 	var_assign_boolean($2, $4);
7456212Saw148015 	if (parentscript) {
7466212Saw148015 		$$->cmd_tgt1 = $2;
7476212Saw148015 		parser_vars($$);
7486212Saw148015 	}
7496212Saw148015 	$$->cmd = NULL;
7506212Saw148015 }
7515184Sek110237 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
7525184Sek110237 {
7535184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7545184Sek110237 		YYERROR;
7555184Sek110237 	var_assign_string($2, $5);
7565184Sek110237 	if (parentscript) {
7575184Sek110237 		$$->cmd_tgt1 = $2;
7585184Sek110237 		parser_vars($$);
7595184Sek110237 	}
7605184Sek110237 	$$->cmd = NULL;
7615184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_STRING
7625184Sek110237 {
7635184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7645184Sek110237 		YYERROR;
7655184Sek110237 	var_assign_string($2, $4);
7665184Sek110237 	if (parentscript) {
7675184Sek110237 		$$->cmd_tgt1 = $2;
7685184Sek110237 		parser_vars($$);
7695184Sek110237 	}
7705184Sek110237 	$$->cmd = NULL;
7715184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE
7725184Sek110237 {
7735184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7745184Sek110237 		YYERROR;
7755184Sek110237 	var_assign_var($2, $4);
7765184Sek110237 	if (parentscript) {
7775184Sek110237 		$$->cmd_tgt1 = $2;
7785184Sek110237 		parser_vars($$);
7795184Sek110237 	}
7805184Sek110237 	$$->cmd = NULL;
7816084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_TIMEOUT
7826084Saw148015 {
7836084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT;
7846084Saw148015 	if (($$ = alloc_cmd()) == NULL)
7856084Saw148015 		YYERROR;
7866084Saw148015 	$$->cmd = NULL;
7876084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_ALLDONE
7886084Saw148015 {
7896084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_QALLDONE;
7906084Saw148015 	if (($$ = alloc_cmd()) == NULL)
7916084Saw148015 		YYERROR;
7926084Saw148015 	$$->cmd = NULL;
7936084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_FIRSTDONE
7946084Saw148015 {
7956084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_Q1STDONE;
7966084Saw148015 	if (($$ = alloc_cmd()) == NULL)
7976084Saw148015 		YYERROR;
7986084Saw148015 	$$->cmd = NULL;
7996212Saw148015 }| FSC_SET FSV_RANDVAR FSS_TYPE FSK_ASSIGN randvar_attr_typop
8006212Saw148015 {
8016212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8026212Saw148015 		YYERROR;
8036212Saw148015 	$$->cmd = &parser_randvar_set;
8046212Saw148015 	$$->cmd_tgt1 = $2;
8056212Saw148015 	$$->cmd_qty = FSS_TYPE;
8066212Saw148015 	$$->cmd_attr_list = $5;
8076212Saw148015 
8086212Saw148015 }| FSC_SET FSV_RANDVAR FSS_SRC FSK_ASSIGN randvar_attr_srcop
8096212Saw148015 {
8106212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8116212Saw148015 		YYERROR;
8126212Saw148015 	$$->cmd = &parser_randvar_set;
8136212Saw148015 	$$->cmd_tgt1 = $2;
8146212Saw148015 	$$->cmd_qty = FSS_SRC;
8156212Saw148015 	$$->cmd_attr_list = $5;
8166212Saw148015 
8176212Saw148015 }| FSC_SET FSV_RANDVAR randvar_attr_param FSK_ASSIGN attr_value
8186212Saw148015 {
8196212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8206212Saw148015 		YYERROR;
8216212Saw148015 	$$->cmd = &parser_randvar_set;
8226212Saw148015 	$$->cmd_tgt1 = $2;
8236212Saw148015 	$$->cmd_qty = $3;
8246212Saw148015 	$$->cmd_attr_list = $5;
8256212Saw148015 
8265184Sek110237 };
8275184Sek110237 
8285184Sek110237 stats_command: FSC_STATS FSE_SNAP
8295184Sek110237 {
8305184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8315184Sek110237 		YYERROR;
8325184Sek110237 	$$->cmd = (void (*)(struct cmd *))&parser_statssnap;
8335184Sek110237 	break;
8345184Sek110237 
8355184Sek110237 }
8365184Sek110237 | FSC_STATS FSE_CLEAR
8375184Sek110237 {
8385184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8395184Sek110237 		YYERROR;
8405184Sek110237 	$$->cmd = (void (*)(struct cmd *))&stats_clear;
8415184Sek110237 
8425184Sek110237 }
8435184Sek110237 | FSC_STATS FSE_DIRECTORY var_string_list
8445184Sek110237 {
8455184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8465184Sek110237 		YYERROR;
8475184Sek110237 	$$->cmd_param_list = $3;
8485184Sek110237 	$$->cmd = (void (*)(struct cmd *))&parser_directory;
8495184Sek110237 
8505184Sek110237 }
8515184Sek110237 | FSC_STATS FSE_COMMAND whitevar_string_list
8525184Sek110237 {
8535184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8545184Sek110237 		YYERROR;
8555184Sek110237 
8565184Sek110237 	$$->cmd_param_list = $3;
8575184Sek110237 	$$->cmd = parser_statscmd;
8585184Sek110237 
8595184Sek110237 }| FSC_STATS FSE_DUMP whitevar_string_list
8605184Sek110237 {
8615184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8625184Sek110237 		YYERROR;
8635184Sek110237 
8645184Sek110237 	$$->cmd_param_list = $3;
8655184Sek110237 	$$->cmd = parser_statsdump;
8665184Sek110237 }| FSC_STATS FSE_XMLDUMP whitevar_string_list
8675184Sek110237 {
8685184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8695184Sek110237 		YYERROR;
8705184Sek110237 
8715184Sek110237 	$$->cmd_param_list = $3;
8725184Sek110237 	$$->cmd = parser_statsxmldump;
8735184Sek110237 };
8745184Sek110237 
8755184Sek110237 quit_command: FSC_QUIT
8765184Sek110237 {
8775184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8785184Sek110237 		YYERROR;
8795184Sek110237 	$$->cmd = parser_filebench_shutdown;
8805184Sek110237 };
8815184Sek110237 
8825184Sek110237 flowop_list: flowop_command
8835184Sek110237 {
8845184Sek110237 	$$ = $1;
8855184Sek110237 }| flowop_list flowop_command
8865184Sek110237 {
8875184Sek110237 	cmd_t *list = NULL;
8885184Sek110237 	cmd_t *list_end = NULL;
8895184Sek110237 
8905184Sek110237 	/* Find end of list */
8915184Sek110237 	for (list = $1; list != NULL;
8925184Sek110237 	    list = list->cmd_next)
8935184Sek110237 		list_end = list;
8945184Sek110237 
8955184Sek110237 	list_end->cmd_next = $2;
8965184Sek110237 
8975184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
8985184Sek110237 	    "flowop_list adding cmd %zx to list %zx", $2, $1);
8995184Sek110237 
9005184Sek110237 	$$ = $1;
9015184Sek110237 };
9025184Sek110237 
9036212Saw148015 thread: FSE_THREAD pt_attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
9045184Sek110237 {
9055184Sek110237 	/*
9065184Sek110237 	 * Allocate a cmd node per thread, with a
9075184Sek110237 	 * list of flowops attached to the cmd_list
9085184Sek110237 	 */
9095184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9105184Sek110237 		YYERROR;
9115184Sek110237 	$$->cmd_list = $4;
9125184Sek110237 	$$->cmd_attr_list = $2;
9135184Sek110237 };
9145184Sek110237 
9155184Sek110237 thread_list: thread
9165184Sek110237 {
9175184Sek110237 	$$ = $1;
9185184Sek110237 }| thread_list thread
9195184Sek110237 {
9205184Sek110237 	cmd_t *list = NULL;
9215184Sek110237 	cmd_t *list_end = NULL;
9225184Sek110237 
9235184Sek110237 	/* Find end of list */
9245184Sek110237 	for (list = $1; list != NULL;
9255184Sek110237 	    list = list->cmd_next)
9265184Sek110237 		list_end = list;
9275184Sek110237 
9285184Sek110237 	list_end->cmd_next = $2;
9295184Sek110237 
9305184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
9315184Sek110237 	    "thread_list adding cmd %zx to list %zx", $2, $1);
9325184Sek110237 
9335184Sek110237 	$$ = $1;
9345184Sek110237 };
9355184Sek110237 
9366212Saw148015 proc_define_command: FSC_DEFINE FSE_PROC pt_attr_ops FSK_OPENLST thread_list FSK_CLOSELST
9375184Sek110237 {
9385184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9395184Sek110237 		YYERROR;
9405184Sek110237 	$$->cmd = &parser_proc_define;
9415184Sek110237 	$$->cmd_list = $5;
9425184Sek110237 	$$->cmd_attr_list = $3;
9435184Sek110237 
9446212Saw148015 }
9456212Saw148015 | proc_define_command pt_attr_ops
9466212Saw148015 {
9476212Saw148015 	$1->cmd_attr_list = $2;
9486212Saw148015 };
9496212Saw148015 
9506212Saw148015 files_define_command: FSC_DEFINE FSE_FILE
9515184Sek110237 {
9525184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9535184Sek110237 		YYERROR;
9545184Sek110237 	$$->cmd = &parser_file_define;
9555184Sek110237 }| FSC_DEFINE FSE_FILESET
9565184Sek110237 {
9575184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9585184Sek110237 		YYERROR;
9595184Sek110237 	$$->cmd = &parser_fileset_define;
9605184Sek110237 }
9616212Saw148015 | files_define_command files_attr_ops
9625184Sek110237 {
9635184Sek110237 	$1->cmd_attr_list = $2;
9645184Sek110237 };
9655184Sek110237 
9666212Saw148015 randvar_define_command: FSC_DEFINE FSE_RAND randvar_attr_ops
9676212Saw148015 {
9686212Saw148015 	if (($$ = alloc_cmd()) == NULL)
9696212Saw148015 		YYERROR;
9706212Saw148015 	$$->cmd = &parser_randvar_define;
9716212Saw148015 	$$->cmd_attr_list = $3;
9726212Saw148015 };
9736212Saw148015 
9746550Saw148015 fo_define_command: FSC_DEFINE FSC_FLOWOP comp_attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
9756550Saw148015 {
9766550Saw148015 	if (($$ = alloc_cmd()) == NULL)
9776550Saw148015 		YYERROR;
9786550Saw148015 	$$->cmd = &parser_composite_flowop_define;
9796550Saw148015 	$$->cmd_list = $5;
9806550Saw148015 	$$->cmd_attr_list = $3;
9816550Saw148015 }
9826550Saw148015 | fo_define_command comp_attr_ops
9836550Saw148015 {
9846550Saw148015 	$1->cmd_attr_list = $2;
9856550Saw148015 };
9866550Saw148015 
9875184Sek110237 create_command: FSC_CREATE entity
9885184Sek110237 {
9895184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9905184Sek110237 		YYERROR;
9915184Sek110237 	switch ($2) {
9925184Sek110237 	case FSE_PROC:
9935184Sek110237 		$$->cmd = &parser_proc_create;
9945184Sek110237 		break;
9955673Saw148015 	case FSE_FILESET:
9965184Sek110237 	case FSE_FILE:
9975184Sek110237 		$$->cmd = &parser_fileset_create;
9985184Sek110237 		break;
9995184Sek110237 	default:
10005184Sek110237 		filebench_log(LOG_ERROR, "unknown entity", $2);
10015184Sek110237 		YYERROR;
10025184Sek110237 	}
10035184Sek110237 
10045184Sek110237 };
10055184Sek110237 
10065184Sek110237 shutdown_command: FSC_SHUTDOWN entity
10075184Sek110237 {
10085184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10095184Sek110237 		YYERROR;
10105184Sek110237 	switch ($2) {
10115184Sek110237 	case FSE_PROC:
10125184Sek110237 		$$->cmd = &parser_proc_shutdown;
10135184Sek110237 		break;
10145184Sek110237 	default:
10155184Sek110237 		filebench_log(LOG_ERROR, "unknown entity", $2);
10165184Sek110237 		YYERROR;
10175184Sek110237 	}
10185184Sek110237 
10195184Sek110237 };
10205184Sek110237 
10215184Sek110237 sleep_command: FSC_SLEEP FSV_VAL_INT
10225184Sek110237 {
10235184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10245184Sek110237 		YYERROR;
10255184Sek110237 	$$->cmd = parser_sleep;
10265184Sek110237 	$$->cmd_qty = $2;
10275184Sek110237 }
10285184Sek110237 | FSC_SLEEP FSV_VARIABLE
10295184Sek110237 {
10306212Saw148015 	fbint_t *integer;
10315184Sek110237 
10325184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10335184Sek110237 		YYERROR;
10345184Sek110237 	$$->cmd = parser_sleep_variable;
10355184Sek110237 	$$->cmd_tgt1 = fb_stralloc($2);
10365184Sek110237 };
10375184Sek110237 
10385184Sek110237 run_command: FSC_RUN FSV_VAL_INT
10395184Sek110237 {
10405184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10415184Sek110237 		YYERROR;
10425184Sek110237 	$$->cmd = parser_run;
10435184Sek110237 	$$->cmd_qty = $2;
10445184Sek110237 }
10455184Sek110237 | FSC_RUN FSV_VARIABLE
10465184Sek110237 {
10476212Saw148015 	fbint_t *integer;
10485184Sek110237 
10495184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10505184Sek110237 		YYERROR;
10515184Sek110237 	$$->cmd = parser_run_variable;
10525184Sek110237 	$$->cmd_tgt1 = fb_stralloc($2);
10535184Sek110237 }
10545184Sek110237 | FSC_RUN
10555184Sek110237 {
10566212Saw148015 	fbint_t *integer;
10575184Sek110237 
10585184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10595184Sek110237 		YYERROR;
10605184Sek110237 	$$->cmd = parser_run;
10615184Sek110237 	$$->cmd_qty = 60UL;
10625184Sek110237 };
10635184Sek110237 
10645184Sek110237 help_command: FSC_HELP
10655184Sek110237 {
10665184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10675184Sek110237 		YYERROR;
10685184Sek110237 	$$->cmd = parser_help;
10695184Sek110237 };
10705184Sek110237 
10715184Sek110237 flowop_command: FSC_FLOWOP name
10725184Sek110237 {
10735184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10745184Sek110237 		YYERROR;
10755184Sek110237 	$$->cmd_name = fb_stralloc($2);
10765184Sek110237 }
10776212Saw148015 | flowop_command fo_attr_ops
10785184Sek110237 {
10795184Sek110237 	$1->cmd_attr_list = $2;
10805184Sek110237 };
10815184Sek110237 
10825184Sek110237 load_command: FSC_LOAD FSV_STRING
10835184Sek110237 {
10845184Sek110237 	FILE *newfile;
10855184Sek110237 	char loadfile[128];
10865184Sek110237 
10875184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10885184Sek110237 		YYERROR;
10895184Sek110237 
10905184Sek110237 	(void) strcpy(loadfile, $2);
10915184Sek110237 	(void) strcat(loadfile, ".f");
10925184Sek110237 
10935184Sek110237 	if ((newfile = fopen(loadfile, "r")) == NULL) {
10945184Sek110237 		(void) strcpy(loadfile, FILEBENCHDIR);
10955184Sek110237 		(void) strcat(loadfile, "/workloads/");
10965184Sek110237 		(void) strcat(loadfile, $2);
10975184Sek110237 		(void) strcat(loadfile, ".f");
10985184Sek110237 		if ((newfile = fopen(loadfile, "r")) == NULL) {
10995184Sek110237 			filebench_log(LOG_ERROR, "Cannot open %s", loadfile);
11005184Sek110237 			YYERROR;
11015184Sek110237 		}
11025184Sek110237 	}
11035184Sek110237 
11045184Sek110237 	parentscript = yyin;
11055184Sek110237 	yyin = newfile;
11065184Sek110237 	yy_switchfileparent(yyin);
11075184Sek110237 };
11085184Sek110237 
11096212Saw148015 
11105184Sek110237 entity: FSE_PROC {$$ = FSE_PROC;}
11115184Sek110237 | FSE_THREAD {$$ = FSE_THREAD;}
11125184Sek110237 | FSE_FILESET {$$ = FSE_FILESET;}
11135184Sek110237 | FSE_FILE {$$ = FSE_FILE;};
11145184Sek110237 
11155184Sek110237 value: FSV_VAL_INT { $$.i = $1;}
11165184Sek110237 | FSV_STRING { $$.s = $1;}
11175184Sek110237 | FSV_VAL_BOOLEAN { $$.b = $1;};
11185184Sek110237 
11195184Sek110237 name: FSV_STRING;
11205184Sek110237 
11216212Saw148015 /* attribute parsing for define file and define fileset */
11226212Saw148015 files_attr_ops: files_attr_op
11236212Saw148015 {
11246212Saw148015 	$$ = $1;
11256212Saw148015 }
11266212Saw148015 | files_attr_ops FSK_SEPLST files_attr_op
11276212Saw148015 {
11286212Saw148015 	attr_t *attr = NULL;
11296212Saw148015 	attr_t *list_end = NULL;
11306212Saw148015 
11316212Saw148015 	for (attr = $1; attr != NULL;
11326212Saw148015 	    attr = attr->attr_next)
11336212Saw148015 		list_end = attr; /* Find end of list */
11346212Saw148015 
11356212Saw148015 	list_end->attr_next = $3;
11366212Saw148015 
11376212Saw148015 	$$ = $1;
11386212Saw148015 };
11396212Saw148015 
11406212Saw148015 files_attr_op: files_attr_name FSK_ASSIGN attr_list_value
11416212Saw148015 {
11426212Saw148015 	$$ = $3;
11436212Saw148015 	$$->attr_name = $1;
11446212Saw148015 }
11456212Saw148015 | files_attr_name
11466212Saw148015 {
11476212Saw148015 	if (($$ = alloc_attr()) == NULL)
11486212Saw148015 		YYERROR;
11496212Saw148015 	$$->attr_name = $1;
11506212Saw148015 };
11516212Saw148015 
11526212Saw148015 /* attribute parsing for random variables */
11536212Saw148015 randvar_attr_ops: randvar_attr_op
11545184Sek110237 {
11555184Sek110237 	$$ = $1;
11565184Sek110237 }
11576212Saw148015 | randvar_attr_ops FSK_SEPLST randvar_attr_op
11586212Saw148015 {
11596212Saw148015 	attr_t *attr = NULL;
11606212Saw148015 	attr_t *list_end = NULL;
11616212Saw148015 
11626212Saw148015 	for (attr = $1; attr != NULL;
11636212Saw148015 	    attr = attr->attr_next)
11646212Saw148015 		list_end = attr; /* Find end of list */
11656212Saw148015 
11666212Saw148015 	list_end->attr_next = $3;
11676212Saw148015 
11686212Saw148015 	$$ = $1;
11696212Saw148015 }
11706212Saw148015 | randvar_attr_ops FSK_SEPLST FSA_RANDTABLE FSK_ASSIGN FSK_OPENLST probtabentry_list FSK_CLOSELST
11716212Saw148015 {
11726212Saw148015 	attr_t *attr = NULL;
11736212Saw148015 	attr_t *list_end = NULL;
11746212Saw148015 
11756212Saw148015 	for (attr = $1; attr != NULL;
11766212Saw148015 	    attr = attr->attr_next)
11776212Saw148015 		list_end = attr; /* Find end of list */
11786212Saw148015 
11796212Saw148015 
11806212Saw148015 	if ((attr = alloc_attr()) == NULL)
11816212Saw148015 		YYERROR;
11826212Saw148015 
11836212Saw148015 	attr->attr_name = FSA_RANDTABLE;
11846212Saw148015 	attr->attr_obj = (void *)$6;
11856212Saw148015 	list_end->attr_next = attr;
11866212Saw148015 	$$ = $1;
11876212Saw148015 };
11886212Saw148015 
11896212Saw148015 randvar_attr_op: randvar_attr_name FSK_ASSIGN attr_list_value
11906212Saw148015 {
11916212Saw148015 	$$ = $3;
11926212Saw148015 	$$->attr_name = $1;
11936212Saw148015 }
11946212Saw148015 | randvar_attr_name
11956212Saw148015 {
11966212Saw148015 	if (($$ = alloc_attr()) == NULL)
11976212Saw148015 		YYERROR;
11986212Saw148015 	$$->attr_name = $1;
11996212Saw148015 }
12006212Saw148015 | FSA_TYPE FSK_ASSIGN randvar_attr_typop
12016212Saw148015 {
12026212Saw148015 	$$ = $3;
12036212Saw148015 	$$->attr_name = FSA_TYPE;
12046212Saw148015 }
12056212Saw148015 | FSA_RANDSRC FSK_ASSIGN randvar_attr_srcop
12066212Saw148015 {
12076212Saw148015 	$$ = $3;
12086212Saw148015 	$$->attr_name = FSA_RANDSRC;
12096212Saw148015 };
12106212Saw148015 
12116212Saw148015 probtabentry: FSK_OPENLST var_int_val FSK_SEPLST var_int_val FSK_SEPLST var_int_val FSK_CLOSELST
12126212Saw148015 {
12136212Saw148015 	if (($$ = alloc_probtabent()) == NULL)
12146212Saw148015 		YYERROR;
12156212Saw148015 	$$->pte_percent = $2;
12166212Saw148015 	$$->pte_segmin  = $4;
12176212Saw148015 	$$->pte_segmax  = $6;
12186212Saw148015 };
12196212Saw148015 
12206212Saw148015 /* attribute parsing for prob density function table */
12216212Saw148015 probtabentry_list: probtabentry
12226212Saw148015 {
12236212Saw148015 	$$ = $1;
12246212Saw148015 }
12256212Saw148015 | probtabentry_list FSK_SEPLST probtabentry
12266212Saw148015 {
12276212Saw148015 	probtabent_t *pte = NULL;
12286212Saw148015 	probtabent_t *ptelist_end = NULL;
12296212Saw148015 
12306212Saw148015 	for (pte = $1; pte != NULL;
12316212Saw148015 	    pte = pte->pte_next)
12326212Saw148015 		ptelist_end = pte; /* Find end of prob table entry list */
12336212Saw148015 
12346212Saw148015 	ptelist_end->pte_next = $3;
12356212Saw148015 
12366212Saw148015 	$$ = $1;
12376212Saw148015 };
12386212Saw148015 
12396212Saw148015 /* attribute parsing for define thread and process */
12406212Saw148015 pt_attr_ops: pt_attr_op
12416212Saw148015 {
12426212Saw148015 	$$ = $1;
12436212Saw148015 }
12446212Saw148015 | pt_attr_ops FSK_SEPLST pt_attr_op
12456212Saw148015 {
12466212Saw148015 	attr_t *attr = NULL;
12476212Saw148015 	attr_t *list_end = NULL;
12486212Saw148015 
12496212Saw148015 	for (attr = $1; attr != NULL;
12506212Saw148015 	    attr = attr->attr_next)
12516212Saw148015 		list_end = attr; /* Find end of list */
12526212Saw148015 
12536212Saw148015 	list_end->attr_next = $3;
12546212Saw148015 
12556212Saw148015 	$$ = $1;
12566212Saw148015 };
12576212Saw148015 
12586212Saw148015 pt_attr_op: pt_attr_name FSK_ASSIGN attr_value
12596212Saw148015 {
12606212Saw148015 	$$ = $3;
12616212Saw148015 	$$->attr_name = $1;
12626212Saw148015 }
12636212Saw148015 | pt_attr_name
12646212Saw148015 {
12656212Saw148015 	if (($$ = alloc_attr()) == NULL)
12666212Saw148015 		YYERROR;
12676212Saw148015 	$$->attr_name = $1;
12686212Saw148015 };
12696212Saw148015 
12706212Saw148015 /* attribute parsing for flowops */
12716212Saw148015 fo_attr_ops: fo_attr_op
12726212Saw148015 {
12736212Saw148015 	$$ = $1;
12746212Saw148015 }
12756212Saw148015 | fo_attr_ops FSK_SEPLST fo_attr_op
12765184Sek110237 {
12775184Sek110237 	attr_t *attr = NULL;
12785184Sek110237 	attr_t *list_end = NULL;
12795184Sek110237 
12805184Sek110237 	for (attr = $1; attr != NULL;
12815184Sek110237 	    attr = attr->attr_next)
12825184Sek110237 		list_end = attr; /* Find end of list */
12835184Sek110237 
12845184Sek110237 	list_end->attr_next = $3;
12855184Sek110237 
12865184Sek110237 	$$ = $1;
12876550Saw148015 }
12886550Saw148015 | fo_attr_ops FSK_SEPLST comp_lvar_def
12896550Saw148015 {
12906550Saw148015 	attr_t *attr = NULL;
12916550Saw148015 	attr_t *list_end = NULL;
12926550Saw148015 
12936550Saw148015 	for (attr = $1; attr != NULL;
12946550Saw148015 	    attr = attr->attr_next)
12956550Saw148015 		list_end = attr; /* Find end of list */
12966550Saw148015 
12976550Saw148015 	list_end->attr_next = $3;
12986550Saw148015 
12996550Saw148015 	$$ = $1;
13005184Sek110237 };
13015184Sek110237 
13026212Saw148015 fo_attr_op: fo_attr_name FSK_ASSIGN attr_value
13035184Sek110237 {
13045184Sek110237 	$$ = $3;
13055184Sek110237 	$$->attr_name = $1;
13065184Sek110237 }
13076212Saw148015 | fo_attr_name
13085184Sek110237 {
13095184Sek110237 	if (($$ = alloc_attr()) == NULL)
13105184Sek110237 		YYERROR;
13115184Sek110237 	$$->attr_name = $1;
13126212Saw148015 };
13136212Saw148015 
13146212Saw148015 /* attribute parsing for Event Generator */
13156212Saw148015 ev_attr_ops: ev_attr_op
13166212Saw148015 {
13176212Saw148015 	$$ = $1;
13185184Sek110237 }
13196212Saw148015 | ev_attr_ops FSK_SEPLST ev_attr_op
13206212Saw148015 {
13216212Saw148015 	attr_t *attr = NULL;
13226212Saw148015 	attr_t *list_end = NULL;
13236212Saw148015 
13246212Saw148015 	for (attr = $1; attr != NULL;
13256212Saw148015 	    attr = attr->attr_next)
13266212Saw148015 		list_end = attr; /* Find end of list */
13276212Saw148015 
13286212Saw148015 	list_end->attr_next = $3;
13296212Saw148015 
13306212Saw148015 	$$ = $1;
13316212Saw148015 };
13326212Saw148015 
13336212Saw148015 ev_attr_op: ev_attr_name FSK_ASSIGN attr_value
13346212Saw148015 {
13356212Saw148015 	$$ = $3;
13366212Saw148015 	$$->attr_name = $1;
13376212Saw148015 }
13386212Saw148015 | ev_attr_name
13396212Saw148015 {
13406212Saw148015 	if (($$ = alloc_attr()) == NULL)
13416212Saw148015 		YYERROR;
13426212Saw148015 	$$->attr_name = $1;
13436212Saw148015 };
13446212Saw148015 
13456212Saw148015 files_attr_name: attrs_define_file
13466212Saw148015 |attrs_define_fileset;
13476212Saw148015 
13486212Saw148015 pt_attr_name: attrs_define_thread
13496212Saw148015 |attrs_define_proc;
13506212Saw148015 
13516212Saw148015 fo_attr_name: attrs_flowop;
13526212Saw148015 
13536212Saw148015 ev_attr_name: attrs_eventgen;
13545184Sek110237 
13555184Sek110237 attrs_define_proc:
13566212Saw148015   FSA_NICE { $$ = FSA_NICE;}
13576212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
13586212Saw148015 | FSA_INSTANCES { $$ = FSA_INSTANCES;};
13595184Sek110237 
13605184Sek110237 attrs_define_file:
13616212Saw148015   FSA_SIZE { $$ = FSA_SIZE;}
13626212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
13635184Sek110237 | FSA_PATH { $$ = FSA_PATH;}
13645184Sek110237 | FSA_REUSE { $$ = FSA_REUSE;}
13655184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;}
13665184Sek110237 | FSA_PARALLOC { $$ = FSA_PARALLOC;};
13675184Sek110237 
13685184Sek110237 attrs_define_fileset:
13696212Saw148015   FSA_SIZE { $$ = FSA_SIZE;}
13706212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
13715184Sek110237 | FSA_PATH { $$ = FSA_PATH;}
13725184Sek110237 | FSA_DIRWIDTH { $$ = FSA_DIRWIDTH;}
13736212Saw148015 | FSA_DIRDEPTHRV { $$ = FSA_DIRDEPTHRV;}
13745184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;}
13755184Sek110237 | FSA_FILESIZEGAMMA { $$ = FSA_FILESIZEGAMMA;}
13765184Sek110237 | FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;}
13775184Sek110237 | FSA_CACHED { $$ = FSA_CACHED;}
13785184Sek110237 | FSA_ENTRIES { $$ = FSA_ENTRIES;};
13795184Sek110237 
13806212Saw148015 randvar_attr_name:
13816212Saw148015   FSA_NAME { $$ = FSA_NAME;}
13826212Saw148015 | FSA_RANDSEED { $$ = FSA_RANDSEED;}
13836212Saw148015 | FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;}
13846212Saw148015 | FSA_RANDMEAN { $$ = FSA_RANDMEAN;}
13856212Saw148015 | FSA_RANDMIN { $$ = FSA_RANDMIN;}
13866212Saw148015 | FSA_RANDROUND { $$ = FSA_RANDROUND;};
13876212Saw148015 
13886212Saw148015 randvar_attr_tsp:
13896212Saw148015   FSS_TYPE { $$ = FSS_TYPE;}
13906212Saw148015 | FSS_SRC { $$ = FSS_SRC;}
13916212Saw148015 | FSS_SEED { $$ = FSS_SEED;}
13926212Saw148015 | FSS_GAMMA { $$ = FSS_GAMMA;}
13936212Saw148015 | FSS_MEAN { $$ = FSS_MEAN;}
13946212Saw148015 | FSS_MIN { $$ = FSS_MIN;}
13956212Saw148015 | FSS_ROUND { $$ = FSS_ROUND;};
13966212Saw148015 
13976212Saw148015 
13986212Saw148015 randvar_attr_param:
13996212Saw148015   FSS_SEED { $$ = FSS_SEED;}
14006212Saw148015 | FSS_GAMMA { $$ = FSS_GAMMA;}
14016212Saw148015 | FSS_MEAN { $$ = FSS_MEAN;}
14026212Saw148015 | FSS_MIN { $$ = FSS_MIN;}
14036212Saw148015 | FSS_ROUND { $$ = FSS_ROUND;};
14046212Saw148015 
14056212Saw148015 randvar_attr_typop: randtype_name
14066212Saw148015 {
14076212Saw148015 	if (($$ = alloc_attr()) == NULL)
14086212Saw148015 		YYERROR;
14096212Saw148015 	$$->attr_avd = avd_int_alloc($1);
14106212Saw148015 };
14116212Saw148015 
14126212Saw148015 randtype_name:
14136212Saw148015   FSV_RANDUNI { $$ = FSV_RANDUNI;}
14146212Saw148015 | FSV_RANDTAB { $$ = FSV_RANDTAB;}
14156212Saw148015 | FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;};
14166212Saw148015 
14176212Saw148015 randvar_attr_srcop: randsrc_name
14186212Saw148015 {
14196212Saw148015 	if (($$ = alloc_attr()) == NULL)
14206212Saw148015 		YYERROR;
14216212Saw148015 	$$->attr_avd = avd_int_alloc($1);
14226212Saw148015 };
14236212Saw148015 
14246212Saw148015 randsrc_name:
14256212Saw148015   FSV_URAND { $$ = FSV_URAND;}
14266212Saw148015 | FSV_RAND48 { $$ = FSV_RAND48;};
14276212Saw148015 
14285184Sek110237 attrs_define_thread:
14296212Saw148015   FSA_PROCESS { $$ = FSA_PROCESS;}
14306212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
14316212Saw148015 | FSA_MEMSIZE { $$ = FSA_MEMSIZE;}
14326212Saw148015 | FSA_USEISM { $$ = FSA_USEISM;}
14336212Saw148015 | FSA_INSTANCES { $$ = FSA_INSTANCES;};
14345184Sek110237 
14355184Sek110237 attrs_flowop:
14366212Saw148015   FSA_WSS { $$ = FSA_WSS;}
14376212Saw148015 | FSA_FILE { $$ = FSA_FILE;}
14386212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
14396212Saw148015 | FSA_RANDOM { $$ = FSA_RANDOM;}
14406212Saw148015 | FSA_FD { $$ = FSA_FD;}
14416212Saw148015 | FSA_SRCFD { $$ = FSA_SRCFD;}
14426212Saw148015 | FSA_ROTATEFD { $$ = FSA_ROTATEFD;}
14436212Saw148015 | FSA_DSYNC { $$ = FSA_DSYNC;}
14446212Saw148015 | FSA_DIRECTIO { $$ = FSA_DIRECTIO;}
14456212Saw148015 | FSA_TARGET { $$ = FSA_TARGET;}
14466212Saw148015 | FSA_ITERS { $$ = FSA_ITERS;}
14476212Saw148015 | FSA_VALUE { $$ = FSA_VALUE;}
14486212Saw148015 | FSA_BLOCKING { $$ = FSA_BLOCKING;}
14496212Saw148015 | FSA_HIGHWATER { $$ = FSA_HIGHWATER;}
14506212Saw148015 | FSA_IOSIZE { $$ = FSA_IOSIZE;};
14515184Sek110237 
14525184Sek110237 attrs_eventgen:
14536212Saw148015   FSA_RATE { $$ = FSA_RATE;};
14546212Saw148015 
14556550Saw148015 comp_attr_ops: comp_attr_op
14566550Saw148015 {
14576550Saw148015 	$$ = $1;
14586550Saw148015 }
14596550Saw148015 | comp_attr_ops FSK_SEPLST comp_attr_op
14606550Saw148015 {
14616550Saw148015 	attr_t *attr = NULL;
14626550Saw148015 	attr_t *list_end = NULL;
14636550Saw148015 
14646550Saw148015 	for (attr = $1; attr != NULL;
14656550Saw148015 	    attr = attr->attr_next)
14666550Saw148015 		list_end = attr; /* Find end of list */
14676550Saw148015 
14686550Saw148015 	list_end->attr_next = $3;
14696550Saw148015 
14706550Saw148015 	$$ = $1;
14716550Saw148015 }
14726550Saw148015 | comp_attr_ops FSK_SEPLST comp_lvar_def
14736550Saw148015 {
14746550Saw148015 	attr_t *attr = NULL;
14756550Saw148015 	attr_t *list_end = NULL;
14766550Saw148015 
14776550Saw148015 	for (attr = $1; attr != NULL;
14786550Saw148015 	    attr = attr->attr_next)
14796550Saw148015 		list_end = attr; /* Find end of list */
14806550Saw148015 
14816550Saw148015 	list_end->attr_next = $3;
14826550Saw148015 
14836550Saw148015 	$$ = $1;
14846550Saw148015 };
14856550Saw148015 
14866550Saw148015 comp_attr_op: attrs_define_comp FSK_ASSIGN attr_value
14876550Saw148015 {
14886550Saw148015 	$$ = $3;
14896550Saw148015 	$$->attr_name = $1;
14906550Saw148015 };
14916550Saw148015 
14926550Saw148015 comp_lvar_def: FSV_VARIABLE FSK_ASSIGN FSV_VAL_BOOLEAN
14936550Saw148015 {
14946550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_boolean($1, $3))) == NULL)
14956550Saw148015 		YYERROR;
14966550Saw148015 }
14976550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
14986550Saw148015 {
14996550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_integer($1, $3))) == NULL)
15006550Saw148015 		YYERROR;
15016550Saw148015 }
15026550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
15036550Saw148015 {
15046550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_string($1, $4))) == NULL)
15056550Saw148015 		YYERROR;
15066550Saw148015 }
15076550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_STRING
15086550Saw148015 {
15096550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_string($1, $3))) == NULL)
15106550Saw148015 		YYERROR;
15116550Saw148015 }
15126550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE
15136550Saw148015 {
15146550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_var($1, $3))) == NULL)
15156550Saw148015 		YYERROR;
15166550Saw148015 }
15176550Saw148015 | FSV_VARIABLE
15186550Saw148015 {
15196550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_alloc_local($1))) == NULL)
15206550Saw148015 		YYERROR;
15216550Saw148015 };
15226550Saw148015 
15236550Saw148015 
15246550Saw148015 attrs_define_comp:
15256550Saw148015   FSA_NAME { $$ = FSA_NAME;}
15266550Saw148015 | FSA_ITERS { $$ = FSA_ITERS;};
15276550Saw148015 
15286212Saw148015 attr_value: FSV_STRING
15296212Saw148015 {
15306212Saw148015 	if (($$ = alloc_attr()) == NULL)
15316212Saw148015 		YYERROR;
15326212Saw148015 	$$->attr_avd = avd_str_alloc($1);
15336212Saw148015 } | FSV_VAL_INT {
15346212Saw148015 	if (($$ = alloc_attr()) == NULL)
15356212Saw148015 		YYERROR;
15366212Saw148015 	$$->attr_avd = avd_int_alloc($1);
15376212Saw148015 } | FSV_VAL_BOOLEAN {
15386212Saw148015 	if (($$ = alloc_attr()) == NULL)
15396212Saw148015 		YYERROR;
15406212Saw148015 	$$->attr_avd = avd_bool_alloc($1);
15416212Saw148015 } | FSV_VARIABLE {
15426212Saw148015 	if (($$ = alloc_attr()) == NULL)
15436212Saw148015 		YYERROR;
15446212Saw148015 	$$->attr_avd = var_ref_attr($1);
15456212Saw148015 };
15466212Saw148015 
15476212Saw148015 attr_list_value: var_string_list {
15485184Sek110237 	if (($$ = alloc_attr()) == NULL)
15495184Sek110237 		YYERROR;
15505184Sek110237 	$$->attr_param_list = $1;
15515184Sek110237 } | FSV_STRING
15525184Sek110237 {
15535184Sek110237 	if (($$ = alloc_attr()) == NULL)
15545184Sek110237 		YYERROR;
15556212Saw148015 	$$->attr_avd = avd_str_alloc($1);
15565184Sek110237 } | FSV_VAL_INT {
15575184Sek110237 	if (($$ = alloc_attr()) == NULL)
15585184Sek110237 		YYERROR;
15596212Saw148015 	$$->attr_avd = avd_int_alloc($1);
15606212Saw148015 } | FSV_VAL_BOOLEAN {
15616212Saw148015 	if (($$ = alloc_attr()) == NULL)
15626212Saw148015 		YYERROR;
15636212Saw148015 	$$->attr_avd = avd_bool_alloc($1);
15645184Sek110237 } | FSV_VARIABLE {
15655184Sek110237 	if (($$ = alloc_attr()) == NULL)
15665184Sek110237 		YYERROR;
15676212Saw148015 	$$->attr_avd = var_ref_attr($1);
15686212Saw148015 };
15696212Saw148015 
15706212Saw148015 var_int_val: FSV_VAL_INT
15716212Saw148015 {
15726212Saw148015 	$$ = avd_int_alloc($1);
15736212Saw148015 } | FSV_VARIABLE
15746212Saw148015 {
15756212Saw148015 	$$ = var_ref_attr($1);
15765184Sek110237 };
15775184Sek110237 
15785184Sek110237 %%
15795184Sek110237 
15805184Sek110237 /*
15815184Sek110237  *  The following 'c' routines implement the various commands defined in the
15825184Sek110237  * above yacc parser code. The yacc portion checks the syntax of the commands
15835184Sek110237  * found in a workload file, or typed on interactive command lines, parsing
15845184Sek110237  * the commands' parameters into lists. The lists are then passed in a cmd_t
15855184Sek110237  * struct for each command to its related routine in the following section
15865184Sek110237  * for actual execution. This section also includes a few utility routines
15875184Sek110237  * and the main entry point for the program.
15885184Sek110237  */
15895184Sek110237 
15905184Sek110237 /*
15915184Sek110237  * Entry point for filebench. Processes command line arguements. The -f
15925184Sek110237  * option will read in a workload file (the full name and extension must
15935184Sek110237  * must be given). The -a, -s, -m and -i options are used by worker process
15945184Sek110237  * to receive their name, the base address of shared memory, its path, and
15955184Sek110237  * the process' instance number, respectively. This information is supplied
15965184Sek110237  * by the master process when it execs worker processes under the process
15975184Sek110237  * model of execution. If the worker process arguments are passed then main
15985184Sek110237  * will call the procflow_exec routine which creates worker threadflows and
15995184Sek110237  * flowops and executes the procflow's portion of the workload model until
16005184Sek110237  * completion. If worker process arguments are not passed to the process,
16015184Sek110237  * then it becomes the master process for a filebench run. It initializes
16025184Sek110237  * the various filebench components and either executes the supplied workload
16035184Sek110237  * file, or enters interactive mode.
16045184Sek110237  */
16055184Sek110237 
16065184Sek110237 int
16075184Sek110237 main(int argc, char *argv[])
16085184Sek110237 {
16095184Sek110237 	int opt;
16105184Sek110237 	int docmd = FS_FALSE;
16115184Sek110237 	int instance;
16125184Sek110237 	char procname[128];
16135184Sek110237 	caddr_t shmaddr;
16145184Sek110237 	char dir[MAXPATHLEN];
16155184Sek110237 #ifdef HAVE_SETRLIMIT
16165184Sek110237 	struct rlimit rlp;
16175184Sek110237 #endif
16185184Sek110237 #ifdef HAVE_LIBTECLA
16195184Sek110237 	char *line;
16205184Sek110237 #else
16215184Sek110237 	char line[1024];
16225184Sek110237 #endif
16235184Sek110237 	char shmpathtmp[1024];
16245184Sek110237 
16255184Sek110237 #ifdef HAVE_SETRLIMIT
16265184Sek110237 	/* Set resource limits */
16275184Sek110237 	(void) getrlimit(RLIMIT_NOFILE, &rlp);
16285184Sek110237 	rlp.rlim_cur = rlp.rlim_max;
16295184Sek110237 	setrlimit(RLIMIT_NOFILE, &rlp);
16305184Sek110237 #endif
16315184Sek110237 
16325184Sek110237 	yydebug = 0;
16335184Sek110237 	execname = argv[0];
16345184Sek110237 	*procname = 0;
16355184Sek110237 	cwd = getcwd(dir, MAXPATHLEN);
16365184Sek110237 
16375184Sek110237 	while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) {
16385184Sek110237 
16395184Sek110237 		switch (opt) {
16405184Sek110237 		case 'h':
16415184Sek110237 			usage(2);
16425184Sek110237 			break;
16435184Sek110237 
16445184Sek110237 		case 'p':
16455184Sek110237 			noproc = 1;
16465184Sek110237 			break;
16475184Sek110237 
16485184Sek110237 		case 'f':
16495184Sek110237 			if (optarg == NULL)
16505184Sek110237 				usage(1);
16515184Sek110237 			if ((yyin = fopen(optarg, "r")) == NULL) {
16525184Sek110237 				(void) fprintf(stderr,
16535184Sek110237 				    "Cannot open file %s", optarg);
16545184Sek110237 				exit(1);
16555184Sek110237 			}
16565184Sek110237 			dofile = FS_TRUE;
16575184Sek110237 			fscriptname = optarg;
16585184Sek110237 
16595184Sek110237 			break;
16605184Sek110237 
16615184Sek110237 		case 'a':
16625184Sek110237 			if (optarg == NULL)
16635184Sek110237 				usage(1);
16645184Sek110237 			sscanf(optarg, "%s", &procname[0]);
16655184Sek110237 			break;
16665184Sek110237 
16675184Sek110237 		case 's':
16685184Sek110237 			if (optarg == NULL)
16695184Sek110237 				usage(1);
16705184Sek110237 #if defined(_LP64) || (__WORDSIZE == 64)
16715184Sek110237 			sscanf(optarg, "%llx", &shmaddr);
16725184Sek110237 #else
16735184Sek110237 			sscanf(optarg, "%x", &shmaddr);
16745184Sek110237 #endif
16755184Sek110237 			break;
16765184Sek110237 
16775184Sek110237 		case 'm':
16785184Sek110237 			if (optarg == NULL)
16795184Sek110237 				usage(1);
16805184Sek110237 			sscanf(optarg, "%s", shmpathtmp);
16815184Sek110237 			shmpath = shmpathtmp;
16825184Sek110237 			break;
16835184Sek110237 
16845184Sek110237 		case 'i':
16855184Sek110237 			if (optarg == NULL)
16865184Sek110237 				usage(1);
16875184Sek110237 			sscanf(optarg, "%d", &instance);
16885184Sek110237 			break;
16895184Sek110237 
16905184Sek110237 		case '?':
16915184Sek110237 		default:
16925184Sek110237 			usage(1);
16935184Sek110237 			break;
16945184Sek110237 		}
16955184Sek110237 	}
16965184Sek110237 
16975184Sek110237 #ifdef USE_PROCESS_MODEL
16985184Sek110237 	if (!(*procname))
16995184Sek110237 #endif
17005184Sek110237 	printf("FileBench Version %s\n", FILEBENCH_VERSION);
17015184Sek110237 	filebench_init();
17025184Sek110237 
17036084Saw148015 	/* get process pid for use with message logging */
17046084Saw148015 	my_pid = getpid();
17056084Saw148015 
17065184Sek110237 #ifdef USE_PROCESS_MODEL
17075184Sek110237 	if (*procname) {
17086084Saw148015 		/* A child FileBench instance */
17095184Sek110237 		if (ipc_attach(shmaddr) < 0) {
17105184Sek110237 			filebench_log(LOG_ERROR, "Cannot attach shm for %s",
17115184Sek110237 			    procname);
17125184Sek110237 			exit(1);
17135184Sek110237 		}
17145184Sek110237 
17156212Saw148015 		if (procflow_exec(procname, instance) < 0) {
17166212Saw148015 			filebench_log(LOG_ERROR, "Cannot startup process %s",
17176212Saw148015 			    procname);
17185184Sek110237 			exit(1);
17196212Saw148015 		}
17206084Saw148015 
17216084Saw148015 		exit(0);
17225184Sek110237 	}
17235184Sek110237 #endif
17245184Sek110237 
17256084Saw148015 	/* master (or only) process */
17265184Sek110237 	ipc_init();
17275184Sek110237 
17285184Sek110237 	if (fscriptname)
17296391Saw148015 		(void) strcpy(filebench_shm->shm_fscriptname, fscriptname);
17305184Sek110237 
17315184Sek110237 	flowop_init();
17325184Sek110237 	stats_init();
17335184Sek110237 	eventgen_init();
17345184Sek110237 
17355184Sek110237 	signal(SIGINT, parser_abort);
17365184Sek110237 
17375184Sek110237 	if (dofile)
17385184Sek110237 		yyparse();
17395184Sek110237 	else {
17405184Sek110237 #ifdef HAVE_LIBTECLA
17415184Sek110237 		if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) {
17425184Sek110237 			filebench_log(LOG_ERROR,
17435184Sek110237 			    "Failed to create GetLine object");
17445184Sek110237 			filebench_shutdown(1);
17455184Sek110237 		}
17465184Sek110237 
17475184Sek110237 		if (gl_customize_completion(gl, NULL, command_complete)) {
17485184Sek110237 			filebench_log(LOG_ERROR,
17495184Sek110237 			    "Failed to register auto-completion function");
17505184Sek110237 			filebench_shutdown(1);
17515184Sek110237 		}
17525184Sek110237 
17535184Sek110237 		while (line = gl_get_line(gl, FILEBENCH_PROMPT, NULL, -1)) {
17545184Sek110237 			arg_parse(line);
17555184Sek110237 			yyparse();
17565184Sek110237 		}
17575184Sek110237 
17585184Sek110237 		del_GetLine(gl);
17595184Sek110237 #else
17605184Sek110237 		while (!feof(stdin)) {
17615184Sek110237 			printf(FILEBENCH_PROMPT);
17625184Sek110237 			fflush(stdout);
17635184Sek110237 			if (fgets(line, sizeof (line), stdin) == NULL) {
17645184Sek110237 				if (errno == EINTR)
17655184Sek110237 					continue;
17665184Sek110237 				else
17675184Sek110237 					break;
17685184Sek110237 			}
17695184Sek110237 			arg_parse(line);
17705184Sek110237 			yyparse();
17715184Sek110237 		}
17725184Sek110237 		printf("\n");
17735184Sek110237 #endif	/* HAVE_LIBTECLA */
17745184Sek110237 	}
17755184Sek110237 
17765184Sek110237 	parser_filebench_shutdown((cmd_t *)0);
17775184Sek110237 
17785184Sek110237 	return (0);
17795184Sek110237 }
17805184Sek110237 
17815184Sek110237 /*
17825184Sek110237  * arg_parse() puts the parser into command parsing mode. Create a tmpfile
17835184Sek110237  * and instruct the parser to read instructions from this location by setting
17845184Sek110237  * yyin to the value returned by tmpfile. Write the command into the file.
17855184Sek110237  * Then seek back to to the start of the file so that the parser can read
17865184Sek110237  * the instructions.
17875184Sek110237  */
17885184Sek110237 static void
17895184Sek110237 arg_parse(const char *command)
17905184Sek110237 {
1791*6750Sek110237 	if ((yyin = tmpfile()) == NULL) {
17925184Sek110237 		filebench_log(LOG_FATAL,
1793*6750Sek110237 		    "Exiting: Cannot create tmpfile: %s", strerror(errno));
1794*6750Sek110237 		exit(1);
1795*6750Sek110237 	}
17965184Sek110237 
17975184Sek110237 	if (fwrite(command, strlen(command), 1, yyin) != 1)
17985184Sek110237 		filebench_log(LOG_FATAL,
17995184Sek110237 		    "Cannot write tmpfile: %s", strerror(errno));
18005184Sek110237 
18015184Sek110237 	if (fseek(yyin, 0, SEEK_SET) != 0)
18025184Sek110237 		filebench_log(LOG_FATAL,
18035184Sek110237 		    "Cannot seek tmpfile: %s", strerror(errno));
18045184Sek110237 }
18055184Sek110237 
18065184Sek110237 /*
18075184Sek110237  * Converts a list of var_strings or ordinary strings to a single ordinary
18085184Sek110237  * string. It returns a pointer to the string (in malloc'd memory) if found,
18095184Sek110237  * or NULL otherwise.
18105184Sek110237  */
18115184Sek110237 char *
18125184Sek110237 parser_list2string(list_t *list)
18135184Sek110237 {
18145184Sek110237 	list_t *l;
18155184Sek110237 	char *string;
18165184Sek110237 	char *tmp;
18176212Saw148015 	fbint_t *integer;
18185184Sek110237 	if ((string = malloc(MAXPATHLEN)) == NULL) {
18195184Sek110237 		filebench_log(LOG_ERROR, "Failed to allocate memory");
18205184Sek110237 		return (NULL);
18215184Sek110237 	}
18225184Sek110237 
18235184Sek110237 	*string = 0;
18245184Sek110237 
18255184Sek110237 
18265184Sek110237 	/* Format args */
18276212Saw148015 	for (l = list; l != NULL; l = l->list_next) {
18286212Saw148015 		char *lstr = avd_get_str(l->list_string);
18296212Saw148015 
18305184Sek110237 		filebench_log(LOG_DEBUG_SCRIPT,
18316212Saw148015 		    "converting string '%s'", lstr);
18326212Saw148015 
18336212Saw148015 		/* see if it is a random variable */
18346212Saw148015 		if (l->list_integer) {
18356212Saw148015 			fbint_t param_name;
18366212Saw148015 
18376212Saw148015 			tmp = NULL;
18386212Saw148015 			param_name = avd_get_int(l->list_integer);
18396212Saw148015 			switch (param_name) {
18406212Saw148015 			case FSS_TYPE:
18416212Saw148015 				tmp = var_randvar_to_string(lstr,
18426212Saw148015 				    RAND_PARAM_TYPE);
18436212Saw148015 				break;
18446212Saw148015 
18456212Saw148015 			case FSS_SRC:
18466212Saw148015 				tmp = var_randvar_to_string(lstr,
18476212Saw148015 				    RAND_PARAM_SRC);
18486212Saw148015 				break;
18496212Saw148015 
18506212Saw148015 			case FSS_SEED:
18516212Saw148015 				tmp = var_randvar_to_string(lstr,
18526212Saw148015 				    RAND_PARAM_SEED);
18536212Saw148015 				break;
18546212Saw148015 
18556212Saw148015 			case FSS_MIN:
18566212Saw148015 				tmp = var_randvar_to_string(lstr,
18576212Saw148015 				    RAND_PARAM_MIN);
18586212Saw148015 				break;
18596212Saw148015 
18606212Saw148015 			case FSS_MEAN:
18616212Saw148015 				tmp = var_randvar_to_string(lstr,
18626212Saw148015 				    RAND_PARAM_MEAN);
18636212Saw148015 				break;
18646212Saw148015 
18656212Saw148015 			case FSS_GAMMA:
18666212Saw148015 				tmp = var_randvar_to_string(lstr,
18676212Saw148015 				    RAND_PARAM_GAMMA);
18686212Saw148015 				break;
18696212Saw148015 
18706212Saw148015 			case FSS_ROUND:
18716212Saw148015 				tmp = var_randvar_to_string(lstr,
18726212Saw148015 				    RAND_PARAM_ROUND);
18736212Saw148015 				break;
18746212Saw148015 			}
18756212Saw148015 
18766212Saw148015 			if (tmp) {
18776212Saw148015 				(void) strcat(string, tmp);
18786212Saw148015 				free(tmp);
18796212Saw148015 			} else {
18806212Saw148015 				(void) strcat(string, lstr);
18816212Saw148015 			}
18825184Sek110237 		} else {
18836212Saw148015 			/* perhaps a normal variable? */
18846212Saw148015 			if ((tmp = var_to_string(lstr)) != NULL) {
18856212Saw148015 				(void) strcat(string, tmp);
18866212Saw148015 				free(tmp);
18876212Saw148015 			} else {
18886212Saw148015 				(void) strcat(string, lstr);
18896212Saw148015 			}
18905184Sek110237 		}
18915184Sek110237 	}
18925184Sek110237 	return (string);
18935184Sek110237 }
18945184Sek110237 
18955184Sek110237 /*
18965184Sek110237  * If the list just contains a single string starting with '$', then find
18975184Sek110237  * or create the named var and return the var's var_string component.
18985184Sek110237  * Otherwise, convert the list to a string, and allocate a var_string
18995184Sek110237  * containing a copy of that string. On failure either returns NULL
19005184Sek110237  * or shuts down the run.
19015184Sek110237  */
19026212Saw148015 avd_t
19035184Sek110237 parser_list2varstring(list_t *list)
19045184Sek110237 {
19056212Saw148015 	char *lstr = avd_get_str(list->list_string);
19066212Saw148015 
19075184Sek110237 	/* Special case - variable name */
19086212Saw148015 	if ((list->list_next == NULL) && (*lstr == '$'))
19096212Saw148015 		return (var_ref_attr(lstr));
19106212Saw148015 
19116212Saw148015 	return (avd_str_alloc(parser_list2string(list)));
19125184Sek110237 }
19135184Sek110237 
19145184Sek110237 /*
19155184Sek110237  * Looks for the var named in list_string of the first element of the
19166212Saw148015  * supplied list. If found, returns the var_val portion of the var in
19176212Saw148015  * an attribute value descriptor. If the var is not found, cannot be
19186212Saw148015  * allocated, the supplied list is NULL, or the list_string filed is
19196212Saw148015  * empty, returns NULL.
19205184Sek110237  */
19216212Saw148015 avd_t
19226212Saw148015 parser_list2avd(list_t *list)
19235184Sek110237 {
19246212Saw148015 	avd_t avd;
19256212Saw148015 	char *lstr;
19266212Saw148015 
19276212Saw148015 	if (list && ((lstr = avd_get_str(list->list_string)) != NULL)) {
19286212Saw148015 		avd = var_ref_attr(lstr);
19296212Saw148015 		return (avd);
19305184Sek110237 	}
19315184Sek110237 
19325184Sek110237 	return (NULL);
19335184Sek110237 }
19345184Sek110237 
19355184Sek110237 /*
19365184Sek110237  * Sets the event generator rate from the attribute supplied with the
19375184Sek110237  * command. If the attribute doesn't exist the routine does nothing.
19385184Sek110237  */
19395184Sek110237 static void
19405184Sek110237 parser_eventgen(cmd_t *cmd)
19415184Sek110237 {
19425184Sek110237 	attr_t *attr;
19436212Saw148015 	fbint_t rate;
19445184Sek110237 
19455184Sek110237 	/* Get the rate from attribute */
19465184Sek110237 	if (attr = get_attr_integer(cmd, FSA_RATE)) {
19476212Saw148015 		if (attr->attr_avd) {
19486212Saw148015 			rate = avd_get_int(attr->attr_avd);
19495184Sek110237 			filebench_log(LOG_VERBOSE,
19506286Saw148015 			    "Eventgen: %llu per second",
19516286Saw148015 			    (u_longlong_t)rate);
19526212Saw148015 			eventgen_setrate(rate);
19535184Sek110237 		}
19545184Sek110237 	}
19555184Sek110237 }
19565184Sek110237 
19575184Sek110237 /*
19585184Sek110237  * Assigns the designated integer variable successive values from the
19595184Sek110237  * supplied comma seperated integer list. After each successive integer
19605184Sek110237  * assignment, it executes the bracket enclosed list of commands. For
19615184Sek110237  * example, repeated runs of a workload with increasing io sizes can
19625184Sek110237  * be done using the following command line:
19635184Sek110237  * 	foreach $iosize in 2k, 4k, 8k {run 60}
19645184Sek110237  */
19655184Sek110237 static void
19665184Sek110237 parser_foreach_integer(cmd_t *cmd)
19675184Sek110237 {
19685184Sek110237 	list_t *list = cmd->cmd_param_list;
19695184Sek110237 	cmd_t *inner_cmd;
19705184Sek110237 
19715184Sek110237 	for (; list != NULL; list = list->list_next) {
19726212Saw148015 		fbint_t list_int = avd_get_int(list->list_integer);
19736212Saw148015 
19746212Saw148015 		var_assign_integer(cmd->cmd_tgt1, list_int);
19756286Saw148015 		filebench_log(LOG_VERBOSE, "Iterating %s=%llu",
19766286Saw148015 		    cmd->cmd_tgt1, (u_longlong_t)list_int);
19775184Sek110237 		for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
19785184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
19795184Sek110237 			inner_cmd->cmd(inner_cmd);
19805184Sek110237 		}
19815184Sek110237 	}
19825184Sek110237 }
19835184Sek110237 
19845184Sek110237 /*
19855184Sek110237  * Similar to parser_foreach_integer(), except takes a list of strings after
19865184Sek110237  * the "in" token. For example, to run twice using a different directory,
19875184Sek110237  * perhaps using a different filesystem, the following command line
19885184Sek110237  * could be used:
19895184Sek110237  * 	foreach $dir in "/ufs_top/fbt", "/zfs_top/fbt" {run 60)
19905184Sek110237  */
19915184Sek110237 static void
19925184Sek110237 parser_foreach_string(cmd_t *cmd)
19935184Sek110237 {
19945184Sek110237 	list_t *list = cmd->cmd_param_list;
19955184Sek110237 
19965184Sek110237 	for (; list != NULL; list = list->list_next) {
19976212Saw148015 		cmd_t *inner_cmd;
19986212Saw148015 		char *lstr = avd_get_str(list->list_string);
19996212Saw148015 		var_assign_string(cmd->cmd_tgt1, lstr);
20005184Sek110237 		filebench_log(LOG_VERBOSE, "Iterating %s=%s",
20016212Saw148015 		    cmd->cmd_tgt1, lstr);
20025184Sek110237 		for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
20035184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
20045184Sek110237 			inner_cmd->cmd(inner_cmd);
20055184Sek110237 		}
20065184Sek110237 	}
20075184Sek110237 }
20085184Sek110237 
20095184Sek110237 /*
20105673Saw148015  * Lists the fileset name, path name and average size for all defined
20115673Saw148015  * filesets.
20125184Sek110237  */
20135184Sek110237 static void
20145184Sek110237 parser_list(cmd_t *cmd)
20155184Sek110237 {
20165673Saw148015 	(void) fileset_iter(fileset_print);
20175184Sek110237 }
20185184Sek110237 
20195184Sek110237 /*
20206212Saw148015  * Lists the flowop name and instance number for all flowops.
20216212Saw148015  */
20226212Saw148015 static void
20236212Saw148015 parser_flowop_list(cmd_t *cmd)
20246212Saw148015 {
20256212Saw148015 	flowop_printall();
20266212Saw148015 }
20276212Saw148015 
20286212Saw148015 /*
20295184Sek110237  * Calls procflow_define() to allocate "instances" number of  procflow(s)
20305184Sek110237  * (processes) with the supplied name. The default number of instances is
20315184Sek110237  * one. An optional priority level attribute can be supplied and is stored in
20325184Sek110237  * pf_nice. Finally the routine loops through the list of inner commands, if
20335184Sek110237  * any, which are defines for threadflows, and passes them one at a time to
20345184Sek110237  * parser_thread_define() to allocate threadflow entities for the process(es).
20355184Sek110237  */
20365184Sek110237 static void
20375184Sek110237 parser_proc_define(cmd_t *cmd)
20385184Sek110237 {
20395184Sek110237 	procflow_t *procflow, template;
20405184Sek110237 	char *name;
20415184Sek110237 	attr_t *attr;
20426212Saw148015 	avd_t var_instances;
20436212Saw148015 	fbint_t instances;
20445184Sek110237 	cmd_t *inner_cmd;
20455184Sek110237 
20465184Sek110237 	/* Get the name of the process */
20475184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
20486212Saw148015 		name = avd_get_str(attr->attr_avd);
20495184Sek110237 	} else {
20505184Sek110237 		filebench_log(LOG_ERROR,
20515184Sek110237 		    "define proc: proc specifies no name");
20525184Sek110237 		filebench_shutdown(1);
20535184Sek110237 	}
20545184Sek110237 
20555184Sek110237 	/* Get the memory size from attribute */
20565184Sek110237 	if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
20576212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
20586212Saw148015 			filebench_log(LOG_ERROR,
20596212Saw148015 			    "proc_define: Instances attr cannot be random");
20606212Saw148015 			filebench_shutdown(1);
20616212Saw148015 		}
20626212Saw148015 		var_instances = attr->attr_avd;
20636212Saw148015 		instances = avd_get_int(var_instances);
20645184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
20656286Saw148015 		    "Setting instances = %llu", (u_longlong_t)instances);
20666212Saw148015 	} else {
20676212Saw148015 		filebench_log(LOG_DEBUG_IMPL,
20686212Saw148015 		    "Defaulting to instances = 1");
20696212Saw148015 		var_instances = avd_int_alloc(1);
20706212Saw148015 		instances = 1;
20715184Sek110237 	}
20725184Sek110237 
20736212Saw148015 	if ((procflow = procflow_define(name, NULL, var_instances)) == NULL) {
20745184Sek110237 		filebench_log(LOG_ERROR,
20755184Sek110237 		    "Failed to instantiate %d %s process(es)\n",
20765184Sek110237 		    instances, name);
20775184Sek110237 		filebench_shutdown(1);
20785184Sek110237 	}
20795184Sek110237 
20805184Sek110237 	/* Get the pri from attribute */
20815184Sek110237 	if (attr = get_attr_integer(cmd, FSA_NICE)) {
20826212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
20836212Saw148015 			filebench_log(LOG_ERROR,
20846212Saw148015 			    "proc_define: priority cannot be random");
20856212Saw148015 			filebench_shutdown(1);
20866212Saw148015 		}
20876286Saw148015 		filebench_log(LOG_DEBUG_IMPL, "Setting pri = %llu",
20886286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
20896212Saw148015 		procflow->pf_nice = attr->attr_avd;
20905184Sek110237 	} else
20916212Saw148015 		procflow->pf_nice = avd_int_alloc(0);
20925184Sek110237 
20935184Sek110237 
20945184Sek110237 	/* Create the list of threads for this process  */
20955184Sek110237 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
20965184Sek110237 	    inner_cmd = inner_cmd->cmd_next) {
20976212Saw148015 		parser_thread_define(inner_cmd, procflow, instances);
20985184Sek110237 	}
20995184Sek110237 }
21005184Sek110237 
21015184Sek110237 /*
21025184Sek110237  * Calls threadflow_define() to allocate "instances" number of  threadflow(s)
21035184Sek110237  * (threads) with the supplied name. The default number of instances is
21045184Sek110237  * one. Two other optional attributes may be supplied, one to set the memory
21055184Sek110237  * size, stored in tf_memsize, and to select the use of Interprocess Shared
21065184Sek110237  * Memory, which sets the THREADFLOW_USEISM flag in tf_attrs. Finally
21075184Sek110237  * the routine loops through the list of inner commands, if any, which are
21085184Sek110237  * defines for flowops, and passes them one at a time to
21095184Sek110237  * parser_flowop_define() to allocate flowop entities for the threadflows.
21105184Sek110237  */
21115184Sek110237 static void
21125184Sek110237 parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
21135184Sek110237 {
21145184Sek110237 	threadflow_t *threadflow, template;
21155184Sek110237 	attr_t *attr;
21166212Saw148015 	avd_t instances;
21175184Sek110237 	cmd_t *inner_cmd;
21185184Sek110237 	char *name;
21195184Sek110237 
21205184Sek110237 	memset(&template, 0, sizeof (threadflow_t));
21215184Sek110237 
21225184Sek110237 	/* Get the name of the thread */
21235184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
21246212Saw148015 		name = avd_get_str(attr->attr_avd);
21255184Sek110237 	} else {
21265184Sek110237 		filebench_log(LOG_ERROR,
21275184Sek110237 		    "define thread: thread in process %s specifies no name",
21285184Sek110237 		    procflow->pf_name);
21295184Sek110237 		filebench_shutdown(1);
21305184Sek110237 	}
21315184Sek110237 
21325184Sek110237 	/* Get the number of instances from attribute */
21335184Sek110237 	if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
21346212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
21356212Saw148015 			filebench_log(LOG_ERROR,
21366212Saw148015 			    "define thread: Instances attr cannot be random");
21376212Saw148015 			filebench_shutdown(1);
21386212Saw148015 		}
21395184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
21406286Saw148015 		    "define thread: Setting instances = %llu",
21416286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
21426212Saw148015 		instances = attr->attr_avd;
21436212Saw148015 	} else
21446212Saw148015 		instances = avd_int_alloc(1);
21455184Sek110237 
21465184Sek110237 	/* Get the memory size from attribute */
21475184Sek110237 	if (attr = get_attr_integer(cmd, FSA_MEMSIZE)) {
21486212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
21496212Saw148015 			filebench_log(LOG_ERROR,
21506212Saw148015 			    "define thread: Memory size cannot be random");
21516212Saw148015 			filebench_shutdown(1);
21526212Saw148015 		}
21535184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
21546286Saw148015 		    "define thread: Setting memsize = %llu",
21556286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
21566212Saw148015 		template.tf_memsize = attr->attr_avd;
21575184Sek110237 	} else
21586212Saw148015 		template.tf_memsize = avd_int_alloc(0);
21595184Sek110237 
21605184Sek110237 	if ((threadflow = threadflow_define(procflow, name,
21615184Sek110237 	    &template, instances)) == NULL) {
21625184Sek110237 		filebench_log(LOG_ERROR,
21635184Sek110237 		    "define thread: Failed to instantiate thread\n");
21645184Sek110237 		filebench_shutdown(1);
21655184Sek110237 	}
21665184Sek110237 
21675184Sek110237 	/* Use ISM Memory? */
21685184Sek110237 	if (attr = get_attr(cmd, FSA_USEISM)) {
21695184Sek110237 		threadflow->tf_attrs |= THREADFLOW_USEISM;
21705184Sek110237 	}
21715184Sek110237 
21725184Sek110237 	/* Create the list of flowops */
21735184Sek110237 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
21745184Sek110237 	    inner_cmd = inner_cmd->cmd_next) {
21756212Saw148015 		parser_flowop_define(inner_cmd, threadflow,
21766550Saw148015 		    &threadflow->tf_thrd_fops, FLOW_MASTER);
21775184Sek110237 	}
21785184Sek110237 }
21795184Sek110237 
21805184Sek110237 /*
21816212Saw148015  * Files in the attributes for a newly allocated flowop
21826212Saw148015  */
21836212Saw148015 static void
21846212Saw148015 parser_flowop_get_attrs(cmd_t *cmd, flowop_t *flowop)
21856212Saw148015 {
21866212Saw148015 	attr_t *attr;
21876212Saw148015 
21886212Saw148015 	/* Get the filename from attribute */
21896212Saw148015 	if (attr = get_attr(cmd, FSA_FILE)) {
21906212Saw148015 		flowop->fo_filename = attr->attr_avd;
21916212Saw148015 		if (flowop->fo_filename == NULL) {
21926212Saw148015 			filebench_log(LOG_ERROR,
21936212Saw148015 			    "define flowop: no filename specfied");
21946212Saw148015 			filebench_shutdown(1);
21956212Saw148015 		}
21966212Saw148015 	}
21976212Saw148015 
21986212Saw148015 	/* Get the iosize of the op */
21996212Saw148015 	if (attr = get_attr_integer(cmd, FSA_IOSIZE))
22006212Saw148015 		flowop->fo_iosize = attr->attr_avd;
22016212Saw148015 	else
22026212Saw148015 		flowop->fo_iosize = avd_int_alloc(0);
22036212Saw148015 
22046212Saw148015 	/* Get the working set size of the op */
22056212Saw148015 	if (attr = get_attr_integer(cmd, FSA_WSS))
22066212Saw148015 		flowop->fo_wss = attr->attr_avd;
22076212Saw148015 	else
22086212Saw148015 		flowop->fo_wss = avd_int_alloc(0);
22096212Saw148015 
22106212Saw148015 	/* Random I/O? */
22116212Saw148015 	if (attr = get_attr_bool(cmd, FSA_RANDOM))
22126212Saw148015 		flowop->fo_random = attr->attr_avd;
22136212Saw148015 	else
22146212Saw148015 		flowop->fo_random = avd_bool_alloc(FALSE);
22156212Saw148015 
22166212Saw148015 	/* Sync I/O? */
22176212Saw148015 	if (attr = get_attr_bool(cmd, FSA_DSYNC))
22186212Saw148015 		flowop->fo_dsync = attr->attr_avd;
22196212Saw148015 	else
22206212Saw148015 		flowop->fo_dsync = avd_bool_alloc(FALSE);
22216212Saw148015 
22226212Saw148015 	/* Target, for wakeup etc */
22236212Saw148015 	if (attr = get_attr(cmd, FSA_TARGET))
22246212Saw148015 		(void) strcpy(flowop->fo_targetname,
22256212Saw148015 		    avd_get_str(attr->attr_avd));
22266212Saw148015 
22276212Saw148015 	/* Value */
22286212Saw148015 	if (attr = get_attr_integer(cmd, FSA_VALUE))
22296212Saw148015 		flowop->fo_value = attr->attr_avd;
22306212Saw148015 	else
22316212Saw148015 		flowop->fo_value = avd_int_alloc(0);
22326212Saw148015 
22336212Saw148015 	/* FD */
22346212Saw148015 	if (attr = get_attr_integer(cmd, FSA_FD))
22356212Saw148015 		flowop->fo_fdnumber = avd_get_int(attr->attr_avd);
22366212Saw148015 
22376212Saw148015 	/* Rotatefd? */
22386212Saw148015 	if (attr = get_attr_bool(cmd, FSA_ROTATEFD))
22396212Saw148015 		flowop->fo_rotatefd = attr->attr_avd;
22406212Saw148015 	else
22416212Saw148015 		flowop->fo_rotatefd = avd_bool_alloc(FALSE);
22426212Saw148015 
22436212Saw148015 	/* SRC FD, for copies etc... */
22446212Saw148015 	if (attr = get_attr_integer(cmd, FSA_SRCFD))
22456212Saw148015 		flowop->fo_srcfdnumber = avd_get_int(attr->attr_avd);
22466212Saw148015 
22476212Saw148015 	/* Blocking operation? */
22486212Saw148015 	if (attr = get_attr_bool(cmd, FSA_BLOCKING))
22496212Saw148015 		flowop->fo_blocking = attr->attr_avd;
22506212Saw148015 	else
22516212Saw148015 		flowop->fo_blocking = avd_bool_alloc(FALSE);
22526212Saw148015 
22536212Saw148015 	/* Direct I/O Operation */
22546212Saw148015 	if (attr = get_attr_bool(cmd, FSA_DIRECTIO))
22556212Saw148015 		flowop->fo_directio = attr->attr_avd;
22566212Saw148015 	else
22576212Saw148015 		flowop->fo_directio = avd_bool_alloc(FALSE);
22586212Saw148015 
22596212Saw148015 	/* Highwater mark */
22606212Saw148015 	if (attr = get_attr_integer(cmd, FSA_HIGHWATER)) {
22616212Saw148015 		flowop->fo_highwater = attr->attr_avd;
22626212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
22636212Saw148015 			filebench_log(LOG_ERROR,
22646212Saw148015 			    "define flowop: Highwater attr cannot be random");
22656212Saw148015 			filebench_shutdown(1);
22666212Saw148015 		}
22676212Saw148015 	} else {
22686212Saw148015 		flowop->fo_highwater = avd_int_alloc(1);
22696212Saw148015 	}
22706212Saw148015 }
22716212Saw148015 
22726550Saw148015 /*
22736550Saw148015  * defines the FLOW_MASTER flowops within a FLOW_MASTER instance of
22746550Saw148015  * a composit flowop. Default attributes from the FLOW_INNER_DEF instances
22756550Saw148015  * of the composit flowop's inner flowops are used if set. Otherwise
22766550Saw148015  * default attributes from the FLOW_MASTER instance of the composit flowop
22776550Saw148015  * are used, which may include defaults from the original FLOW_DEFINITION
22786550Saw148015  * of the composit flowop.
22796550Saw148015  */
22806550Saw148015 static void
22816550Saw148015 parser_inner_flowop_define(threadflow_t *thread, flowop_t *comp0_flow,
22826550Saw148015 			   flowop_t *comp_mstr_flow)
22836550Saw148015 {
22846550Saw148015 	flowop_t *inner_flowtype, *inner_flowop;
22856550Saw148015 
22866550Saw148015 	/* follow flowop list, creating composit names */
22876550Saw148015 	inner_flowtype = comp0_flow->fo_comp_fops;
22886550Saw148015 	comp_mstr_flow->fo_comp_fops = NULL;
22896550Saw148015 
22906550Saw148015 	while (inner_flowtype) {
22916550Saw148015 		char fullname[MAXPATHLEN];
22926550Saw148015 
22936550Saw148015 		/* create composite_name.name for new flowop */
22946613Sek110237 		snprintf(fullname, MAXPATHLEN, "%s.%s",
22956613Sek110237 		    comp_mstr_flow->fo_name, inner_flowtype->fo_name);
22966550Saw148015 
22976550Saw148015 		if ((inner_flowop = flowop_define(thread, fullname,
22986550Saw148015 		    inner_flowtype, &comp_mstr_flow->fo_comp_fops,
22996550Saw148015 		    FLOW_MASTER, 0)) == NULL) {
23006550Saw148015 			filebench_log(LOG_ERROR,
23016550Saw148015 			    "define flowop: Failed to instantiate flowop %s\n",
23026550Saw148015 			    fullname);
23036550Saw148015 			filebench_shutdown(1);
23046550Saw148015 		}
23056550Saw148015 
23066550Saw148015 		/* if applicable, update filename attribute */
23076550Saw148015 		if (inner_flowop->fo_filename) {
23086550Saw148015 			char *name;
23096550Saw148015 
23106550Saw148015 			/* fix up avd_t */
23116550Saw148015 			avd_update(&inner_flowop->fo_filename,
23126550Saw148015 			    comp_mstr_flow->fo_lvar_list);
23136550Saw148015 
23146550Saw148015 			/* see if ready to get the file or fileset */
23156550Saw148015 			name = avd_get_str(inner_flowop->fo_filename);
23166550Saw148015 			if (name) {
23176550Saw148015 
23186550Saw148015 				inner_flowop->fo_fileset = fileset_find(name);
23196550Saw148015 
23206550Saw148015 				if (inner_flowop->fo_fileset == NULL) {
23216550Saw148015 					filebench_log(LOG_ERROR,
23226550Saw148015 					    "inr flowop %s: file %s not found",
23236550Saw148015 					    inner_flowop->fo_name, name);
23246550Saw148015 					filebench_shutdown(1);
23256550Saw148015 				}
23266550Saw148015 			}
23276550Saw148015 		}
23286550Saw148015 
23296550Saw148015 		/* update attributes from local variables */
23306550Saw148015 		avd_update(&inner_flowop->fo_iters,
23316550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23326550Saw148015 
23336550Saw148015 		/* if the inner flowop is a composit flowop, recurse */
23346550Saw148015 		if (inner_flowtype->fo_type == FLOW_TYPE_COMPOSITE) {
23356550Saw148015 			var_t *newlvar, *proto_lvars, *lvar_ptr;
23366550Saw148015 
23376550Saw148015 			proto_lvars = inner_flowop->fo_lvar_list;
23386550Saw148015 			inner_flowop->fo_lvar_list = 0;
23396550Saw148015 
23406550Saw148015 			for (lvar_ptr = inner_flowtype->fo_lvar_list; lvar_ptr;
23416550Saw148015 			    lvar_ptr = lvar_ptr->var_next) {
23426550Saw148015 
23436550Saw148015 				if ((newlvar = var_lvar_alloc_local(
23446550Saw148015 				    lvar_ptr->var_name)) != NULL) {
23456550Saw148015 
23466550Saw148015 					add_lvar_to_list(newlvar,
23476550Saw148015 					    &inner_flowop->fo_lvar_list);
23486550Saw148015 
23496550Saw148015 					var_update_comp_lvars(newlvar,
23506550Saw148015 					    proto_lvars,
23516550Saw148015 					    comp_mstr_flow->fo_lvar_list);
23526550Saw148015 				}
23536550Saw148015 			}
23546550Saw148015 
23556550Saw148015 			parser_inner_flowop_define(thread,
23566550Saw148015 			    inner_flowtype,
23576550Saw148015 			    inner_flowop);
23586550Saw148015 
23596550Saw148015 			inner_flowtype = inner_flowtype->fo_exec_next;
23606550Saw148015 			continue;
23616550Saw148015 		}
23626550Saw148015 
23636550Saw148015 		avd_update(&inner_flowop->fo_iosize,
23646550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23656550Saw148015 		avd_update(&inner_flowop->fo_wss,
23666550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23676550Saw148015 		avd_update(&inner_flowop->fo_iters,
23686550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23696550Saw148015 		avd_update(&inner_flowop->fo_value,
23706550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23716550Saw148015 		avd_update(&inner_flowop->fo_random,
23726550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23736550Saw148015 		avd_update(&inner_flowop->fo_dsync,
23746550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23756550Saw148015 		avd_update(&inner_flowop->fo_rotatefd,
23766550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23776550Saw148015 		avd_update(&inner_flowop->fo_blocking,
23786550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23796550Saw148015 		avd_update(&inner_flowop->fo_directio,
23806550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23816550Saw148015 		avd_update(&inner_flowop->fo_highwater,
23826550Saw148015 		    comp_mstr_flow->fo_lvar_list);
23836550Saw148015 
23846550Saw148015 		inner_flowtype = inner_flowtype->fo_exec_next;
23856550Saw148015 	}
23866550Saw148015 }
23876212Saw148015 
23886212Saw148015 /*
23895184Sek110237  * Calls flowop_define() to allocate a flowop with the supplied name.
23905184Sek110237  * The allocated flowop inherits attributes from a base flowop of the
23915184Sek110237  * same type.  If the new flowop has a file or fileset attribute specified,
23925184Sek110237  * it must specify a defined fileobj or fileset or an error will be logged.
23935184Sek110237  * The new flowop may  also have the following attributes set by
23945184Sek110237  * the program:
23955184Sek110237  *  - file size (fo_iosize)
23965184Sek110237  *  - working set size (fo_wss)
23975184Sek110237  *  - do random io (fo_random)
23985184Sek110237  *  - do synchronous io (fo_dsync)
23995184Sek110237  *  - perform each operation multiple times before advancing (fo_iter)
24005184Sek110237  *  - target name (fo_targetname)
24015184Sek110237  *  - An integer value (fo_value)
24025184Sek110237  *  - a file descriptor (fo_fd)
24035184Sek110237  *  - specify to rotate file descriptors (fo_rotatefd)
24045184Sek110237  *  - a source fd (fo_srcfdnumber)
24055184Sek110237  *  - specify a blocking operation (fo_blocking)
24065184Sek110237  *  - specify a highwater mark (fo_highwater)
24075184Sek110237  *
24085184Sek110237  * After all the supplied attributes are stored in their respective locations
24095184Sek110237  * in the flowop object, the flowop's init function is called. No errors are
24105184Sek110237  * returned, but the filebench run will be terminated if the flowtype is not
24115184Sek110237  * specified, a name for the new flowop is not supplied, the flowop_define
24125184Sek110237  * call fails, or a file or fileset name is supplied but the corresponding
24135184Sek110237  * fileobj or fileset cannot be located.
24145184Sek110237  */
24155184Sek110237 static void
24166212Saw148015 parser_flowop_define(cmd_t *cmd, threadflow_t *thread,
24176212Saw148015     flowop_t **flowoplist_hdp, int category)
24185184Sek110237 {
24195184Sek110237 	flowop_t *flowop, *flowop_type;
24205184Sek110237 	char *type = (char *)cmd->cmd_name;
24215184Sek110237 	char *name;
24225184Sek110237 	attr_t *attr;
24235184Sek110237 
24245184Sek110237 	/* Get the inherited flowop */
24255184Sek110237 	flowop_type = flowop_find(type);
24265184Sek110237 	if (flowop_type == NULL) {
24275184Sek110237 		filebench_log(LOG_ERROR,
24285184Sek110237 		    "define flowop: flowop type %s not found",
24295184Sek110237 		    type);
24305184Sek110237 		filebench_shutdown(1);
24315184Sek110237 	}
24325184Sek110237 
24335184Sek110237 	/* Get the name of the flowop */
24345184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
24356212Saw148015 		name = avd_get_str(attr->attr_avd);
24365184Sek110237 	} else {
24375184Sek110237 		filebench_log(LOG_ERROR,
24385184Sek110237 		    "define flowop: flowop %s specifies no name",
24395184Sek110237 		    flowop_type->fo_name);
24405184Sek110237 		filebench_shutdown(1);
24415184Sek110237 	}
24425184Sek110237 
24435184Sek110237 	if ((flowop = flowop_define(thread, name,
24446550Saw148015 	    flowop_type, flowoplist_hdp, category, 0)) == NULL) {
24455184Sek110237 		filebench_log(LOG_ERROR,
24465184Sek110237 		    "define flowop: Failed to instantiate flowop %s\n",
24475184Sek110237 		    cmd->cmd_name);
24485184Sek110237 		filebench_shutdown(1);
24495184Sek110237 	}
24505184Sek110237 
24515184Sek110237 	/* Iterations */
24525184Sek110237 	if (attr = get_attr_integer(cmd, FSA_ITERS))
24536212Saw148015 		flowop->fo_iters = attr->attr_avd;
24545184Sek110237 	else
24556212Saw148015 		flowop->fo_iters = avd_int_alloc(1);
24566212Saw148015 
24576550Saw148015 
24586550Saw148015 	/* if this is a use of a composit flowop, create inner FLOW MASTERS */
24596550Saw148015 	if (flowop_type->fo_type == FLOW_TYPE_COMPOSITE) {
24606550Saw148015 		get_attr_lvars(cmd, flowop);
24616550Saw148015 		if (category == FLOW_MASTER)
24626550Saw148015 			parser_inner_flowop_define(thread,
24636550Saw148015 			    flowop_type, flowop);
24646550Saw148015 	}
24656550Saw148015 	else {
24666550Saw148015 		parser_flowop_get_attrs(cmd, flowop);
24676550Saw148015 	}
24685184Sek110237 }
24695184Sek110237 
24706550Saw148015 static void
24716550Saw148015 parser_composite_flowop_define(cmd_t *cmd)
24726550Saw148015 {
24736550Saw148015 	flowop_t *flowop;
24746550Saw148015 	cmd_t *inner_cmd;
24756550Saw148015 	char *name;
24766550Saw148015 	attr_t *attr;
24776550Saw148015 
24786550Saw148015 	/* Get the name of the flowop */
24796550Saw148015 	if (attr = get_attr(cmd, FSA_NAME)) {
24806550Saw148015 		name = avd_get_str(attr->attr_avd);
24816550Saw148015 	} else {
24826550Saw148015 		filebench_log(LOG_ERROR,
24836550Saw148015 		    "define flowop: Composit flowop specifies no name");
24846550Saw148015 
24856550Saw148015 		filebench_shutdown(1);
24866550Saw148015 	}
24876550Saw148015 
24886550Saw148015 	if ((flowop = flowop_new_composite_define(name)) == NULL) {
24896550Saw148015 		filebench_log(LOG_ERROR,
24906550Saw148015 		    "define flowop: Failed to instantiate flowop %s\n",
24916550Saw148015 		    cmd->cmd_name);
24926550Saw148015 		filebench_shutdown(1);
24936550Saw148015 	}
24946550Saw148015 
24956550Saw148015 	/* place any local var_t variables on the flowop's local list */
24966550Saw148015 	get_attr_lvars(cmd, flowop);
24976550Saw148015 
24986550Saw148015 	/* Iterations */
24996550Saw148015 	if (attr = get_attr_integer(cmd, FSA_ITERS))
25006550Saw148015 		flowop->fo_iters = attr->attr_avd;
25016550Saw148015 	else
25026550Saw148015 		flowop->fo_iters = avd_int_alloc(1);
25036550Saw148015 
25046550Saw148015 	/* define inner flowops */
25056550Saw148015 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
25066550Saw148015 	    inner_cmd = inner_cmd->cmd_next) {
25076550Saw148015 		parser_flowop_define(inner_cmd, NULL,
25086550Saw148015 		    &flowop->fo_comp_fops, FLOW_INNER_DEF);
25096550Saw148015 	}
25106550Saw148015 }
25116550Saw148015 
25126550Saw148015 
25135184Sek110237 /*
25145184Sek110237  * Calls fileset_define() to allocate a fileset with the supplied name and
25156212Saw148015  * initializes the fileset's pathname attribute, and optionally the
25166212Saw148015  * fileset_cached, fileset_reuse, fileset_prealloc and fileset_size attributes.
25175673Saw148015  *
25185184Sek110237  */
25195673Saw148015 static fileset_t *
25205673Saw148015 parser_fileset_define_common(cmd_t *cmd)
25215184Sek110237 {
25225184Sek110237 	fileset_t *fileset;
25236212Saw148015 	avd_t name;
25245184Sek110237 	attr_t *attr;
25256212Saw148015 	avd_t pathname;
25265184Sek110237 
25275184Sek110237 	/* Get the name of the file */
25285184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
25296212Saw148015 		name = attr->attr_avd;
25305184Sek110237 	} else {
25315184Sek110237 		filebench_log(LOG_ERROR,
25325673Saw148015 		    "define fileset: file or fileset specifies no name");
25335673Saw148015 		return (NULL);
25345184Sek110237 	}
25355184Sek110237 
25365184Sek110237 	if ((fileset = fileset_define(name)) == NULL) {
25375184Sek110237 		filebench_log(LOG_ERROR,
25385184Sek110237 		    "define file: failed to instantiate file %s\n",
25396212Saw148015 		    avd_get_str(name));
25405673Saw148015 		return (NULL);
25415184Sek110237 	}
25425184Sek110237 
25435184Sek110237 	/* Get the pathname from attribute */
25445184Sek110237 	if ((attr = get_attr(cmd, FSA_PATH)) == NULL) {
25455184Sek110237 		filebench_log(LOG_ERROR, "define file: no pathname specified");
25465673Saw148015 		return (NULL);
25475184Sek110237 	}
25485184Sek110237 
25495184Sek110237 	/* Expand variables in pathname */
25505673Saw148015 	if ((pathname = parser_list2varstring(attr->attr_param_list))
25515673Saw148015 	    == NULL) {
25525184Sek110237 		filebench_log(LOG_ERROR, "Cannot interpret path");
25535673Saw148015 		return (NULL);
25545184Sek110237 	}
25555184Sek110237 
25565184Sek110237 	fileset->fs_path = pathname;
25575184Sek110237 
25585673Saw148015 	/* Should we prealloc in parallel? */
25596212Saw148015 	if (attr = get_attr_bool(cmd, FSA_PARALLOC))
25606212Saw148015 		fileset->fs_paralloc = attr->attr_avd;
25616212Saw148015 	else
25626212Saw148015 		fileset->fs_paralloc = avd_bool_alloc(FALSE);
25635673Saw148015 
25645673Saw148015 	/* Should we reuse the existing file? */
25655673Saw148015 	if (attr = get_attr_bool(cmd, FSA_REUSE)) {
25666212Saw148015 		fileset->fs_reuse = attr->attr_avd;
25675673Saw148015 	} else
25686212Saw148015 		fileset->fs_reuse = avd_bool_alloc(FALSE);
25695673Saw148015 
25705184Sek110237 	/* Should we leave in cache? */
25715184Sek110237 	if (attr = get_attr_bool(cmd, FSA_CACHED)) {
25726212Saw148015 		fileset->fs_cached = attr->attr_avd;
25735184Sek110237 	} else
25746212Saw148015 		fileset->fs_cached = avd_bool_alloc(FALSE);
25755184Sek110237 
25765673Saw148015 	/* Get the mean or absolute size of the file */
25775673Saw148015 	if (attr = get_attr_integer(cmd, FSA_SIZE)) {
25786212Saw148015 		fileset->fs_size = attr->attr_avd;
25795184Sek110237 	} else
25806212Saw148015 		fileset->fs_size = avd_int_alloc(0);
25815673Saw148015 
25825673Saw148015 	return (fileset);
25835673Saw148015 }
25845673Saw148015 
25855673Saw148015 /*
25865673Saw148015  * Calls parser_fileset_define_common() to allocate a fileset with
25876212Saw148015  * one entry and optionally the fileset_prealloc. Sets the
25886212Saw148015  * fileset_preallocpercent, fileset_entries, fileset_dirwidth,
25896212Saw148015  * fileset_dirgamma, and fileset_sizegamma attributes
25905673Saw148015  * to appropriate values for emulating the old "fileobj" entity
25915673Saw148015  */
25925673Saw148015 static void
25935673Saw148015 parser_file_define(cmd_t *cmd)
25945673Saw148015 {
25955673Saw148015 	fileset_t *fileset;
25965673Saw148015 	attr_t *attr;
25975673Saw148015 
25985673Saw148015 	if ((fileset = parser_fileset_define_common(cmd)) == NULL) {
25995673Saw148015 		filebench_log(LOG_ERROR,
26005673Saw148015 		    "define file: failed to instantiate file");
26015673Saw148015 		filebench_shutdown(1);
26025673Saw148015 		return;
26035673Saw148015 	}
26045673Saw148015 
26055673Saw148015 	/* fileset is emulating a single file */
26065673Saw148015 	fileset->fs_attrs = FILESET_IS_FILE;
26075673Saw148015 
26085673Saw148015 	/* Set the size of the fileset to 1 */
26096212Saw148015 	fileset->fs_entries = avd_int_alloc(1);
26105673Saw148015 
26115673Saw148015 	/* Set the mean dir width to more than 1 */
26126212Saw148015 	fileset->fs_dirwidth = avd_int_alloc(10);
26135673Saw148015 
26145673Saw148015 	/* Set the dir and size gammas to 0 */
26156212Saw148015 	fileset->fs_dirgamma = avd_int_alloc(0);
26166212Saw148015 	fileset->fs_sizegamma = avd_int_alloc(0);
26175673Saw148015 
26185673Saw148015 	/* Does file need to be preallocated? */
26195673Saw148015 	if (attr = get_attr_bool(cmd, FSA_PREALLOC)) {
26205673Saw148015 		/* yes */
26216212Saw148015 		fileset->fs_prealloc = attr->attr_avd;
26226212Saw148015 		fileset->fs_preallocpercent = avd_int_alloc(100);
26235673Saw148015 	} else {
26245673Saw148015 		/* no */
26256212Saw148015 		fileset->fs_prealloc = avd_bool_alloc(FALSE);
26266212Saw148015 		fileset->fs_preallocpercent = avd_int_alloc(0);
26275673Saw148015 	}
26285673Saw148015 }
26295673Saw148015 
26305673Saw148015 /*
26315673Saw148015  * Calls parser_fileset_define_common() to allocate a fileset with the
26326212Saw148015  * supplied name and initializes the fileset's fileset_preallocpercent,
26336212Saw148015  * fileset_prealloc, fileset_entries, fileset_dirwidth, fileset_dirgamma,
26346212Saw148015  * and fileset_sizegamma attributes.
26355673Saw148015  */
26365673Saw148015 static void
26375673Saw148015 parser_fileset_define(cmd_t *cmd)
26385673Saw148015 {
26395673Saw148015 	fileset_t *fileset;
26405673Saw148015 	attr_t *attr;
26415673Saw148015 
26425673Saw148015 	if ((fileset = parser_fileset_define_common(cmd)) == NULL) {
26435673Saw148015 		filebench_log(LOG_ERROR,
26445673Saw148015 		    "define fileset: failed to instantiate fileset");
26455673Saw148015 		filebench_shutdown(1);
26465673Saw148015 		return;
26475673Saw148015 	}
26485673Saw148015 
26495673Saw148015 	/* How much should we preallocate? */
26505184Sek110237 	if ((attr = get_attr_integer(cmd, FSA_PREALLOC)) &&
26516212Saw148015 	    attr->attr_avd) {
26526212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
26536212Saw148015 			filebench_log(LOG_ERROR,
26546212Saw148015 			    "define fileset: Prealloc attr cannot be random");
26556212Saw148015 			filebench_shutdown(1);
26566212Saw148015 		}
26576212Saw148015 		fileset->fs_preallocpercent = attr->attr_avd;
26586212Saw148015 	} else if (attr && !attr->attr_avd) {
26596212Saw148015 		fileset->fs_preallocpercent = avd_int_alloc(100);
26605184Sek110237 	} else {
26616212Saw148015 		fileset->fs_preallocpercent = avd_int_alloc(0);
26625184Sek110237 	}
26635184Sek110237 
26645184Sek110237 	/* Should we preallocate? */
26655184Sek110237 	if (attr = get_attr_bool(cmd, FSA_PREALLOC)) {
26666212Saw148015 		fileset->fs_prealloc = attr->attr_avd;
26675184Sek110237 	} else
26686212Saw148015 		fileset->fs_prealloc = avd_bool_alloc(FALSE);
26695184Sek110237 
26705673Saw148015 	/* Get the number of files in the fileset */
26715184Sek110237 	if (attr = get_attr_integer(cmd, FSA_ENTRIES)) {
26726212Saw148015 		fileset->fs_entries = attr->attr_avd;
26735184Sek110237 	} else {
26745184Sek110237 		filebench_log(LOG_ERROR, "Fileset has zero entries");
26756212Saw148015 		fileset->fs_entries = avd_int_alloc(0);
26765184Sek110237 	}
26775184Sek110237 
26785184Sek110237 	/* Get the mean dir width of the fileset */
26795184Sek110237 	if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) {
26806212Saw148015 		fileset->fs_dirwidth = attr->attr_avd;
26815184Sek110237 	} else {
26825184Sek110237 		filebench_log(LOG_ERROR, "Fileset has zero directory width");
26836212Saw148015 		fileset->fs_dirwidth = avd_int_alloc(0);
26845184Sek110237 	}
26855184Sek110237 
26866212Saw148015 	/* Get the random variable for dir depth, if supplied */
26876212Saw148015 	if (attr = get_attr_integer(cmd, FSA_DIRDEPTHRV)) {
26886212Saw148015 		if (!AVD_IS_RANDOM(attr->attr_avd)) {
26896212Saw148015 			filebench_log(LOG_ERROR,
26906212Saw148015 			    "Define fileset: dirdepthrv must be random var");
26916212Saw148015 			filebench_shutdown(1);
26926212Saw148015 		}
26936212Saw148015 		fileset->fs_dirdepthrv = attr->attr_avd;
26946212Saw148015 	} else {
26956212Saw148015 		fileset->fs_dirdepthrv = NULL;
26966212Saw148015 	}
26976212Saw148015 
26986212Saw148015 	/* Get the gamma value for dir depth distributions */
26995184Sek110237 	if (attr = get_attr_integer(cmd, FSA_DIRGAMMA)) {
27006212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
27016212Saw148015 			filebench_log(LOG_ERROR,
27026212Saw148015 			    "Define fileset: dirgamma attr cannot be random");
27036212Saw148015 			filebench_shutdown(1);
27046212Saw148015 		}
27056212Saw148015 		fileset->fs_dirgamma = attr->attr_avd;
27065184Sek110237 	} else
27076212Saw148015 		fileset->fs_dirgamma = avd_int_alloc(1500);
27085184Sek110237 
27095184Sek110237 	/* Get the gamma value for dir width distributions */
27105184Sek110237 	if (attr = get_attr_integer(cmd, FSA_FILESIZEGAMMA)) {
27116212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
27126212Saw148015 			filebench_log(LOG_ERROR,
27136212Saw148015 			    "Define fileset: filesizegamma cannot be random");
27146212Saw148015 			filebench_shutdown(1);
27156212Saw148015 		}
27166212Saw148015 		fileset->fs_sizegamma = attr->attr_avd;
27175184Sek110237 	} else
27186212Saw148015 		fileset->fs_sizegamma = avd_int_alloc(1500);
27195184Sek110237 }
27205184Sek110237 
27215184Sek110237 /*
27225184Sek110237  * Creates and starts all defined procflow processes. The call to
27235184Sek110237  * procflow_init() results in creation of the requested number of
27245184Sek110237  * process instances for each previously defined procflow. The
27255184Sek110237  * child processes exec() a new instance of filebench, passing it
27265184Sek110237  * the instance number and address of the shared memory region.
27275184Sek110237  * The child processes will then create their threads and flowops.
27285184Sek110237  * The routine then unlocks the run_lock to allow all the processes'
27295184Sek110237  * threads to start and  waits for all of them to begin execution.
27305184Sek110237  * Finally, it records the start time and resets the event generation
27315184Sek110237  * system.
27325184Sek110237  */
27335184Sek110237 static void
27345184Sek110237 parser_proc_create(cmd_t *cmd)
27355184Sek110237 {
27366084Saw148015 	filebench_shm->shm_1st_err = 0;
27375184Sek110237 	if (procflow_init() != 0) {
27385184Sek110237 		filebench_log(LOG_ERROR, "Failed to create processes\n");
27395184Sek110237 		filebench_shutdown(1);
27405184Sek110237 	}
27415184Sek110237 
27425184Sek110237 	/* Release the read lock, allowing threads to start */
27436391Saw148015 	(void) pthread_rwlock_unlock(&filebench_shm->shm_run_lock);
27445184Sek110237 
27455184Sek110237 	/* Wait for all threads to start */
27465184Sek110237 	if (procflow_allstarted() != 0) {
27475184Sek110237 		filebench_log(LOG_ERROR, "Could not start run");
27485184Sek110237 		return;
27495184Sek110237 	}
27505184Sek110237 
27515184Sek110237 
27525184Sek110237 	if (filebench_shm->shm_required &&
27535184Sek110237 	    (ipc_ismcreate(filebench_shm->shm_required) < 0)) {
27545184Sek110237 		filebench_log(LOG_ERROR, "Could not allocate shared memory");
27555184Sek110237 		return;
27565184Sek110237 	}
27575184Sek110237 
27586305Saw148015 	filebench_shm->shm_starttime = gethrtime();
27595184Sek110237 	eventgen_reset();
27605184Sek110237 }
27615184Sek110237 
27625184Sek110237 /*
27635673Saw148015  * Calls fileset_createset() to populate all files and filesets and
27645673Saw148015  * create all associated, initially existant,  files and subdirectories.
27655184Sek110237  * If errors are encountered, calls filebench_shutdown()
27665184Sek110237  * to exit filebench.
27675184Sek110237  */
27685184Sek110237 static void
27695184Sek110237 parser_fileset_create(cmd_t *cmd)
27705184Sek110237 {
27715673Saw148015 	if (!filecreate_done) {
27725673Saw148015 		filecreate_done = 1;
27736212Saw148015 
27746212Saw148015 		/* initialize the random number system first */
27756212Saw148015 		randdist_init();
27766212Saw148015 
27776212Saw148015 		/* create all the filesets */
27785673Saw148015 		if (fileset_createset(NULL) != 0) {
27795673Saw148015 			filebench_log(LOG_ERROR, "Failed to create filesets");
27805673Saw148015 			filebench_shutdown(1);
27815673Saw148015 		}
27825673Saw148015 	} else {
27835673Saw148015 		filebench_log(LOG_INFO,
27845673Saw148015 		    "Attempting to create fileset more than once, ignoring");
27855184Sek110237 	}
27865673Saw148015 
27875184Sek110237 }
27885184Sek110237 
27895184Sek110237 /*
27905184Sek110237  * Shuts down all processes and their associated threads. When finished
27915184Sek110237  * it deletes interprocess shared memory and resets the event generator.
27925184Sek110237  * It does not exit the filebench program though.
27935184Sek110237  */
27945184Sek110237 static void
27955184Sek110237 parser_proc_shutdown(cmd_t *cmd)
27965184Sek110237 {
27975184Sek110237 	filebench_log(LOG_INFO, "Shutting down processes");
27985673Saw148015 	filecreate_done = 0;
27995184Sek110237 	procflow_shutdown();
28005184Sek110237 	if (filebench_shm->shm_required)
28015184Sek110237 		ipc_ismdelete();
28025184Sek110237 	eventgen_reset();
28035184Sek110237 }
28045184Sek110237 
28055184Sek110237 /*
28065184Sek110237  * Ends filebench run after first destoring any interprocess
28075184Sek110237  * shared memory. The call to filebench_shutdown()
28085184Sek110237  * also causes filebench to exit.
28095184Sek110237  */
28105184Sek110237 static void
28115184Sek110237 parser_filebench_shutdown(cmd_t *cmd)
28125184Sek110237 {
28136391Saw148015 	int f_abort = filebench_shm->shm_f_abort;
28146391Saw148015 
2815*6750Sek110237 	ipc_fini();
28166391Saw148015 
28176391Saw148015 	if (f_abort == FILEBENCH_ABORT_ERROR)
28186391Saw148015 		filebench_shutdown(1);
28196391Saw148015 	else
28206391Saw148015 		filebench_shutdown(0);
28215184Sek110237 }
28225184Sek110237 
28235184Sek110237 /*
28246084Saw148015  * This is Used for timing runs.Pauses the master thread in one second
28256084Saw148015  * intervals until the supplied ptime runs out or the f_abort flag
28266084Saw148015  * is raised. If given a time of zero or less, or the mode is stop on
28276084Saw148015  * lack of resources, it will pause until f_abort is raised.
28285184Sek110237  */
28295184Sek110237 static void
28306084Saw148015 parser_pause(int ptime)
28315184Sek110237 {
28326084Saw148015 	int timeslept = 0;
28336084Saw148015 
28346084Saw148015 	if ((filebench_shm->shm_rmode == FILEBENCH_MODE_TIMEOUT) &&
28356084Saw148015 	    (ptime > 0)) {
28366084Saw148015 		while (timeslept < ptime) {
28376084Saw148015 			(void) sleep(1);
28386084Saw148015 			timeslept++;
28396391Saw148015 			if (filebench_shm->shm_f_abort)
28406084Saw148015 				break;
28416084Saw148015 		}
28426084Saw148015 	} else {
28436084Saw148015 		/* initial runtime of 0 means run till abort */
28446084Saw148015 		/* CONSTCOND */
28456084Saw148015 		while (1) {
28466084Saw148015 			(void) sleep(1);
28476084Saw148015 			timeslept++;
28486391Saw148015 			if (filebench_shm->shm_f_abort)
28496084Saw148015 				break;
28506084Saw148015 		}
28515184Sek110237 	}
28526084Saw148015 
28536286Saw148015 	filebench_log(LOG_INFO, "Run took %d seconds...", timeslept);
28545184Sek110237 }
28555184Sek110237 
28565184Sek110237 /*
28575184Sek110237  * Do a file bench run. Calls routines to create file sets, files, and
28585184Sek110237  * processes. It resets the statistics counters, then sleeps for the runtime
28595184Sek110237  * passed as an argument to it on the command line in 1 second increments.
28605184Sek110237  * When it is finished sleeping, it collects a snapshot of the statistics
28615184Sek110237  * and ends the run.
28625184Sek110237  */
28635184Sek110237 static void
28645184Sek110237 parser_run(cmd_t *cmd)
28655184Sek110237 {
28665184Sek110237 	int runtime;
28675184Sek110237 
28685184Sek110237 	runtime = cmd->cmd_qty;
28696084Saw148015 
28705184Sek110237 	parser_fileset_create(cmd);
28715184Sek110237 	parser_proc_create(cmd);
28725184Sek110237 
28735184Sek110237 	/* check for startup errors */
28746391Saw148015 	if (filebench_shm->shm_f_abort)
28755184Sek110237 		return;
28765184Sek110237 
28775184Sek110237 	filebench_log(LOG_INFO, "Running...");
28785184Sek110237 	stats_clear();
28796084Saw148015 
28806084Saw148015 	parser_pause(runtime);
28816084Saw148015 
28825184Sek110237 	parser_statssnap(cmd);
28835184Sek110237 	parser_proc_shutdown(cmd);
28845184Sek110237 }
28855184Sek110237 
28865184Sek110237 /*
28875184Sek110237  * Similar to parser_run, but gets the sleep time from a variable
28885184Sek110237  * whose name is supplied as an argument to the command.
28895184Sek110237  */
28905184Sek110237 static void
28915184Sek110237 parser_run_variable(cmd_t *cmd)
28925184Sek110237 {
28936212Saw148015 	avd_t integer = var_ref_attr(cmd->cmd_tgt1);
28945184Sek110237 	int runtime;
28955184Sek110237 
28965184Sek110237 	if (integer == NULL) {
28975184Sek110237 		filebench_log(LOG_ERROR, "Unknown variable %s",
28985184Sek110237 		cmd->cmd_tgt1);
28995184Sek110237 		return;
29005184Sek110237 	}
29015184Sek110237 
29026212Saw148015 	runtime = avd_get_int(integer);
29035184Sek110237 
29045184Sek110237 	/* check for startup errors */
29056391Saw148015 	if (filebench_shm->shm_f_abort)
29065184Sek110237 		return;
29075184Sek110237 
29085184Sek110237 	filebench_log(LOG_INFO, "Running...");
29095184Sek110237 	stats_clear();
29106084Saw148015 
29116084Saw148015 	parser_pause(runtime);
29126084Saw148015 
29135184Sek110237 	parser_statssnap(cmd);
29146084Saw148015 	parser_proc_shutdown(cmd);
29155184Sek110237 }
29165184Sek110237 
29175184Sek110237 char *usagestr = NULL;
29185184Sek110237 
29195184Sek110237 /*
29205184Sek110237  * Prints usage string if defined, else just a message requesting load of a
29215184Sek110237  * personality.
29225184Sek110237  */
29235184Sek110237 static void
29245184Sek110237 parser_help(cmd_t *cmd)
29255184Sek110237 {
29265184Sek110237 	if (usagestr) {
29275184Sek110237 		filebench_log(LOG_INFO, "%s", usagestr);
29285184Sek110237 	} else {
29295184Sek110237 		filebench_log(LOG_INFO,
29305184Sek110237 		    "load <personality> (ls "
29316613Sek110237 		    FILEBENCHDIR "/workloads for list)");
29325184Sek110237 	}
29335184Sek110237 }
29345184Sek110237 
29355184Sek110237 char *varstr = NULL;
29365184Sek110237 
29375184Sek110237 /*
29385184Sek110237  * Prints the string of all var definitions, if there is one.
29395184Sek110237  */
29405184Sek110237 static void
29415184Sek110237 parser_printvars(cmd_t *cmd)
29425184Sek110237 {
29435184Sek110237 	char *str, *c;
29445184Sek110237 
29455184Sek110237 	if (varstr) {
29465184Sek110237 		str = strdup(varstr);
29475184Sek110237 		for (c = str; *c != '\0'; c++) {
29485184Sek110237 			if ((char)*c == '$')
29495184Sek110237 				*c = ' ';
29505184Sek110237 		}
29515184Sek110237 		filebench_log(LOG_INFO, "%s", str);
29525184Sek110237 		free(str);
29535184Sek110237 	}
29545184Sek110237 }
29555184Sek110237 
29565184Sek110237 /*
29575184Sek110237  * Used by the SET command to add a var and default value string to the
29585184Sek110237  * varstr string. It allocates a new, larger varstr string, copies the
29595184Sek110237  * old contents of varstr into it, then adds the new var string on the end.
29605184Sek110237  */
29615184Sek110237 static void
29625184Sek110237 parser_vars(cmd_t *cmd)
29635184Sek110237 {
29645184Sek110237 	char *string = cmd->cmd_tgt1;
29655184Sek110237 	char *newvars;
29665184Sek110237 
29675184Sek110237 	if (string == NULL)
29685184Sek110237 		return;
29695184Sek110237 
29705184Sek110237 	if (dofile)
29715184Sek110237 		return;
29725184Sek110237 
29735184Sek110237 	if (varstr == NULL) {
29745184Sek110237 		newvars = malloc(strlen(string) + 2);
29755184Sek110237 		*newvars = 0;
29765184Sek110237 	} else {
29775184Sek110237 		newvars = malloc(strlen(varstr) + strlen(string) + 2);
29785184Sek110237 		(void) strcpy(newvars, varstr);
29795184Sek110237 	}
29805184Sek110237 	(void) strcat(newvars, string);
29815184Sek110237 	(void) strcat(newvars, " ");
29825184Sek110237 
29835184Sek110237 	if (varstr)
29845184Sek110237 		free(varstr);
29855184Sek110237 
29865184Sek110237 	varstr = newvars;
29875184Sek110237 }
29885184Sek110237 
29895184Sek110237 /*
29906084Saw148015  * Sleeps for cmd->cmd_qty seconds, one second at a time.
29916084Saw148015  */
29926084Saw148015 static void
29936084Saw148015 parser_sleep(cmd_t *cmd)
29946084Saw148015 {
29956084Saw148015 	int sleeptime;
29966084Saw148015 
29976084Saw148015 	/* check for startup errors */
29986391Saw148015 	if (filebench_shm->shm_f_abort)
29996084Saw148015 		return;
30006084Saw148015 
30016084Saw148015 	sleeptime = cmd->cmd_qty;
30026084Saw148015 	filebench_log(LOG_INFO, "Running...");
30036084Saw148015 
30046084Saw148015 	parser_pause(sleeptime);
30056084Saw148015 }
30066084Saw148015 
30076084Saw148015 /*
30086212Saw148015  * used by the set command to set the integer part of a regular
30096212Saw148015  * variable, or the appropriate field of a random variable
30106212Saw148015  */
30116212Saw148015 static void
30126212Saw148015 parser_set_integer(char *name, fbint_t integer)
30136212Saw148015 {
30146212Saw148015 	var_assign_integer(name, integer);
30156212Saw148015 }
30166212Saw148015 
30176212Saw148015 /*
30186212Saw148015  * used by the set command to set the integer part of a regular
30196212Saw148015  * variable from another variable, or the appropriate field of a
30206212Saw148015  * random variable from another variable
30216212Saw148015  */
30226212Saw148015 static void
30236212Saw148015 parser_set_var(char *dst_name, char *src_name)
30246212Saw148015 {
30256212Saw148015 	var_assign_var(dst_name, src_name);
30266212Saw148015 }
30276212Saw148015 
30286212Saw148015 
30296212Saw148015 /*
30305184Sek110237  * Same as parser_sleep, except the sleep time is obtained from a variable
30315184Sek110237  * whose name is passed to it as an argument on the command line.
30325184Sek110237  */
30335184Sek110237 static void
30345184Sek110237 parser_sleep_variable(cmd_t *cmd)
30355184Sek110237 {
30366212Saw148015 	avd_t integer = var_ref_attr(cmd->cmd_tgt1);
30375184Sek110237 	int sleeptime;
30385184Sek110237 
30395184Sek110237 	if (integer == NULL) {
30405184Sek110237 		filebench_log(LOG_ERROR, "Unknown variable %s",
30415184Sek110237 		cmd->cmd_tgt1);
30425184Sek110237 		return;
30435184Sek110237 	}
30445184Sek110237 
30456212Saw148015 	sleeptime = avd_get_int(integer);
30465184Sek110237 
30475184Sek110237 	/* check for startup errors */
30486391Saw148015 	if (filebench_shm->shm_f_abort)
30495184Sek110237 		return;
30505184Sek110237 
30515184Sek110237 	filebench_log(LOG_INFO, "Running...");
30526084Saw148015 
30536084Saw148015 	parser_pause(sleeptime);
30545184Sek110237 }
30555184Sek110237 
30565184Sek110237 /*
30575184Sek110237  * Parser log prints the values of a list of variables to the log file.
30585184Sek110237  * The list of variables is placed on the command line, separated
30595184Sek110237  * by comas and the entire list is enclosed in quotes.
30605184Sek110237  * For example, if $dir contains "/export/home/tmp" and $filesize = 1048576,
30615184Sek110237  * then typing: log "$dir, $filesize" prints: log /export/home/tmp, 1048576
30625184Sek110237  */
30635184Sek110237 static void
30645184Sek110237 parser_log(cmd_t *cmd)
30655184Sek110237 {
30665184Sek110237 	char *string;
30675184Sek110237 
30685184Sek110237 	if (cmd->cmd_param_list == NULL)
30695184Sek110237 		return;
30705184Sek110237 
30715184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
30725184Sek110237 
30735184Sek110237 	if (string == NULL)
30745184Sek110237 		return;
30755184Sek110237 
30765184Sek110237 	filebench_log(LOG_VERBOSE, "log %s", string);
30775184Sek110237 	filebench_log(LOG_LOG, "%s", string);
30785184Sek110237 }
30795184Sek110237 
30805184Sek110237 /*
30815184Sek110237  * Implements the stats directory command. changes the directory for
30825184Sek110237  * dumping statistics to supplied directory path. For example:
30835184Sek110237  * 	stats directory /tmp
30845184Sek110237  * changes the stats directory to "/tmp".
30855184Sek110237  */
30865184Sek110237 static void
30875184Sek110237 parser_directory(cmd_t *cmd)
30885184Sek110237 {
30895184Sek110237 	char newdir[MAXPATHLEN];
30905184Sek110237 	char *dir;
30915184Sek110237 
30925184Sek110237 	if ((dir = parser_list2string(cmd->cmd_param_list)) == NULL) {
30935184Sek110237 		filebench_log(LOG_ERROR, "Cannot interpret directory");
30945184Sek110237 		return;
30955184Sek110237 	}
30965184Sek110237 
30975184Sek110237 	*newdir = 0;
30985184Sek110237 	/* Change dir relative to cwd if path not fully qualified */
30995184Sek110237 	if (*dir != '/') {
31005184Sek110237 		(void) strcat(newdir, cwd);
31015184Sek110237 		(void) strcat(newdir, "/");
31025184Sek110237 	}
31035184Sek110237 	(void) strcat(newdir, dir);
31045184Sek110237 	(void) mkdir(newdir, 0755);
31055184Sek110237 	filebench_log(LOG_VERBOSE, "Change dir to %s", newdir);
31065184Sek110237 	chdir(newdir);
31075184Sek110237 	free(dir);
31085184Sek110237 }
31095184Sek110237 
31105184Sek110237 #define	PIPE_PARENT 1
31115184Sek110237 #define	PIPE_CHILD  0
31125184Sek110237 
31135184Sek110237 /*
31145184Sek110237  * Runs the quoted unix command as a background process. Intended for
31155184Sek110237  * running statistics gathering utilities such as mpstat while the filebench
31165184Sek110237  * workload is running. Also records the pid's of the background processes
31175184Sek110237  * so that parser_statssnap() can terminate them when the run completes.
31185184Sek110237  */
31195184Sek110237 static void
31205184Sek110237 parser_statscmd(cmd_t *cmd)
31215184Sek110237 {
31225184Sek110237 	char *string;
31235184Sek110237 	pid_t pid;
31245184Sek110237 	pidlist_t *pidlistent;
31255184Sek110237 	int pipe_fd[2];
31265184Sek110237 	int newstdout;
31275184Sek110237 
31285184Sek110237 	if (cmd->cmd_param_list == NULL)
31295184Sek110237 		return;
31305184Sek110237 
31315184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
31325184Sek110237 
31335184Sek110237 	if (string == NULL)
31345184Sek110237 		return;
31355184Sek110237 
31365184Sek110237 	if ((pipe(pipe_fd)) < 0) {
31375184Sek110237 		filebench_log(LOG_ERROR, "statscmd pipe failed");
31385184Sek110237 		return;
31395184Sek110237 	}
31405184Sek110237 
31415184Sek110237 #ifdef HAVE_FORK1
31425184Sek110237 	if ((pid = fork1()) < 0) {
31435184Sek110237 		filebench_log(LOG_ERROR, "statscmd fork failed");
31445184Sek110237 		return;
31455184Sek110237 	}
31465184Sek110237 #elif HAVE_FORK
31475184Sek110237 	if ((pid = fork()) < 0) {
31485184Sek110237 		filebench_log(LOG_ERROR, "statscmd fork failed");
31495184Sek110237 		return;
31505184Sek110237 	}
31515184Sek110237 #else
31525184Sek110237 	Crash! - Need code to deal with no fork1!
31535184Sek110237 #endif /* HAVE_FORK1 */
31545184Sek110237 
31555184Sek110237 	if (pid == 0) {
31565184Sek110237 
31575184Sek110237 		setsid();
31585184Sek110237 
31595184Sek110237 		filebench_log(LOG_VERBOSE,
31605184Sek110237 		    "Backgrounding %s", string);
31615184Sek110237 		/*
31625184Sek110237 		 * Child
31635184Sek110237 		 * - close stdout
31645184Sek110237 		 * - dup to create new stdout
31655184Sek110237 		 * - close pipe fds
31665184Sek110237 		 */
31675184Sek110237 		(void) close(1);
31685184Sek110237 
31695184Sek110237 		if ((newstdout = dup(pipe_fd[PIPE_CHILD])) < 0) {
31705184Sek110237 			filebench_log(LOG_ERROR,
31715184Sek110237 			    "statscmd dup failed: %s",
31725184Sek110237 			    strerror(errno));
31735184Sek110237 		}
31745184Sek110237 
31755184Sek110237 		(void) close(pipe_fd[PIPE_PARENT]);
31765184Sek110237 		(void) close(pipe_fd[PIPE_CHILD]);
31775184Sek110237 
31785184Sek110237 		if (system(string) < 0) {
31795184Sek110237 			filebench_log(LOG_ERROR,
31805184Sek110237 			    "statscmd exec failed: %s",
31815184Sek110237 			    strerror(errno));
31825184Sek110237 		}
31835184Sek110237 		/* Failed! */
31845184Sek110237 		exit(1);
31855184Sek110237 
31865184Sek110237 	} else {
31875184Sek110237 
31885184Sek110237 		/* Record pid in pidlist for subsequent reaping by stats snap */
31895184Sek110237 		if ((pidlistent = (pidlist_t *)malloc(sizeof (pidlist_t)))
31905184Sek110237 		    == NULL) {
31915184Sek110237 			filebench_log(LOG_ERROR, "pidlistent malloc failed");
31925184Sek110237 			return;
31935184Sek110237 		}
31945184Sek110237 
31955184Sek110237 		pidlistent->pl_pid = pid;
31965184Sek110237 		pidlistent->pl_fd = pipe_fd[PIPE_PARENT];
31975184Sek110237 		(void) close(pipe_fd[PIPE_CHILD]);
31985184Sek110237 
31995184Sek110237 		/* Add fileobj to global list */
32005184Sek110237 		if (pidlist == NULL) {
32015184Sek110237 			pidlist = pidlistent;
32025184Sek110237 			pidlistent->pl_next = NULL;
32035184Sek110237 		} else {
32045184Sek110237 			pidlistent->pl_next = pidlist;
32055184Sek110237 			pidlist = pidlistent;
32065184Sek110237 		}
32075184Sek110237 	}
32085184Sek110237 }
32095184Sek110237 
32105184Sek110237 /*
32115184Sek110237  * Launches a shell to run the unix command supplied in the argument.
32125184Sek110237  * The command should be enclosed in quotes, as in:
32135184Sek110237  * 	system "rm xyz"
32145184Sek110237  * which would run the "rm" utility to delete the file "xyz".
32155184Sek110237  */
32165184Sek110237 static void
32175184Sek110237 parser_system(cmd_t *cmd)
32185184Sek110237 {
32195184Sek110237 	char *string;
32205184Sek110237 
32215184Sek110237 	if (cmd->cmd_param_list == NULL)
32225184Sek110237 		return;
32235184Sek110237 
32245184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
32255184Sek110237 
32265184Sek110237 	if (string == NULL)
32275184Sek110237 		return;
32285184Sek110237 
32295184Sek110237 	filebench_log(LOG_VERBOSE,
32305184Sek110237 	    "Running '%s'", string);
32315184Sek110237 
32325184Sek110237 	if (system(string) < 0) {
32335184Sek110237 		filebench_log(LOG_ERROR,
32345184Sek110237 		    "system exec failed: %s",
32355184Sek110237 		    strerror(errno));
32365184Sek110237 	}
32375184Sek110237 	free(string);
32385184Sek110237 }
32395184Sek110237 
32405184Sek110237 /*
32415184Sek110237  * Echos string supplied with command to the log.
32425184Sek110237  */
32435184Sek110237 static void
32445184Sek110237 parser_echo(cmd_t *cmd)
32455184Sek110237 {
32465184Sek110237 	char *string;
32475184Sek110237 
32485184Sek110237 	if (cmd->cmd_param_list == NULL)
32495184Sek110237 		return;
32505184Sek110237 
32515184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
32525184Sek110237 
32535184Sek110237 	if (string == NULL)
32545184Sek110237 		return;
32555184Sek110237 
32565184Sek110237 	filebench_log(LOG_INFO, "%s", string);
32575184Sek110237 }
32585184Sek110237 
3259*6750Sek110237 /*
3260*6750Sek110237  * Prints out the version of FileBench.
3261*6750Sek110237  */
3262*6750Sek110237 static void
3263*6750Sek110237 parser_version(cmd_t *cmd)
3264*6750Sek110237 {
3265*6750Sek110237 	filebench_log(LOG_INFO, "FileBench Version: %s", FILEBENCH_VERSION);
3266*6750Sek110237 }
32675184Sek110237 
32685184Sek110237 /*
32695184Sek110237  * Adds the string supplied as the argument to the usage command
32705184Sek110237  * to the end of the string printed by the help command.
32715184Sek110237  */
32725184Sek110237 static void
32735184Sek110237 parser_usage(cmd_t *cmd)
32745184Sek110237 {
32755184Sek110237 	char *string;
32765184Sek110237 	char *newusage;
32775184Sek110237 
32785184Sek110237 	if (cmd->cmd_param_list == NULL)
32795184Sek110237 		return;
32805184Sek110237 
32815184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
32825184Sek110237 
32835184Sek110237 	if (string == NULL)
32845184Sek110237 		return;
32855184Sek110237 
32865184Sek110237 	if (dofile)
32875184Sek110237 		return;
32885184Sek110237 
32895184Sek110237 	if (usagestr == NULL) {
32905184Sek110237 		newusage = malloc(strlen(string) + 2);
32915184Sek110237 		*newusage = 0;
32925184Sek110237 	} else {
32935184Sek110237 		newusage = malloc(strlen(usagestr) + strlen(string) + 2);
32945184Sek110237 		(void) strcpy(newusage, usagestr);
32955184Sek110237 	}
32965184Sek110237 	(void) strcat(newusage, "\n");
32975184Sek110237 	(void) strcat(newusage, string);
32985184Sek110237 
32995184Sek110237 	if (usagestr)
33005184Sek110237 		free(usagestr);
33015184Sek110237 
33025184Sek110237 	usagestr = newusage;
33035184Sek110237 
33045184Sek110237 	filebench_log(LOG_INFO, "%s", string);
33055184Sek110237 }
33065184Sek110237 
33075184Sek110237 /*
33085184Sek110237  * Updates the global dump filename with the filename supplied
33095184Sek110237  * as the command's argument. Then dumps the statistics of each
33105184Sek110237  * worker flowop into the dump file, followed by a summary of
33115184Sek110237  * overall totals.
33125184Sek110237  */
33135184Sek110237 static void
33145184Sek110237 parser_statsdump(cmd_t *cmd)
33155184Sek110237 {
33165184Sek110237 	char *string;
33175184Sek110237 
33185184Sek110237 	if (cmd->cmd_param_list == NULL)
33195184Sek110237 		return;
33205184Sek110237 
33215184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
33225184Sek110237 
33235184Sek110237 	if (string == NULL)
33245184Sek110237 		return;
33255184Sek110237 
33265184Sek110237 	filebench_log(LOG_VERBOSE,
33275184Sek110237 	    "Stats dump to file '%s'", string);
33285184Sek110237 
33295184Sek110237 	stats_dump(string);
33305184Sek110237 
33315184Sek110237 	free(string);
33325184Sek110237 }
33335184Sek110237 
33345184Sek110237 /*
33355184Sek110237  * Same as parser_statsdump, but in xml format.
33365184Sek110237  */
33375184Sek110237 static void
33385184Sek110237 parser_statsxmldump(cmd_t *cmd)
33395184Sek110237 {
33405184Sek110237 	char *string;
33415184Sek110237 
33425184Sek110237 	if (cmd->cmd_param_list == NULL)
33435184Sek110237 		return;
33445184Sek110237 
33455184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
33465184Sek110237 
33475184Sek110237 	if (string == NULL)
33485184Sek110237 		return;
33495184Sek110237 
33505184Sek110237 	filebench_log(LOG_VERBOSE,
33515184Sek110237 	    "Stats dump to file '%s'", string);
33525184Sek110237 
33535184Sek110237 	stats_xmldump(string);
33545184Sek110237 
33555184Sek110237 	free(string);
33565184Sek110237 }
33575184Sek110237 
33585184Sek110237 /*
33595184Sek110237  * Kills off background statistics collection processes, then takes a snapshot
33605184Sek110237  * of the filebench run's collected statistics using stats_snap() from
33615184Sek110237  * stats.c.
33625184Sek110237  */
33635184Sek110237 static void
33645184Sek110237 parser_statssnap(cmd_t *cmd)
33655184Sek110237 {
33665184Sek110237 	pidlist_t *pidlistent;
33675184Sek110237 	int stat;
33685184Sek110237 	pid_t pid;
33695184Sek110237 
33705184Sek110237 	for (pidlistent = pidlist; pidlistent != NULL;
33715184Sek110237 	    pidlistent = pidlistent->pl_next) {
33725184Sek110237 		filebench_log(LOG_VERBOSE, "Killing session %d for pid %d",
33735184Sek110237 		    getsid(pidlistent->pl_pid),
33745184Sek110237 		    pidlistent->pl_pid);
33755184Sek110237 		if (pidlistent->pl_fd)
33765184Sek110237 			(void) close(pidlistent->pl_fd);
33775184Sek110237 #ifdef HAVE_SIGSEND
33785184Sek110237 		sigsend(P_SID, getsid(pidlistent->pl_pid), SIGTERM);
33795184Sek110237 #else
33805184Sek110237 		(void) kill(-1, SIGTERM);
33815184Sek110237 #endif
33825184Sek110237 
33835184Sek110237 		/* Close pipe */
33845184Sek110237 		if (pidlistent->pl_fd)
33855184Sek110237 			(void) close(pidlistent->pl_fd);
33865184Sek110237 
33875184Sek110237 		/* Wait for cmd and all its children */
33885184Sek110237 		while ((pid = waitpid(pidlistent->pl_pid * -1, &stat, 0)) > 0)
33895184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
33906286Saw148015 			"Waited for pid %d", (int)pid);
33915184Sek110237 	}
33925184Sek110237 
33935184Sek110237 	for (pidlistent = pidlist; pidlistent != NULL;
33945184Sek110237 	    pidlistent = pidlistent->pl_next) {
33955184Sek110237 		free(pidlistent);
33965184Sek110237 	}
33975184Sek110237 
33985184Sek110237 	pidlist = NULL;
33995184Sek110237 	stats_snap();
34005184Sek110237 }
34015184Sek110237 
34025184Sek110237 /*
34035184Sek110237  * Shutdown filebench.
34045184Sek110237  */
34055184Sek110237 static void
34065184Sek110237 parser_abort(int arg)
34075184Sek110237 {
34085184Sek110237 	(void) sigignore(SIGINT);
34095184Sek110237 	filebench_log(LOG_INFO, "Aborting...");
34105184Sek110237 	filebench_shutdown(1);
34115184Sek110237 }
34125184Sek110237 
34135184Sek110237 /*
34146212Saw148015  * define a random variable and initialize the distribution parameters
34156212Saw148015  */
34166212Saw148015 static void
34176212Saw148015 parser_randvar_define(cmd_t *cmd)
34186212Saw148015 {
34196212Saw148015 	var_t		*var;
34206212Saw148015 	randdist_t	*rndp;
34216212Saw148015 	attr_t		*attr;
34226212Saw148015 	char		*name;
34236212Saw148015 
34246212Saw148015 	/* Get the name for the random variable */
34256212Saw148015 	if (attr = get_attr(cmd, FSA_NAME)) {
34266212Saw148015 		name = avd_get_str(attr->attr_avd);
34276212Saw148015 	} else {
34286212Saw148015 		filebench_log(LOG_ERROR,
34296212Saw148015 		    "define randvar: no name specified");
34306212Saw148015 		return;
34316212Saw148015 	}
34326212Saw148015 
34336212Saw148015 	if ((var = var_define_randvar(name)) == NULL) {
34346212Saw148015 		filebench_log(LOG_ERROR,
34356212Saw148015 		    "define randvar: failed for random variable %s",
34366212Saw148015 		    name);
34376212Saw148015 		return;
34386212Saw148015 	}
34396212Saw148015 
34406212Saw148015 	rndp = var->var_val.randptr;
34416212Saw148015 	rndp->rnd_type = 0;
34426212Saw148015 
34436212Saw148015 	/* Get the source of the random numbers */
34446212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDSRC)) {
34456212Saw148015 		int randsrc = (int)avd_get_int(attr->attr_avd);
34466212Saw148015 
34476212Saw148015 		switch (randsrc) {
34486212Saw148015 		case FSV_URAND:
34496212Saw148015 			rndp->rnd_type |= RAND_SRC_URANDOM;
34506212Saw148015 			break;
34516212Saw148015 		case FSV_RAND48:
34526212Saw148015 			rndp->rnd_type |= RAND_SRC_GENERATOR;
34536212Saw148015 			break;
34546212Saw148015 		}
34556212Saw148015 	} else {
34566212Saw148015 		/* default to rand48 random number generator */
34576212Saw148015 		rndp->rnd_type |= RAND_SRC_GENERATOR;
34586212Saw148015 	}
34596212Saw148015 
34606212Saw148015 	/* Get the min value of the random distribution */
34616212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDMIN))
34626212Saw148015 		rndp->rnd_min = attr->attr_avd;
34636212Saw148015 	else
34646212Saw148015 		rndp->rnd_min = avd_int_alloc(0);
34656212Saw148015 
34666212Saw148015 	/* Get the mean value of the random distribution */
34676212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDMEAN))
34686212Saw148015 		rndp->rnd_mean = attr->attr_avd;
34696212Saw148015 	else
34706212Saw148015 		rndp->rnd_mean = avd_int_alloc(0);
34716212Saw148015 
34726212Saw148015 	/* Get the roundoff value for the random distribution */
34736212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDROUND))
34746212Saw148015 		rndp->rnd_round = attr->attr_avd;
34756212Saw148015 	else
34766212Saw148015 		rndp->rnd_round = avd_int_alloc(0);
34776212Saw148015 
34786212Saw148015 	/* Get a tablular probablility distribution if there is one */
34796212Saw148015 	if (attr = get_attr(cmd, FSA_RANDTABLE)) {
34806212Saw148015 		rndp->rnd_probtabs = (probtabent_t *)(attr->attr_obj);
34816212Saw148015 		rndp->rnd_type |= RAND_TYPE_TABLE;
34826212Saw148015 
34836212Saw148015 		/* no need for the rest of the attributes */
34846212Saw148015 		return;
34856212Saw148015 	} else {
34866212Saw148015 		rndp->rnd_probtabs = NULL;
34876212Saw148015 	}
34886212Saw148015 
34896212Saw148015 	/* Get the type for the random variable */
34906212Saw148015 	if (attr = get_attr(cmd, FSA_TYPE)) {
34916212Saw148015 		int disttype = (int)avd_get_int(attr->attr_avd);
34926212Saw148015 
34936212Saw148015 		switch (disttype) {
34946212Saw148015 		case FSV_RANDUNI:
34956212Saw148015 			rndp->rnd_type |= RAND_TYPE_UNIFORM;
34966212Saw148015 			break;
34976212Saw148015 		case FSA_RANDGAMMA:
34986212Saw148015 			rndp->rnd_type |= RAND_TYPE_GAMMA;
34996212Saw148015 			break;
35006212Saw148015 		case FSV_RANDTAB:
35016212Saw148015 			filebench_log(LOG_ERROR,
35026212Saw148015 			    "Table distribution type without prob table");
35036212Saw148015 			break;
35046212Saw148015 		}
35056212Saw148015 	} else {
35066212Saw148015 		/* default to gamma distribution type */
35076212Saw148015 		rndp->rnd_type |= RAND_TYPE_GAMMA;
35086212Saw148015 	}
35096212Saw148015 
35106212Saw148015 	/* Get the seed for the random variable */
35116212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDSEED))
35126212Saw148015 		rndp->rnd_seed = attr->attr_avd;
35136212Saw148015 	else
35146212Saw148015 		rndp->rnd_seed = avd_int_alloc(0);
35156212Saw148015 
35166212Saw148015 	/* Get the gamma value of the random distribution */
35176212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDGAMMA))
35186212Saw148015 		rndp->rnd_gamma = attr->attr_avd;
35196212Saw148015 	else
35206212Saw148015 		rndp->rnd_gamma = avd_int_alloc(1500);
35216212Saw148015 }
35226212Saw148015 
35236212Saw148015 /*
35246212Saw148015  * Set a specified random distribution parameter in a random variable.
35256212Saw148015  */
35266212Saw148015 static void
35276212Saw148015 parser_randvar_set(cmd_t *cmd)
35286212Saw148015 {
35296212Saw148015 	var_t		*src_var, *randvar;
35306212Saw148015 	randdist_t	*rndp;
35316212Saw148015 	avd_t	value;
35326212Saw148015 
35336212Saw148015 	if ((randvar = var_find_randvar(cmd->cmd_tgt1)) == NULL) {
35346212Saw148015 		filebench_log(LOG_ERROR,
35356212Saw148015 		    "set randvar: failed",
35366212Saw148015 		    cmd->cmd_tgt1);
35376212Saw148015 		return;
35386212Saw148015 	}
35396212Saw148015 
35406212Saw148015 	rndp = randvar->var_val.randptr;
35416212Saw148015 	value = cmd->cmd_attr_list->attr_avd;
35426212Saw148015 
35436212Saw148015 	switch (cmd->cmd_qty) {
35446212Saw148015 	case FSS_TYPE:
35456212Saw148015 		{
35466212Saw148015 			int disttype = (int)avd_get_int(value);
35476212Saw148015 
35486212Saw148015 			rndp->rnd_type &= (~RAND_TYPE_MASK);
35496212Saw148015 
35506212Saw148015 			switch (disttype) {
35516212Saw148015 			case FSV_RANDUNI:
35526212Saw148015 				rndp->rnd_type |= RAND_TYPE_UNIFORM;
35536212Saw148015 				break;
35546212Saw148015 			case FSA_RANDGAMMA:
35556212Saw148015 				rndp->rnd_type |= RAND_TYPE_GAMMA;
35566212Saw148015 				break;
35576212Saw148015 			case FSV_RANDTAB:
35586212Saw148015 				rndp->rnd_type |= RAND_TYPE_TABLE;
35596212Saw148015 				break;
35606212Saw148015 			}
35616212Saw148015 			break;
35626212Saw148015 		}
35636212Saw148015 
35646212Saw148015 	case FSS_SRC:
35656212Saw148015 		{
35666212Saw148015 			int randsrc = (int)avd_get_int(value);
35676212Saw148015 
35686212Saw148015 			rndp->rnd_type &=
35696212Saw148015 			    (~(RAND_SRC_URANDOM | RAND_SRC_GENERATOR));
35706212Saw148015 
35716212Saw148015 			switch (randsrc) {
35726212Saw148015 			case FSV_URAND:
35736212Saw148015 				rndp->rnd_type |= RAND_SRC_URANDOM;
35746212Saw148015 				break;
35756212Saw148015 			case FSV_RAND48:
35766212Saw148015 				rndp->rnd_type |= RAND_SRC_GENERATOR;
35776212Saw148015 				break;
35786212Saw148015 			}
35796212Saw148015 			break;
35806212Saw148015 		}
35816212Saw148015 
35826212Saw148015 	case FSS_SEED:
35836212Saw148015 		rndp->rnd_seed = value;
35846212Saw148015 		break;
35856212Saw148015 
35866212Saw148015 	case FSS_GAMMA:
35876212Saw148015 		rndp->rnd_gamma = value;
35886212Saw148015 		break;
35896212Saw148015 
35906212Saw148015 	case FSS_MEAN:
35916212Saw148015 		rndp->rnd_mean = value;
35926212Saw148015 		break;
35936212Saw148015 
35946212Saw148015 	case FSS_MIN:
35956212Saw148015 		rndp->rnd_min = value;
35966212Saw148015 		break;
35976212Saw148015 
35986212Saw148015 	case FSS_ROUND:
35996212Saw148015 		rndp->rnd_round = value;
36006212Saw148015 		break;
36016212Saw148015 
36026212Saw148015 	default:
36036212Saw148015 		filebench_log(LOG_ERROR, "setrandvar: undefined attribute");
36046212Saw148015 	}
36056212Saw148015 }
36066212Saw148015 
36076212Saw148015 /*
36085184Sek110237  * alloc_cmd() allocates the required resources for a cmd_t. On failure, a
36095184Sek110237  * filebench_log is issued and NULL is returned.
36105184Sek110237  */
36115184Sek110237 static cmd_t *
36125184Sek110237 alloc_cmd(void)
36135184Sek110237 {
36145184Sek110237 	cmd_t *cmd;
36155184Sek110237 
36165184Sek110237 	if ((cmd = malloc(sizeof (cmd_t))) == NULL) {
36175184Sek110237 		filebench_log(LOG_ERROR, "Alloc cmd failed");
36185184Sek110237 		return (NULL);
36195184Sek110237 	}
36205184Sek110237 
36215184Sek110237 	(void) memset(cmd, 0, sizeof (cmd_t));
36225184Sek110237 
36235184Sek110237 	return (cmd);
36245184Sek110237 }
36255184Sek110237 
36265184Sek110237 /*
36275184Sek110237  * Frees the resources of a cmd_t and then the cmd_t "cmd" itself.
36285184Sek110237  */
36295184Sek110237 static void
36305184Sek110237 free_cmd(cmd_t *cmd)
36315184Sek110237 {
36325184Sek110237 	free((void *)cmd->cmd_tgt1);
36335184Sek110237 	free((void *)cmd->cmd_tgt2);
36345184Sek110237 	free(cmd);
36355184Sek110237 }
36365184Sek110237 
36375184Sek110237 /*
36385184Sek110237  * Allocates an attr_t structure and zeros it. Returns NULL on failure, or
36395184Sek110237  * a pointer to the attr_t.
36405184Sek110237  */
36415184Sek110237 static attr_t *
36426550Saw148015 alloc_attr(void)
36435184Sek110237 {
36445184Sek110237 	attr_t *attr;
36455184Sek110237 
36465184Sek110237 	if ((attr = malloc(sizeof (attr_t))) == NULL) {
36475184Sek110237 		return (NULL);
36485184Sek110237 	}
36495184Sek110237 
36505184Sek110237 	(void) memset(attr, 0, sizeof (attr_t));
36515184Sek110237 	return (attr);
36525184Sek110237 }
36535184Sek110237 
36545184Sek110237 /*
36556212Saw148015  * Allocates a probtabent_t structure and zeros it. Returns NULL on failure, or
36566212Saw148015  * a pointer to the probtabent_t.
36576212Saw148015  */
36586212Saw148015 static probtabent_t *
36596212Saw148015 alloc_probtabent(void)
36606212Saw148015 {
36616212Saw148015 	probtabent_t *rte;
36626212Saw148015 
36636212Saw148015 	if ((rte = malloc(sizeof (probtabent_t))) == NULL) {
36646212Saw148015 		return (NULL);
36656212Saw148015 	}
36666212Saw148015 
36676212Saw148015 	(void) memset(rte, 0, sizeof (probtabent_t));
36686212Saw148015 	return (rte);
36696212Saw148015 }
36706212Saw148015 
36716212Saw148015 /*
36726550Saw148015  * Allocates an attr_t structure and puts the supplied var_t into
36736550Saw148015  * its attr_avd location, and sets its name to FSA_LVAR_ASSIGN
36746550Saw148015  */
36756550Saw148015 static attr_t *
36766550Saw148015 alloc_lvar_attr(var_t *var)
36776550Saw148015 {
36786550Saw148015 	attr_t *attr;
36796550Saw148015 
36806550Saw148015 	if ((attr = alloc_attr()) == NULL)
36816550Saw148015 		return (NULL);
36826550Saw148015 
36836550Saw148015 	attr->attr_name = FSA_LVAR_ASSIGN;
36846550Saw148015 	attr->attr_avd = (avd_t)var;
36856550Saw148015 
36866550Saw148015 	return (attr);
36876550Saw148015 }
36886550Saw148015 
36896550Saw148015 /*
36905184Sek110237  * Searches the attribute list for the command for the named attribute type.
36915184Sek110237  * The attribute list is created by the parser from the list of attributes
36925184Sek110237  * supplied with certain commands, such as the define and flowop commands.
36935184Sek110237  * Returns a pointer to the attribute structure if the named attribute is
36945184Sek110237  * found, otherwise returns NULL. If the attribute includes a parameter list,
36956212Saw148015  * the list is converted to a string and stored in the attr_avd field of
36965184Sek110237  * the returned attr_t struct.
36975184Sek110237  */
36985184Sek110237 static attr_t *
36995184Sek110237 get_attr(cmd_t *cmd, int64_t name)
37005184Sek110237 {
37015184Sek110237 	attr_t *attr;
37025184Sek110237 	attr_t *rtn = NULL;
37035184Sek110237 	char *string;
37045184Sek110237 
37055184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
37065184Sek110237 	    attr = attr->attr_next) {
37075184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
37085184Sek110237 		    "attr %d = %d %llx?",
37095184Sek110237 		    attr->attr_name,
37105184Sek110237 		    name,
37116212Saw148015 		    attr->attr_avd);
37125184Sek110237 
37135184Sek110237 		if (attr->attr_name == name)
37145184Sek110237 			rtn = attr;
37155184Sek110237 	}
37165184Sek110237 
37175184Sek110237 	if (rtn == NULL)
37185184Sek110237 		return (NULL);
37195184Sek110237 
37205184Sek110237 	if (rtn->attr_param_list) {
37215184Sek110237 		filebench_log(LOG_DEBUG_SCRIPT, "attr is param list");
37225184Sek110237 		string = parser_list2string(rtn->attr_param_list);
37235184Sek110237 		if (string != NULL) {
37246212Saw148015 			rtn->attr_avd = avd_str_alloc(string);
37255184Sek110237 			filebench_log(LOG_DEBUG_SCRIPT,
37265184Sek110237 			    "attr string %s", string);
37275184Sek110237 		}
37285184Sek110237 	}
37295184Sek110237 
37305184Sek110237 	return (rtn);
37315184Sek110237 }
37325184Sek110237 
37335184Sek110237 /*
37345184Sek110237  * Similar to get_attr, but converts the parameter string supplied with the
37356212Saw148015  * named attribute to an integer and stores the integer in the attr_avd
37365184Sek110237  * portion of the returned attr_t struct.
37375184Sek110237  */
37385184Sek110237 static attr_t *
37395184Sek110237 get_attr_integer(cmd_t *cmd, int64_t name)
37405184Sek110237 {
37415184Sek110237 	attr_t *attr;
37425184Sek110237 	attr_t *rtn = NULL;
37435184Sek110237 
37445184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
37455184Sek110237 	    attr = attr->attr_next) {
37465184Sek110237 		if (attr->attr_name == name)
37475184Sek110237 			rtn = attr;
37485184Sek110237 	}
37495184Sek110237 
37505184Sek110237 	if (rtn == NULL)
37515184Sek110237 		return (NULL);
37525184Sek110237 
37536212Saw148015 	if (rtn->attr_param_list)
37546212Saw148015 		rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
37555184Sek110237 
37565184Sek110237 	return (rtn);
37575184Sek110237 }
37585184Sek110237 
37595184Sek110237 /*
37605184Sek110237  * Similar to get_attr, but converts the parameter string supplied with the
37616212Saw148015  * named attribute to an integer and stores the integer in the attr_avd
37625184Sek110237  * portion of the returned attr_t struct. If no parameter string is supplied
37635184Sek110237  * then it defaults to TRUE (1).
37645184Sek110237  */
37655184Sek110237 static attr_t *
37665184Sek110237 get_attr_bool(cmd_t *cmd, int64_t name)
37675184Sek110237 {
37685184Sek110237 	attr_t *attr;
37695184Sek110237 	attr_t *rtn = NULL;
37705184Sek110237 
37715184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
37725184Sek110237 	    attr = attr->attr_next) {
37735184Sek110237 		if (attr->attr_name == name)
37745184Sek110237 			rtn = attr;
37755184Sek110237 	}
37765184Sek110237 
37775184Sek110237 	if (rtn == NULL)
37785184Sek110237 		return (NULL);
37795184Sek110237 
37805184Sek110237 	if (rtn->attr_param_list) {
37816212Saw148015 		rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
37826212Saw148015 
37836212Saw148015 	} else if (rtn->attr_avd == NULL) {
37846212Saw148015 		rtn->attr_avd = avd_bool_alloc(TRUE);
37856212Saw148015 	}
37866212Saw148015 
37876212Saw148015 	/* boolean attributes cannot point to random variables */
37886212Saw148015 	if (AVD_IS_RANDOM(rtn->attr_avd)) {
37896212Saw148015 		filebench_log(LOG_ERROR,
37906212Saw148015 		    "define flowop: Boolean attr %s cannot be random", name);
37916212Saw148015 		filebench_shutdown(1);
37926212Saw148015 		return (NULL);
37935184Sek110237 	}
37945184Sek110237 
37955184Sek110237 	return (rtn);
37965184Sek110237 }
37975184Sek110237 
37985184Sek110237 /*
37996550Saw148015  * removes the newly allocated local var from the shared local var
38006550Saw148015  * list, then puts it at the head of the private local var list
38016550Saw148015  * supplied as the second argument.
38026550Saw148015  */
38036550Saw148015 static void
38046550Saw148015 add_lvar_to_list(var_t *newlvar, var_t **lvar_list)
38056550Saw148015 {
38066550Saw148015 	var_t *prev;
38076550Saw148015 
38086550Saw148015 	/* remove from shared local list, if there */
38096550Saw148015 	if (newlvar == filebench_shm->shm_var_loc_list) {
38106550Saw148015 		/* on top of list, just grap */
38116550Saw148015 		filebench_shm->shm_var_loc_list = newlvar->var_next;
38126550Saw148015 	} else {
38136550Saw148015 		/* find newvar on list and remove */
38146550Saw148015 		for (prev = filebench_shm->shm_var_loc_list; prev;
38156550Saw148015 		    prev = prev->var_next) {
38166550Saw148015 			if (prev->var_next == newlvar)
38176550Saw148015 				prev->var_next = newlvar->var_next;
38186550Saw148015 		}
38196550Saw148015 	}
38206550Saw148015 	newlvar->var_next = NULL;
38216550Saw148015 
38226550Saw148015 	/* add to flowop private local list at head */
38236550Saw148015 	newlvar->var_next = *lvar_list;
38246550Saw148015 	*lvar_list = newlvar;
38256550Saw148015 }
38266550Saw148015 
38276550Saw148015 /*
38286550Saw148015  * Searches the attribute list for the command for any allocated local
38296550Saw148015  * variables. The attribute list is created by the parser from the list of
38306550Saw148015  * attributes supplied with certain commands, such as the define and flowop
38316550Saw148015  * commands. Places all found local vars onto the flowop's local variable
38326550Saw148015  * list.
38336550Saw148015  */
38346550Saw148015 static void
38356550Saw148015 get_attr_lvars(cmd_t *cmd, flowop_t *flowop)
38366550Saw148015 {
38376550Saw148015 	attr_t *attr;
38386550Saw148015 	var_t *list_tail, *orig_lvar_list;
38396550Saw148015 
38406550Saw148015 	/* save the local var list */
38416550Saw148015 	orig_lvar_list = flowop->fo_lvar_list;
38426550Saw148015 
38436550Saw148015 	for (attr = cmd->cmd_attr_list; attr != NULL;
38446550Saw148015 	    attr = attr->attr_next) {
38456550Saw148015 
38466550Saw148015 		if (attr->attr_name == FSA_LVAR_ASSIGN) {
38476550Saw148015 			var_t *newvar, *prev;
38486550Saw148015 
38496550Saw148015 			if ((newvar = (var_t *)attr->attr_avd) == NULL)
38506550Saw148015 				continue;
38516550Saw148015 
38526550Saw148015 			add_lvar_to_list(newvar, &flowop->fo_lvar_list);
38536550Saw148015 			var_update_comp_lvars(newvar, orig_lvar_list, NULL);
38546550Saw148015 		}
38556550Saw148015 	}
38566550Saw148015 }
38576550Saw148015 
38586550Saw148015 /*
38595184Sek110237  * Allocates memory for a list_t structure, initializes it to zero, and
38605184Sek110237  * returns a pointer to it. On failure, returns NULL.
38615184Sek110237  */
38625184Sek110237 static list_t *
38635184Sek110237 alloc_list()
38645184Sek110237 {
38655184Sek110237 	list_t *list;
38665184Sek110237 
38675184Sek110237 	if ((list = malloc(sizeof (list_t))) == NULL) {
38685184Sek110237 		return (NULL);
38695184Sek110237 	}
38705184Sek110237 
38715184Sek110237 	(void) memset(list, 0, sizeof (list_t));
38725184Sek110237 	return (list);
38735184Sek110237 }
38745184Sek110237 
38755184Sek110237 
38765184Sek110237 #define	USAGE1	\
38775184Sek110237 "Usage:\n" \
38786613Sek110237 "go_filebench: interpret f script and generate file workload\n" \
38795184Sek110237 "Options:\n" \
38805184Sek110237 "   [-h] Display verbose help\n" \
38815184Sek110237 "   [-p] Disable opening /proc to set uacct to enable truss\n"
38825184Sek110237 
38835184Sek110237 #define	PARSER_CMDS \
38845184Sek110237 "create [files|filesets|processes]\n" \
38855184Sek110237 "stats [clear|snap]\n" \
38865184Sek110237 "stats command \"shell command $var1,$var2...\"\n" \
38875184Sek110237 "stats directory <directory>\n" \
38885184Sek110237 "sleep <sleep-value>\n" \
38895184Sek110237 "quit\n\n" \
38905184Sek110237 "Variables:\n" \
38915184Sek110237 "set $var = value\n" \
38925184Sek110237 "    $var   - regular variables\n" \
38935184Sek110237 "    ${var} - internal special variables\n" \
38945184Sek110237 "    $(var) - environment variables\n\n"
38955184Sek110237 
38965184Sek110237 #define	PARSER_EXAMPLE \
38975184Sek110237 "Example:\n\n" \
38986613Sek110237 "#!" FILEBENCHDIR "/bin/go_filebench -f\n" \
38995184Sek110237 "\n" \
39005184Sek110237 "define file name=bigfile,path=bigfile,size=1g,prealloc,reuse\n" \
39015184Sek110237 "define process name=randomizer\n" \
39025184Sek110237 "{\n" \
39035184Sek110237 "  thread random-thread procname=randomizer\n"	\
39045184Sek110237 "  {\n" \
39055184Sek110237 "    flowop read name=random-read,filename=bigfile,iosize=16k,random\n" \
39065184Sek110237 "  }\n" \
39075184Sek110237 "}\n" \
39085184Sek110237 "create files\n" \
39095184Sek110237 "create processes\n" \
39105184Sek110237 "stats clear\n" \
39115184Sek110237 "sleep 30\n" \
39125184Sek110237 "stats snap\n"
39135184Sek110237 
39145184Sek110237 /*
39155184Sek110237  * usage() display brief or verbose help for the filebench(1) command.
39165184Sek110237  */
39175184Sek110237 static void
39185184Sek110237 usage(int help)
39195184Sek110237 {
39205184Sek110237 	if (help >= 1)
39215184Sek110237 		(void) fprintf(stderr, USAGE1, cmdname);
39225184Sek110237 	if (help >= 2) {
39235184Sek110237 
39245184Sek110237 		(void) fprintf(stderr,
39255184Sek110237 		    "\n'f' language definition:\n\n");
39265184Sek110237 		fileset_usage();
39275184Sek110237 		procflow_usage();
39285184Sek110237 		threadflow_usage();
39295184Sek110237 		flowoplib_usage();
39305184Sek110237 		eventgen_usage();
39315184Sek110237 		(void) fprintf(stderr, PARSER_CMDS);
39325184Sek110237 		(void) fprintf(stderr, PARSER_EXAMPLE);
39335184Sek110237 	}
39345184Sek110237 	exit(E_USAGE);
39355184Sek110237 }
39365184Sek110237 
39375184Sek110237 int
39385184Sek110237 yywrap()
39395184Sek110237 {
39405184Sek110237 	char buf[1024];
39415184Sek110237 
39425184Sek110237 	if (parentscript) {
39435184Sek110237 		yyin = parentscript;
39445184Sek110237 		yy_switchfilescript(yyin);
39455184Sek110237 		parentscript = NULL;
39465184Sek110237 		return (0);
39475184Sek110237 	} else
39485184Sek110237 		return (1);
39495184Sek110237 }
3950