xref: /onnv-gate/usr/src/cmd/filebench/common/parser_gram.y (revision 9356:2ff1c33b24c1)
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 /*
228615SAndrew.W.Wilson@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235184Sek110237  * Use is subject to license terms.
246613Sek110237  *
256613Sek110237  * Portions Copyright 2008 Denis Cheng
265184Sek110237  */
275184Sek110237 
285184Sek110237 %{
295184Sek110237 
305184Sek110237 #include <stdlib.h>
315184Sek110237 #include <stdio.h>
325184Sek110237 #include <string.h>
335184Sek110237 #include <signal.h>
345184Sek110237 #include <errno.h>
355184Sek110237 #include <sys/types.h>
365184Sek110237 #include <locale.h>
375184Sek110237 #include <sys/utsname.h>
385184Sek110237 #ifdef HAVE_STDINT_H
395184Sek110237 #include <stdint.h>
405184Sek110237 #endif
415184Sek110237 #include <fcntl.h>
425184Sek110237 #include <sys/mman.h>
435184Sek110237 #include <sys/wait.h>
445184Sek110237 #ifdef HAVE_LIBTECLA
455184Sek110237 #include <libtecla.h>
465184Sek110237 #endif
475184Sek110237 #include "parsertypes.h"
485184Sek110237 #include "filebench.h"
495184Sek110237 #include "utils.h"
505184Sek110237 #include "stats.h"
515184Sek110237 #include "vars.h"
525184Sek110237 #include "eventgen.h"
535184Sek110237 #ifdef HAVE_LIBTECLA
545184Sek110237 #include "auto_comp.h"
555184Sek110237 #endif
567736SAndrew.W.Wilson@sun.com #include "multi_client_sync.h"
575184Sek110237 
585184Sek110237 int dofile = FS_FALSE;
595184Sek110237 static const char cmdname[] = "filebench";
605184Sek110237 static const char cmd_options[] = "pa:f:hi:s:m:";
615184Sek110237 static void usage(int);
625184Sek110237 
635184Sek110237 static cmd_t *cmd = NULL;		/* Command being processed */
645184Sek110237 #ifdef HAVE_LIBTECLA
655184Sek110237 static GetLine *gl;			/* GetLine resource object */
665184Sek110237 #endif
675184Sek110237 
685184Sek110237 char *execname;
695184Sek110237 char *fscriptname;
705184Sek110237 int noproc = 0;
715184Sek110237 var_t *var_list = NULL;
725184Sek110237 pidlist_t *pidlist = NULL;
735184Sek110237 char *cwd = NULL;
745184Sek110237 FILE *parentscript = NULL;
755673Saw148015 
765673Saw148015 static int filecreate_done = 0;
775673Saw148015 
785184Sek110237 /* yacc externals */
795184Sek110237 extern FILE *yyin;
805184Sek110237 extern int yydebug;
815184Sek110237 extern void yyerror(char *s);
825184Sek110237 
835184Sek110237 /* utilities */
845184Sek110237 static void terminate(void);
855184Sek110237 static cmd_t *alloc_cmd(void);
865184Sek110237 static attr_t *alloc_attr(void);
876550Saw148015 static attr_t *alloc_lvar_attr(var_t *var);
885184Sek110237 static attr_t *get_attr(cmd_t *cmd, int64_t name);
898404SAndrew.W.Wilson@sun.com static attr_t *get_attr_fileset(cmd_t *cmd, int64_t name);
905184Sek110237 static attr_t *get_attr_integer(cmd_t *cmd, int64_t name);
915184Sek110237 static attr_t *get_attr_bool(cmd_t *cmd, int64_t name);
926550Saw148015 static void get_attr_lvars(cmd_t *cmd, flowop_t *flowop);
935184Sek110237 static var_t *alloc_var(void);
945184Sek110237 static var_t *get_var(cmd_t *cmd, int64_t name);
955184Sek110237 static list_t *alloc_list();
966212Saw148015 static probtabent_t *alloc_probtabent(void);
976550Saw148015 static void add_lvar_to_list(var_t *newlvar, var_t **lvar_list);
985184Sek110237 
995184Sek110237 /* Info Commands */
1005184Sek110237 static void parser_list(cmd_t *);
1016212Saw148015 static void parser_flowop_list(cmd_t *);
1025184Sek110237 
1035184Sek110237 /* Define Commands */
1045184Sek110237 static void parser_proc_define(cmd_t *);
1055184Sek110237 static void parser_thread_define(cmd_t *, procflow_t *, int instances);
1066212Saw148015 static void parser_flowop_define(cmd_t *, threadflow_t *, flowop_t **, int);
1075184Sek110237 static void parser_file_define(cmd_t *);
1085184Sek110237 static void parser_fileset_define(cmd_t *);
1096212Saw148015 static void parser_randvar_define(cmd_t *);
1106212Saw148015 static void parser_randvar_set(cmd_t *);
1116550Saw148015 static void parser_composite_flowop_define(cmd_t *);
1125184Sek110237 
1135184Sek110237 /* Create Commands */
1145184Sek110237 static void parser_proc_create(cmd_t *);
1155184Sek110237 static void parser_thread_create(cmd_t *);
1165184Sek110237 static void parser_flowop_create(cmd_t *);
1175184Sek110237 static void parser_fileset_create(cmd_t *);
1185184Sek110237 
1196212Saw148015 /* set commands */
1206212Saw148015 static void parser_set_integer(char *, fbint_t);
1216212Saw148015 static void parser_set_var(char *, char *);
1226212Saw148015 
1235184Sek110237 /* Shutdown Commands */
1245184Sek110237 static void parser_proc_shutdown(cmd_t *);
1255184Sek110237 static void parser_filebench_shutdown(cmd_t *cmd);
1265184Sek110237 
1275184Sek110237 /* Other Commands */
1285184Sek110237 static void parser_foreach_integer(cmd_t *cmd);
1295184Sek110237 static void parser_foreach_string(cmd_t *cmd);
1305184Sek110237 static void parser_log(cmd_t *cmd);
1315184Sek110237 static void parser_statscmd(cmd_t *cmd);
1325184Sek110237 static void parser_statsdump(cmd_t *cmd);
1335184Sek110237 static void parser_statsxmldump(cmd_t *cmd);
1347736SAndrew.W.Wilson@sun.com static void parser_statsmultidump(cmd_t *cmd);
1355184Sek110237 static void parser_echo(cmd_t *cmd);
1365184Sek110237 static void parser_usage(cmd_t *cmd);
1375184Sek110237 static void parser_vars(cmd_t *cmd);
1385184Sek110237 static void parser_printvars(cmd_t *cmd);
1395184Sek110237 static void parser_system(cmd_t *cmd);
1405184Sek110237 static void parser_statssnap(cmd_t *cmd);
1415184Sek110237 static void parser_directory(cmd_t *cmd);
1425184Sek110237 static void parser_eventgen(cmd_t *cmd);
1437736SAndrew.W.Wilson@sun.com static void parser_enable_mc(cmd_t *cmd);
1447736SAndrew.W.Wilson@sun.com static void parser_domultisync(cmd_t *cmd);
1455184Sek110237 static void parser_run(cmd_t *cmd);
1465184Sek110237 static void parser_run_variable(cmd_t *cmd);
1479326SAndrew.W.Wilson@sun.com static void parser_sleep(cmd_t *cmd);
1489326SAndrew.W.Wilson@sun.com static void parser_sleep_variable(cmd_t *cmd);
1499326SAndrew.W.Wilson@sun.com static void parser_warmup(cmd_t *cmd);
1509326SAndrew.W.Wilson@sun.com static void parser_warmup_variable(cmd_t *cmd);
1515184Sek110237 static void parser_help(cmd_t *cmd);
1525184Sek110237 static void arg_parse(const char *command);
1535184Sek110237 static void parser_abort(int arg);
1546750Sek110237 static void parser_version(cmd_t *cmd);
1555184Sek110237 
1565184Sek110237 %}
1575184Sek110237 
1585184Sek110237 %union {
1596212Saw148015 	int64_t		 ival;
1606212Saw148015 	uchar_t		 bval;
1616212Saw148015 	char *		 sval;
1626212Saw148015 	fs_u		 val;
1636212Saw148015 	avd_t		 avd;
1646212Saw148015 	cmd_t		*cmd;
1656212Saw148015 	attr_t		*attr;
1666212Saw148015 	list_t		*list;
1676212Saw148015 	probtabent_t	*rndtb;
1685184Sek110237 }
1695184Sek110237 
1705184Sek110237 %start commands
1715184Sek110237 
1725184Sek110237 %token FSC_LIST FSC_DEFINE FSC_EXEC FSC_QUIT FSC_DEBUG FSC_CREATE
1735184Sek110237 %token FSC_SLEEP FSC_STATS FSC_FOREACH FSC_SET FSC_SHUTDOWN FSC_LOG
1745184Sek110237 %token FSC_SYSTEM FSC_FLOWOP FSC_EVENTGEN FSC_ECHO FSC_LOAD FSC_RUN
175*9356SAndrew.W.Wilson@sun.com %token FSC_WARMUP FSC_NOUSESTATS
1767736SAndrew.W.Wilson@sun.com %token FSC_USAGE FSC_HELP FSC_VARS FSC_VERSION FSC_ENABLE FSC_DOMULTISYNC
1775184Sek110237 %token FSV_STRING FSV_VAL_INT FSV_VAL_BOOLEAN FSV_VARIABLE FSV_WHITESTRING
1786212Saw148015 %token FSV_RANDUNI FSV_RANDTAB FSV_RANDVAR FSV_URAND FSV_RAND48
1795184Sek110237 %token FST_INT FST_BOOLEAN
1805184Sek110237 %token FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSE_ALL FSE_SNAP FSE_DUMP
1816212Saw148015 %token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP FSE_RAND FSE_MODE
1827736SAndrew.W.Wilson@sun.com %token FSE_MULTI FSE_MULTIDUMP
1835184Sek110237 %token FSK_SEPLST FSK_OPENLST FSK_CLOSELST FSK_ASSIGN FSK_IN FSK_QUOTE
1845184Sek110237 %token FSK_DIRSEPLST
1855184Sek110237 %token FSA_SIZE FSA_PREALLOC FSA_PARALLOC FSA_PATH FSA_REUSE
1869326SAndrew.W.Wilson@sun.com %token FSA_PROCESS FSA_MEMSIZE FSA_RATE FSA_CACHED FSA_READONLY FSA_TRUSTTREE
1875184Sek110237 %token FSA_IOSIZE FSA_FILE FSA_WSS FSA_NAME FSA_RANDOM FSA_INSTANCES
1885184Sek110237 %token FSA_DSYNC FSA_TARGET FSA_ITERS FSA_NICE FSA_VALUE FSA_BLOCKING
1895184Sek110237 %token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD
1906212Saw148015 %token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA FSA_DIRDEPTHRV
1916212Saw148015 %token FSA_DIRGAMMA FSA_USEISM FSA_TYPE FSA_RANDTABLE FSA_RANDSRC FSA_RANDROUND
1928404SAndrew.W.Wilson@sun.com %token FSA_LEAFDIRS FSA_INDEXED
1937736SAndrew.W.Wilson@sun.com %token FSA_RANDSEED FSA_RANDGAMMA FSA_RANDMEAN FSA_RANDMIN FSA_MASTER
1947736SAndrew.W.Wilson@sun.com %token FSA_CLIENT
1956212Saw148015 %token FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC FSS_ROUND
1966550Saw148015 %token FSV_SET_LOCAL_VAR FSA_LVAR_ASSIGN
1976212Saw148015 %token FSA_ALLDONE FSA_FIRSTDONE FSA_TIMEOUT
1985184Sek110237 
1995184Sek110237 %type <ival> FSV_VAL_INT
2005184Sek110237 %type <bval> FSV_VAL_BOOLEAN
2015184Sek110237 %type <sval> FSV_STRING
2025184Sek110237 %type <sval> FSV_WHITESTRING
2035184Sek110237 %type <sval> FSV_VARIABLE
2046212Saw148015 %type <sval> FSV_RANDVAR
2055184Sek110237 %type <sval> FSK_ASSIGN
2066550Saw148015 %type <sval> FSV_SET_LOCAL_VAR
2075184Sek110237 
2087736SAndrew.W.Wilson@sun.com %type <ival> FSC_LIST FSC_DEFINE FSC_SET FSC_LOAD FSC_RUN FSC_ENABLE
2097736SAndrew.W.Wilson@sun.com %type <ival> FSC_DOMULTISYNC
2106750Sek110237 %type <ival> FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSC_HELP FSC_VERSION
2115184Sek110237 
2125184Sek110237 %type <sval> name
2135184Sek110237 %type <ival> entity
2145184Sek110237 %type <val>  value
2155184Sek110237 
2166212Saw148015 %type <cmd> command inner_commands load_command run_command list_command
2176212Saw148015 %type <cmd> proc_define_command files_define_command randvar_define_command
2186550Saw148015 %type <cmd> fo_define_command debug_command create_command
2195184Sek110237 %type <cmd> sleep_command stats_command set_command shutdown_command
2205184Sek110237 %type <cmd> foreach_command log_command system_command flowop_command
2215184Sek110237 %type <cmd> eventgen_command quit_command flowop_list thread_list
2225184Sek110237 %type <cmd> thread echo_command usage_command help_command vars_command
2239326SAndrew.W.Wilson@sun.com %type <cmd> version_command enable_command multisync_command warmup_command
2245184Sek110237 
2256212Saw148015 %type <attr> files_attr_op files_attr_ops pt_attr_op pt_attr_ops
2266212Saw148015 %type <attr> fo_attr_op fo_attr_ops ev_attr_op ev_attr_ops
2276212Saw148015 %type <attr> randvar_attr_op randvar_attr_ops randvar_attr_typop
2286212Saw148015 %type <attr> randvar_attr_srcop attr_value attr_list_value
2296550Saw148015 %type <attr> comp_lvar_def comp_attr_op comp_attr_ops
2307736SAndrew.W.Wilson@sun.com %type <attr> enable_multi_ops enable_multi_op multisync_op
2316212Saw148015 %type <list> integer_seplist string_seplist string_list var_string_list
2326212Saw148015 %type <list> var_string whitevar_string whitevar_string_list
2336212Saw148015 %type <ival> attrs_define_file attrs_define_thread attrs_flowop
2346550Saw148015 %type <ival> attrs_define_fileset attrs_define_proc attrs_eventgen attrs_define_comp
2356212Saw148015 %type <ival> files_attr_name pt_attr_name fo_attr_name ev_attr_name
2366212Saw148015 %type <ival> randvar_attr_name FSA_TYPE randtype_name randvar_attr_param
2377736SAndrew.W.Wilson@sun.com %type <ival> randsrc_name FSA_RANDSRC randvar_attr_tsp em_attr_name
2386212Saw148015 %type <ival> FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC
2396212Saw148015 
2406212Saw148015 %type <rndtb>  probtabentry_list probtabentry
2416212Saw148015 %type <avd> var_int_val
2425184Sek110237 %%
2435184Sek110237 
2445184Sek110237 commands: commands command
2455184Sek110237 {
2465184Sek110237 	list_t *list = NULL;
2475184Sek110237 	list_t *list_end = NULL;
2485184Sek110237 
2495184Sek110237 	if ($2->cmd != NULL)
2505184Sek110237 		$2->cmd($2);
2515184Sek110237 
2525184Sek110237 	free($2);
2535184Sek110237 }
2545184Sek110237 | commands error
2555184Sek110237 {
2565184Sek110237 	if (dofile)
2575184Sek110237 		YYABORT;
2585184Sek110237 }
2595184Sek110237 |;
2605184Sek110237 
2615184Sek110237 inner_commands: command
2625184Sek110237 {
2635184Sek110237 	filebench_log(LOG_DEBUG_IMPL, "inner_command %zx", $1);
2645184Sek110237 	$$ = $1;
2655184Sek110237 }
2665184Sek110237 | inner_commands command
2675184Sek110237 {
2685184Sek110237 	cmd_t *list = NULL;
2695184Sek110237 	cmd_t *list_end = NULL;
2705184Sek110237 
2715184Sek110237 	/* Find end of list */
2725184Sek110237 	for (list = $1; list != NULL;
2735184Sek110237 	    list = list->cmd_next)
2745184Sek110237 		list_end = list;
2755184Sek110237 
2765184Sek110237 	list_end->cmd_next = $2;
2775184Sek110237 
2785184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
2795184Sek110237 	    "inner_commands adding cmd %zx to list %zx", $2, $1);
2805184Sek110237 
2815184Sek110237 	$$ = $1;
2825184Sek110237 };
2835184Sek110237 
2845184Sek110237 command:
2856212Saw148015   proc_define_command
2866212Saw148015 | files_define_command
2876212Saw148015 | randvar_define_command
2886550Saw148015 | fo_define_command
2895184Sek110237 | debug_command
2905184Sek110237 | eventgen_command
2915184Sek110237 | create_command
2925184Sek110237 | echo_command
2935184Sek110237 | usage_command
2945184Sek110237 | vars_command
2955184Sek110237 | foreach_command
2965184Sek110237 | help_command
2975184Sek110237 | list_command
2985184Sek110237 | load_command
2995184Sek110237 | log_command
3005184Sek110237 | run_command
3015184Sek110237 | set_command
3025184Sek110237 | shutdown_command
3035184Sek110237 | sleep_command
3049326SAndrew.W.Wilson@sun.com | warmup_command
3055184Sek110237 | stats_command
3065184Sek110237 | system_command
3076750Sek110237 | version_command
3087736SAndrew.W.Wilson@sun.com | enable_command
3097736SAndrew.W.Wilson@sun.com | multisync_command
3105184Sek110237 | quit_command;
3115184Sek110237 
3125184Sek110237 foreach_command: FSC_FOREACH
3135184Sek110237 {
3145184Sek110237 	if (($$ = alloc_cmd()) == NULL)
3155184Sek110237 		YYERROR;
3165184Sek110237 	filebench_log(LOG_DEBUG_IMPL, "foreach_command %zx", $$);
3175184Sek110237 }
3185184Sek110237 | foreach_command FSV_VARIABLE FSK_IN integer_seplist FSK_OPENLST inner_commands FSK_CLOSELST
3195184Sek110237 {
3205184Sek110237 	cmd_t *cmd, *inner_cmd;
3215184Sek110237 	list_t *list;
3225184Sek110237 
3235184Sek110237 	$$ = $1;
3245184Sek110237 	$$->cmd_list = $6;
3255184Sek110237 	$$->cmd_tgt1 = $2;
3265184Sek110237 	$$->cmd_param_list = $4;
3275184Sek110237 	$$->cmd = parser_foreach_integer;
3285184Sek110237 
3295184Sek110237 	for (list = $$->cmd_param_list; list != NULL;
3305184Sek110237 	    list = list->list_next) {
3315184Sek110237 		for (inner_cmd = $$->cmd_list;
3325184Sek110237 		    inner_cmd != NULL;
3335184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
3345184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
3356286Saw148015 			    "packing foreach: %zx %s=%llu, cmd %zx",
3366212Saw148015 			    $$, $$->cmd_tgt1,
3376286Saw148015 			    (u_longlong_t)avd_get_int(list->list_integer),
3386286Saw148015 			    inner_cmd);
3395184Sek110237 		}
3405184Sek110237 	}
3415184Sek110237 }| foreach_command FSV_VARIABLE FSK_IN string_seplist FSK_OPENLST inner_commands FSK_CLOSELST
3425184Sek110237 {
3435184Sek110237 	cmd_t *cmd, *inner_cmd;
3445184Sek110237 	list_t *list;
3455184Sek110237 
3465184Sek110237 	$$ = $1;
3475184Sek110237 	$$->cmd_list = $6;
3485184Sek110237 	$$->cmd_tgt1 = $2;
3495184Sek110237 	$$->cmd_param_list = $4;
3505184Sek110237 	$$->cmd = parser_foreach_string;
3515184Sek110237 
3525184Sek110237 	for (list = $$->cmd_param_list; list != NULL;
3535184Sek110237 	    list = list->list_next) {
3545184Sek110237 		for (inner_cmd = $$->cmd_list;
3555184Sek110237 		    inner_cmd != NULL;
3565184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
3575184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
3585184Sek110237 			    "packing foreach: %zx %s=%s, cmd %zx",
3595184Sek110237 			    $$,
3605184Sek110237 			    $$->cmd_tgt1,
3615184Sek110237 			    *list->list_string, inner_cmd);
3625184Sek110237 		}
3635184Sek110237 	}
3645184Sek110237 };
3655184Sek110237 
3665184Sek110237 integer_seplist: FSV_VAL_INT
3675184Sek110237 {
3685184Sek110237 	if (($$ = alloc_list()) == NULL)
3695184Sek110237 		YYERROR;
3705184Sek110237 
3716212Saw148015 	$$->list_integer = avd_int_alloc($1);
3725184Sek110237 }
3735184Sek110237 | integer_seplist FSK_SEPLST FSV_VAL_INT
3745184Sek110237 {
3755184Sek110237 	list_t *list = NULL;
3765184Sek110237 	list_t *list_end = NULL;
3775184Sek110237 
3785184Sek110237 	if (($$ = alloc_list()) == NULL)
3795184Sek110237 		YYERROR;
3805184Sek110237 
3816212Saw148015 	$$->list_integer = avd_int_alloc($3);
3825184Sek110237 
3835184Sek110237 	/* Find end of list */
3845184Sek110237 	for (list = $1; list != NULL;
3855184Sek110237 	    list = list->list_next)
3865184Sek110237 		list_end = list;
3875184Sek110237 	list_end->list_next = $$;
3885184Sek110237 	$$ = $1;
3895184Sek110237 };
3905184Sek110237 
3915184Sek110237 string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
3925184Sek110237 {
3935184Sek110237 	if (($$ = alloc_list()) == NULL)
3945184Sek110237 		YYERROR;
3955184Sek110237 
3966212Saw148015 	$$->list_string = avd_str_alloc($2);
3975184Sek110237 }
3985184Sek110237 | string_seplist FSK_SEPLST FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
3995184Sek110237 {
4005184Sek110237 	list_t *list = NULL;
4015184Sek110237 	list_t *list_end = NULL;
4025184Sek110237 
4035184Sek110237 	if (($$ = alloc_list()) == NULL)
4045184Sek110237 			YYERROR;
4055184Sek110237 
4066212Saw148015 	$$->list_string = avd_str_alloc($4);
4075184Sek110237 
4085184Sek110237 	/* Find end of list */
4095184Sek110237 	for (list = $1; list != NULL;
4105184Sek110237 	    list = list->list_next)
4115184Sek110237 		list_end = list;
4125184Sek110237 	list_end->list_next = $$;
4135184Sek110237 	$$ = $1;
4145184Sek110237 };
4155184Sek110237 
4165184Sek110237 eventgen_command: FSC_EVENTGEN
4175184Sek110237 {
4185184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4195184Sek110237 		YYERROR;
4205184Sek110237 	$$->cmd = &parser_eventgen;
4215184Sek110237 }
4226212Saw148015 | eventgen_command ev_attr_ops
4235184Sek110237 {
4245184Sek110237 	$1->cmd_attr_list = $2;
4255184Sek110237 };
4265184Sek110237 
4275184Sek110237 system_command: FSC_SYSTEM whitevar_string_list
4285184Sek110237 {
4295184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4305184Sek110237 		YYERROR;
4315184Sek110237 
4325184Sek110237 	$$->cmd_param_list = $2;
4335184Sek110237 	$$->cmd = parser_system;
4345184Sek110237 };
4355184Sek110237 
4365184Sek110237 echo_command: FSC_ECHO whitevar_string_list
4375184Sek110237 {
4385184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4395184Sek110237 		YYERROR;
4405184Sek110237 
4415184Sek110237 	$$->cmd_param_list = $2;
4425184Sek110237 	$$->cmd = parser_echo;
4435184Sek110237 };
4445184Sek110237 
4456750Sek110237 version_command: FSC_VERSION
4466750Sek110237 {
4476750Sek110237 	if (($$ = alloc_cmd()) == NULL)
4486750Sek110237 		YYERROR;
4496750Sek110237 	$$->cmd = parser_version;
4506750Sek110237 };
4516750Sek110237 
4525184Sek110237 usage_command: FSC_USAGE whitevar_string_list
4535184Sek110237 {
4545184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4555184Sek110237 		YYERROR;
4565184Sek110237 
4575184Sek110237 	$$->cmd_param_list = $2;
4585184Sek110237 	$$->cmd = parser_usage;
4595184Sek110237 };
4605184Sek110237 
4615184Sek110237 vars_command: FSC_VARS
4625184Sek110237 {
4635184Sek110237 	if (($$ = alloc_cmd()) == NULL)
4645184Sek110237 		YYERROR;
4655184Sek110237 
4665184Sek110237 	$$->cmd = parser_printvars;
4675184Sek110237 };
4685184Sek110237 
4697736SAndrew.W.Wilson@sun.com enable_command: FSC_ENABLE FSE_MULTI
4707736SAndrew.W.Wilson@sun.com {
4717736SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
4727736SAndrew.W.Wilson@sun.com 		YYERROR;
4737736SAndrew.W.Wilson@sun.com 
4747736SAndrew.W.Wilson@sun.com 	$$->cmd = parser_enable_mc;
4757736SAndrew.W.Wilson@sun.com }
4767736SAndrew.W.Wilson@sun.com | enable_command  enable_multi_ops
4777736SAndrew.W.Wilson@sun.com {
4787736SAndrew.W.Wilson@sun.com 	$1->cmd_attr_list = $2;
4797736SAndrew.W.Wilson@sun.com };
4807736SAndrew.W.Wilson@sun.com 
4817736SAndrew.W.Wilson@sun.com multisync_command: FSC_DOMULTISYNC multisync_op
4827736SAndrew.W.Wilson@sun.com {
4837736SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
4847736SAndrew.W.Wilson@sun.com 		YYERROR;
4857736SAndrew.W.Wilson@sun.com 
4867736SAndrew.W.Wilson@sun.com 	$$->cmd = parser_domultisync;
4877736SAndrew.W.Wilson@sun.com 	$$->cmd_attr_list = $2;
4887736SAndrew.W.Wilson@sun.com }
4897736SAndrew.W.Wilson@sun.com 
4905184Sek110237 string_list: FSV_VARIABLE
4915184Sek110237 {
4925184Sek110237 	if (($$ = alloc_list()) == NULL)
4935184Sek110237 			YYERROR;
4946212Saw148015 	$$->list_string = avd_str_alloc($1);
4955184Sek110237 }
4965184Sek110237 | string_list FSK_SEPLST FSV_VARIABLE
4975184Sek110237 {
4985184Sek110237 	list_t *list = NULL;
4995184Sek110237 	list_t *list_end = NULL;
5005184Sek110237 
5015184Sek110237 	if (($$ = alloc_list()) == NULL)
5025184Sek110237 		YYERROR;
5035184Sek110237 
5046212Saw148015 	$$->list_string = avd_str_alloc($3);
5055184Sek110237 
5065184Sek110237 	/* Find end of list */
5075184Sek110237 	for (list = $1; list != NULL;
5085184Sek110237 	    list = list->list_next)
5095184Sek110237 		list_end = list;
5105184Sek110237 	list_end->list_next = $$;
5115184Sek110237 	$$ = $1;
5125184Sek110237 };
5135184Sek110237 
5145184Sek110237 var_string: FSV_VARIABLE
5155184Sek110237 {
5165184Sek110237 	if (($$ = alloc_list()) == NULL)
5175184Sek110237 			YYERROR;
5185184Sek110237 
5196212Saw148015 	$$->list_string = avd_str_alloc($1);
5205184Sek110237 }
5215184Sek110237 | FSV_STRING
5225184Sek110237 {
5235184Sek110237 	if (($$ = alloc_list()) == NULL)
5245184Sek110237 			YYERROR;
5255184Sek110237 
5266212Saw148015 	$$->list_string = avd_str_alloc($1);
5275184Sek110237 };
5285184Sek110237 
5295184Sek110237 var_string_list: var_string
5305184Sek110237 {
5315184Sek110237 	$$ = $1;
5325184Sek110237 }| var_string FSV_STRING
5335184Sek110237 {
5345184Sek110237 	list_t *list = NULL;
5355184Sek110237 	list_t *list_end = NULL;
5365184Sek110237 
5375184Sek110237 	/* Add string */
5385184Sek110237 	if (($$ = alloc_list()) == NULL)
5395184Sek110237 		YYERROR;
5405184Sek110237 
5416212Saw148015 	$$->list_string = avd_str_alloc($2);
5425184Sek110237 
5435184Sek110237 	/* Find end of list */
5445184Sek110237 	for (list = $1; list != NULL;
5455184Sek110237 	    list = list->list_next)
5465184Sek110237 		list_end = list;
5475184Sek110237 	list_end->list_next = $$;
5485184Sek110237 	$$ = $1;
5495184Sek110237 
5505184Sek110237 }| var_string FSV_VARIABLE
5515184Sek110237 {
5525184Sek110237 	list_t *list = NULL;
5535184Sek110237 	list_t *list_end = NULL;
5545184Sek110237 
5555184Sek110237 	/* Add variable */
5565184Sek110237 	if (($$ = alloc_list()) == NULL)
5575184Sek110237 		YYERROR;
5585184Sek110237 
5596212Saw148015 	$$->list_string = avd_str_alloc($2);
5605184Sek110237 
5615184Sek110237 	/* Find end of list */
5625184Sek110237 	for (list = $1; list != NULL;
5635184Sek110237 	    list = list->list_next)
5645184Sek110237 		list_end = list;
5655184Sek110237 	list_end->list_next = $$;
5665184Sek110237 	$$ = $1;
5675184Sek110237 } |var_string_list FSV_STRING
5685184Sek110237 {
5695184Sek110237 	list_t *list = NULL;
5705184Sek110237 	list_t *list_end = NULL;
5715184Sek110237 
5725184Sek110237 	/* Add string */
5735184Sek110237 	if (($$ = alloc_list()) == NULL)
5745184Sek110237 		YYERROR;
5755184Sek110237 
5766212Saw148015 	$$->list_string = avd_str_alloc($2);
5775184Sek110237 
5785184Sek110237 	/* Find end of list */
5795184Sek110237 	for (list = $1; list != NULL;
5805184Sek110237 	    list = list->list_next)
5815184Sek110237 		list_end = list;
5825184Sek110237 	list_end->list_next = $$;
5835184Sek110237 	$$ = $1;
5845184Sek110237 
5855184Sek110237 }| var_string_list FSV_VARIABLE
5865184Sek110237 {
5875184Sek110237 	list_t *list = NULL;
5885184Sek110237 	list_t *list_end = NULL;
5895184Sek110237 
5905184Sek110237 	/* Add variable */
5915184Sek110237 	if (($$ = alloc_list()) == NULL)
5925184Sek110237 		YYERROR;
5935184Sek110237 
5946212Saw148015 	$$->list_string = avd_str_alloc($2);
5955184Sek110237 
5965184Sek110237 	/* Find end of list */
5975184Sek110237 	for (list = $1; list != NULL;
5985184Sek110237 	    list = list->list_next)
5995184Sek110237 		list_end = list;
6005184Sek110237 	list_end->list_next = $$;
6015184Sek110237 	$$ = $1;
6025184Sek110237 };
6035184Sek110237 
6045184Sek110237 whitevar_string: FSK_QUOTE FSV_VARIABLE
6055184Sek110237 {
6065184Sek110237 	if (($$ = alloc_list()) == NULL)
6075184Sek110237 			YYERROR;
6085184Sek110237 
6096212Saw148015 	$$->list_string = avd_str_alloc($2);
6105184Sek110237 }
6115184Sek110237 | FSK_QUOTE FSV_WHITESTRING
6125184Sek110237 {
6135184Sek110237 	if (($$ = alloc_list()) == NULL)
6145184Sek110237 			YYERROR;
6155184Sek110237 
6166212Saw148015 	$$->list_string = avd_str_alloc($2);
6175184Sek110237 };
6185184Sek110237 
6195184Sek110237 whitevar_string_list: whitevar_string FSV_WHITESTRING
6205184Sek110237 {
6215184Sek110237 	list_t *list = NULL;
6225184Sek110237 	list_t *list_end = NULL;
6235184Sek110237 
6245184Sek110237 	/* Add string */
6255184Sek110237 	if (($$ = alloc_list()) == NULL)
6265184Sek110237 		YYERROR;
6275184Sek110237 
6286212Saw148015 	$$->list_string = avd_str_alloc($2);
6295184Sek110237 
6305184Sek110237 	/* Find end of list */
6315184Sek110237 	for (list = $1; list != NULL;
6325184Sek110237 	    list = list->list_next)
6335184Sek110237 		list_end = list;
6345184Sek110237 	list_end->list_next = $$;
6355184Sek110237 	$$ = $1;
6365184Sek110237 
6375184Sek110237 }| whitevar_string FSV_VARIABLE
6385184Sek110237 {
6395184Sek110237 	list_t *list = NULL;
6405184Sek110237 	list_t *list_end = NULL;
6415184Sek110237 
6425184Sek110237 	/* Add variable */
6435184Sek110237 	if (($$ = alloc_list()) == NULL)
6445184Sek110237 		YYERROR;
6455184Sek110237 
6466212Saw148015 	$$->list_string = avd_str_alloc($2);
6475184Sek110237 
6485184Sek110237 	/* Find end of list */
6495184Sek110237 	for (list = $1; list != NULL;
6505184Sek110237 	    list = list->list_next)
6515184Sek110237 		list_end = list;
6525184Sek110237 	list_end->list_next = $$;
6535184Sek110237 	$$ = $1;
6546212Saw148015 }| whitevar_string FSV_RANDVAR randvar_attr_tsp
6556212Saw148015 {
6566212Saw148015 	list_t *list = NULL;
6576212Saw148015 	list_t *list_end = NULL;
6586212Saw148015 
6596212Saw148015 	/* Add variable */
6606212Saw148015 	if (($$ = alloc_list()) == NULL)
6616212Saw148015 		YYERROR;
6626212Saw148015 
6636212Saw148015 	$$->list_string = avd_str_alloc($2);
6646212Saw148015 	$$->list_integer = avd_int_alloc($3);
6656212Saw148015 
6666212Saw148015 	/* Find end of list */
6676212Saw148015 	for (list = $1; list != NULL;
6686212Saw148015 	    list = list->list_next)
6696212Saw148015 		list_end = list;
6706212Saw148015 	list_end->list_next = $$;
6716212Saw148015 	$$ = $1;
6726212Saw148015 }| whitevar_string_list FSV_WHITESTRING
6735184Sek110237 {
6745184Sek110237 	list_t *list = NULL;
6755184Sek110237 	list_t *list_end = NULL;
6765184Sek110237 
6775184Sek110237 	/* Add string */
6785184Sek110237 	if (($$ = alloc_list()) == NULL)
6795184Sek110237 		YYERROR;
6805184Sek110237 
6816212Saw148015 	$$->list_string = avd_str_alloc($2);
6825184Sek110237 
6835184Sek110237 	/* Find end of list */
6845184Sek110237 	for (list = $1; list != NULL;
6855184Sek110237 	    list = list->list_next)
6865184Sek110237 		list_end = list;
6875184Sek110237 	list_end->list_next = $$;
6885184Sek110237 	$$ = $1;
6895184Sek110237 
6905184Sek110237 }| whitevar_string_list FSV_VARIABLE
6915184Sek110237 {
6925184Sek110237 	list_t *list = NULL;
6935184Sek110237 	list_t *list_end = NULL;
6945184Sek110237 
6955184Sek110237 	/* Add variable */
6965184Sek110237 	if (($$ = alloc_list()) == NULL)
6975184Sek110237 		YYERROR;
6985184Sek110237 
6996212Saw148015 	$$->list_string = avd_str_alloc($2);
7006212Saw148015 
7016212Saw148015 	/* Find end of list */
7026212Saw148015 	for (list = $1; list != NULL;
7036212Saw148015 	    list = list->list_next)
7046212Saw148015 		list_end = list;
7056212Saw148015 	list_end->list_next = $$;
7066212Saw148015 	$$ = $1;
7076212Saw148015 }| whitevar_string_list FSV_RANDVAR randvar_attr_tsp
7086212Saw148015 {
7096212Saw148015 	list_t *list = NULL;
7106212Saw148015 	list_t *list_end = NULL;
7116212Saw148015 
7126212Saw148015 	/* Add variable */
7136212Saw148015 	if (($$ = alloc_list()) == NULL)
7146212Saw148015 		YYERROR;
7156212Saw148015 
7166212Saw148015 	$$->list_string = avd_str_alloc($2);
7176212Saw148015 	$$->list_integer = avd_int_alloc($3);
7185184Sek110237 
7195184Sek110237 	/* Find end of list */
7205184Sek110237 	for (list = $1; list != NULL;
7215184Sek110237 	    list = list->list_next)
7225184Sek110237 		list_end = list;
7235184Sek110237 	list_end->list_next = $$;
7245184Sek110237 	$$ = $1;
7255184Sek110237 }| whitevar_string_list FSK_QUOTE
7265184Sek110237 {
7275184Sek110237 	$$ = $1;
7285184Sek110237 }| whitevar_string FSK_QUOTE
7295184Sek110237 {
7305184Sek110237 	$$ = $1;
7315184Sek110237 };
7325184Sek110237 
7335184Sek110237 list_command: FSC_LIST
7345184Sek110237 {
7355184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7365184Sek110237 		YYERROR;
7375184Sek110237 	$$->cmd = &parser_list;
7386212Saw148015 }
7396212Saw148015 | list_command FSC_FLOWOP
7406212Saw148015 {
7416212Saw148015 	$1->cmd = &parser_flowop_list;
7425184Sek110237 };
7435184Sek110237 
7445184Sek110237 log_command: FSC_LOG whitevar_string_list
7455184Sek110237 {
7465184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7475184Sek110237 		YYERROR;
7485184Sek110237 	$$->cmd = &parser_log;
7495184Sek110237 	$$->cmd_param_list = $2;
7505184Sek110237 };
7515184Sek110237 
7525184Sek110237 debug_command: FSC_DEBUG FSV_VAL_INT
7535184Sek110237 {
7545184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7555184Sek110237 		YYERROR;
7565184Sek110237 	$$->cmd = NULL;
7576391Saw148015 	filebench_shm->shm_debug_level = $2;
7586391Saw148015 	if (filebench_shm->shm_debug_level > 9)
7595184Sek110237 		yydebug = 1;
7605184Sek110237 };
7615184Sek110237 
7625184Sek110237 set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
7635184Sek110237 {
7645184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7655184Sek110237 		YYERROR;
7665184Sek110237 	var_assign_integer($2, $4);
7675184Sek110237 	if (parentscript) {
7685184Sek110237 		$$->cmd_tgt1 = $2;
7695184Sek110237 		parser_vars($$);
7705184Sek110237 	}
7715184Sek110237 	$$->cmd = NULL;
7725184Sek110237 }
7736212Saw148015 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_BOOLEAN
7746212Saw148015 {
7756212Saw148015 	if (($$ = alloc_cmd()) == NULL)
7766212Saw148015 		YYERROR;
7776212Saw148015 	var_assign_boolean($2, $4);
7786212Saw148015 	if (parentscript) {
7796212Saw148015 		$$->cmd_tgt1 = $2;
7806212Saw148015 		parser_vars($$);
7816212Saw148015 	}
7826212Saw148015 	$$->cmd = NULL;
7836212Saw148015 }
7845184Sek110237 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
7855184Sek110237 {
7865184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7875184Sek110237 		YYERROR;
7885184Sek110237 	var_assign_string($2, $5);
7895184Sek110237 	if (parentscript) {
7905184Sek110237 		$$->cmd_tgt1 = $2;
7915184Sek110237 		parser_vars($$);
7925184Sek110237 	}
7935184Sek110237 	$$->cmd = NULL;
7945184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_STRING
7955184Sek110237 {
7965184Sek110237 	if (($$ = alloc_cmd()) == NULL)
7975184Sek110237 		YYERROR;
7985184Sek110237 	var_assign_string($2, $4);
7995184Sek110237 	if (parentscript) {
8005184Sek110237 		$$->cmd_tgt1 = $2;
8015184Sek110237 		parser_vars($$);
8025184Sek110237 	}
8035184Sek110237 	$$->cmd = NULL;
8045184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE
8055184Sek110237 {
8065184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8075184Sek110237 		YYERROR;
8085184Sek110237 	var_assign_var($2, $4);
8095184Sek110237 	if (parentscript) {
8105184Sek110237 		$$->cmd_tgt1 = $2;
8115184Sek110237 		parser_vars($$);
8125184Sek110237 	}
8135184Sek110237 	$$->cmd = NULL;
8146084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_TIMEOUT
8156084Saw148015 {
8166084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT;
8176084Saw148015 	if (($$ = alloc_cmd()) == NULL)
8186084Saw148015 		YYERROR;
8196084Saw148015 	$$->cmd = NULL;
8206084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_ALLDONE
8216084Saw148015 {
8226084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_QALLDONE;
8236084Saw148015 	if (($$ = alloc_cmd()) == NULL)
8246084Saw148015 		YYERROR;
8256084Saw148015 	$$->cmd = NULL;
8266084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_FIRSTDONE
8276084Saw148015 {
8286084Saw148015 	filebench_shm->shm_rmode = FILEBENCH_MODE_Q1STDONE;
8296084Saw148015 	if (($$ = alloc_cmd()) == NULL)
8306084Saw148015 		YYERROR;
8316084Saw148015 	$$->cmd = NULL;
832*9356SAndrew.W.Wilson@sun.com } | FSC_SET FSE_MODE FSC_NOUSESTATS
833*9356SAndrew.W.Wilson@sun.com {
834*9356SAndrew.W.Wilson@sun.com 	filebench_shm->shm_mmode |= FILEBENCH_MODE_NOUSAGE;
835*9356SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "disabling CPU usage statistics");
836*9356SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
837*9356SAndrew.W.Wilson@sun.com 		YYERROR;
838*9356SAndrew.W.Wilson@sun.com 	$$->cmd = NULL;
8396212Saw148015 }| FSC_SET FSV_RANDVAR FSS_TYPE FSK_ASSIGN randvar_attr_typop
8406212Saw148015 {
8416212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8426212Saw148015 		YYERROR;
8436212Saw148015 	$$->cmd = &parser_randvar_set;
8446212Saw148015 	$$->cmd_tgt1 = $2;
8456212Saw148015 	$$->cmd_qty = FSS_TYPE;
8466212Saw148015 	$$->cmd_attr_list = $5;
8476212Saw148015 
8486212Saw148015 }| FSC_SET FSV_RANDVAR FSS_SRC FSK_ASSIGN randvar_attr_srcop
8496212Saw148015 {
8506212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8516212Saw148015 		YYERROR;
8526212Saw148015 	$$->cmd = &parser_randvar_set;
8536212Saw148015 	$$->cmd_tgt1 = $2;
8546212Saw148015 	$$->cmd_qty = FSS_SRC;
8556212Saw148015 	$$->cmd_attr_list = $5;
8566212Saw148015 
8576212Saw148015 }| FSC_SET FSV_RANDVAR randvar_attr_param FSK_ASSIGN attr_value
8586212Saw148015 {
8596212Saw148015 	if (($$ = alloc_cmd()) == NULL)
8606212Saw148015 		YYERROR;
8616212Saw148015 	$$->cmd = &parser_randvar_set;
8626212Saw148015 	$$->cmd_tgt1 = $2;
8636212Saw148015 	$$->cmd_qty = $3;
8646212Saw148015 	$$->cmd_attr_list = $5;
8656212Saw148015 
8665184Sek110237 };
8675184Sek110237 
8685184Sek110237 stats_command: FSC_STATS FSE_SNAP
8695184Sek110237 {
8705184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8715184Sek110237 		YYERROR;
8725184Sek110237 	$$->cmd = (void (*)(struct cmd *))&parser_statssnap;
8735184Sek110237 	break;
8745184Sek110237 
8755184Sek110237 }
8765184Sek110237 | FSC_STATS FSE_CLEAR
8775184Sek110237 {
8785184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8795184Sek110237 		YYERROR;
8805184Sek110237 	$$->cmd = (void (*)(struct cmd *))&stats_clear;
8815184Sek110237 
8825184Sek110237 }
8835184Sek110237 | FSC_STATS FSE_DIRECTORY var_string_list
8845184Sek110237 {
8855184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8865184Sek110237 		YYERROR;
8875184Sek110237 	$$->cmd_param_list = $3;
8885184Sek110237 	$$->cmd = (void (*)(struct cmd *))&parser_directory;
8895184Sek110237 
8905184Sek110237 }
8915184Sek110237 | FSC_STATS FSE_COMMAND whitevar_string_list
8925184Sek110237 {
8935184Sek110237 	if (($$ = alloc_cmd()) == NULL)
8945184Sek110237 		YYERROR;
8955184Sek110237 
8965184Sek110237 	$$->cmd_param_list = $3;
8975184Sek110237 	$$->cmd = parser_statscmd;
8985184Sek110237 
8995184Sek110237 }| FSC_STATS FSE_DUMP whitevar_string_list
9005184Sek110237 {
9015184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9025184Sek110237 		YYERROR;
9035184Sek110237 
9045184Sek110237 	$$->cmd_param_list = $3;
9055184Sek110237 	$$->cmd = parser_statsdump;
9065184Sek110237 }| FSC_STATS FSE_XMLDUMP whitevar_string_list
9075184Sek110237 {
9085184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9095184Sek110237 		YYERROR;
9105184Sek110237 
9115184Sek110237 	$$->cmd_param_list = $3;
9125184Sek110237 	$$->cmd = parser_statsxmldump;
9137736SAndrew.W.Wilson@sun.com }| FSC_STATS FSE_MULTIDUMP whitevar_string_list
9147736SAndrew.W.Wilson@sun.com {
9157736SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
9167736SAndrew.W.Wilson@sun.com 		YYERROR;
9177736SAndrew.W.Wilson@sun.com 
9187736SAndrew.W.Wilson@sun.com 	$$->cmd_param_list = $3;
9197736SAndrew.W.Wilson@sun.com 	$$->cmd = parser_statsmultidump;
9205184Sek110237 };
9215184Sek110237 
9225184Sek110237 quit_command: FSC_QUIT
9235184Sek110237 {
9245184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9255184Sek110237 		YYERROR;
9265184Sek110237 	$$->cmd = parser_filebench_shutdown;
9275184Sek110237 };
9285184Sek110237 
9295184Sek110237 flowop_list: flowop_command
9305184Sek110237 {
9315184Sek110237 	$$ = $1;
9325184Sek110237 }| flowop_list flowop_command
9335184Sek110237 {
9345184Sek110237 	cmd_t *list = NULL;
9355184Sek110237 	cmd_t *list_end = NULL;
9365184Sek110237 
9375184Sek110237 	/* Find end of list */
9385184Sek110237 	for (list = $1; list != NULL;
9395184Sek110237 	    list = list->cmd_next)
9405184Sek110237 		list_end = list;
9415184Sek110237 
9425184Sek110237 	list_end->cmd_next = $2;
9435184Sek110237 
9445184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
9455184Sek110237 	    "flowop_list adding cmd %zx to list %zx", $2, $1);
9465184Sek110237 
9475184Sek110237 	$$ = $1;
9485184Sek110237 };
9495184Sek110237 
9506212Saw148015 thread: FSE_THREAD pt_attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
9515184Sek110237 {
9525184Sek110237 	/*
9535184Sek110237 	 * Allocate a cmd node per thread, with a
9545184Sek110237 	 * list of flowops attached to the cmd_list
9555184Sek110237 	 */
9565184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9575184Sek110237 		YYERROR;
9585184Sek110237 	$$->cmd_list = $4;
9595184Sek110237 	$$->cmd_attr_list = $2;
9605184Sek110237 };
9615184Sek110237 
9625184Sek110237 thread_list: thread
9635184Sek110237 {
9645184Sek110237 	$$ = $1;
9655184Sek110237 }| thread_list thread
9665184Sek110237 {
9675184Sek110237 	cmd_t *list = NULL;
9685184Sek110237 	cmd_t *list_end = NULL;
9695184Sek110237 
9705184Sek110237 	/* Find end of list */
9715184Sek110237 	for (list = $1; list != NULL;
9725184Sek110237 	    list = list->cmd_next)
9735184Sek110237 		list_end = list;
9745184Sek110237 
9755184Sek110237 	list_end->cmd_next = $2;
9765184Sek110237 
9775184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
9785184Sek110237 	    "thread_list adding cmd %zx to list %zx", $2, $1);
9795184Sek110237 
9805184Sek110237 	$$ = $1;
9815184Sek110237 };
9825184Sek110237 
9836212Saw148015 proc_define_command: FSC_DEFINE FSE_PROC pt_attr_ops FSK_OPENLST thread_list FSK_CLOSELST
9845184Sek110237 {
9855184Sek110237 	if (($$ = alloc_cmd()) == NULL)
9865184Sek110237 		YYERROR;
9875184Sek110237 	$$->cmd = &parser_proc_define;
9885184Sek110237 	$$->cmd_list = $5;
9895184Sek110237 	$$->cmd_attr_list = $3;
9905184Sek110237 
9916212Saw148015 }
9926212Saw148015 | proc_define_command pt_attr_ops
9936212Saw148015 {
9946212Saw148015 	$1->cmd_attr_list = $2;
9956212Saw148015 };
9966212Saw148015 
9976212Saw148015 files_define_command: FSC_DEFINE FSE_FILE
9985184Sek110237 {
9995184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10005184Sek110237 		YYERROR;
10015184Sek110237 	$$->cmd = &parser_file_define;
10025184Sek110237 }| FSC_DEFINE FSE_FILESET
10035184Sek110237 {
10045184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10055184Sek110237 		YYERROR;
10065184Sek110237 	$$->cmd = &parser_fileset_define;
10075184Sek110237 }
10086212Saw148015 | files_define_command files_attr_ops
10095184Sek110237 {
10105184Sek110237 	$1->cmd_attr_list = $2;
10115184Sek110237 };
10125184Sek110237 
10136212Saw148015 randvar_define_command: FSC_DEFINE FSE_RAND randvar_attr_ops
10146212Saw148015 {
10156212Saw148015 	if (($$ = alloc_cmd()) == NULL)
10166212Saw148015 		YYERROR;
10176212Saw148015 	$$->cmd = &parser_randvar_define;
10186212Saw148015 	$$->cmd_attr_list = $3;
10196212Saw148015 };
10206212Saw148015 
10216550Saw148015 fo_define_command: FSC_DEFINE FSC_FLOWOP comp_attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
10226550Saw148015 {
10236550Saw148015 	if (($$ = alloc_cmd()) == NULL)
10246550Saw148015 		YYERROR;
10256550Saw148015 	$$->cmd = &parser_composite_flowop_define;
10266550Saw148015 	$$->cmd_list = $5;
10276550Saw148015 	$$->cmd_attr_list = $3;
10286550Saw148015 }
10296550Saw148015 | fo_define_command comp_attr_ops
10306550Saw148015 {
10316550Saw148015 	$1->cmd_attr_list = $2;
10326550Saw148015 };
10336550Saw148015 
10345184Sek110237 create_command: FSC_CREATE entity
10355184Sek110237 {
10365184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10375184Sek110237 		YYERROR;
10385184Sek110237 	switch ($2) {
10395184Sek110237 	case FSE_PROC:
10405184Sek110237 		$$->cmd = &parser_proc_create;
10415184Sek110237 		break;
10425673Saw148015 	case FSE_FILESET:
10435184Sek110237 	case FSE_FILE:
10445184Sek110237 		$$->cmd = &parser_fileset_create;
10455184Sek110237 		break;
10465184Sek110237 	default:
10475184Sek110237 		filebench_log(LOG_ERROR, "unknown entity", $2);
10485184Sek110237 		YYERROR;
10495184Sek110237 	}
10505184Sek110237 
10515184Sek110237 };
10525184Sek110237 
10535184Sek110237 shutdown_command: FSC_SHUTDOWN entity
10545184Sek110237 {
10555184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10565184Sek110237 		YYERROR;
10575184Sek110237 	switch ($2) {
10585184Sek110237 	case FSE_PROC:
10595184Sek110237 		$$->cmd = &parser_proc_shutdown;
10605184Sek110237 		break;
1061*9356SAndrew.W.Wilson@sun.com 	case FSE_FILE:
1062*9356SAndrew.W.Wilson@sun.com 	case FSE_FILESET:
1063*9356SAndrew.W.Wilson@sun.com 		$$->cmd = &parser_fileset_shutdown;
1064*9356SAndrew.W.Wilson@sun.com 		break;
10655184Sek110237 	default:
10665184Sek110237 		filebench_log(LOG_ERROR, "unknown entity", $2);
10675184Sek110237 		YYERROR;
10685184Sek110237 	}
10695184Sek110237 
10705184Sek110237 };
10715184Sek110237 
10729326SAndrew.W.Wilson@sun.com warmup_command: FSC_WARMUP FSV_VAL_INT
10739326SAndrew.W.Wilson@sun.com {
10749326SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
10759326SAndrew.W.Wilson@sun.com 		YYERROR;
10769326SAndrew.W.Wilson@sun.com 	$$->cmd = parser_warmup;
10779326SAndrew.W.Wilson@sun.com 	$$->cmd_qty = $2;
10789326SAndrew.W.Wilson@sun.com }
10799326SAndrew.W.Wilson@sun.com | FSC_WARMUP FSV_VARIABLE
10809326SAndrew.W.Wilson@sun.com {
10819326SAndrew.W.Wilson@sun.com 	fbint_t *integer;
10829326SAndrew.W.Wilson@sun.com 
10839326SAndrew.W.Wilson@sun.com 	if (($$ = alloc_cmd()) == NULL)
10849326SAndrew.W.Wilson@sun.com 		YYERROR;
10859326SAndrew.W.Wilson@sun.com 	$$->cmd = parser_warmup_variable;
10869326SAndrew.W.Wilson@sun.com 	$$->cmd_tgt1 = fb_stralloc($2);
10879326SAndrew.W.Wilson@sun.com };
10889326SAndrew.W.Wilson@sun.com 
10895184Sek110237 sleep_command: FSC_SLEEP FSV_VAL_INT
10905184Sek110237 {
10915184Sek110237 	if (($$ = alloc_cmd()) == NULL)
10925184Sek110237 		YYERROR;
10935184Sek110237 	$$->cmd = parser_sleep;
10945184Sek110237 	$$->cmd_qty = $2;
10955184Sek110237 }
10965184Sek110237 | FSC_SLEEP FSV_VARIABLE
10975184Sek110237 {
10986212Saw148015 	fbint_t *integer;
10995184Sek110237 
11005184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11015184Sek110237 		YYERROR;
11025184Sek110237 	$$->cmd = parser_sleep_variable;
11035184Sek110237 	$$->cmd_tgt1 = fb_stralloc($2);
11045184Sek110237 };
11055184Sek110237 
11065184Sek110237 run_command: FSC_RUN FSV_VAL_INT
11075184Sek110237 {
11085184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11095184Sek110237 		YYERROR;
11105184Sek110237 	$$->cmd = parser_run;
11115184Sek110237 	$$->cmd_qty = $2;
11125184Sek110237 }
11135184Sek110237 | FSC_RUN FSV_VARIABLE
11145184Sek110237 {
11156212Saw148015 	fbint_t *integer;
11165184Sek110237 
11175184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11185184Sek110237 		YYERROR;
11195184Sek110237 	$$->cmd = parser_run_variable;
11205184Sek110237 	$$->cmd_tgt1 = fb_stralloc($2);
11215184Sek110237 }
11225184Sek110237 | FSC_RUN
11235184Sek110237 {
11246212Saw148015 	fbint_t *integer;
11255184Sek110237 
11265184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11275184Sek110237 		YYERROR;
11285184Sek110237 	$$->cmd = parser_run;
11295184Sek110237 	$$->cmd_qty = 60UL;
11305184Sek110237 };
11315184Sek110237 
11325184Sek110237 help_command: FSC_HELP
11335184Sek110237 {
11345184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11355184Sek110237 		YYERROR;
11365184Sek110237 	$$->cmd = parser_help;
11375184Sek110237 };
11385184Sek110237 
11395184Sek110237 flowop_command: FSC_FLOWOP name
11405184Sek110237 {
11415184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11425184Sek110237 		YYERROR;
11435184Sek110237 	$$->cmd_name = fb_stralloc($2);
11445184Sek110237 }
11456212Saw148015 | flowop_command fo_attr_ops
11465184Sek110237 {
11475184Sek110237 	$1->cmd_attr_list = $2;
11485184Sek110237 };
11495184Sek110237 
11505184Sek110237 load_command: FSC_LOAD FSV_STRING
11515184Sek110237 {
11525184Sek110237 	FILE *newfile;
11535184Sek110237 	char loadfile[128];
11545184Sek110237 
11555184Sek110237 	if (($$ = alloc_cmd()) == NULL)
11565184Sek110237 		YYERROR;
11575184Sek110237 
11585184Sek110237 	(void) strcpy(loadfile, $2);
11595184Sek110237 	(void) strcat(loadfile, ".f");
11605184Sek110237 
11615184Sek110237 	if ((newfile = fopen(loadfile, "r")) == NULL) {
11625184Sek110237 		(void) strcpy(loadfile, FILEBENCHDIR);
11635184Sek110237 		(void) strcat(loadfile, "/workloads/");
11645184Sek110237 		(void) strcat(loadfile, $2);
11655184Sek110237 		(void) strcat(loadfile, ".f");
11665184Sek110237 		if ((newfile = fopen(loadfile, "r")) == NULL) {
11675184Sek110237 			filebench_log(LOG_ERROR, "Cannot open %s", loadfile);
11685184Sek110237 			YYERROR;
11695184Sek110237 		}
11705184Sek110237 	}
11715184Sek110237 
11725184Sek110237 	parentscript = yyin;
11735184Sek110237 	yyin = newfile;
11745184Sek110237 	yy_switchfileparent(yyin);
11755184Sek110237 };
11765184Sek110237 
11776212Saw148015 
11785184Sek110237 entity: FSE_PROC {$$ = FSE_PROC;}
11795184Sek110237 | FSE_THREAD {$$ = FSE_THREAD;}
11805184Sek110237 | FSE_FILESET {$$ = FSE_FILESET;}
11815184Sek110237 | FSE_FILE {$$ = FSE_FILE;};
11825184Sek110237 
11835184Sek110237 value: FSV_VAL_INT { $$.i = $1;}
11845184Sek110237 | FSV_STRING { $$.s = $1;}
11855184Sek110237 | FSV_VAL_BOOLEAN { $$.b = $1;};
11865184Sek110237 
11875184Sek110237 name: FSV_STRING;
11885184Sek110237 
11896212Saw148015 /* attribute parsing for define file and define fileset */
11906212Saw148015 files_attr_ops: files_attr_op
11916212Saw148015 {
11926212Saw148015 	$$ = $1;
11936212Saw148015 }
11946212Saw148015 | files_attr_ops FSK_SEPLST files_attr_op
11956212Saw148015 {
11966212Saw148015 	attr_t *attr = NULL;
11976212Saw148015 	attr_t *list_end = NULL;
11986212Saw148015 
11996212Saw148015 	for (attr = $1; attr != NULL;
12006212Saw148015 	    attr = attr->attr_next)
12016212Saw148015 		list_end = attr; /* Find end of list */
12026212Saw148015 
12036212Saw148015 	list_end->attr_next = $3;
12046212Saw148015 
12056212Saw148015 	$$ = $1;
12066212Saw148015 };
12076212Saw148015 
12086212Saw148015 files_attr_op: files_attr_name FSK_ASSIGN attr_list_value
12096212Saw148015 {
12106212Saw148015 	$$ = $3;
12116212Saw148015 	$$->attr_name = $1;
12126212Saw148015 }
12136212Saw148015 | files_attr_name
12146212Saw148015 {
12156212Saw148015 	if (($$ = alloc_attr()) == NULL)
12166212Saw148015 		YYERROR;
12176212Saw148015 	$$->attr_name = $1;
12186212Saw148015 };
12196212Saw148015 
12206212Saw148015 /* attribute parsing for random variables */
12216212Saw148015 randvar_attr_ops: randvar_attr_op
12225184Sek110237 {
12235184Sek110237 	$$ = $1;
12245184Sek110237 }
12256212Saw148015 | randvar_attr_ops FSK_SEPLST randvar_attr_op
12266212Saw148015 {
12276212Saw148015 	attr_t *attr = NULL;
12286212Saw148015 	attr_t *list_end = NULL;
12296212Saw148015 
12306212Saw148015 	for (attr = $1; attr != NULL;
12316212Saw148015 	    attr = attr->attr_next)
12326212Saw148015 		list_end = attr; /* Find end of list */
12336212Saw148015 
12346212Saw148015 	list_end->attr_next = $3;
12356212Saw148015 
12366212Saw148015 	$$ = $1;
12376212Saw148015 }
12386212Saw148015 | randvar_attr_ops FSK_SEPLST FSA_RANDTABLE FSK_ASSIGN FSK_OPENLST probtabentry_list FSK_CLOSELST
12396212Saw148015 {
12406212Saw148015 	attr_t *attr = NULL;
12416212Saw148015 	attr_t *list_end = NULL;
12426212Saw148015 
12436212Saw148015 	for (attr = $1; attr != NULL;
12446212Saw148015 	    attr = attr->attr_next)
12456212Saw148015 		list_end = attr; /* Find end of list */
12466212Saw148015 
12476212Saw148015 
12486212Saw148015 	if ((attr = alloc_attr()) == NULL)
12496212Saw148015 		YYERROR;
12506212Saw148015 
12516212Saw148015 	attr->attr_name = FSA_RANDTABLE;
12526212Saw148015 	attr->attr_obj = (void *)$6;
12536212Saw148015 	list_end->attr_next = attr;
12546212Saw148015 	$$ = $1;
12556212Saw148015 };
12566212Saw148015 
12576212Saw148015 randvar_attr_op: randvar_attr_name FSK_ASSIGN attr_list_value
12586212Saw148015 {
12596212Saw148015 	$$ = $3;
12606212Saw148015 	$$->attr_name = $1;
12616212Saw148015 }
12626212Saw148015 | randvar_attr_name
12636212Saw148015 {
12646212Saw148015 	if (($$ = alloc_attr()) == NULL)
12656212Saw148015 		YYERROR;
12666212Saw148015 	$$->attr_name = $1;
12676212Saw148015 }
12686212Saw148015 | FSA_TYPE FSK_ASSIGN randvar_attr_typop
12696212Saw148015 {
12706212Saw148015 	$$ = $3;
12716212Saw148015 	$$->attr_name = FSA_TYPE;
12726212Saw148015 }
12736212Saw148015 | FSA_RANDSRC FSK_ASSIGN randvar_attr_srcop
12746212Saw148015 {
12756212Saw148015 	$$ = $3;
12766212Saw148015 	$$->attr_name = FSA_RANDSRC;
12776212Saw148015 };
12786212Saw148015 
12796212Saw148015 probtabentry: FSK_OPENLST var_int_val FSK_SEPLST var_int_val FSK_SEPLST var_int_val FSK_CLOSELST
12806212Saw148015 {
12816212Saw148015 	if (($$ = alloc_probtabent()) == NULL)
12826212Saw148015 		YYERROR;
12836212Saw148015 	$$->pte_percent = $2;
12846212Saw148015 	$$->pte_segmin  = $4;
12856212Saw148015 	$$->pte_segmax  = $6;
12866212Saw148015 };
12876212Saw148015 
12886212Saw148015 /* attribute parsing for prob density function table */
12896212Saw148015 probtabentry_list: probtabentry
12906212Saw148015 {
12916212Saw148015 	$$ = $1;
12926212Saw148015 }
12936212Saw148015 | probtabentry_list FSK_SEPLST probtabentry
12946212Saw148015 {
12956212Saw148015 	probtabent_t *pte = NULL;
12966212Saw148015 	probtabent_t *ptelist_end = NULL;
12976212Saw148015 
12986212Saw148015 	for (pte = $1; pte != NULL;
12996212Saw148015 	    pte = pte->pte_next)
13006212Saw148015 		ptelist_end = pte; /* Find end of prob table entry list */
13016212Saw148015 
13026212Saw148015 	ptelist_end->pte_next = $3;
13036212Saw148015 
13046212Saw148015 	$$ = $1;
13056212Saw148015 };
13066212Saw148015 
13076212Saw148015 /* attribute parsing for define thread and process */
13086212Saw148015 pt_attr_ops: pt_attr_op
13096212Saw148015 {
13106212Saw148015 	$$ = $1;
13116212Saw148015 }
13126212Saw148015 | pt_attr_ops FSK_SEPLST pt_attr_op
13136212Saw148015 {
13146212Saw148015 	attr_t *attr = NULL;
13156212Saw148015 	attr_t *list_end = NULL;
13166212Saw148015 
13176212Saw148015 	for (attr = $1; attr != NULL;
13186212Saw148015 	    attr = attr->attr_next)
13196212Saw148015 		list_end = attr; /* Find end of list */
13206212Saw148015 
13216212Saw148015 	list_end->attr_next = $3;
13226212Saw148015 
13236212Saw148015 	$$ = $1;
13246212Saw148015 };
13256212Saw148015 
13266212Saw148015 pt_attr_op: pt_attr_name FSK_ASSIGN attr_value
13276212Saw148015 {
13286212Saw148015 	$$ = $3;
13296212Saw148015 	$$->attr_name = $1;
13306212Saw148015 }
13316212Saw148015 | pt_attr_name
13326212Saw148015 {
13336212Saw148015 	if (($$ = alloc_attr()) == NULL)
13346212Saw148015 		YYERROR;
13356212Saw148015 	$$->attr_name = $1;
13366212Saw148015 };
13376212Saw148015 
13386212Saw148015 /* attribute parsing for flowops */
13396212Saw148015 fo_attr_ops: fo_attr_op
13406212Saw148015 {
13416212Saw148015 	$$ = $1;
13426212Saw148015 }
13436212Saw148015 | fo_attr_ops FSK_SEPLST fo_attr_op
13445184Sek110237 {
13455184Sek110237 	attr_t *attr = NULL;
13465184Sek110237 	attr_t *list_end = NULL;
13475184Sek110237 
13485184Sek110237 	for (attr = $1; attr != NULL;
13495184Sek110237 	    attr = attr->attr_next)
13505184Sek110237 		list_end = attr; /* Find end of list */
13515184Sek110237 
13525184Sek110237 	list_end->attr_next = $3;
13535184Sek110237 
13545184Sek110237 	$$ = $1;
13556550Saw148015 }
13566550Saw148015 | fo_attr_ops FSK_SEPLST comp_lvar_def
13576550Saw148015 {
13586550Saw148015 	attr_t *attr = NULL;
13596550Saw148015 	attr_t *list_end = NULL;
13606550Saw148015 
13616550Saw148015 	for (attr = $1; attr != NULL;
13626550Saw148015 	    attr = attr->attr_next)
13636550Saw148015 		list_end = attr; /* Find end of list */
13646550Saw148015 
13656550Saw148015 	list_end->attr_next = $3;
13666550Saw148015 
13676550Saw148015 	$$ = $1;
13685184Sek110237 };
13695184Sek110237 
13706212Saw148015 fo_attr_op: fo_attr_name FSK_ASSIGN attr_value
13715184Sek110237 {
13725184Sek110237 	$$ = $3;
13735184Sek110237 	$$->attr_name = $1;
13745184Sek110237 }
13756212Saw148015 | fo_attr_name
13765184Sek110237 {
13775184Sek110237 	if (($$ = alloc_attr()) == NULL)
13785184Sek110237 		YYERROR;
13795184Sek110237 	$$->attr_name = $1;
13806212Saw148015 };
13816212Saw148015 
13826212Saw148015 /* attribute parsing for Event Generator */
13836212Saw148015 ev_attr_ops: ev_attr_op
13846212Saw148015 {
13856212Saw148015 	$$ = $1;
13865184Sek110237 }
13876212Saw148015 | ev_attr_ops FSK_SEPLST ev_attr_op
13886212Saw148015 {
13896212Saw148015 	attr_t *attr = NULL;
13906212Saw148015 	attr_t *list_end = NULL;
13916212Saw148015 
13926212Saw148015 	for (attr = $1; attr != NULL;
13936212Saw148015 	    attr = attr->attr_next)
13946212Saw148015 		list_end = attr; /* Find end of list */
13956212Saw148015 
13966212Saw148015 	list_end->attr_next = $3;
13976212Saw148015 
13986212Saw148015 	$$ = $1;
13996212Saw148015 };
14006212Saw148015 
14016212Saw148015 ev_attr_op: ev_attr_name FSK_ASSIGN attr_value
14026212Saw148015 {
14036212Saw148015 	$$ = $3;
14046212Saw148015 	$$->attr_name = $1;
14056212Saw148015 }
14066212Saw148015 | ev_attr_name
14076212Saw148015 {
14086212Saw148015 	if (($$ = alloc_attr()) == NULL)
14096212Saw148015 		YYERROR;
14106212Saw148015 	$$->attr_name = $1;
14116212Saw148015 };
14126212Saw148015 
14137736SAndrew.W.Wilson@sun.com /* attribute parsing for enable multiple client command */
14147736SAndrew.W.Wilson@sun.com enable_multi_ops: enable_multi_op
14157736SAndrew.W.Wilson@sun.com {
14167736SAndrew.W.Wilson@sun.com 	$$ = $1;
14177736SAndrew.W.Wilson@sun.com }
14187736SAndrew.W.Wilson@sun.com | enable_multi_ops FSK_SEPLST enable_multi_op
14197736SAndrew.W.Wilson@sun.com {
14207736SAndrew.W.Wilson@sun.com 	attr_t *attr = NULL;
14217736SAndrew.W.Wilson@sun.com 	attr_t *list_end = NULL;
14227736SAndrew.W.Wilson@sun.com 
14237736SAndrew.W.Wilson@sun.com 	for (attr = $1; attr != NULL;
14247736SAndrew.W.Wilson@sun.com 	    attr = attr->attr_next)
14257736SAndrew.W.Wilson@sun.com 		list_end = attr; /* Find end of list */
14267736SAndrew.W.Wilson@sun.com 
14277736SAndrew.W.Wilson@sun.com 	list_end->attr_next = $3;
14287736SAndrew.W.Wilson@sun.com 
14297736SAndrew.W.Wilson@sun.com 	$$ = $1;
14307736SAndrew.W.Wilson@sun.com };
14317736SAndrew.W.Wilson@sun.com 
14327736SAndrew.W.Wilson@sun.com enable_multi_op: em_attr_name FSK_ASSIGN attr_value
14337736SAndrew.W.Wilson@sun.com {
14347736SAndrew.W.Wilson@sun.com 	$$ = $3;
14357736SAndrew.W.Wilson@sun.com 	$$->attr_name = $1;
14369326SAndrew.W.Wilson@sun.com };
14377736SAndrew.W.Wilson@sun.com 
14387736SAndrew.W.Wilson@sun.com multisync_op: FSA_VALUE FSK_ASSIGN attr_value
14397736SAndrew.W.Wilson@sun.com {
14407736SAndrew.W.Wilson@sun.com 	$$ = $3;
14417736SAndrew.W.Wilson@sun.com 	$$->attr_name = FSA_VALUE;
14429326SAndrew.W.Wilson@sun.com };
14437736SAndrew.W.Wilson@sun.com 
14446212Saw148015 files_attr_name: attrs_define_file
14456212Saw148015 |attrs_define_fileset;
14466212Saw148015 
14476212Saw148015 pt_attr_name: attrs_define_thread
14486212Saw148015 |attrs_define_proc;
14496212Saw148015 
14506212Saw148015 fo_attr_name: attrs_flowop;
14516212Saw148015 
14526212Saw148015 ev_attr_name: attrs_eventgen;
14535184Sek110237 
14545184Sek110237 attrs_define_proc:
14556212Saw148015   FSA_NICE { $$ = FSA_NICE;}
14566212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
14576212Saw148015 | FSA_INSTANCES { $$ = FSA_INSTANCES;};
14585184Sek110237 
14595184Sek110237 attrs_define_file:
14606212Saw148015   FSA_SIZE { $$ = FSA_SIZE;}
14616212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
14625184Sek110237 | FSA_PATH { $$ = FSA_PATH;}
14639326SAndrew.W.Wilson@sun.com | FSA_READONLY { $$ = FSA_READONLY;}
14649326SAndrew.W.Wilson@sun.com | FSA_TRUSTTREE { $$ = FSA_TRUSTTREE;}
14655184Sek110237 | FSA_REUSE { $$ = FSA_REUSE;}
14665184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;}
14675184Sek110237 | FSA_PARALLOC { $$ = FSA_PARALLOC;};
14685184Sek110237 
14695184Sek110237 attrs_define_fileset:
14706212Saw148015   FSA_SIZE { $$ = FSA_SIZE;}
14716212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
14725184Sek110237 | FSA_PATH { $$ = FSA_PATH;}
14735184Sek110237 | FSA_DIRWIDTH { $$ = FSA_DIRWIDTH;}
14746212Saw148015 | FSA_DIRDEPTHRV { $$ = FSA_DIRDEPTHRV;}
14755184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;}
14768404SAndrew.W.Wilson@sun.com | FSA_PARALLOC { $$ = FSA_PARALLOC;}
14778404SAndrew.W.Wilson@sun.com | FSA_REUSE { $$ = FSA_REUSE;}
14789326SAndrew.W.Wilson@sun.com | FSA_READONLY { $$ = FSA_READONLY;}
14799326SAndrew.W.Wilson@sun.com | FSA_TRUSTTREE { $$ = FSA_TRUSTTREE;}
14805184Sek110237 | FSA_FILESIZEGAMMA { $$ = FSA_FILESIZEGAMMA;}
14815184Sek110237 | FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;}
14825184Sek110237 | FSA_CACHED { $$ = FSA_CACHED;}
14839326SAndrew.W.Wilson@sun.com | FSA_ENTRIES { $$ = FSA_ENTRIES;}
14847946SAndrew.W.Wilson@sun.com | FSA_LEAFDIRS { $$ = FSA_LEAFDIRS;};
14855184Sek110237 
14866212Saw148015 randvar_attr_name:
14876212Saw148015   FSA_NAME { $$ = FSA_NAME;}
14886212Saw148015 | FSA_RANDSEED { $$ = FSA_RANDSEED;}
14896212Saw148015 | FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;}
14906212Saw148015 | FSA_RANDMEAN { $$ = FSA_RANDMEAN;}
14916212Saw148015 | FSA_RANDMIN { $$ = FSA_RANDMIN;}
14926212Saw148015 | FSA_RANDROUND { $$ = FSA_RANDROUND;};
14936212Saw148015 
14946212Saw148015 randvar_attr_tsp:
14956212Saw148015   FSS_TYPE { $$ = FSS_TYPE;}
14966212Saw148015 | FSS_SRC { $$ = FSS_SRC;}
14976212Saw148015 | FSS_SEED { $$ = FSS_SEED;}
14986212Saw148015 | FSS_GAMMA { $$ = FSS_GAMMA;}
14996212Saw148015 | FSS_MEAN { $$ = FSS_MEAN;}
15006212Saw148015 | FSS_MIN { $$ = FSS_MIN;}
15016212Saw148015 | FSS_ROUND { $$ = FSS_ROUND;};
15026212Saw148015 
15036212Saw148015 
15046212Saw148015 randvar_attr_param:
15056212Saw148015   FSS_SEED { $$ = FSS_SEED;}
15066212Saw148015 | FSS_GAMMA { $$ = FSS_GAMMA;}
15076212Saw148015 | FSS_MEAN { $$ = FSS_MEAN;}
15086212Saw148015 | FSS_MIN { $$ = FSS_MIN;}
15096212Saw148015 | FSS_ROUND { $$ = FSS_ROUND;};
15106212Saw148015 
15116212Saw148015 randvar_attr_typop: randtype_name
15126212Saw148015 {
15136212Saw148015 	if (($$ = alloc_attr()) == NULL)
15146212Saw148015 		YYERROR;
15156212Saw148015 	$$->attr_avd = avd_int_alloc($1);
15166212Saw148015 };
15176212Saw148015 
15186212Saw148015 randtype_name:
15196212Saw148015   FSV_RANDUNI { $$ = FSV_RANDUNI;}
15206212Saw148015 | FSV_RANDTAB { $$ = FSV_RANDTAB;}
15216212Saw148015 | FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;};
15226212Saw148015 
15236212Saw148015 randvar_attr_srcop: randsrc_name
15246212Saw148015 {
15256212Saw148015 	if (($$ = alloc_attr()) == NULL)
15266212Saw148015 		YYERROR;
15276212Saw148015 	$$->attr_avd = avd_int_alloc($1);
15286212Saw148015 };
15296212Saw148015 
15306212Saw148015 randsrc_name:
15316212Saw148015   FSV_URAND { $$ = FSV_URAND;}
15326212Saw148015 | FSV_RAND48 { $$ = FSV_RAND48;};
15336212Saw148015 
15345184Sek110237 attrs_define_thread:
15356212Saw148015   FSA_PROCESS { $$ = FSA_PROCESS;}
15366212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
15376212Saw148015 | FSA_MEMSIZE { $$ = FSA_MEMSIZE;}
15386212Saw148015 | FSA_USEISM { $$ = FSA_USEISM;}
15396212Saw148015 | FSA_INSTANCES { $$ = FSA_INSTANCES;};
15405184Sek110237 
15415184Sek110237 attrs_flowop:
15426212Saw148015   FSA_WSS { $$ = FSA_WSS;}
15436212Saw148015 | FSA_FILE { $$ = FSA_FILE;}
15446212Saw148015 | FSA_NAME { $$ = FSA_NAME;}
15456212Saw148015 | FSA_RANDOM { $$ = FSA_RANDOM;}
15466212Saw148015 | FSA_FD { $$ = FSA_FD;}
15476212Saw148015 | FSA_SRCFD { $$ = FSA_SRCFD;}
15486212Saw148015 | FSA_ROTATEFD { $$ = FSA_ROTATEFD;}
15496212Saw148015 | FSA_DSYNC { $$ = FSA_DSYNC;}
15506212Saw148015 | FSA_DIRECTIO { $$ = FSA_DIRECTIO;}
15518404SAndrew.W.Wilson@sun.com | FSA_INDEXED { $$ = FSA_INDEXED;}
15526212Saw148015 | FSA_TARGET { $$ = FSA_TARGET;}
15536212Saw148015 | FSA_ITERS { $$ = FSA_ITERS;}
15546212Saw148015 | FSA_VALUE { $$ = FSA_VALUE;}
15556212Saw148015 | FSA_BLOCKING { $$ = FSA_BLOCKING;}
15566212Saw148015 | FSA_HIGHWATER { $$ = FSA_HIGHWATER;}
15576212Saw148015 | FSA_IOSIZE { $$ = FSA_IOSIZE;};
15585184Sek110237 
15595184Sek110237 attrs_eventgen:
15606212Saw148015   FSA_RATE { $$ = FSA_RATE;};
15616212Saw148015 
15627736SAndrew.W.Wilson@sun.com em_attr_name:
15639326SAndrew.W.Wilson@sun.com   FSA_MASTER { $$ = FSA_MASTER;}
15647736SAndrew.W.Wilson@sun.com | FSA_CLIENT { $$ = FSA_CLIENT;};
15657736SAndrew.W.Wilson@sun.com 
15666550Saw148015 comp_attr_ops: comp_attr_op
15676550Saw148015 {
15686550Saw148015 	$$ = $1;
15696550Saw148015 }
15706550Saw148015 | comp_attr_ops FSK_SEPLST comp_attr_op
15716550Saw148015 {
15726550Saw148015 	attr_t *attr = NULL;
15736550Saw148015 	attr_t *list_end = NULL;
15746550Saw148015 
15756550Saw148015 	for (attr = $1; attr != NULL;
15766550Saw148015 	    attr = attr->attr_next)
15776550Saw148015 		list_end = attr; /* Find end of list */
15786550Saw148015 
15796550Saw148015 	list_end->attr_next = $3;
15806550Saw148015 
15816550Saw148015 	$$ = $1;
15826550Saw148015 }
15836550Saw148015 | comp_attr_ops FSK_SEPLST comp_lvar_def
15846550Saw148015 {
15856550Saw148015 	attr_t *attr = NULL;
15866550Saw148015 	attr_t *list_end = NULL;
15876550Saw148015 
15886550Saw148015 	for (attr = $1; attr != NULL;
15896550Saw148015 	    attr = attr->attr_next)
15906550Saw148015 		list_end = attr; /* Find end of list */
15916550Saw148015 
15926550Saw148015 	list_end->attr_next = $3;
15936550Saw148015 
15946550Saw148015 	$$ = $1;
15956550Saw148015 };
15966550Saw148015 
15976550Saw148015 comp_attr_op: attrs_define_comp FSK_ASSIGN attr_value
15986550Saw148015 {
15996550Saw148015 	$$ = $3;
16006550Saw148015 	$$->attr_name = $1;
16016550Saw148015 };
16026550Saw148015 
16036550Saw148015 comp_lvar_def: FSV_VARIABLE FSK_ASSIGN FSV_VAL_BOOLEAN
16046550Saw148015 {
16056550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_boolean($1, $3))) == NULL)
16066550Saw148015 		YYERROR;
16076550Saw148015 }
16086550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
16096550Saw148015 {
16106550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_integer($1, $3))) == NULL)
16116550Saw148015 		YYERROR;
16126550Saw148015 }
16136550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
16146550Saw148015 {
16156550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_string($1, $4))) == NULL)
16166550Saw148015 		YYERROR;
16176550Saw148015 }
16186550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_STRING
16196550Saw148015 {
16206550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_string($1, $3))) == NULL)
16216550Saw148015 		YYERROR;
16226550Saw148015 }
16236550Saw148015 | FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE
16246550Saw148015 {
16256550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_assign_var($1, $3))) == NULL)
16266550Saw148015 		YYERROR;
16276550Saw148015 }
16286550Saw148015 | FSV_VARIABLE
16296550Saw148015 {
16306550Saw148015 	if (($$ = alloc_lvar_attr(var_lvar_alloc_local($1))) == NULL)
16316550Saw148015 		YYERROR;
16326550Saw148015 };
16336550Saw148015 
16346550Saw148015 
16356550Saw148015 attrs_define_comp:
16366550Saw148015   FSA_NAME { $$ = FSA_NAME;}
16376550Saw148015 | FSA_ITERS { $$ = FSA_ITERS;};
16386550Saw148015 
16396212Saw148015 attr_value: FSV_STRING
16406212Saw148015 {
16416212Saw148015 	if (($$ = alloc_attr()) == NULL)
16426212Saw148015 		YYERROR;
16436212Saw148015 	$$->attr_avd = avd_str_alloc($1);
16446212Saw148015 } | FSV_VAL_INT {
16456212Saw148015 	if (($$ = alloc_attr()) == NULL)
16466212Saw148015 		YYERROR;
16476212Saw148015 	$$->attr_avd = avd_int_alloc($1);
16486212Saw148015 } | FSV_VAL_BOOLEAN {
16496212Saw148015 	if (($$ = alloc_attr()) == NULL)
16506212Saw148015 		YYERROR;
16516212Saw148015 	$$->attr_avd = avd_bool_alloc($1);
16526212Saw148015 } | FSV_VARIABLE {
16536212Saw148015 	if (($$ = alloc_attr()) == NULL)
16546212Saw148015 		YYERROR;
16556212Saw148015 	$$->attr_avd = var_ref_attr($1);
16566212Saw148015 };
16576212Saw148015 
16586212Saw148015 attr_list_value: var_string_list {
16595184Sek110237 	if (($$ = alloc_attr()) == NULL)
16605184Sek110237 		YYERROR;
16615184Sek110237 	$$->attr_param_list = $1;
16628404SAndrew.W.Wilson@sun.com } | FSV_STRING {
16635184Sek110237 	if (($$ = alloc_attr()) == NULL)
16645184Sek110237 		YYERROR;
16656212Saw148015 	$$->attr_avd = avd_str_alloc($1);
16665184Sek110237 } | FSV_VAL_INT {
16675184Sek110237 	if (($$ = alloc_attr()) == NULL)
16685184Sek110237 		YYERROR;
16696212Saw148015 	$$->attr_avd = avd_int_alloc($1);
16706212Saw148015 } | FSV_VAL_BOOLEAN {
16716212Saw148015 	if (($$ = alloc_attr()) == NULL)
16726212Saw148015 		YYERROR;
16736212Saw148015 	$$->attr_avd = avd_bool_alloc($1);
16745184Sek110237 } | FSV_VARIABLE {
16755184Sek110237 	if (($$ = alloc_attr()) == NULL)
16765184Sek110237 		YYERROR;
16776212Saw148015 	$$->attr_avd = var_ref_attr($1);
16786212Saw148015 };
16796212Saw148015 
16806212Saw148015 var_int_val: FSV_VAL_INT
16816212Saw148015 {
16826212Saw148015 	$$ = avd_int_alloc($1);
16836212Saw148015 } | FSV_VARIABLE
16846212Saw148015 {
16856212Saw148015 	$$ = var_ref_attr($1);
16865184Sek110237 };
16875184Sek110237 
16885184Sek110237 %%
16895184Sek110237 
16905184Sek110237 /*
16915184Sek110237  *  The following 'c' routines implement the various commands defined in the
16925184Sek110237  * above yacc parser code. The yacc portion checks the syntax of the commands
16935184Sek110237  * found in a workload file, or typed on interactive command lines, parsing
16945184Sek110237  * the commands' parameters into lists. The lists are then passed in a cmd_t
16955184Sek110237  * struct for each command to its related routine in the following section
16965184Sek110237  * for actual execution. This section also includes a few utility routines
16975184Sek110237  * and the main entry point for the program.
16985184Sek110237  */
16995184Sek110237 
17005184Sek110237 /*
17015184Sek110237  * Entry point for filebench. Processes command line arguements. The -f
17025184Sek110237  * option will read in a workload file (the full name and extension must
17035184Sek110237  * must be given). The -a, -s, -m and -i options are used by worker process
17045184Sek110237  * to receive their name, the base address of shared memory, its path, and
17055184Sek110237  * the process' instance number, respectively. This information is supplied
17065184Sek110237  * by the master process when it execs worker processes under the process
17075184Sek110237  * model of execution. If the worker process arguments are passed then main
17085184Sek110237  * will call the procflow_exec routine which creates worker threadflows and
17095184Sek110237  * flowops and executes the procflow's portion of the workload model until
17105184Sek110237  * completion. If worker process arguments are not passed to the process,
17115184Sek110237  * then it becomes the master process for a filebench run. It initializes
17125184Sek110237  * the various filebench components and either executes the supplied workload
17135184Sek110237  * file, or enters interactive mode.
17145184Sek110237  */
17155184Sek110237 
17165184Sek110237 int
17175184Sek110237 main(int argc, char *argv[])
17185184Sek110237 {
17195184Sek110237 	int opt;
17205184Sek110237 	int docmd = FS_FALSE;
17215184Sek110237 	int instance;
17225184Sek110237 	char procname[128];
17235184Sek110237 	caddr_t shmaddr;
17245184Sek110237 	char dir[MAXPATHLEN];
17255184Sek110237 #ifdef HAVE_SETRLIMIT
17265184Sek110237 	struct rlimit rlp;
17275184Sek110237 #endif
17285184Sek110237 #ifdef HAVE_LIBTECLA
17295184Sek110237 	char *line;
17305184Sek110237 #else
17315184Sek110237 	char line[1024];
17325184Sek110237 #endif
17335184Sek110237 	char shmpathtmp[1024];
17345184Sek110237 
17355184Sek110237 #ifdef HAVE_SETRLIMIT
17365184Sek110237 	/* Set resource limits */
17375184Sek110237 	(void) getrlimit(RLIMIT_NOFILE, &rlp);
17385184Sek110237 	rlp.rlim_cur = rlp.rlim_max;
17395184Sek110237 	setrlimit(RLIMIT_NOFILE, &rlp);
17405184Sek110237 #endif
17415184Sek110237 
17425184Sek110237 	yydebug = 0;
17435184Sek110237 	execname = argv[0];
17445184Sek110237 	*procname = 0;
17455184Sek110237 	cwd = getcwd(dir, MAXPATHLEN);
17465184Sek110237 
17475184Sek110237 	while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) {
17485184Sek110237 
17495184Sek110237 		switch (opt) {
17505184Sek110237 		case 'h':
17515184Sek110237 			usage(2);
17525184Sek110237 			break;
17535184Sek110237 
17545184Sek110237 		case 'p':
17555184Sek110237 			noproc = 1;
17565184Sek110237 			break;
17575184Sek110237 
17585184Sek110237 		case 'f':
17595184Sek110237 			if (optarg == NULL)
17605184Sek110237 				usage(1);
17615184Sek110237 			if ((yyin = fopen(optarg, "r")) == NULL) {
17625184Sek110237 				(void) fprintf(stderr,
17635184Sek110237 				    "Cannot open file %s", optarg);
17645184Sek110237 				exit(1);
17655184Sek110237 			}
17665184Sek110237 			dofile = FS_TRUE;
17675184Sek110237 			fscriptname = optarg;
17685184Sek110237 
17695184Sek110237 			break;
17705184Sek110237 
17715184Sek110237 		case 'a':
17725184Sek110237 			if (optarg == NULL)
17735184Sek110237 				usage(1);
17745184Sek110237 			sscanf(optarg, "%s", &procname[0]);
17755184Sek110237 			break;
17765184Sek110237 
17775184Sek110237 		case 's':
17785184Sek110237 			if (optarg == NULL)
17795184Sek110237 				usage(1);
17805184Sek110237 #if defined(_LP64) || (__WORDSIZE == 64)
17815184Sek110237 			sscanf(optarg, "%llx", &shmaddr);
17825184Sek110237 #else
17835184Sek110237 			sscanf(optarg, "%x", &shmaddr);
17845184Sek110237 #endif
17855184Sek110237 			break;
17865184Sek110237 
17875184Sek110237 		case 'm':
17885184Sek110237 			if (optarg == NULL)
17895184Sek110237 				usage(1);
17905184Sek110237 			sscanf(optarg, "%s", shmpathtmp);
17915184Sek110237 			shmpath = shmpathtmp;
17925184Sek110237 			break;
17935184Sek110237 
17945184Sek110237 		case 'i':
17955184Sek110237 			if (optarg == NULL)
17965184Sek110237 				usage(1);
17975184Sek110237 			sscanf(optarg, "%d", &instance);
17985184Sek110237 			break;
17995184Sek110237 
18005184Sek110237 		case '?':
18015184Sek110237 		default:
18025184Sek110237 			usage(1);
18035184Sek110237 			break;
18045184Sek110237 		}
18055184Sek110237 	}
18065184Sek110237 
18075184Sek110237 #ifdef USE_PROCESS_MODEL
18085184Sek110237 	if (!(*procname))
18095184Sek110237 #endif
18105184Sek110237 	printf("FileBench Version %s\n", FILEBENCH_VERSION);
18115184Sek110237 	filebench_init();
18125184Sek110237 
18136084Saw148015 	/* get process pid for use with message logging */
18146084Saw148015 	my_pid = getpid();
18156084Saw148015 
18165184Sek110237 #ifdef USE_PROCESS_MODEL
18175184Sek110237 	if (*procname) {
18186084Saw148015 		/* A child FileBench instance */
18195184Sek110237 		if (ipc_attach(shmaddr) < 0) {
18205184Sek110237 			filebench_log(LOG_ERROR, "Cannot attach shm for %s",
18215184Sek110237 			    procname);
18225184Sek110237 			exit(1);
18235184Sek110237 		}
18245184Sek110237 
18258615SAndrew.W.Wilson@sun.com 		/* get correct function pointer for each child process */
18268615SAndrew.W.Wilson@sun.com 		filebench_plugin_funcvecinit();
18278615SAndrew.W.Wilson@sun.com 
18286212Saw148015 		if (procflow_exec(procname, instance) < 0) {
18296212Saw148015 			filebench_log(LOG_ERROR, "Cannot startup process %s",
18306212Saw148015 			    procname);
18315184Sek110237 			exit(1);
18326212Saw148015 		}
18336084Saw148015 
18346084Saw148015 		exit(0);
18355184Sek110237 	}
18365184Sek110237 #endif
18375184Sek110237 
18386084Saw148015 	/* master (or only) process */
18395184Sek110237 	ipc_init();
18405184Sek110237 
18415184Sek110237 	if (fscriptname)
18426391Saw148015 		(void) strcpy(filebench_shm->shm_fscriptname, fscriptname);
18435184Sek110237 
18448615SAndrew.W.Wilson@sun.com 	filebench_plugin_funcvecinit();
18455184Sek110237 	flowop_init();
18465184Sek110237 	stats_init();
18475184Sek110237 	eventgen_init();
18485184Sek110237 
18495184Sek110237 	signal(SIGINT, parser_abort);
18505184Sek110237 
18515184Sek110237 	if (dofile)
18525184Sek110237 		yyparse();
18535184Sek110237 	else {
18545184Sek110237 #ifdef HAVE_LIBTECLA
18555184Sek110237 		if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) {
18565184Sek110237 			filebench_log(LOG_ERROR,
18575184Sek110237 			    "Failed to create GetLine object");
18585184Sek110237 			filebench_shutdown(1);
18595184Sek110237 		}
18605184Sek110237 
18615184Sek110237 		if (gl_customize_completion(gl, NULL, command_complete)) {
18625184Sek110237 			filebench_log(LOG_ERROR,
18635184Sek110237 			    "Failed to register auto-completion function");
18645184Sek110237 			filebench_shutdown(1);
18655184Sek110237 		}
18665184Sek110237 
18675184Sek110237 		while (line = gl_get_line(gl, FILEBENCH_PROMPT, NULL, -1)) {
18685184Sek110237 			arg_parse(line);
18695184Sek110237 			yyparse();
18705184Sek110237 		}
18715184Sek110237 
18725184Sek110237 		del_GetLine(gl);
18735184Sek110237 #else
18745184Sek110237 		while (!feof(stdin)) {
18755184Sek110237 			printf(FILEBENCH_PROMPT);
18765184Sek110237 			fflush(stdout);
18775184Sek110237 			if (fgets(line, sizeof (line), stdin) == NULL) {
18785184Sek110237 				if (errno == EINTR)
18795184Sek110237 					continue;
18805184Sek110237 				else
18815184Sek110237 					break;
18825184Sek110237 			}
18835184Sek110237 			arg_parse(line);
18845184Sek110237 			yyparse();
18855184Sek110237 		}
18865184Sek110237 		printf("\n");
18875184Sek110237 #endif	/* HAVE_LIBTECLA */
18885184Sek110237 	}
18895184Sek110237 
18905184Sek110237 	parser_filebench_shutdown((cmd_t *)0);
18915184Sek110237 
18925184Sek110237 	return (0);
18935184Sek110237 }
18945184Sek110237 
18955184Sek110237 /*
18965184Sek110237  * arg_parse() puts the parser into command parsing mode. Create a tmpfile
18975184Sek110237  * and instruct the parser to read instructions from this location by setting
18985184Sek110237  * yyin to the value returned by tmpfile. Write the command into the file.
18995184Sek110237  * Then seek back to to the start of the file so that the parser can read
19005184Sek110237  * the instructions.
19015184Sek110237  */
19025184Sek110237 static void
19035184Sek110237 arg_parse(const char *command)
19045184Sek110237 {
19056750Sek110237 	if ((yyin = tmpfile()) == NULL) {
19065184Sek110237 		filebench_log(LOG_FATAL,
19076750Sek110237 		    "Exiting: Cannot create tmpfile: %s", strerror(errno));
19086750Sek110237 		exit(1);
19096750Sek110237 	}
19105184Sek110237 
19115184Sek110237 	if (fwrite(command, strlen(command), 1, yyin) != 1)
19125184Sek110237 		filebench_log(LOG_FATAL,
19135184Sek110237 		    "Cannot write tmpfile: %s", strerror(errno));
19145184Sek110237 
19155184Sek110237 	if (fseek(yyin, 0, SEEK_SET) != 0)
19165184Sek110237 		filebench_log(LOG_FATAL,
19175184Sek110237 		    "Cannot seek tmpfile: %s", strerror(errno));
19185184Sek110237 }
19195184Sek110237 
19205184Sek110237 /*
19215184Sek110237  * Converts a list of var_strings or ordinary strings to a single ordinary
19225184Sek110237  * string. It returns a pointer to the string (in malloc'd memory) if found,
19235184Sek110237  * or NULL otherwise.
19245184Sek110237  */
19255184Sek110237 char *
19265184Sek110237 parser_list2string(list_t *list)
19275184Sek110237 {
19285184Sek110237 	list_t *l;
19295184Sek110237 	char *string;
19305184Sek110237 	char *tmp;
19316212Saw148015 	fbint_t *integer;
19325184Sek110237 	if ((string = malloc(MAXPATHLEN)) == NULL) {
19335184Sek110237 		filebench_log(LOG_ERROR, "Failed to allocate memory");
19345184Sek110237 		return (NULL);
19355184Sek110237 	}
19365184Sek110237 
19375184Sek110237 	*string = 0;
19385184Sek110237 
19398404SAndrew.W.Wilson@sun.com 	/*	printf("parser_list2string: called\n"); */
19405184Sek110237 	/* Format args */
19416212Saw148015 	for (l = list; l != NULL; l = l->list_next) {
19426212Saw148015 		char *lstr = avd_get_str(l->list_string);
19436212Saw148015 
19445184Sek110237 		filebench_log(LOG_DEBUG_SCRIPT,
19456212Saw148015 		    "converting string '%s'", lstr);
19466212Saw148015 
19476212Saw148015 		/* see if it is a random variable */
19486212Saw148015 		if (l->list_integer) {
19496212Saw148015 			fbint_t param_name;
19506212Saw148015 
19516212Saw148015 			tmp = NULL;
19526212Saw148015 			param_name = avd_get_int(l->list_integer);
19536212Saw148015 			switch (param_name) {
19546212Saw148015 			case FSS_TYPE:
19556212Saw148015 				tmp = var_randvar_to_string(lstr,
19566212Saw148015 				    RAND_PARAM_TYPE);
19576212Saw148015 				break;
19586212Saw148015 
19596212Saw148015 			case FSS_SRC:
19606212Saw148015 				tmp = var_randvar_to_string(lstr,
19616212Saw148015 				    RAND_PARAM_SRC);
19626212Saw148015 				break;
19636212Saw148015 
19646212Saw148015 			case FSS_SEED:
19656212Saw148015 				tmp = var_randvar_to_string(lstr,
19666212Saw148015 				    RAND_PARAM_SEED);
19676212Saw148015 				break;
19686212Saw148015 
19696212Saw148015 			case FSS_MIN:
19706212Saw148015 				tmp = var_randvar_to_string(lstr,
19716212Saw148015 				    RAND_PARAM_MIN);
19726212Saw148015 				break;
19736212Saw148015 
19746212Saw148015 			case FSS_MEAN:
19756212Saw148015 				tmp = var_randvar_to_string(lstr,
19766212Saw148015 				    RAND_PARAM_MEAN);
19776212Saw148015 				break;
19786212Saw148015 
19796212Saw148015 			case FSS_GAMMA:
19806212Saw148015 				tmp = var_randvar_to_string(lstr,
19816212Saw148015 				    RAND_PARAM_GAMMA);
19826212Saw148015 				break;
19836212Saw148015 
19846212Saw148015 			case FSS_ROUND:
19856212Saw148015 				tmp = var_randvar_to_string(lstr,
19866212Saw148015 				    RAND_PARAM_ROUND);
19876212Saw148015 				break;
19886212Saw148015 			}
19896212Saw148015 
19906212Saw148015 			if (tmp) {
19916212Saw148015 				(void) strcat(string, tmp);
19926212Saw148015 				free(tmp);
19936212Saw148015 			} else {
19946212Saw148015 				(void) strcat(string, lstr);
19956212Saw148015 			}
19965184Sek110237 		} else {
19976212Saw148015 			/* perhaps a normal variable? */
19986212Saw148015 			if ((tmp = var_to_string(lstr)) != NULL) {
19996212Saw148015 				(void) strcat(string, tmp);
20006212Saw148015 				free(tmp);
20016212Saw148015 			} else {
20026212Saw148015 				(void) strcat(string, lstr);
20036212Saw148015 			}
20045184Sek110237 		}
20055184Sek110237 	}
20065184Sek110237 	return (string);
20075184Sek110237 }
20085184Sek110237 
20095184Sek110237 /*
20105184Sek110237  * If the list just contains a single string starting with '$', then find
20115184Sek110237  * or create the named var and return the var's var_string component.
20125184Sek110237  * Otherwise, convert the list to a string, and allocate a var_string
20135184Sek110237  * containing a copy of that string. On failure either returns NULL
20145184Sek110237  * or shuts down the run.
20155184Sek110237  */
20166212Saw148015 avd_t
20175184Sek110237 parser_list2varstring(list_t *list)
20185184Sek110237 {
20196212Saw148015 	char *lstr = avd_get_str(list->list_string);
20206212Saw148015 
20218404SAndrew.W.Wilson@sun.com 	/*	printf("parser_list2varstring: Called\n"); */
20225184Sek110237 	/* Special case - variable name */
20236212Saw148015 	if ((list->list_next == NULL) && (*lstr == '$'))
20246212Saw148015 		return (var_ref_attr(lstr));
20256212Saw148015 
20266212Saw148015 	return (avd_str_alloc(parser_list2string(list)));
20275184Sek110237 }
20285184Sek110237 
20295184Sek110237 /*
20305184Sek110237  * Looks for the var named in list_string of the first element of the
20316212Saw148015  * supplied list. If found, returns the var_val portion of the var in
20326212Saw148015  * an attribute value descriptor. If the var is not found, cannot be
20336212Saw148015  * allocated, the supplied list is NULL, or the list_string filed is
20346212Saw148015  * empty, returns NULL.
20355184Sek110237  */
20366212Saw148015 avd_t
20376212Saw148015 parser_list2avd(list_t *list)
20385184Sek110237 {
20396212Saw148015 	avd_t avd;
20406212Saw148015 	char *lstr;
20416212Saw148015 
20426212Saw148015 	if (list && ((lstr = avd_get_str(list->list_string)) != NULL)) {
20436212Saw148015 		avd = var_ref_attr(lstr);
20446212Saw148015 		return (avd);
20455184Sek110237 	}
20465184Sek110237 
20475184Sek110237 	return (NULL);
20485184Sek110237 }
20495184Sek110237 
20505184Sek110237 /*
20515184Sek110237  * Sets the event generator rate from the attribute supplied with the
20525184Sek110237  * command. If the attribute doesn't exist the routine does nothing.
20535184Sek110237  */
20545184Sek110237 static void
20555184Sek110237 parser_eventgen(cmd_t *cmd)
20565184Sek110237 {
20575184Sek110237 	attr_t *attr;
20585184Sek110237 
20595184Sek110237 	/* Get the rate from attribute */
20605184Sek110237 	if (attr = get_attr_integer(cmd, FSA_RATE)) {
20616212Saw148015 		if (attr->attr_avd) {
20627946SAndrew.W.Wilson@sun.com 			eventgen_setrate(attr->attr_avd);
20635184Sek110237 		}
20645184Sek110237 	}
20655184Sek110237 }
20665184Sek110237 
20675184Sek110237 /*
20685184Sek110237  * Assigns the designated integer variable successive values from the
20695184Sek110237  * supplied comma seperated integer list. After each successive integer
20705184Sek110237  * assignment, it executes the bracket enclosed list of commands. For
20715184Sek110237  * example, repeated runs of a workload with increasing io sizes can
20725184Sek110237  * be done using the following command line:
20735184Sek110237  * 	foreach $iosize in 2k, 4k, 8k {run 60}
20745184Sek110237  */
20755184Sek110237 static void
20765184Sek110237 parser_foreach_integer(cmd_t *cmd)
20775184Sek110237 {
20785184Sek110237 	list_t *list = cmd->cmd_param_list;
20795184Sek110237 	cmd_t *inner_cmd;
20805184Sek110237 
20815184Sek110237 	for (; list != NULL; list = list->list_next) {
20826212Saw148015 		fbint_t list_int = avd_get_int(list->list_integer);
20836212Saw148015 
20846212Saw148015 		var_assign_integer(cmd->cmd_tgt1, list_int);
20856286Saw148015 		filebench_log(LOG_VERBOSE, "Iterating %s=%llu",
20866286Saw148015 		    cmd->cmd_tgt1, (u_longlong_t)list_int);
20875184Sek110237 		for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
20885184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
20895184Sek110237 			inner_cmd->cmd(inner_cmd);
20905184Sek110237 		}
20915184Sek110237 	}
20925184Sek110237 }
20935184Sek110237 
20945184Sek110237 /*
20955184Sek110237  * Similar to parser_foreach_integer(), except takes a list of strings after
20965184Sek110237  * the "in" token. For example, to run twice using a different directory,
20975184Sek110237  * perhaps using a different filesystem, the following command line
20985184Sek110237  * could be used:
20995184Sek110237  * 	foreach $dir in "/ufs_top/fbt", "/zfs_top/fbt" {run 60)
21005184Sek110237  */
21015184Sek110237 static void
21025184Sek110237 parser_foreach_string(cmd_t *cmd)
21035184Sek110237 {
21045184Sek110237 	list_t *list = cmd->cmd_param_list;
21055184Sek110237 
21065184Sek110237 	for (; list != NULL; list = list->list_next) {
21076212Saw148015 		cmd_t *inner_cmd;
21086212Saw148015 		char *lstr = avd_get_str(list->list_string);
21096212Saw148015 		var_assign_string(cmd->cmd_tgt1, lstr);
21105184Sek110237 		filebench_log(LOG_VERBOSE, "Iterating %s=%s",
21116212Saw148015 		    cmd->cmd_tgt1, lstr);
21125184Sek110237 		for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
21135184Sek110237 		    inner_cmd = inner_cmd->cmd_next) {
21145184Sek110237 			inner_cmd->cmd(inner_cmd);
21155184Sek110237 		}
21165184Sek110237 	}
21175184Sek110237 }
21185184Sek110237 
21195184Sek110237 /*
21205673Saw148015  * Lists the fileset name, path name and average size for all defined
21215673Saw148015  * filesets.
21225184Sek110237  */
21235184Sek110237 static void
21245184Sek110237 parser_list(cmd_t *cmd)
21255184Sek110237 {
21265673Saw148015 	(void) fileset_iter(fileset_print);
21275184Sek110237 }
21285184Sek110237 
21295184Sek110237 /*
21306212Saw148015  * Lists the flowop name and instance number for all flowops.
21316212Saw148015  */
21326212Saw148015 static void
21336212Saw148015 parser_flowop_list(cmd_t *cmd)
21346212Saw148015 {
21356212Saw148015 	flowop_printall();
21366212Saw148015 }
21376212Saw148015 
21386212Saw148015 /*
21395184Sek110237  * Calls procflow_define() to allocate "instances" number of  procflow(s)
21405184Sek110237  * (processes) with the supplied name. The default number of instances is
21415184Sek110237  * one. An optional priority level attribute can be supplied and is stored in
21425184Sek110237  * pf_nice. Finally the routine loops through the list of inner commands, if
21435184Sek110237  * any, which are defines for threadflows, and passes them one at a time to
21445184Sek110237  * parser_thread_define() to allocate threadflow entities for the process(es).
21455184Sek110237  */
21465184Sek110237 static void
21475184Sek110237 parser_proc_define(cmd_t *cmd)
21485184Sek110237 {
21495184Sek110237 	procflow_t *procflow, template;
21505184Sek110237 	char *name;
21515184Sek110237 	attr_t *attr;
21526212Saw148015 	avd_t var_instances;
21536212Saw148015 	fbint_t instances;
21545184Sek110237 	cmd_t *inner_cmd;
21555184Sek110237 
21565184Sek110237 	/* Get the name of the process */
21575184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
21586212Saw148015 		name = avd_get_str(attr->attr_avd);
21595184Sek110237 	} else {
21605184Sek110237 		filebench_log(LOG_ERROR,
21615184Sek110237 		    "define proc: proc specifies no name");
21625184Sek110237 		filebench_shutdown(1);
21635184Sek110237 	}
21645184Sek110237 
21655184Sek110237 	/* Get the memory size from attribute */
21665184Sek110237 	if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
21676212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
21686212Saw148015 			filebench_log(LOG_ERROR,
21696212Saw148015 			    "proc_define: Instances attr cannot be random");
21706212Saw148015 			filebench_shutdown(1);
21716212Saw148015 		}
21726212Saw148015 		var_instances = attr->attr_avd;
21736212Saw148015 		instances = avd_get_int(var_instances);
21745184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
21756286Saw148015 		    "Setting instances = %llu", (u_longlong_t)instances);
21766212Saw148015 	} else {
21776212Saw148015 		filebench_log(LOG_DEBUG_IMPL,
21786212Saw148015 		    "Defaulting to instances = 1");
21796212Saw148015 		var_instances = avd_int_alloc(1);
21806212Saw148015 		instances = 1;
21815184Sek110237 	}
21825184Sek110237 
21836212Saw148015 	if ((procflow = procflow_define(name, NULL, var_instances)) == NULL) {
21845184Sek110237 		filebench_log(LOG_ERROR,
21855184Sek110237 		    "Failed to instantiate %d %s process(es)\n",
21865184Sek110237 		    instances, name);
21875184Sek110237 		filebench_shutdown(1);
21885184Sek110237 	}
21895184Sek110237 
21905184Sek110237 	/* Get the pri from attribute */
21915184Sek110237 	if (attr = get_attr_integer(cmd, FSA_NICE)) {
21926212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
21936212Saw148015 			filebench_log(LOG_ERROR,
21946212Saw148015 			    "proc_define: priority cannot be random");
21956212Saw148015 			filebench_shutdown(1);
21966212Saw148015 		}
21976286Saw148015 		filebench_log(LOG_DEBUG_IMPL, "Setting pri = %llu",
21986286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
21996212Saw148015 		procflow->pf_nice = attr->attr_avd;
22005184Sek110237 	} else
22016212Saw148015 		procflow->pf_nice = avd_int_alloc(0);
22025184Sek110237 
22035184Sek110237 
22045184Sek110237 	/* Create the list of threads for this process  */
22055184Sek110237 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
22065184Sek110237 	    inner_cmd = inner_cmd->cmd_next) {
22076212Saw148015 		parser_thread_define(inner_cmd, procflow, instances);
22085184Sek110237 	}
22095184Sek110237 }
22105184Sek110237 
22115184Sek110237 /*
22125184Sek110237  * Calls threadflow_define() to allocate "instances" number of  threadflow(s)
22135184Sek110237  * (threads) with the supplied name. The default number of instances is
22145184Sek110237  * one. Two other optional attributes may be supplied, one to set the memory
22155184Sek110237  * size, stored in tf_memsize, and to select the use of Interprocess Shared
22165184Sek110237  * Memory, which sets the THREADFLOW_USEISM flag in tf_attrs. Finally
22175184Sek110237  * the routine loops through the list of inner commands, if any, which are
22185184Sek110237  * defines for flowops, and passes them one at a time to
22195184Sek110237  * parser_flowop_define() to allocate flowop entities for the threadflows.
22205184Sek110237  */
22215184Sek110237 static void
22225184Sek110237 parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
22235184Sek110237 {
22245184Sek110237 	threadflow_t *threadflow, template;
22255184Sek110237 	attr_t *attr;
22266212Saw148015 	avd_t instances;
22275184Sek110237 	cmd_t *inner_cmd;
22285184Sek110237 	char *name;
22295184Sek110237 
22305184Sek110237 	memset(&template, 0, sizeof (threadflow_t));
22315184Sek110237 
22325184Sek110237 	/* Get the name of the thread */
22335184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
22346212Saw148015 		name = avd_get_str(attr->attr_avd);
22355184Sek110237 	} else {
22365184Sek110237 		filebench_log(LOG_ERROR,
22375184Sek110237 		    "define thread: thread in process %s specifies no name",
22385184Sek110237 		    procflow->pf_name);
22395184Sek110237 		filebench_shutdown(1);
22405184Sek110237 	}
22415184Sek110237 
22425184Sek110237 	/* Get the number of instances from attribute */
22435184Sek110237 	if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
22446212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
22456212Saw148015 			filebench_log(LOG_ERROR,
22466212Saw148015 			    "define thread: Instances attr cannot be random");
22476212Saw148015 			filebench_shutdown(1);
22486212Saw148015 		}
22495184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
22506286Saw148015 		    "define thread: Setting instances = %llu",
22516286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
22526212Saw148015 		instances = attr->attr_avd;
22536212Saw148015 	} else
22546212Saw148015 		instances = avd_int_alloc(1);
22555184Sek110237 
22565184Sek110237 	/* Get the memory size from attribute */
22575184Sek110237 	if (attr = get_attr_integer(cmd, FSA_MEMSIZE)) {
22586212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
22596212Saw148015 			filebench_log(LOG_ERROR,
22606212Saw148015 			    "define thread: Memory size cannot be random");
22616212Saw148015 			filebench_shutdown(1);
22626212Saw148015 		}
22635184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
22646286Saw148015 		    "define thread: Setting memsize = %llu",
22656286Saw148015 		    (u_longlong_t)avd_get_int(attr->attr_avd));
22666212Saw148015 		template.tf_memsize = attr->attr_avd;
22675184Sek110237 	} else
22686212Saw148015 		template.tf_memsize = avd_int_alloc(0);
22695184Sek110237 
22705184Sek110237 	if ((threadflow = threadflow_define(procflow, name,
22715184Sek110237 	    &template, instances)) == NULL) {
22725184Sek110237 		filebench_log(LOG_ERROR,
22735184Sek110237 		    "define thread: Failed to instantiate thread\n");
22745184Sek110237 		filebench_shutdown(1);
22755184Sek110237 	}
22765184Sek110237 
22775184Sek110237 	/* Use ISM Memory? */
22785184Sek110237 	if (attr = get_attr(cmd, FSA_USEISM)) {
22795184Sek110237 		threadflow->tf_attrs |= THREADFLOW_USEISM;
22805184Sek110237 	}
22815184Sek110237 
22825184Sek110237 	/* Create the list of flowops */
22835184Sek110237 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
22845184Sek110237 	    inner_cmd = inner_cmd->cmd_next) {
22856212Saw148015 		parser_flowop_define(inner_cmd, threadflow,
22866550Saw148015 		    &threadflow->tf_thrd_fops, FLOW_MASTER);
22875184Sek110237 	}
22885184Sek110237 }
22895184Sek110237 
22905184Sek110237 /*
22918404SAndrew.W.Wilson@sun.com  * Fills in the attributes for a newly allocated flowop
22926212Saw148015  */
22936212Saw148015 static void
22946212Saw148015 parser_flowop_get_attrs(cmd_t *cmd, flowop_t *flowop)
22956212Saw148015 {
22966212Saw148015 	attr_t *attr;
22976212Saw148015 
22986212Saw148015 	/* Get the filename from attribute */
22996212Saw148015 	if (attr = get_attr(cmd, FSA_FILE)) {
23006212Saw148015 		flowop->fo_filename = attr->attr_avd;
23016212Saw148015 		if (flowop->fo_filename == NULL) {
23026212Saw148015 			filebench_log(LOG_ERROR,
23036212Saw148015 			    "define flowop: no filename specfied");
23046212Saw148015 			filebench_shutdown(1);
23056212Saw148015 		}
23069326SAndrew.W.Wilson@sun.com 	} else {
23079326SAndrew.W.Wilson@sun.com 		/* no filename attribute specified */
23089326SAndrew.W.Wilson@sun.com 		flowop->fo_filename = NULL;
23096212Saw148015 	}
23106212Saw148015 
23116212Saw148015 	/* Get the iosize of the op */
23126212Saw148015 	if (attr = get_attr_integer(cmd, FSA_IOSIZE))
23136212Saw148015 		flowop->fo_iosize = attr->attr_avd;
23146212Saw148015 	else
23156212Saw148015 		flowop->fo_iosize = avd_int_alloc(0);
23166212Saw148015 
23176212Saw148015 	/* Get the working set size of the op */
23186212Saw148015 	if (attr = get_attr_integer(cmd, FSA_WSS))
23196212Saw148015 		flowop->fo_wss = attr->attr_avd;
23206212Saw148015 	else
23216212Saw148015 		flowop->fo_wss = avd_int_alloc(0);
23226212Saw148015 
23236212Saw148015 	/* Random I/O? */
23246212Saw148015 	if (attr = get_attr_bool(cmd, FSA_RANDOM))
23256212Saw148015 		flowop->fo_random = attr->attr_avd;
23266212Saw148015 	else
23276212Saw148015 		flowop->fo_random = avd_bool_alloc(FALSE);
23286212Saw148015 
23296212Saw148015 	/* Sync I/O? */
23306212Saw148015 	if (attr = get_attr_bool(cmd, FSA_DSYNC))
23316212Saw148015 		flowop->fo_dsync = attr->attr_avd;
23326212Saw148015 	else
23336212Saw148015 		flowop->fo_dsync = avd_bool_alloc(FALSE);
23346212Saw148015 
23356212Saw148015 	/* Target, for wakeup etc */
23366212Saw148015 	if (attr = get_attr(cmd, FSA_TARGET))
23376212Saw148015 		(void) strcpy(flowop->fo_targetname,
23386212Saw148015 		    avd_get_str(attr->attr_avd));
23396212Saw148015 
23406212Saw148015 	/* Value */
23416212Saw148015 	if (attr = get_attr_integer(cmd, FSA_VALUE))
23426212Saw148015 		flowop->fo_value = attr->attr_avd;
23436212Saw148015 	else
23446212Saw148015 		flowop->fo_value = avd_int_alloc(0);
23456212Saw148015 
23466212Saw148015 	/* FD */
23479326SAndrew.W.Wilson@sun.com 	if (attr = get_attr_integer(cmd, FSA_FD)) {
23486212Saw148015 		flowop->fo_fdnumber = avd_get_int(attr->attr_avd);
23499326SAndrew.W.Wilson@sun.com 		if (flowop->fo_filename != NULL)
23509326SAndrew.W.Wilson@sun.com 			filebench_log(LOG_DEBUG_SCRIPT, "It is not "
23519326SAndrew.W.Wilson@sun.com 			    "advisable to supply both an fd number "
23529326SAndrew.W.Wilson@sun.com 			    "and a fileset name in most cases");
23539326SAndrew.W.Wilson@sun.com 	}
23546212Saw148015 
23556212Saw148015 	/* Rotatefd? */
23566212Saw148015 	if (attr = get_attr_bool(cmd, FSA_ROTATEFD))
23576212Saw148015 		flowop->fo_rotatefd = attr->attr_avd;
23586212Saw148015 	else
23596212Saw148015 		flowop->fo_rotatefd = avd_bool_alloc(FALSE);
23606212Saw148015 
23616212Saw148015 	/* SRC FD, for copies etc... */
23626212Saw148015 	if (attr = get_attr_integer(cmd, FSA_SRCFD))
23636212Saw148015 		flowop->fo_srcfdnumber = avd_get_int(attr->attr_avd);
23646212Saw148015 
23656212Saw148015 	/* Blocking operation? */
23666212Saw148015 	if (attr = get_attr_bool(cmd, FSA_BLOCKING))
23676212Saw148015 		flowop->fo_blocking = attr->attr_avd;
23686212Saw148015 	else
23696212Saw148015 		flowop->fo_blocking = avd_bool_alloc(FALSE);
23706212Saw148015 
23716212Saw148015 	/* Direct I/O Operation */
23726212Saw148015 	if (attr = get_attr_bool(cmd, FSA_DIRECTIO))
23736212Saw148015 		flowop->fo_directio = attr->attr_avd;
23746212Saw148015 	else
23756212Saw148015 		flowop->fo_directio = avd_bool_alloc(FALSE);
23766212Saw148015 
23776212Saw148015 	/* Highwater mark */
23786212Saw148015 	if (attr = get_attr_integer(cmd, FSA_HIGHWATER)) {
23796212Saw148015 		flowop->fo_highwater = attr->attr_avd;
23806212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
23816212Saw148015 			filebench_log(LOG_ERROR,
23826212Saw148015 			    "define flowop: Highwater attr cannot be random");
23836212Saw148015 			filebench_shutdown(1);
23846212Saw148015 		}
23856212Saw148015 	} else {
23866212Saw148015 		flowop->fo_highwater = avd_int_alloc(1);
23876212Saw148015 	}
23888404SAndrew.W.Wilson@sun.com 
23898404SAndrew.W.Wilson@sun.com 	/* find file or leaf directory by index number */
23908404SAndrew.W.Wilson@sun.com 	if (attr = get_attr_integer(cmd, FSA_INDEXED))
23918404SAndrew.W.Wilson@sun.com 		flowop->fo_fileindex = attr->attr_avd;
23928404SAndrew.W.Wilson@sun.com 	else
23938404SAndrew.W.Wilson@sun.com 		flowop->fo_fileindex = NULL;
23946212Saw148015 }
23956212Saw148015 
23966550Saw148015 /*
23976550Saw148015  * defines the FLOW_MASTER flowops within a FLOW_MASTER instance of
23986550Saw148015  * a composit flowop. Default attributes from the FLOW_INNER_DEF instances
23996550Saw148015  * of the composit flowop's inner flowops are used if set. Otherwise
24006550Saw148015  * default attributes from the FLOW_MASTER instance of the composit flowop
24016550Saw148015  * are used, which may include defaults from the original FLOW_DEFINITION
24026550Saw148015  * of the composit flowop.
24036550Saw148015  */
24046550Saw148015 static void
24056550Saw148015 parser_inner_flowop_define(threadflow_t *thread, flowop_t *comp0_flow,
24066550Saw148015 			   flowop_t *comp_mstr_flow)
24076550Saw148015 {
24086550Saw148015 	flowop_t *inner_flowtype, *inner_flowop;
24096550Saw148015 
24106550Saw148015 	/* follow flowop list, creating composit names */
24116550Saw148015 	inner_flowtype = comp0_flow->fo_comp_fops;
24126550Saw148015 	comp_mstr_flow->fo_comp_fops = NULL;
24136550Saw148015 
24146550Saw148015 	while (inner_flowtype) {
24156550Saw148015 		char fullname[MAXPATHLEN];
24166550Saw148015 
24176550Saw148015 		/* create composite_name.name for new flowop */
24186613Sek110237 		snprintf(fullname, MAXPATHLEN, "%s.%s",
24196613Sek110237 		    comp_mstr_flow->fo_name, inner_flowtype->fo_name);
24206550Saw148015 
24216550Saw148015 		if ((inner_flowop = flowop_define(thread, fullname,
24226550Saw148015 		    inner_flowtype, &comp_mstr_flow->fo_comp_fops,
24236550Saw148015 		    FLOW_MASTER, 0)) == NULL) {
24246550Saw148015 			filebench_log(LOG_ERROR,
24256550Saw148015 			    "define flowop: Failed to instantiate flowop %s\n",
24266550Saw148015 			    fullname);
24276550Saw148015 			filebench_shutdown(1);
24286550Saw148015 		}
24296550Saw148015 
24306550Saw148015 		/* if applicable, update filename attribute */
24316550Saw148015 		if (inner_flowop->fo_filename) {
24326550Saw148015 			char *name;
24336550Saw148015 
24346550Saw148015 			/* fix up avd_t */
24356550Saw148015 			avd_update(&inner_flowop->fo_filename,
24366550Saw148015 			    comp_mstr_flow->fo_lvar_list);
24376550Saw148015 
24386550Saw148015 			/* see if ready to get the file or fileset */
24396550Saw148015 			name = avd_get_str(inner_flowop->fo_filename);
24406550Saw148015 			if (name) {
24416550Saw148015 
24426550Saw148015 				inner_flowop->fo_fileset = fileset_find(name);
24436550Saw148015 
24446550Saw148015 				if (inner_flowop->fo_fileset == NULL) {
24456550Saw148015 					filebench_log(LOG_ERROR,
24466550Saw148015 					    "inr flowop %s: file %s not found",
24476550Saw148015 					    inner_flowop->fo_name, name);
24486550Saw148015 					filebench_shutdown(1);
24496550Saw148015 				}
24506550Saw148015 			}
24516550Saw148015 		}
24526550Saw148015 
24536550Saw148015 		/* update attributes from local variables */
24546550Saw148015 		avd_update(&inner_flowop->fo_iters,
24556550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24566550Saw148015 
24576550Saw148015 		/* if the inner flowop is a composit flowop, recurse */
24586550Saw148015 		if (inner_flowtype->fo_type == FLOW_TYPE_COMPOSITE) {
24596550Saw148015 			var_t *newlvar, *proto_lvars, *lvar_ptr;
24606550Saw148015 
24616550Saw148015 			proto_lvars = inner_flowop->fo_lvar_list;
24626550Saw148015 			inner_flowop->fo_lvar_list = 0;
24636550Saw148015 
24646550Saw148015 			for (lvar_ptr = inner_flowtype->fo_lvar_list; lvar_ptr;
24656550Saw148015 			    lvar_ptr = lvar_ptr->var_next) {
24666550Saw148015 
24676550Saw148015 				if ((newlvar = var_lvar_alloc_local(
24686550Saw148015 				    lvar_ptr->var_name)) != NULL) {
24696550Saw148015 
24706550Saw148015 					add_lvar_to_list(newlvar,
24716550Saw148015 					    &inner_flowop->fo_lvar_list);
24726550Saw148015 
24736550Saw148015 					var_update_comp_lvars(newlvar,
24746550Saw148015 					    proto_lvars,
24756550Saw148015 					    comp_mstr_flow->fo_lvar_list);
24766550Saw148015 				}
24776550Saw148015 			}
24786550Saw148015 
24796550Saw148015 			parser_inner_flowop_define(thread,
24806550Saw148015 			    inner_flowtype,
24816550Saw148015 			    inner_flowop);
24826550Saw148015 
24836550Saw148015 			inner_flowtype = inner_flowtype->fo_exec_next;
24846550Saw148015 			continue;
24856550Saw148015 		}
24866550Saw148015 
24876550Saw148015 		avd_update(&inner_flowop->fo_iosize,
24886550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24896550Saw148015 		avd_update(&inner_flowop->fo_wss,
24906550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24916550Saw148015 		avd_update(&inner_flowop->fo_iters,
24926550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24936550Saw148015 		avd_update(&inner_flowop->fo_value,
24946550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24956550Saw148015 		avd_update(&inner_flowop->fo_random,
24966550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24976550Saw148015 		avd_update(&inner_flowop->fo_dsync,
24986550Saw148015 		    comp_mstr_flow->fo_lvar_list);
24996550Saw148015 		avd_update(&inner_flowop->fo_rotatefd,
25006550Saw148015 		    comp_mstr_flow->fo_lvar_list);
25016550Saw148015 		avd_update(&inner_flowop->fo_blocking,
25026550Saw148015 		    comp_mstr_flow->fo_lvar_list);
25036550Saw148015 		avd_update(&inner_flowop->fo_directio,
25046550Saw148015 		    comp_mstr_flow->fo_lvar_list);
25056550Saw148015 		avd_update(&inner_flowop->fo_highwater,
25066550Saw148015 		    comp_mstr_flow->fo_lvar_list);
25076550Saw148015 
25086550Saw148015 		inner_flowtype = inner_flowtype->fo_exec_next;
25096550Saw148015 	}
25106550Saw148015 }
25116212Saw148015 
25126212Saw148015 /*
25135184Sek110237  * Calls flowop_define() to allocate a flowop with the supplied name.
25145184Sek110237  * The allocated flowop inherits attributes from a base flowop of the
25155184Sek110237  * same type.  If the new flowop has a file or fileset attribute specified,
25165184Sek110237  * it must specify a defined fileobj or fileset or an error will be logged.
25175184Sek110237  * The new flowop may  also have the following attributes set by
25185184Sek110237  * the program:
25195184Sek110237  *  - file size (fo_iosize)
25205184Sek110237  *  - working set size (fo_wss)
25215184Sek110237  *  - do random io (fo_random)
25225184Sek110237  *  - do synchronous io (fo_dsync)
25235184Sek110237  *  - perform each operation multiple times before advancing (fo_iter)
25245184Sek110237  *  - target name (fo_targetname)
25255184Sek110237  *  - An integer value (fo_value)
25265184Sek110237  *  - a file descriptor (fo_fd)
25275184Sek110237  *  - specify to rotate file descriptors (fo_rotatefd)
25285184Sek110237  *  - a source fd (fo_srcfdnumber)
25295184Sek110237  *  - specify a blocking operation (fo_blocking)
25305184Sek110237  *  - specify a highwater mark (fo_highwater)
25315184Sek110237  *
25325184Sek110237  * After all the supplied attributes are stored in their respective locations
25335184Sek110237  * in the flowop object, the flowop's init function is called. No errors are
25345184Sek110237  * returned, but the filebench run will be terminated if the flowtype is not
25355184Sek110237  * specified, a name for the new flowop is not supplied, the flowop_define
25365184Sek110237  * call fails, or a file or fileset name is supplied but the corresponding
25375184Sek110237  * fileobj or fileset cannot be located.
25385184Sek110237  */
25395184Sek110237 static void
25406212Saw148015 parser_flowop_define(cmd_t *cmd, threadflow_t *thread,
25416212Saw148015     flowop_t **flowoplist_hdp, int category)
25425184Sek110237 {
25435184Sek110237 	flowop_t *flowop, *flowop_type;
25445184Sek110237 	char *type = (char *)cmd->cmd_name;
25455184Sek110237 	char *name;
25465184Sek110237 	attr_t *attr;
25475184Sek110237 
25485184Sek110237 	/* Get the inherited flowop */
25495184Sek110237 	flowop_type = flowop_find(type);
25505184Sek110237 	if (flowop_type == NULL) {
25515184Sek110237 		filebench_log(LOG_ERROR,
25525184Sek110237 		    "define flowop: flowop type %s not found",
25535184Sek110237 		    type);
25545184Sek110237 		filebench_shutdown(1);
25555184Sek110237 	}
25565184Sek110237 
25575184Sek110237 	/* Get the name of the flowop */
25585184Sek110237 	if (attr = get_attr(cmd, FSA_NAME)) {
25596212Saw148015 		name = avd_get_str(attr->attr_avd);
25605184Sek110237 	} else {
25615184Sek110237 		filebench_log(LOG_ERROR,
25625184Sek110237 		    "define flowop: flowop %s specifies no name",
25635184Sek110237 		    flowop_type->fo_name);
25645184Sek110237 		filebench_shutdown(1);
25655184Sek110237 	}
25665184Sek110237 
25675184Sek110237 	if ((flowop = flowop_define(thread, name,
25686550Saw148015 	    flowop_type, flowoplist_hdp, category, 0)) == NULL) {
25695184Sek110237 		filebench_log(LOG_ERROR,
25705184Sek110237 		    "define flowop: Failed to instantiate flowop %s\n",
25715184Sek110237 		    cmd->cmd_name);
25725184Sek110237 		filebench_shutdown(1);
25735184Sek110237 	}
25745184Sek110237 
25755184Sek110237 	/* Iterations */
25765184Sek110237 	if (attr = get_attr_integer(cmd, FSA_ITERS))
25776212Saw148015 		flowop->fo_iters = attr->attr_avd;
25785184Sek110237 	else
25796212Saw148015 		flowop->fo_iters = avd_int_alloc(1);
25806212Saw148015 
25816550Saw148015 
25826550Saw148015 	/* if this is a use of a composit flowop, create inner FLOW MASTERS */
25836550Saw148015 	if (flowop_type->fo_type == FLOW_TYPE_COMPOSITE) {
25846550Saw148015 		get_attr_lvars(cmd, flowop);
25856550Saw148015 		if (category == FLOW_MASTER)
25866550Saw148015 			parser_inner_flowop_define(thread,
25876550Saw148015 			    flowop_type, flowop);
25886550Saw148015 	}
25896550Saw148015 	else {
25906550Saw148015 		parser_flowop_get_attrs(cmd, flowop);
25916550Saw148015 	}
25925184Sek110237 }
25935184Sek110237 
25946550Saw148015 static void
25956550Saw148015 parser_composite_flowop_define(cmd_t *cmd)
25966550Saw148015 {
25976550Saw148015 	flowop_t *flowop;
25986550Saw148015 	cmd_t *inner_cmd;
25996550Saw148015 	char *name;
26006550Saw148015 	attr_t *attr;
26016550Saw148015 
26026550Saw148015 	/* Get the name of the flowop */
26036550Saw148015 	if (attr = get_attr(cmd, FSA_NAME)) {
26046550Saw148015 		name = avd_get_str(attr->attr_avd);
26056550Saw148015 	} else {
26066550Saw148015 		filebench_log(LOG_ERROR,
26076550Saw148015 		    "define flowop: Composit flowop specifies no name");
26086550Saw148015 
26096550Saw148015 		filebench_shutdown(1);
26106550Saw148015 	}
26116550Saw148015 
26126550Saw148015 	if ((flowop = flowop_new_composite_define(name)) == NULL) {
26136550Saw148015 		filebench_log(LOG_ERROR,
26146550Saw148015 		    "define flowop: Failed to instantiate flowop %s\n",
26156550Saw148015 		    cmd->cmd_name);
26166550Saw148015 		filebench_shutdown(1);
26176550Saw148015 	}
26186550Saw148015 
26196550Saw148015 	/* place any local var_t variables on the flowop's local list */
26206550Saw148015 	get_attr_lvars(cmd, flowop);
26216550Saw148015 
26226550Saw148015 	/* Iterations */
26236550Saw148015 	if (attr = get_attr_integer(cmd, FSA_ITERS))
26246550Saw148015 		flowop->fo_iters = attr->attr_avd;
26256550Saw148015 	else
26266550Saw148015 		flowop->fo_iters = avd_int_alloc(1);
26276550Saw148015 
26286550Saw148015 	/* define inner flowops */
26296550Saw148015 	for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
26306550Saw148015 	    inner_cmd = inner_cmd->cmd_next) {
26316550Saw148015 		parser_flowop_define(inner_cmd, NULL,
26326550Saw148015 		    &flowop->fo_comp_fops, FLOW_INNER_DEF);
26336550Saw148015 	}
26346550Saw148015 }
26356550Saw148015 
26366550Saw148015 
26375184Sek110237 /*
26385184Sek110237  * Calls fileset_define() to allocate a fileset with the supplied name and
26396212Saw148015  * initializes the fileset's pathname attribute, and optionally the
26406212Saw148015  * fileset_cached, fileset_reuse, fileset_prealloc and fileset_size attributes.
26415673Saw148015  *
26425184Sek110237  */
26435673Saw148015 static fileset_t *
26445673Saw148015 parser_fileset_define_common(cmd_t *cmd)
26455184Sek110237 {
26465184Sek110237 	fileset_t *fileset;
26476212Saw148015 	avd_t name;
26485184Sek110237 	attr_t *attr;
26496212Saw148015 	avd_t pathname;
26505184Sek110237 
26518615SAndrew.W.Wilson@sun.com 	/*
26528615SAndrew.W.Wilson@sun.com 	 * Make sure all plugin flowops are initialized.
26538615SAndrew.W.Wilson@sun.com 	 * Defaults to local fs for now
26548615SAndrew.W.Wilson@sun.com 	 */
26558615SAndrew.W.Wilson@sun.com 	flowop_plugin_flowinit();
26568615SAndrew.W.Wilson@sun.com 
26575184Sek110237 	/* Get the name of the file */
26588404SAndrew.W.Wilson@sun.com 	if (attr = get_attr_fileset(cmd, FSA_NAME)) {
26596212Saw148015 		name = attr->attr_avd;
26605184Sek110237 	} else {
26615184Sek110237 		filebench_log(LOG_ERROR,
26625673Saw148015 		    "define fileset: file or fileset specifies no name");
26635673Saw148015 		return (NULL);
26645184Sek110237 	}
26655184Sek110237 
26665184Sek110237 	if ((fileset = fileset_define(name)) == NULL) {
26675184Sek110237 		filebench_log(LOG_ERROR,
26685184Sek110237 		    "define file: failed to instantiate file %s\n",
26696212Saw148015 		    avd_get_str(name));
26705673Saw148015 		return (NULL);
26715184Sek110237 	}
26725184Sek110237 
26735184Sek110237 	/* Get the pathname from attribute */
26745184Sek110237 	if ((attr = get_attr(cmd, FSA_PATH)) == NULL) {
26755184Sek110237 		filebench_log(LOG_ERROR, "define file: no pathname specified");
26765673Saw148015 		return (NULL);
26775184Sek110237 	}
26785184Sek110237 
26795184Sek110237 	/* Expand variables in pathname */
26805673Saw148015 	if ((pathname = parser_list2varstring(attr->attr_param_list))
26815673Saw148015 	    == NULL) {
26825184Sek110237 		filebench_log(LOG_ERROR, "Cannot interpret path");
26835673Saw148015 		return (NULL);
26845184Sek110237 	}
26855184Sek110237 
26865184Sek110237 	fileset->fs_path = pathname;
26875184Sek110237 
26887736SAndrew.W.Wilson@sun.com 	/* How much should we preallocate? */
26897736SAndrew.W.Wilson@sun.com 	if ((attr = get_attr_integer(cmd, FSA_PREALLOC)) &&
26907736SAndrew.W.Wilson@sun.com 	    attr->attr_avd) {
26917736SAndrew.W.Wilson@sun.com 		if (AVD_IS_RANDOM(attr->attr_avd)) {
26927736SAndrew.W.Wilson@sun.com 			filebench_log(LOG_ERROR,
26937736SAndrew.W.Wilson@sun.com 			    "define fileset: Prealloc attr cannot be random");
26947736SAndrew.W.Wilson@sun.com 			filebench_shutdown(1);
26957736SAndrew.W.Wilson@sun.com 		}
26967736SAndrew.W.Wilson@sun.com 		fileset->fs_preallocpercent = attr->attr_avd;
26977736SAndrew.W.Wilson@sun.com 	} else if (attr && !attr->attr_avd) {
26987736SAndrew.W.Wilson@sun.com 		fileset->fs_preallocpercent = avd_int_alloc(100);
26997736SAndrew.W.Wilson@sun.com 	} else {
27007736SAndrew.W.Wilson@sun.com 		fileset->fs_preallocpercent = avd_int_alloc(0);
27017736SAndrew.W.Wilson@sun.com 	}
27027736SAndrew.W.Wilson@sun.com 
27037736SAndrew.W.Wilson@sun.com 	/* Should we preallocate? */
27047736SAndrew.W.Wilson@sun.com 	if (attr = get_attr_bool(cmd, FSA_PREALLOC))
27057736SAndrew.W.Wilson@sun.com 		fileset->fs_prealloc = attr->attr_avd;
27067736SAndrew.W.Wilson@sun.com 	else
27077736SAndrew.W.Wilson@sun.com 		fileset->fs_prealloc = avd_bool_alloc(FALSE);
27087736SAndrew.W.Wilson@sun.com 
27095673Saw148015 	/* Should we prealloc in parallel? */
27106212Saw148015 	if (attr = get_attr_bool(cmd, FSA_PARALLOC))
27116212Saw148015 		fileset->fs_paralloc = attr->attr_avd;
27126212Saw148015 	else
27136212Saw148015 		fileset->fs_paralloc = avd_bool_alloc(FALSE);
27145673Saw148015 
27159326SAndrew.W.Wilson@sun.com 	/* Should we allow writes to the file? */
27169326SAndrew.W.Wilson@sun.com 	if (attr = get_attr_bool(cmd, FSA_READONLY))
27179326SAndrew.W.Wilson@sun.com 		fileset->fs_readonly = attr->attr_avd;
27189326SAndrew.W.Wilson@sun.com 	else
27199326SAndrew.W.Wilson@sun.com 		fileset->fs_readonly = avd_bool_alloc(FALSE);
27209326SAndrew.W.Wilson@sun.com 
27215673Saw148015 	/* Should we reuse the existing file? */
27227736SAndrew.W.Wilson@sun.com 	if (attr = get_attr_bool(cmd, FSA_REUSE))
27236212Saw148015 		fileset->fs_reuse = attr->attr_avd;
27247736SAndrew.W.Wilson@sun.com 	else
27256212Saw148015 		fileset->fs_reuse = avd_bool_alloc(FALSE);
27265673Saw148015 
27279326SAndrew.W.Wilson@sun.com 	/* Should we check for files actual existance? */
27289326SAndrew.W.Wilson@sun.com 	if (attr = get_attr_bool(cmd, FSA_TRUSTTREE))
27299326SAndrew.W.Wilson@sun.com 		fileset->fs_trust_tree = attr->attr_avd;
27309326SAndrew.W.Wilson@sun.com 	else
27319326SAndrew.W.Wilson@sun.com 		fileset->fs_trust_tree = avd_bool_alloc(FALSE);
27329326SAndrew.W.Wilson@sun.com 
27335184Sek110237 	/* Should we leave in cache? */
27347736SAndrew.W.Wilson@sun.com 	if (attr = get_attr_bool(cmd, FSA_CACHED))
27356212Saw148015 		fileset->fs_cached = attr->attr_avd;
27367736SAndrew.W.Wilson@sun.com 	else
27376212Saw148015 		fileset->fs_cached = avd_bool_alloc(FALSE);
27385184Sek110237 
27395673Saw148015 	/* Get the mean or absolute size of the file */
27407736SAndrew.W.Wilson@sun.com 	if (attr = get_attr_integer(cmd, FSA_SIZE))
27416212Saw148015 		fileset->fs_size = attr->attr_avd;
27427736SAndrew.W.Wilson@sun.com 	else
27436212Saw148015 		fileset->fs_size = avd_int_alloc(0);
27445673Saw148015 
27455673Saw148015 	return (fileset);
27465673Saw148015 }
27475673Saw148015 
27485673Saw148015 /*
27495673Saw148015  * Calls parser_fileset_define_common() to allocate a fileset with
27507736SAndrew.W.Wilson@sun.com  * one entry and optionally the fileset_prealloc. sets the fileset_entries,
27517736SAndrew.W.Wilson@sun.com  * fileset_dirwidth, fileset_dirgamma, and fileset_sizegamma attributes
27525673Saw148015  * to appropriate values for emulating the old "fileobj" entity
27535673Saw148015  */
27545673Saw148015 static void
27555673Saw148015 parser_file_define(cmd_t *cmd)
27565673Saw148015 {
27575673Saw148015 	fileset_t *fileset;
27585673Saw148015 	attr_t *attr;
27595673Saw148015 
27605673Saw148015 	if ((fileset = parser_fileset_define_common(cmd)) == NULL) {
27615673Saw148015 		filebench_log(LOG_ERROR,
27625673Saw148015 		    "define file: failed to instantiate file");
27635673Saw148015 		filebench_shutdown(1);
27645673Saw148015 		return;
27655673Saw148015 	}
27665673Saw148015 
27675673Saw148015 	/* fileset is emulating a single file */
27685673Saw148015 	fileset->fs_attrs = FILESET_IS_FILE;
27695673Saw148015 
27705673Saw148015 	/* Set the size of the fileset to 1 */
27716212Saw148015 	fileset->fs_entries = avd_int_alloc(1);
27725673Saw148015 
27735673Saw148015 	/* Set the mean dir width to more than 1 */
27746212Saw148015 	fileset->fs_dirwidth = avd_int_alloc(10);
27755673Saw148015 
27765673Saw148015 	/* Set the dir and size gammas to 0 */
27776212Saw148015 	fileset->fs_dirgamma = avd_int_alloc(0);
27786212Saw148015 	fileset->fs_sizegamma = avd_int_alloc(0);
27795673Saw148015 }
27805673Saw148015 
27815673Saw148015 /*
27825673Saw148015  * Calls parser_fileset_define_common() to allocate a fileset with the
27836212Saw148015  * supplied name and initializes the fileset's fileset_preallocpercent,
27846212Saw148015  * fileset_prealloc, fileset_entries, fileset_dirwidth, fileset_dirgamma,
27856212Saw148015  * and fileset_sizegamma attributes.
27865673Saw148015  */
27875673Saw148015 static void
27885673Saw148015 parser_fileset_define(cmd_t *cmd)
27895673Saw148015 {
27905673Saw148015 	fileset_t *fileset;
27915673Saw148015 	attr_t *attr;
27925673Saw148015 
27935673Saw148015 	if ((fileset = parser_fileset_define_common(cmd)) == NULL) {
27945673Saw148015 		filebench_log(LOG_ERROR,
27955673Saw148015 		    "define fileset: failed to instantiate fileset");
27965673Saw148015 		filebench_shutdown(1);
27975673Saw148015 		return;
27985673Saw148015 	}
27995673Saw148015 	/* Get the number of files in the fileset */
28005184Sek110237 	if (attr = get_attr_integer(cmd, FSA_ENTRIES)) {
28016212Saw148015 		fileset->fs_entries = attr->attr_avd;
28025184Sek110237 	} else {
28036212Saw148015 		fileset->fs_entries = avd_int_alloc(0);
28045184Sek110237 	}
28055184Sek110237 
28067946SAndrew.W.Wilson@sun.com 	/* Get the number of leafdirs in the fileset */
28077946SAndrew.W.Wilson@sun.com 	if (attr = get_attr_integer(cmd, FSA_LEAFDIRS)) {
28087946SAndrew.W.Wilson@sun.com 		fileset->fs_leafdirs = attr->attr_avd;
28097946SAndrew.W.Wilson@sun.com 	} else {
28107946SAndrew.W.Wilson@sun.com 		fileset->fs_leafdirs = avd_int_alloc(0);
28117946SAndrew.W.Wilson@sun.com 	}
28127946SAndrew.W.Wilson@sun.com 
28137946SAndrew.W.Wilson@sun.com 	if ((avd_get_int(fileset->fs_entries) == 0) &&
28147946SAndrew.W.Wilson@sun.com 	    (avd_get_int(fileset->fs_leafdirs) == 0)) {
28157946SAndrew.W.Wilson@sun.com 		filebench_log(LOG_ERROR, "Fileset has no files or leafdirs");
28167946SAndrew.W.Wilson@sun.com 	}
28177946SAndrew.W.Wilson@sun.com 
28185184Sek110237 	/* Get the mean dir width of the fileset */
28195184Sek110237 	if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) {
28206212Saw148015 		fileset->fs_dirwidth = attr->attr_avd;
28215184Sek110237 	} else {
28225184Sek110237 		filebench_log(LOG_ERROR, "Fileset has zero directory width");
28236212Saw148015 		fileset->fs_dirwidth = avd_int_alloc(0);
28245184Sek110237 	}
28255184Sek110237 
28266212Saw148015 	/* Get the random variable for dir depth, if supplied */
28276212Saw148015 	if (attr = get_attr_integer(cmd, FSA_DIRDEPTHRV)) {
28286212Saw148015 		if (!AVD_IS_RANDOM(attr->attr_avd)) {
28296212Saw148015 			filebench_log(LOG_ERROR,
28306212Saw148015 			    "Define fileset: dirdepthrv must be random var");
28316212Saw148015 			filebench_shutdown(1);
28326212Saw148015 		}
28336212Saw148015 		fileset->fs_dirdepthrv = attr->attr_avd;
28346212Saw148015 	} else {
28356212Saw148015 		fileset->fs_dirdepthrv = NULL;
28366212Saw148015 	}
28376212Saw148015 
28386212Saw148015 	/* Get the gamma value for dir depth distributions */
28395184Sek110237 	if (attr = get_attr_integer(cmd, FSA_DIRGAMMA)) {
28406212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
28416212Saw148015 			filebench_log(LOG_ERROR,
28426212Saw148015 			    "Define fileset: dirgamma attr cannot be random");
28436212Saw148015 			filebench_shutdown(1);
28446212Saw148015 		}
28456212Saw148015 		fileset->fs_dirgamma = attr->attr_avd;
28465184Sek110237 	} else
28476212Saw148015 		fileset->fs_dirgamma = avd_int_alloc(1500);
28485184Sek110237 
28495184Sek110237 	/* Get the gamma value for dir width distributions */
28505184Sek110237 	if (attr = get_attr_integer(cmd, FSA_FILESIZEGAMMA)) {
28516212Saw148015 		if (AVD_IS_RANDOM(attr->attr_avd)) {
28526212Saw148015 			filebench_log(LOG_ERROR,
28536212Saw148015 			    "Define fileset: filesizegamma cannot be random");
28546212Saw148015 			filebench_shutdown(1);
28556212Saw148015 		}
28566212Saw148015 		fileset->fs_sizegamma = attr->attr_avd;
28575184Sek110237 	} else
28586212Saw148015 		fileset->fs_sizegamma = avd_int_alloc(1500);
28595184Sek110237 }
28605184Sek110237 
28615184Sek110237 /*
28625184Sek110237  * Creates and starts all defined procflow processes. The call to
28635184Sek110237  * procflow_init() results in creation of the requested number of
28645184Sek110237  * process instances for each previously defined procflow. The
28655184Sek110237  * child processes exec() a new instance of filebench, passing it
28665184Sek110237  * the instance number and address of the shared memory region.
28675184Sek110237  * The child processes will then create their threads and flowops.
28685184Sek110237  * The routine then unlocks the run_lock to allow all the processes'
28695184Sek110237  * threads to start and  waits for all of them to begin execution.
28705184Sek110237  * Finally, it records the start time and resets the event generation
28715184Sek110237  * system.
28725184Sek110237  */
28735184Sek110237 static void
28745184Sek110237 parser_proc_create(cmd_t *cmd)
28755184Sek110237 {
28766084Saw148015 	filebench_shm->shm_1st_err = 0;
28779326SAndrew.W.Wilson@sun.com 	filebench_shm->shm_f_abort = FILEBENCH_OK;
28789326SAndrew.W.Wilson@sun.com 
28795184Sek110237 	if (procflow_init() != 0) {
28805184Sek110237 		filebench_log(LOG_ERROR, "Failed to create processes\n");
28815184Sek110237 		filebench_shutdown(1);
28825184Sek110237 	}
28835184Sek110237 
28845184Sek110237 	/* Release the read lock, allowing threads to start */
28856391Saw148015 	(void) pthread_rwlock_unlock(&filebench_shm->shm_run_lock);
28865184Sek110237 
28875184Sek110237 	/* Wait for all threads to start */
28885184Sek110237 	if (procflow_allstarted() != 0) {
28895184Sek110237 		filebench_log(LOG_ERROR, "Could not start run");
28905184Sek110237 		return;
28915184Sek110237 	}
28925184Sek110237 
28935184Sek110237 
28945184Sek110237 	if (filebench_shm->shm_required &&
28955184Sek110237 	    (ipc_ismcreate(filebench_shm->shm_required) < 0)) {
28965184Sek110237 		filebench_log(LOG_ERROR, "Could not allocate shared memory");
28975184Sek110237 		return;
28985184Sek110237 	}
28995184Sek110237 
29006305Saw148015 	filebench_shm->shm_starttime = gethrtime();
29015184Sek110237 	eventgen_reset();
29025184Sek110237 }
29035184Sek110237 
29045184Sek110237 /*
29055673Saw148015  * Calls fileset_createset() to populate all files and filesets and
29065673Saw148015  * create all associated, initially existant,  files and subdirectories.
29075184Sek110237  * If errors are encountered, calls filebench_shutdown()
29085184Sek110237  * to exit filebench.
29095184Sek110237  */
29105184Sek110237 static void
29115184Sek110237 parser_fileset_create(cmd_t *cmd)
29125184Sek110237 {
29135673Saw148015 	if (!filecreate_done) {
29145673Saw148015 		filecreate_done = 1;
29156212Saw148015 
29166212Saw148015 		/* initialize the random number system first */
29176212Saw148015 		randdist_init();
29186212Saw148015 
29196212Saw148015 		/* create all the filesets */
29205673Saw148015 		if (fileset_createset(NULL) != 0) {
29215673Saw148015 			filebench_log(LOG_ERROR, "Failed to create filesets");
29225673Saw148015 			filebench_shutdown(1);
29235673Saw148015 		}
29245673Saw148015 	} else {
29255673Saw148015 		filebench_log(LOG_INFO,
29265673Saw148015 		    "Attempting to create fileset more than once, ignoring");
29275184Sek110237 	}
29285673Saw148015 
29295184Sek110237 }
29305184Sek110237 
29315184Sek110237 /*
2932*9356SAndrew.W.Wilson@sun.com  * Deletes the files and directories that represent files and filesets on the
2933*9356SAndrew.W.Wilson@sun.com  * storage medium.
2934*9356SAndrew.W.Wilson@sun.com  */
2935*9356SAndrew.W.Wilson@sun.com static void
2936*9356SAndrew.W.Wilson@sun.com parser_fileset_shutdown(cmd_t *cmd)
2937*9356SAndrew.W.Wilson@sun.com {
2938*9356SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Shutting down filesets");
2939*9356SAndrew.W.Wilson@sun.com 	fileset_delete_all_filesets();
2940*9356SAndrew.W.Wilson@sun.com }
2941*9356SAndrew.W.Wilson@sun.com 
2942*9356SAndrew.W.Wilson@sun.com /*
29435184Sek110237  * Shuts down all processes and their associated threads. When finished
29445184Sek110237  * it deletes interprocess shared memory and resets the event generator.
29455184Sek110237  * It does not exit the filebench program though.
29465184Sek110237  */
29475184Sek110237 static void
29485184Sek110237 parser_proc_shutdown(cmd_t *cmd)
29495184Sek110237 {
29505184Sek110237 	filebench_log(LOG_INFO, "Shutting down processes");
29515673Saw148015 	filecreate_done = 0;
29525184Sek110237 	procflow_shutdown();
29535184Sek110237 	if (filebench_shm->shm_required)
29545184Sek110237 		ipc_ismdelete();
29555184Sek110237 	eventgen_reset();
29565184Sek110237 }
29575184Sek110237 
29585184Sek110237 /*
29595184Sek110237  * Ends filebench run after first destoring any interprocess
29605184Sek110237  * shared memory. The call to filebench_shutdown()
29615184Sek110237  * also causes filebench to exit.
29625184Sek110237  */
29635184Sek110237 static void
29645184Sek110237 parser_filebench_shutdown(cmd_t *cmd)
29655184Sek110237 {
29666391Saw148015 	int f_abort = filebench_shm->shm_f_abort;
29676391Saw148015 
29686750Sek110237 	ipc_fini();
29696391Saw148015 
29706391Saw148015 	if (f_abort == FILEBENCH_ABORT_ERROR)
29716391Saw148015 		filebench_shutdown(1);
29726391Saw148015 	else
29736391Saw148015 		filebench_shutdown(0);
29745184Sek110237 }
29755184Sek110237 
29765184Sek110237 /*
29776084Saw148015  * This is Used for timing runs.Pauses the master thread in one second
29786084Saw148015  * intervals until the supplied ptime runs out or the f_abort flag
29796084Saw148015  * is raised. If given a time of zero or less, or the mode is stop on
29806084Saw148015  * lack of resources, it will pause until f_abort is raised.
29815184Sek110237  */
29829326SAndrew.W.Wilson@sun.com static int
29836084Saw148015 parser_pause(int ptime)
29845184Sek110237 {
29856084Saw148015 	int timeslept = 0;
29866084Saw148015 
29876084Saw148015 	if ((filebench_shm->shm_rmode == FILEBENCH_MODE_TIMEOUT) &&
29886084Saw148015 	    (ptime > 0)) {
29896084Saw148015 		while (timeslept < ptime) {
29906084Saw148015 			(void) sleep(1);
29916084Saw148015 			timeslept++;
29926391Saw148015 			if (filebench_shm->shm_f_abort)
29936084Saw148015 				break;
29946084Saw148015 		}
29956084Saw148015 	} else {
29966084Saw148015 		/* initial runtime of 0 means run till abort */
29976084Saw148015 		/* CONSTCOND */
29986084Saw148015 		while (1) {
29996084Saw148015 			(void) sleep(1);
30006084Saw148015 			timeslept++;
30016391Saw148015 			if (filebench_shm->shm_f_abort)
30026084Saw148015 				break;
30036084Saw148015 		}
30045184Sek110237 	}
30059326SAndrew.W.Wilson@sun.com 	return (timeslept);
30065184Sek110237 }
30075184Sek110237 
30085184Sek110237 /*
30095184Sek110237  * Do a file bench run. Calls routines to create file sets, files, and
30105184Sek110237  * processes. It resets the statistics counters, then sleeps for the runtime
30115184Sek110237  * passed as an argument to it on the command line in 1 second increments.
30125184Sek110237  * When it is finished sleeping, it collects a snapshot of the statistics
30135184Sek110237  * and ends the run.
30145184Sek110237  */
30155184Sek110237 static void
30165184Sek110237 parser_run(cmd_t *cmd)
30175184Sek110237 {
30185184Sek110237 	int runtime;
30199326SAndrew.W.Wilson@sun.com 	int timeslept;
30205184Sek110237 
30215184Sek110237 	runtime = cmd->cmd_qty;
30226084Saw148015 
30235184Sek110237 	parser_fileset_create(cmd);
30245184Sek110237 	parser_proc_create(cmd);
30255184Sek110237 
30265184Sek110237 	/* check for startup errors */
30276391Saw148015 	if (filebench_shm->shm_f_abort)
30285184Sek110237 		return;
30295184Sek110237 
30305184Sek110237 	filebench_log(LOG_INFO, "Running...");
30315184Sek110237 	stats_clear();
30326084Saw148015 
30339326SAndrew.W.Wilson@sun.com 	timeslept = parser_pause(runtime);
30349326SAndrew.W.Wilson@sun.com 
30359326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Run took %d seconds...", timeslept);
30365184Sek110237 	parser_statssnap(cmd);
30375184Sek110237 	parser_proc_shutdown(cmd);
30385184Sek110237 }
30395184Sek110237 
30405184Sek110237 /*
30415184Sek110237  * Similar to parser_run, but gets the sleep time from a variable
30425184Sek110237  * whose name is supplied as an argument to the command.
30435184Sek110237  */
30445184Sek110237 static void
30455184Sek110237 parser_run_variable(cmd_t *cmd)
30465184Sek110237 {
30476212Saw148015 	avd_t integer = var_ref_attr(cmd->cmd_tgt1);
30485184Sek110237 	int runtime;
30499326SAndrew.W.Wilson@sun.com 	int timeslept;
30505184Sek110237 
30515184Sek110237 	if (integer == NULL) {
30525184Sek110237 		filebench_log(LOG_ERROR, "Unknown variable %s",
30535184Sek110237 		cmd->cmd_tgt1);
30545184Sek110237 		return;
30555184Sek110237 	}
30565184Sek110237 
30576212Saw148015 	runtime = avd_get_int(integer);
30585184Sek110237 
30595184Sek110237 	/* check for startup errors */
30606391Saw148015 	if (filebench_shm->shm_f_abort)
30615184Sek110237 		return;
30625184Sek110237 
30635184Sek110237 	filebench_log(LOG_INFO, "Running...");
30645184Sek110237 	stats_clear();
30656084Saw148015 
30669326SAndrew.W.Wilson@sun.com 	timeslept = parser_pause(runtime);
30679326SAndrew.W.Wilson@sun.com 
30689326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Run took %d seconds...", timeslept);
30695184Sek110237 	parser_statssnap(cmd);
30706084Saw148015 	parser_proc_shutdown(cmd);
30715184Sek110237 }
30725184Sek110237 
30735184Sek110237 char *usagestr = NULL;
30745184Sek110237 
30755184Sek110237 /*
30765184Sek110237  * Prints usage string if defined, else just a message requesting load of a
30775184Sek110237  * personality.
30785184Sek110237  */
30795184Sek110237 static void
30805184Sek110237 parser_help(cmd_t *cmd)
30815184Sek110237 {
30825184Sek110237 	if (usagestr) {
30835184Sek110237 		filebench_log(LOG_INFO, "%s", usagestr);
30845184Sek110237 	} else {
30855184Sek110237 		filebench_log(LOG_INFO,
30865184Sek110237 		    "load <personality> (ls "
30876613Sek110237 		    FILEBENCHDIR "/workloads for list)");
30885184Sek110237 	}
30895184Sek110237 }
30905184Sek110237 
30915184Sek110237 char *varstr = NULL;
30925184Sek110237 
30935184Sek110237 /*
30945184Sek110237  * Prints the string of all var definitions, if there is one.
30955184Sek110237  */
30965184Sek110237 static void
30975184Sek110237 parser_printvars(cmd_t *cmd)
30985184Sek110237 {
30995184Sek110237 	char *str, *c;
31005184Sek110237 
31015184Sek110237 	if (varstr) {
31025184Sek110237 		str = strdup(varstr);
31035184Sek110237 		for (c = str; *c != '\0'; c++) {
31045184Sek110237 			if ((char)*c == '$')
31055184Sek110237 				*c = ' ';
31065184Sek110237 		}
31075184Sek110237 		filebench_log(LOG_INFO, "%s", str);
31085184Sek110237 		free(str);
31095184Sek110237 	}
31105184Sek110237 }
31115184Sek110237 
31125184Sek110237 /*
31137736SAndrew.W.Wilson@sun.com  * Establishes multi-client synchronization socket with synch server.
31147736SAndrew.W.Wilson@sun.com  */
31157736SAndrew.W.Wilson@sun.com static void
31167736SAndrew.W.Wilson@sun.com parser_enable_mc(cmd_t *cmd)
31177736SAndrew.W.Wilson@sun.com {
31187736SAndrew.W.Wilson@sun.com 	attr_t *attr;
31197736SAndrew.W.Wilson@sun.com 	char *master;
31207736SAndrew.W.Wilson@sun.com 	char *client;
31217736SAndrew.W.Wilson@sun.com 
31227736SAndrew.W.Wilson@sun.com 	if (attr= get_attr(cmd, FSA_MASTER)) {
31237736SAndrew.W.Wilson@sun.com 		master = avd_get_str(attr->attr_avd);
31247736SAndrew.W.Wilson@sun.com 	} else {
31257736SAndrew.W.Wilson@sun.com 		filebench_log(LOG_ERROR,
31267736SAndrew.W.Wilson@sun.com 		    "enable multi: no master specified");
31277736SAndrew.W.Wilson@sun.com 		return;
31287736SAndrew.W.Wilson@sun.com 	}
31297736SAndrew.W.Wilson@sun.com 
31307736SAndrew.W.Wilson@sun.com 	if (attr= get_attr(cmd, FSA_CLIENT)) {
31317736SAndrew.W.Wilson@sun.com 		client = avd_get_str(attr->attr_avd);
31327736SAndrew.W.Wilson@sun.com 	} else {
31337736SAndrew.W.Wilson@sun.com 		filebench_log(LOG_ERROR,
31347736SAndrew.W.Wilson@sun.com 		    "enable multi: no client specified");
31357736SAndrew.W.Wilson@sun.com 		return;
31367736SAndrew.W.Wilson@sun.com 	}
31377736SAndrew.W.Wilson@sun.com 
31387736SAndrew.W.Wilson@sun.com 	mc_sync_open_sock(master, 8001, client);
31397736SAndrew.W.Wilson@sun.com }
31407736SAndrew.W.Wilson@sun.com 
31417736SAndrew.W.Wilson@sun.com /*
31427736SAndrew.W.Wilson@sun.com  * Exchanges multi-client synchronization message with synch server.
31437736SAndrew.W.Wilson@sun.com  */
31447736SAndrew.W.Wilson@sun.com static void
31457736SAndrew.W.Wilson@sun.com parser_domultisync(cmd_t *cmd)
31467736SAndrew.W.Wilson@sun.com {
31477736SAndrew.W.Wilson@sun.com 	attr_t *attr;
31487736SAndrew.W.Wilson@sun.com 	fbint_t value;
31497736SAndrew.W.Wilson@sun.com 
31507736SAndrew.W.Wilson@sun.com 	if (attr = get_attr(cmd, FSA_VALUE))
31517736SAndrew.W.Wilson@sun.com 		value = avd_get_int(attr->attr_avd);
31527736SAndrew.W.Wilson@sun.com 	else
31537736SAndrew.W.Wilson@sun.com 		value = 1;
31547736SAndrew.W.Wilson@sun.com 
31557736SAndrew.W.Wilson@sun.com 	mc_sync_synchronize((int)value);
31567736SAndrew.W.Wilson@sun.com }
31577736SAndrew.W.Wilson@sun.com 
31587736SAndrew.W.Wilson@sun.com /*
31595184Sek110237  * Used by the SET command to add a var and default value string to the
31605184Sek110237  * varstr string. It allocates a new, larger varstr string, copies the
31615184Sek110237  * old contents of varstr into it, then adds the new var string on the end.
31625184Sek110237  */
31635184Sek110237 static void
31645184Sek110237 parser_vars(cmd_t *cmd)
31655184Sek110237 {
31665184Sek110237 	char *string = cmd->cmd_tgt1;
31675184Sek110237 	char *newvars;
31685184Sek110237 
31695184Sek110237 	if (string == NULL)
31705184Sek110237 		return;
31715184Sek110237 
31725184Sek110237 	if (dofile)
31735184Sek110237 		return;
31745184Sek110237 
31755184Sek110237 	if (varstr == NULL) {
31765184Sek110237 		newvars = malloc(strlen(string) + 2);
31775184Sek110237 		*newvars = 0;
31785184Sek110237 	} else {
31795184Sek110237 		newvars = malloc(strlen(varstr) + strlen(string) + 2);
31805184Sek110237 		(void) strcpy(newvars, varstr);
31815184Sek110237 	}
31825184Sek110237 	(void) strcat(newvars, string);
31835184Sek110237 	(void) strcat(newvars, " ");
31845184Sek110237 
31855184Sek110237 	if (varstr)
31865184Sek110237 		free(varstr);
31875184Sek110237 
31885184Sek110237 	varstr = newvars;
31895184Sek110237 }
31905184Sek110237 
31915184Sek110237 /*
31926212Saw148015  * used by the set command to set the integer part of a regular
31936212Saw148015  * variable, or the appropriate field of a random variable
31946212Saw148015  */
31956212Saw148015 static void
31966212Saw148015 parser_set_integer(char *name, fbint_t integer)
31976212Saw148015 {
31986212Saw148015 	var_assign_integer(name, integer);
31996212Saw148015 }
32006212Saw148015 
32016212Saw148015 /*
32026212Saw148015  * used by the set command to set the integer part of a regular
32036212Saw148015  * variable from another variable, or the appropriate field of a
32046212Saw148015  * random variable from another variable
32056212Saw148015  */
32066212Saw148015 static void
32076212Saw148015 parser_set_var(char *dst_name, char *src_name)
32086212Saw148015 {
32096212Saw148015 	var_assign_var(dst_name, src_name);
32106212Saw148015 }
32116212Saw148015 
32126212Saw148015 
32136212Saw148015 /*
32149326SAndrew.W.Wilson@sun.com  * Sleeps for cmd->cmd_qty seconds, one second at a time.
32159326SAndrew.W.Wilson@sun.com  */
32169326SAndrew.W.Wilson@sun.com static void
32179326SAndrew.W.Wilson@sun.com parser_warmup(cmd_t *cmd)
32189326SAndrew.W.Wilson@sun.com {
32199326SAndrew.W.Wilson@sun.com 	int sleeptime;
32209326SAndrew.W.Wilson@sun.com 
32219326SAndrew.W.Wilson@sun.com 	/* check for startup errors */
32229326SAndrew.W.Wilson@sun.com 	if (filebench_shm->shm_f_abort)
32239326SAndrew.W.Wilson@sun.com 		return;
32249326SAndrew.W.Wilson@sun.com 
32259326SAndrew.W.Wilson@sun.com 	sleeptime = cmd->cmd_qty;
32269326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Warming up...");
32279326SAndrew.W.Wilson@sun.com 
32289326SAndrew.W.Wilson@sun.com 	(void) parser_pause(sleeptime);
32299326SAndrew.W.Wilson@sun.com }
32309326SAndrew.W.Wilson@sun.com 
32319326SAndrew.W.Wilson@sun.com /*
32325184Sek110237  * Same as parser_sleep, except the sleep time is obtained from a variable
32335184Sek110237  * whose name is passed to it as an argument on the command line.
32345184Sek110237  */
32355184Sek110237 static void
32369326SAndrew.W.Wilson@sun.com parser_warmup_variable(cmd_t *cmd)
32375184Sek110237 {
32386212Saw148015 	avd_t integer = var_ref_attr(cmd->cmd_tgt1);
32395184Sek110237 	int sleeptime;
32405184Sek110237 
32415184Sek110237 	if (integer == NULL) {
32425184Sek110237 		filebench_log(LOG_ERROR, "Unknown variable %s",
32435184Sek110237 		cmd->cmd_tgt1);
32445184Sek110237 		return;
32455184Sek110237 	}
32465184Sek110237 
32476212Saw148015 	sleeptime = avd_get_int(integer);
32485184Sek110237 
32495184Sek110237 	/* check for startup errors */
32506391Saw148015 	if (filebench_shm->shm_f_abort)
32515184Sek110237 		return;
32525184Sek110237 
32539326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Warming up...");
32549326SAndrew.W.Wilson@sun.com 
32559326SAndrew.W.Wilson@sun.com 	(void) parser_pause(sleeptime);
32569326SAndrew.W.Wilson@sun.com }
32579326SAndrew.W.Wilson@sun.com 
32589326SAndrew.W.Wilson@sun.com /*
32599326SAndrew.W.Wilson@sun.com  * Sleeps for cmd->cmd_qty seconds, one second at a time.
32609326SAndrew.W.Wilson@sun.com  */
32619326SAndrew.W.Wilson@sun.com static void
32629326SAndrew.W.Wilson@sun.com parser_sleep(cmd_t *cmd)
32639326SAndrew.W.Wilson@sun.com {
32649326SAndrew.W.Wilson@sun.com 	int sleeptime;
32659326SAndrew.W.Wilson@sun.com 	int timeslept;
32669326SAndrew.W.Wilson@sun.com 
32679326SAndrew.W.Wilson@sun.com 	/* check for startup errors */
32689326SAndrew.W.Wilson@sun.com 	if (filebench_shm->shm_f_abort)
32699326SAndrew.W.Wilson@sun.com 		return;
32709326SAndrew.W.Wilson@sun.com 
32719326SAndrew.W.Wilson@sun.com 	sleeptime = cmd->cmd_qty;
32725184Sek110237 	filebench_log(LOG_INFO, "Running...");
32736084Saw148015 
32749326SAndrew.W.Wilson@sun.com 	timeslept = parser_pause(sleeptime);
32759326SAndrew.W.Wilson@sun.com 
32769326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Run took %d seconds...", timeslept);
32779326SAndrew.W.Wilson@sun.com }
32789326SAndrew.W.Wilson@sun.com 
32799326SAndrew.W.Wilson@sun.com /*
32809326SAndrew.W.Wilson@sun.com  * Same as parser_sleep, except the sleep time is obtained from a variable
32819326SAndrew.W.Wilson@sun.com  * whose name is passed to it as an argument on the command line.
32829326SAndrew.W.Wilson@sun.com  */
32839326SAndrew.W.Wilson@sun.com static void
32849326SAndrew.W.Wilson@sun.com parser_sleep_variable(cmd_t *cmd)
32859326SAndrew.W.Wilson@sun.com {
32869326SAndrew.W.Wilson@sun.com 	avd_t integer = var_ref_attr(cmd->cmd_tgt1);
32879326SAndrew.W.Wilson@sun.com 	int sleeptime;
32889326SAndrew.W.Wilson@sun.com 	int timeslept;
32899326SAndrew.W.Wilson@sun.com 
32909326SAndrew.W.Wilson@sun.com 	if (integer == NULL) {
32919326SAndrew.W.Wilson@sun.com 		filebench_log(LOG_ERROR, "Unknown variable %s",
32929326SAndrew.W.Wilson@sun.com 		cmd->cmd_tgt1);
32939326SAndrew.W.Wilson@sun.com 		return;
32949326SAndrew.W.Wilson@sun.com 	}
32959326SAndrew.W.Wilson@sun.com 
32969326SAndrew.W.Wilson@sun.com 	sleeptime = avd_get_int(integer);
32979326SAndrew.W.Wilson@sun.com 
32989326SAndrew.W.Wilson@sun.com 	/* check for startup errors */
32999326SAndrew.W.Wilson@sun.com 	if (filebench_shm->shm_f_abort)
33009326SAndrew.W.Wilson@sun.com 		return;
33019326SAndrew.W.Wilson@sun.com 
33029326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Running...");
33039326SAndrew.W.Wilson@sun.com 
33049326SAndrew.W.Wilson@sun.com 	timeslept = parser_pause(sleeptime);
33059326SAndrew.W.Wilson@sun.com 
33069326SAndrew.W.Wilson@sun.com 	filebench_log(LOG_INFO, "Run took %d seconds...", timeslept);
33075184Sek110237 }
33085184Sek110237 
33095184Sek110237 /*
33105184Sek110237  * Parser log prints the values of a list of variables to the log file.
33115184Sek110237  * The list of variables is placed on the command line, separated
33125184Sek110237  * by comas and the entire list is enclosed in quotes.
33135184Sek110237  * For example, if $dir contains "/export/home/tmp" and $filesize = 1048576,
33145184Sek110237  * then typing: log "$dir, $filesize" prints: log /export/home/tmp, 1048576
33155184Sek110237  */
33165184Sek110237 static void
33175184Sek110237 parser_log(cmd_t *cmd)
33185184Sek110237 {
33195184Sek110237 	char *string;
33205184Sek110237 
33215184Sek110237 	if (cmd->cmd_param_list == NULL)
33225184Sek110237 		return;
33235184Sek110237 
33245184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
33255184Sek110237 
33265184Sek110237 	if (string == NULL)
33275184Sek110237 		return;
33285184Sek110237 
33295184Sek110237 	filebench_log(LOG_VERBOSE, "log %s", string);
33305184Sek110237 	filebench_log(LOG_LOG, "%s", string);
33315184Sek110237 }
33325184Sek110237 
33335184Sek110237 /*
33345184Sek110237  * Implements the stats directory command. changes the directory for
33355184Sek110237  * dumping statistics to supplied directory path. For example:
33365184Sek110237  * 	stats directory /tmp
33375184Sek110237  * changes the stats directory to "/tmp".
33385184Sek110237  */
33395184Sek110237 static void
33405184Sek110237 parser_directory(cmd_t *cmd)
33415184Sek110237 {
33425184Sek110237 	char newdir[MAXPATHLEN];
33435184Sek110237 	char *dir;
33445184Sek110237 
33455184Sek110237 	if ((dir = parser_list2string(cmd->cmd_param_list)) == NULL) {
33465184Sek110237 		filebench_log(LOG_ERROR, "Cannot interpret directory");
33475184Sek110237 		return;
33485184Sek110237 	}
33495184Sek110237 
33505184Sek110237 	*newdir = 0;
33515184Sek110237 	/* Change dir relative to cwd if path not fully qualified */
33525184Sek110237 	if (*dir != '/') {
33535184Sek110237 		(void) strcat(newdir, cwd);
33545184Sek110237 		(void) strcat(newdir, "/");
33555184Sek110237 	}
33565184Sek110237 	(void) strcat(newdir, dir);
33575184Sek110237 	(void) mkdir(newdir, 0755);
33585184Sek110237 	filebench_log(LOG_VERBOSE, "Change dir to %s", newdir);
33595184Sek110237 	chdir(newdir);
33605184Sek110237 	free(dir);
33615184Sek110237 }
33625184Sek110237 
33635184Sek110237 #define	PIPE_PARENT 1
33645184Sek110237 #define	PIPE_CHILD  0
33655184Sek110237 
33665184Sek110237 /*
33675184Sek110237  * Runs the quoted unix command as a background process. Intended for
33685184Sek110237  * running statistics gathering utilities such as mpstat while the filebench
33695184Sek110237  * workload is running. Also records the pid's of the background processes
33705184Sek110237  * so that parser_statssnap() can terminate them when the run completes.
33715184Sek110237  */
33725184Sek110237 static void
33735184Sek110237 parser_statscmd(cmd_t *cmd)
33745184Sek110237 {
33755184Sek110237 	char *string;
33765184Sek110237 	pid_t pid;
33775184Sek110237 	pidlist_t *pidlistent;
33785184Sek110237 	int pipe_fd[2];
33795184Sek110237 	int newstdout;
33805184Sek110237 
33815184Sek110237 	if (cmd->cmd_param_list == NULL)
33825184Sek110237 		return;
33835184Sek110237 
33845184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
33855184Sek110237 
33865184Sek110237 	if (string == NULL)
33875184Sek110237 		return;
33885184Sek110237 
33895184Sek110237 	if ((pipe(pipe_fd)) < 0) {
33905184Sek110237 		filebench_log(LOG_ERROR, "statscmd pipe failed");
33915184Sek110237 		return;
33925184Sek110237 	}
33935184Sek110237 
33945184Sek110237 #ifdef HAVE_FORK1
33955184Sek110237 	if ((pid = fork1()) < 0) {
33965184Sek110237 		filebench_log(LOG_ERROR, "statscmd fork failed");
33975184Sek110237 		return;
33985184Sek110237 	}
33995184Sek110237 #elif HAVE_FORK
34005184Sek110237 	if ((pid = fork()) < 0) {
34015184Sek110237 		filebench_log(LOG_ERROR, "statscmd fork failed");
34025184Sek110237 		return;
34035184Sek110237 	}
34045184Sek110237 #else
34055184Sek110237 	Crash! - Need code to deal with no fork1!
34065184Sek110237 #endif /* HAVE_FORK1 */
34075184Sek110237 
34085184Sek110237 	if (pid == 0) {
34095184Sek110237 
34105184Sek110237 		setsid();
34115184Sek110237 
34125184Sek110237 		filebench_log(LOG_VERBOSE,
34135184Sek110237 		    "Backgrounding %s", string);
34145184Sek110237 		/*
34155184Sek110237 		 * Child
34165184Sek110237 		 * - close stdout
34175184Sek110237 		 * - dup to create new stdout
34185184Sek110237 		 * - close pipe fds
34195184Sek110237 		 */
34205184Sek110237 		(void) close(1);
34215184Sek110237 
34225184Sek110237 		if ((newstdout = dup(pipe_fd[PIPE_CHILD])) < 0) {
34235184Sek110237 			filebench_log(LOG_ERROR,
34245184Sek110237 			    "statscmd dup failed: %s",
34255184Sek110237 			    strerror(errno));
34265184Sek110237 		}
34275184Sek110237 
34285184Sek110237 		(void) close(pipe_fd[PIPE_PARENT]);
34295184Sek110237 		(void) close(pipe_fd[PIPE_CHILD]);
34305184Sek110237 
34315184Sek110237 		if (system(string) < 0) {
34325184Sek110237 			filebench_log(LOG_ERROR,
34335184Sek110237 			    "statscmd exec failed: %s",
34345184Sek110237 			    strerror(errno));
34355184Sek110237 		}
34365184Sek110237 		/* Failed! */
34375184Sek110237 		exit(1);
34385184Sek110237 
34395184Sek110237 	} else {
34405184Sek110237 
34415184Sek110237 		/* Record pid in pidlist for subsequent reaping by stats snap */
34425184Sek110237 		if ((pidlistent = (pidlist_t *)malloc(sizeof (pidlist_t)))
34435184Sek110237 		    == NULL) {
34445184Sek110237 			filebench_log(LOG_ERROR, "pidlistent malloc failed");
34455184Sek110237 			return;
34465184Sek110237 		}
34475184Sek110237 
34485184Sek110237 		pidlistent->pl_pid = pid;
34495184Sek110237 		pidlistent->pl_fd = pipe_fd[PIPE_PARENT];
34505184Sek110237 		(void) close(pipe_fd[PIPE_CHILD]);
34515184Sek110237 
34525184Sek110237 		/* Add fileobj to global list */
34535184Sek110237 		if (pidlist == NULL) {
34545184Sek110237 			pidlist = pidlistent;
34555184Sek110237 			pidlistent->pl_next = NULL;
34565184Sek110237 		} else {
34575184Sek110237 			pidlistent->pl_next = pidlist;
34585184Sek110237 			pidlist = pidlistent;
34595184Sek110237 		}
34605184Sek110237 	}
34615184Sek110237 }
34625184Sek110237 
34635184Sek110237 /*
34645184Sek110237  * Launches a shell to run the unix command supplied in the argument.
34655184Sek110237  * The command should be enclosed in quotes, as in:
34665184Sek110237  * 	system "rm xyz"
34675184Sek110237  * which would run the "rm" utility to delete the file "xyz".
34685184Sek110237  */
34695184Sek110237 static void
34705184Sek110237 parser_system(cmd_t *cmd)
34715184Sek110237 {
34725184Sek110237 	char *string;
34735184Sek110237 
34745184Sek110237 	if (cmd->cmd_param_list == NULL)
34755184Sek110237 		return;
34765184Sek110237 
34775184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
34785184Sek110237 
34795184Sek110237 	if (string == NULL)
34805184Sek110237 		return;
34815184Sek110237 
34825184Sek110237 	filebench_log(LOG_VERBOSE,
34835184Sek110237 	    "Running '%s'", string);
34845184Sek110237 
34855184Sek110237 	if (system(string) < 0) {
34865184Sek110237 		filebench_log(LOG_ERROR,
34875184Sek110237 		    "system exec failed: %s",
34885184Sek110237 		    strerror(errno));
34895184Sek110237 	}
34905184Sek110237 	free(string);
34915184Sek110237 }
34925184Sek110237 
34935184Sek110237 /*
34945184Sek110237  * Echos string supplied with command to the log.
34955184Sek110237  */
34965184Sek110237 static void
34975184Sek110237 parser_echo(cmd_t *cmd)
34985184Sek110237 {
34995184Sek110237 	char *string;
35005184Sek110237 
35015184Sek110237 	if (cmd->cmd_param_list == NULL)
35025184Sek110237 		return;
35035184Sek110237 
35045184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
35055184Sek110237 
35065184Sek110237 	if (string == NULL)
35075184Sek110237 		return;
35085184Sek110237 
35095184Sek110237 	filebench_log(LOG_INFO, "%s", string);
35105184Sek110237 }
35115184Sek110237 
35126750Sek110237 /*
35136750Sek110237  * Prints out the version of FileBench.
35146750Sek110237  */
35156750Sek110237 static void
35166750Sek110237 parser_version(cmd_t *cmd)
35176750Sek110237 {
35186750Sek110237 	filebench_log(LOG_INFO, "FileBench Version: %s", FILEBENCH_VERSION);
35196750Sek110237 }
35205184Sek110237 
35215184Sek110237 /*
35225184Sek110237  * Adds the string supplied as the argument to the usage command
35235184Sek110237  * to the end of the string printed by the help command.
35245184Sek110237  */
35255184Sek110237 static void
35265184Sek110237 parser_usage(cmd_t *cmd)
35275184Sek110237 {
35285184Sek110237 	char *string;
35295184Sek110237 	char *newusage;
35305184Sek110237 
35315184Sek110237 	if (cmd->cmd_param_list == NULL)
35325184Sek110237 		return;
35335184Sek110237 
35345184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
35355184Sek110237 
35365184Sek110237 	if (string == NULL)
35375184Sek110237 		return;
35385184Sek110237 
35395184Sek110237 	if (dofile)
35405184Sek110237 		return;
35415184Sek110237 
35425184Sek110237 	if (usagestr == NULL) {
35435184Sek110237 		newusage = malloc(strlen(string) + 2);
35445184Sek110237 		*newusage = 0;
35455184Sek110237 	} else {
35465184Sek110237 		newusage = malloc(strlen(usagestr) + strlen(string) + 2);
35475184Sek110237 		(void) strcpy(newusage, usagestr);
35485184Sek110237 	}
35495184Sek110237 	(void) strcat(newusage, "\n");
35505184Sek110237 	(void) strcat(newusage, string);
35515184Sek110237 
35525184Sek110237 	if (usagestr)
35535184Sek110237 		free(usagestr);
35545184Sek110237 
35555184Sek110237 	usagestr = newusage;
35565184Sek110237 
35575184Sek110237 	filebench_log(LOG_INFO, "%s", string);
35585184Sek110237 }
35595184Sek110237 
35605184Sek110237 /*
35615184Sek110237  * Updates the global dump filename with the filename supplied
35625184Sek110237  * as the command's argument. Then dumps the statistics of each
35635184Sek110237  * worker flowop into the dump file, followed by a summary of
35645184Sek110237  * overall totals.
35655184Sek110237  */
35665184Sek110237 static void
35675184Sek110237 parser_statsdump(cmd_t *cmd)
35685184Sek110237 {
35695184Sek110237 	char *string;
35705184Sek110237 
35715184Sek110237 	if (cmd->cmd_param_list == NULL)
35725184Sek110237 		return;
35735184Sek110237 
35745184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
35755184Sek110237 
35765184Sek110237 	if (string == NULL)
35775184Sek110237 		return;
35785184Sek110237 
35795184Sek110237 	filebench_log(LOG_VERBOSE,
35805184Sek110237 	    "Stats dump to file '%s'", string);
35815184Sek110237 
35825184Sek110237 	stats_dump(string);
35835184Sek110237 
35845184Sek110237 	free(string);
35855184Sek110237 }
35865184Sek110237 
35875184Sek110237 /*
35887736SAndrew.W.Wilson@sun.com  * Same as statsdump, but outputs in a computer friendly format.
35897736SAndrew.W.Wilson@sun.com  */
35907736SAndrew.W.Wilson@sun.com static void
35917736SAndrew.W.Wilson@sun.com parser_statsmultidump(cmd_t *cmd)
35927736SAndrew.W.Wilson@sun.com {
35937736SAndrew.W.Wilson@sun.com 	char *string;
35947736SAndrew.W.Wilson@sun.com 
35957736SAndrew.W.Wilson@sun.com 	if (cmd->cmd_param_list == NULL)
35967736SAndrew.W.Wilson@sun.com 		return;
35977736SAndrew.W.Wilson@sun.com 
35987736SAndrew.W.Wilson@sun.com 	string = parser_list2string(cmd->cmd_param_list);
35997736SAndrew.W.Wilson@sun.com 
36007736SAndrew.W.Wilson@sun.com 	if (string == NULL)
36017736SAndrew.W.Wilson@sun.com 		return;
36027736SAndrew.W.Wilson@sun.com 
36037736SAndrew.W.Wilson@sun.com 	filebench_log(LOG_VERBOSE,
36047736SAndrew.W.Wilson@sun.com 	    "Stats dump to file '%s'", string);
36057736SAndrew.W.Wilson@sun.com 
36067736SAndrew.W.Wilson@sun.com 	stats_multidump(string);
36077736SAndrew.W.Wilson@sun.com 
36087736SAndrew.W.Wilson@sun.com 	free(string);
36097736SAndrew.W.Wilson@sun.com }
36107736SAndrew.W.Wilson@sun.com 
36117736SAndrew.W.Wilson@sun.com /*
36125184Sek110237  * Same as parser_statsdump, but in xml format.
36135184Sek110237  */
36145184Sek110237 static void
36155184Sek110237 parser_statsxmldump(cmd_t *cmd)
36165184Sek110237 {
36175184Sek110237 	char *string;
36185184Sek110237 
36195184Sek110237 	if (cmd->cmd_param_list == NULL)
36205184Sek110237 		return;
36215184Sek110237 
36225184Sek110237 	string = parser_list2string(cmd->cmd_param_list);
36235184Sek110237 
36245184Sek110237 	if (string == NULL)
36255184Sek110237 		return;
36265184Sek110237 
36275184Sek110237 	filebench_log(LOG_VERBOSE,
36285184Sek110237 	    "Stats dump to file '%s'", string);
36295184Sek110237 
36305184Sek110237 	stats_xmldump(string);
36315184Sek110237 
36325184Sek110237 	free(string);
36335184Sek110237 }
36345184Sek110237 
36355184Sek110237 /*
36365184Sek110237  * Kills off background statistics collection processes, then takes a snapshot
36375184Sek110237  * of the filebench run's collected statistics using stats_snap() from
36385184Sek110237  * stats.c.
36395184Sek110237  */
36405184Sek110237 static void
36415184Sek110237 parser_statssnap(cmd_t *cmd)
36425184Sek110237 {
36435184Sek110237 	pidlist_t *pidlistent;
36445184Sek110237 	int stat;
36455184Sek110237 	pid_t pid;
36465184Sek110237 
36475184Sek110237 	for (pidlistent = pidlist; pidlistent != NULL;
36485184Sek110237 	    pidlistent = pidlistent->pl_next) {
36495184Sek110237 		filebench_log(LOG_VERBOSE, "Killing session %d for pid %d",
36505184Sek110237 		    getsid(pidlistent->pl_pid),
36515184Sek110237 		    pidlistent->pl_pid);
36525184Sek110237 		if (pidlistent->pl_fd)
36535184Sek110237 			(void) close(pidlistent->pl_fd);
36545184Sek110237 #ifdef HAVE_SIGSEND
36555184Sek110237 		sigsend(P_SID, getsid(pidlistent->pl_pid), SIGTERM);
36565184Sek110237 #else
36575184Sek110237 		(void) kill(-1, SIGTERM);
36585184Sek110237 #endif
36595184Sek110237 
36605184Sek110237 		/* Close pipe */
36615184Sek110237 		if (pidlistent->pl_fd)
36625184Sek110237 			(void) close(pidlistent->pl_fd);
36635184Sek110237 
36645184Sek110237 		/* Wait for cmd and all its children */
36655184Sek110237 		while ((pid = waitpid(pidlistent->pl_pid * -1, &stat, 0)) > 0)
36665184Sek110237 			filebench_log(LOG_DEBUG_IMPL,
36676286Saw148015 			"Waited for pid %d", (int)pid);
36685184Sek110237 	}
36695184Sek110237 
36705184Sek110237 	for (pidlistent = pidlist; pidlistent != NULL;
36715184Sek110237 	    pidlistent = pidlistent->pl_next) {
36725184Sek110237 		free(pidlistent);
36735184Sek110237 	}
36745184Sek110237 
36755184Sek110237 	pidlist = NULL;
36765184Sek110237 	stats_snap();
36775184Sek110237 }
36785184Sek110237 
36795184Sek110237 /*
36805184Sek110237  * Shutdown filebench.
36815184Sek110237  */
36825184Sek110237 static void
36835184Sek110237 parser_abort(int arg)
36845184Sek110237 {
36855184Sek110237 	(void) sigignore(SIGINT);
36865184Sek110237 	filebench_log(LOG_INFO, "Aborting...");
36875184Sek110237 	filebench_shutdown(1);
36885184Sek110237 }
36895184Sek110237 
36905184Sek110237 /*
36916212Saw148015  * define a random variable and initialize the distribution parameters
36926212Saw148015  */
36936212Saw148015 static void
36946212Saw148015 parser_randvar_define(cmd_t *cmd)
36956212Saw148015 {
36966212Saw148015 	var_t		*var;
36976212Saw148015 	randdist_t	*rndp;
36986212Saw148015 	attr_t		*attr;
36996212Saw148015 	char		*name;
37006212Saw148015 
37016212Saw148015 	/* Get the name for the random variable */
37026212Saw148015 	if (attr = get_attr(cmd, FSA_NAME)) {
37036212Saw148015 		name = avd_get_str(attr->attr_avd);
37046212Saw148015 	} else {
37056212Saw148015 		filebench_log(LOG_ERROR,
37066212Saw148015 		    "define randvar: no name specified");
37076212Saw148015 		return;
37086212Saw148015 	}
37096212Saw148015 
37106212Saw148015 	if ((var = var_define_randvar(name)) == NULL) {
37116212Saw148015 		filebench_log(LOG_ERROR,
37126212Saw148015 		    "define randvar: failed for random variable %s",
37136212Saw148015 		    name);
37146212Saw148015 		return;
37156212Saw148015 	}
37166212Saw148015 
37176212Saw148015 	rndp = var->var_val.randptr;
37186212Saw148015 	rndp->rnd_type = 0;
37196212Saw148015 
37206212Saw148015 	/* Get the source of the random numbers */
37216212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDSRC)) {
37226212Saw148015 		int randsrc = (int)avd_get_int(attr->attr_avd);
37236212Saw148015 
37246212Saw148015 		switch (randsrc) {
37256212Saw148015 		case FSV_URAND:
37266212Saw148015 			rndp->rnd_type |= RAND_SRC_URANDOM;
37276212Saw148015 			break;
37286212Saw148015 		case FSV_RAND48:
37296212Saw148015 			rndp->rnd_type |= RAND_SRC_GENERATOR;
37306212Saw148015 			break;
37316212Saw148015 		}
37326212Saw148015 	} else {
37336212Saw148015 		/* default to rand48 random number generator */
37346212Saw148015 		rndp->rnd_type |= RAND_SRC_GENERATOR;
37356212Saw148015 	}
37366212Saw148015 
37376212Saw148015 	/* Get the min value of the random distribution */
37386212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDMIN))
37396212Saw148015 		rndp->rnd_min = attr->attr_avd;
37406212Saw148015 	else
37416212Saw148015 		rndp->rnd_min = avd_int_alloc(0);
37426212Saw148015 
37436212Saw148015 	/* Get the roundoff value for the random distribution */
37446212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDROUND))
37456212Saw148015 		rndp->rnd_round = attr->attr_avd;
37466212Saw148015 	else
37476212Saw148015 		rndp->rnd_round = avd_int_alloc(0);
37486212Saw148015 
37496212Saw148015 	/* Get a tablular probablility distribution if there is one */
37506212Saw148015 	if (attr = get_attr(cmd, FSA_RANDTABLE)) {
37516212Saw148015 		rndp->rnd_probtabs = (probtabent_t *)(attr->attr_obj);
37526212Saw148015 		rndp->rnd_type |= RAND_TYPE_TABLE;
37536212Saw148015 
37546212Saw148015 		/* no need for the rest of the attributes */
37556212Saw148015 		return;
37566212Saw148015 	} else {
37576212Saw148015 		rndp->rnd_probtabs = NULL;
37586212Saw148015 	}
37596212Saw148015 
37606212Saw148015 	/* Get the type for the random variable */
37616212Saw148015 	if (attr = get_attr(cmd, FSA_TYPE)) {
37626212Saw148015 		int disttype = (int)avd_get_int(attr->attr_avd);
37636212Saw148015 
37646212Saw148015 		switch (disttype) {
37656212Saw148015 		case FSV_RANDUNI:
37666212Saw148015 			rndp->rnd_type |= RAND_TYPE_UNIFORM;
37676212Saw148015 			break;
37686212Saw148015 		case FSA_RANDGAMMA:
37696212Saw148015 			rndp->rnd_type |= RAND_TYPE_GAMMA;
37706212Saw148015 			break;
37716212Saw148015 		case FSV_RANDTAB:
37726212Saw148015 			filebench_log(LOG_ERROR,
37736212Saw148015 			    "Table distribution type without prob table");
37746212Saw148015 			break;
37756212Saw148015 		}
37766212Saw148015 	} else {
37776212Saw148015 		/* default to gamma distribution type */
37786212Saw148015 		rndp->rnd_type |= RAND_TYPE_GAMMA;
37796212Saw148015 	}
37806212Saw148015 
37816212Saw148015 	/* Get the seed for the random variable */
37826212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDSEED))
37836212Saw148015 		rndp->rnd_seed = attr->attr_avd;
37846212Saw148015 	else
37856212Saw148015 		rndp->rnd_seed = avd_int_alloc(0);
37866212Saw148015 
37876212Saw148015 	/* Get the gamma value of the random distribution */
37886212Saw148015 	if (attr = get_attr_integer(cmd, FSA_RANDGAMMA))
37896212Saw148015 		rndp->rnd_gamma = attr->attr_avd;
37906212Saw148015 	else
37916212Saw148015 		rndp->rnd_gamma = avd_int_alloc(1500);
37928404SAndrew.W.Wilson@sun.com 
37938404SAndrew.W.Wilson@sun.com 	/* Get the mean value of the random distribution */
37948404SAndrew.W.Wilson@sun.com 	if (attr = get_attr_integer(cmd, FSA_RANDMEAN)) {
37958404SAndrew.W.Wilson@sun.com 		rndp->rnd_mean = attr->attr_avd;
37968404SAndrew.W.Wilson@sun.com 	} else if ((rndp->rnd_type & RAND_TYPE_MASK) == RAND_TYPE_GAMMA) {
37978404SAndrew.W.Wilson@sun.com 		rndp->rnd_mean = NULL;
37988404SAndrew.W.Wilson@sun.com 	} else {
37998404SAndrew.W.Wilson@sun.com 		rndp->rnd_mean = avd_int_alloc(0);
38008404SAndrew.W.Wilson@sun.com 	}
38016212Saw148015 }
38026212Saw148015 
38036212Saw148015 /*
38046212Saw148015  * Set a specified random distribution parameter in a random variable.
38056212Saw148015  */
38066212Saw148015 static void
38076212Saw148015 parser_randvar_set(cmd_t *cmd)
38086212Saw148015 {
38096212Saw148015 	var_t		*src_var, *randvar;
38106212Saw148015 	randdist_t	*rndp;
38116212Saw148015 	avd_t	value;
38126212Saw148015 
38136212Saw148015 	if ((randvar = var_find_randvar(cmd->cmd_tgt1)) == NULL) {
38146212Saw148015 		filebench_log(LOG_ERROR,
38156212Saw148015 		    "set randvar: failed",
38166212Saw148015 		    cmd->cmd_tgt1);
38176212Saw148015 		return;
38186212Saw148015 	}
38196212Saw148015 
38206212Saw148015 	rndp = randvar->var_val.randptr;
38216212Saw148015 	value = cmd->cmd_attr_list->attr_avd;
38226212Saw148015 
38236212Saw148015 	switch (cmd->cmd_qty) {
38246212Saw148015 	case FSS_TYPE:
38256212Saw148015 		{
38266212Saw148015 			int disttype = (int)avd_get_int(value);
38276212Saw148015 
38286212Saw148015 			rndp->rnd_type &= (~RAND_TYPE_MASK);
38296212Saw148015 
38306212Saw148015 			switch (disttype) {
38316212Saw148015 			case FSV_RANDUNI:
38326212Saw148015 				rndp->rnd_type |= RAND_TYPE_UNIFORM;
38336212Saw148015 				break;
38346212Saw148015 			case FSA_RANDGAMMA:
38356212Saw148015 				rndp->rnd_type |= RAND_TYPE_GAMMA;
38366212Saw148015 				break;
38376212Saw148015 			case FSV_RANDTAB:
38386212Saw148015 				rndp->rnd_type |= RAND_TYPE_TABLE;
38396212Saw148015 				break;
38406212Saw148015 			}
38416212Saw148015 			break;
38426212Saw148015 		}
38436212Saw148015 
38446212Saw148015 	case FSS_SRC:
38456212Saw148015 		{
38466212Saw148015 			int randsrc = (int)avd_get_int(value);
38476212Saw148015 
38486212Saw148015 			rndp->rnd_type &=
38496212Saw148015 			    (~(RAND_SRC_URANDOM | RAND_SRC_GENERATOR));
38506212Saw148015 
38516212Saw148015 			switch (randsrc) {
38526212Saw148015 			case FSV_URAND:
38536212Saw148015 				rndp->rnd_type |= RAND_SRC_URANDOM;
38546212Saw148015 				break;
38556212Saw148015 			case FSV_RAND48:
38566212Saw148015 				rndp->rnd_type |= RAND_SRC_GENERATOR;
38576212Saw148015 				break;
38586212Saw148015 			}
38596212Saw148015 			break;
38606212Saw148015 		}
38616212Saw148015 
38626212Saw148015 	case FSS_SEED:
38636212Saw148015 		rndp->rnd_seed = value;
38646212Saw148015 		break;
38656212Saw148015 
38666212Saw148015 	case FSS_GAMMA:
38676212Saw148015 		rndp->rnd_gamma = value;
38686212Saw148015 		break;
38696212Saw148015 
38706212Saw148015 	case FSS_MEAN:
38716212Saw148015 		rndp->rnd_mean = value;
38726212Saw148015 		break;
38736212Saw148015 
38746212Saw148015 	case FSS_MIN:
38756212Saw148015 		rndp->rnd_min = value;
38766212Saw148015 		break;
38776212Saw148015 
38786212Saw148015 	case FSS_ROUND:
38796212Saw148015 		rndp->rnd_round = value;
38806212Saw148015 		break;
38816212Saw148015 
38826212Saw148015 	default:
38836212Saw148015 		filebench_log(LOG_ERROR, "setrandvar: undefined attribute");
38846212Saw148015 	}
38856212Saw148015 }
38866212Saw148015 
38876212Saw148015 /*
38885184Sek110237  * alloc_cmd() allocates the required resources for a cmd_t. On failure, a
38895184Sek110237  * filebench_log is issued and NULL is returned.
38905184Sek110237  */
38915184Sek110237 static cmd_t *
38925184Sek110237 alloc_cmd(void)
38935184Sek110237 {
38945184Sek110237 	cmd_t *cmd;
38955184Sek110237 
38965184Sek110237 	if ((cmd = malloc(sizeof (cmd_t))) == NULL) {
38975184Sek110237 		filebench_log(LOG_ERROR, "Alloc cmd failed");
38985184Sek110237 		return (NULL);
38995184Sek110237 	}
39005184Sek110237 
39015184Sek110237 	(void) memset(cmd, 0, sizeof (cmd_t));
39025184Sek110237 
39035184Sek110237 	return (cmd);
39045184Sek110237 }
39055184Sek110237 
39065184Sek110237 /*
39075184Sek110237  * Frees the resources of a cmd_t and then the cmd_t "cmd" itself.
39085184Sek110237  */
39095184Sek110237 static void
39105184Sek110237 free_cmd(cmd_t *cmd)
39115184Sek110237 {
39125184Sek110237 	free((void *)cmd->cmd_tgt1);
39135184Sek110237 	free((void *)cmd->cmd_tgt2);
39145184Sek110237 	free(cmd);
39155184Sek110237 }
39165184Sek110237 
39175184Sek110237 /*
39185184Sek110237  * Allocates an attr_t structure and zeros it. Returns NULL on failure, or
39195184Sek110237  * a pointer to the attr_t.
39205184Sek110237  */
39215184Sek110237 static attr_t *
39226550Saw148015 alloc_attr(void)
39235184Sek110237 {
39245184Sek110237 	attr_t *attr;
39255184Sek110237 
39265184Sek110237 	if ((attr = malloc(sizeof (attr_t))) == NULL) {
39275184Sek110237 		return (NULL);
39285184Sek110237 	}
39295184Sek110237 
39305184Sek110237 	(void) memset(attr, 0, sizeof (attr_t));
39315184Sek110237 	return (attr);
39325184Sek110237 }
39335184Sek110237 
39345184Sek110237 /*
39356212Saw148015  * Allocates a probtabent_t structure and zeros it. Returns NULL on failure, or
39366212Saw148015  * a pointer to the probtabent_t.
39376212Saw148015  */
39386212Saw148015 static probtabent_t *
39396212Saw148015 alloc_probtabent(void)
39406212Saw148015 {
39416212Saw148015 	probtabent_t *rte;
39426212Saw148015 
39436212Saw148015 	if ((rte = malloc(sizeof (probtabent_t))) == NULL) {
39446212Saw148015 		return (NULL);
39456212Saw148015 	}
39466212Saw148015 
39476212Saw148015 	(void) memset(rte, 0, sizeof (probtabent_t));
39486212Saw148015 	return (rte);
39496212Saw148015 }
39506212Saw148015 
39516212Saw148015 /*
39526550Saw148015  * Allocates an attr_t structure and puts the supplied var_t into
39536550Saw148015  * its attr_avd location, and sets its name to FSA_LVAR_ASSIGN
39546550Saw148015  */
39556550Saw148015 static attr_t *
39566550Saw148015 alloc_lvar_attr(var_t *var)
39576550Saw148015 {
39586550Saw148015 	attr_t *attr;
39596550Saw148015 
39606550Saw148015 	if ((attr = alloc_attr()) == NULL)
39616550Saw148015 		return (NULL);
39626550Saw148015 
39636550Saw148015 	attr->attr_name = FSA_LVAR_ASSIGN;
39646550Saw148015 	attr->attr_avd = (avd_t)var;
39656550Saw148015 
39666550Saw148015 	return (attr);
39676550Saw148015 }
39686550Saw148015 
39698404SAndrew.W.Wilson@sun.com 
39708404SAndrew.W.Wilson@sun.com /*
39718404SAndrew.W.Wilson@sun.com  * Searches the attribute list for the command for the named attribute type.
39728404SAndrew.W.Wilson@sun.com  * The attribute list is created by the parser from the list of attributes
39738404SAndrew.W.Wilson@sun.com  * supplied with certain commands, such as the define and flowop commands.
39748404SAndrew.W.Wilson@sun.com  * Returns a pointer to the attribute structure if the named attribute is
39758404SAndrew.W.Wilson@sun.com  * found, otherwise returns NULL. If the attribute includes a parameter list,
39768404SAndrew.W.Wilson@sun.com  * the list is converted to a string and stored in the attr_avd field of
39778404SAndrew.W.Wilson@sun.com  * the returned attr_t struct.
39788404SAndrew.W.Wilson@sun.com  */
39798404SAndrew.W.Wilson@sun.com static attr_t *
39808404SAndrew.W.Wilson@sun.com get_attr_fileset(cmd_t *cmd, int64_t name)
39818404SAndrew.W.Wilson@sun.com {
39828404SAndrew.W.Wilson@sun.com 	attr_t *attr;
39838404SAndrew.W.Wilson@sun.com 	attr_t *rtn = NULL;
39848404SAndrew.W.Wilson@sun.com 	char *string;
39858404SAndrew.W.Wilson@sun.com 
39868404SAndrew.W.Wilson@sun.com 	for (attr = cmd->cmd_attr_list; attr != NULL;
39878404SAndrew.W.Wilson@sun.com 	    attr = attr->attr_next) {
39888404SAndrew.W.Wilson@sun.com 		filebench_log(LOG_DEBUG_IMPL,
39898404SAndrew.W.Wilson@sun.com 		    "attr %d = %d %llx?",
39908404SAndrew.W.Wilson@sun.com 		    attr->attr_name,
39918404SAndrew.W.Wilson@sun.com 		    name,
39928404SAndrew.W.Wilson@sun.com 		    attr->attr_avd);
39938404SAndrew.W.Wilson@sun.com 
39948404SAndrew.W.Wilson@sun.com 		if (attr->attr_name == name)
39958404SAndrew.W.Wilson@sun.com 			rtn = attr;
39968404SAndrew.W.Wilson@sun.com 	}
39978404SAndrew.W.Wilson@sun.com 
39988404SAndrew.W.Wilson@sun.com 	if (rtn == NULL)
39998404SAndrew.W.Wilson@sun.com 		return (NULL);
40008404SAndrew.W.Wilson@sun.com 
40018404SAndrew.W.Wilson@sun.com 	if (rtn->attr_param_list) {
40028404SAndrew.W.Wilson@sun.com 		filebench_log(LOG_DEBUG_SCRIPT, "attr is param list");
40038404SAndrew.W.Wilson@sun.com 		rtn->attr_avd = parser_list2varstring(rtn->attr_param_list);
40048404SAndrew.W.Wilson@sun.com 	}
40058404SAndrew.W.Wilson@sun.com 
40068404SAndrew.W.Wilson@sun.com 	return (rtn);
40078404SAndrew.W.Wilson@sun.com }
40088404SAndrew.W.Wilson@sun.com 
40098404SAndrew.W.Wilson@sun.com 
40106550Saw148015 /*
40115184Sek110237  * Searches the attribute list for the command for the named attribute type.
40125184Sek110237  * The attribute list is created by the parser from the list of attributes
40135184Sek110237  * supplied with certain commands, such as the define and flowop commands.
40145184Sek110237  * Returns a pointer to the attribute structure if the named attribute is
40155184Sek110237  * found, otherwise returns NULL. If the attribute includes a parameter list,
40166212Saw148015  * the list is converted to a string and stored in the attr_avd field of
40175184Sek110237  * the returned attr_t struct.
40185184Sek110237  */
40195184Sek110237 static attr_t *
40205184Sek110237 get_attr(cmd_t *cmd, int64_t name)
40215184Sek110237 {
40225184Sek110237 	attr_t *attr;
40235184Sek110237 	attr_t *rtn = NULL;
40245184Sek110237 	char *string;
40255184Sek110237 
40265184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
40275184Sek110237 	    attr = attr->attr_next) {
40285184Sek110237 		filebench_log(LOG_DEBUG_IMPL,
40295184Sek110237 		    "attr %d = %d %llx?",
40305184Sek110237 		    attr->attr_name,
40315184Sek110237 		    name,
40326212Saw148015 		    attr->attr_avd);
40335184Sek110237 
40345184Sek110237 		if (attr->attr_name == name)
40355184Sek110237 			rtn = attr;
40365184Sek110237 	}
40375184Sek110237 
40385184Sek110237 	if (rtn == NULL)
40395184Sek110237 		return (NULL);
40405184Sek110237 
40415184Sek110237 	if (rtn->attr_param_list) {
40425184Sek110237 		filebench_log(LOG_DEBUG_SCRIPT, "attr is param list");
40435184Sek110237 		string = parser_list2string(rtn->attr_param_list);
40445184Sek110237 		if (string != NULL) {
40456212Saw148015 			rtn->attr_avd = avd_str_alloc(string);
40465184Sek110237 			filebench_log(LOG_DEBUG_SCRIPT,
40475184Sek110237 			    "attr string %s", string);
40485184Sek110237 		}
40495184Sek110237 	}
40505184Sek110237 
40515184Sek110237 	return (rtn);
40525184Sek110237 }
40535184Sek110237 
40545184Sek110237 /*
40555184Sek110237  * Similar to get_attr, but converts the parameter string supplied with the
40566212Saw148015  * named attribute to an integer and stores the integer in the attr_avd
40575184Sek110237  * portion of the returned attr_t struct.
40585184Sek110237  */
40595184Sek110237 static attr_t *
40605184Sek110237 get_attr_integer(cmd_t *cmd, int64_t name)
40615184Sek110237 {
40625184Sek110237 	attr_t *attr;
40635184Sek110237 	attr_t *rtn = NULL;
40645184Sek110237 
40655184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
40665184Sek110237 	    attr = attr->attr_next) {
40675184Sek110237 		if (attr->attr_name == name)
40685184Sek110237 			rtn = attr;
40695184Sek110237 	}
40705184Sek110237 
40715184Sek110237 	if (rtn == NULL)
40725184Sek110237 		return (NULL);
40735184Sek110237 
40746212Saw148015 	if (rtn->attr_param_list)
40756212Saw148015 		rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
40765184Sek110237 
40775184Sek110237 	return (rtn);
40785184Sek110237 }
40795184Sek110237 
40805184Sek110237 /*
40815184Sek110237  * Similar to get_attr, but converts the parameter string supplied with the
40826212Saw148015  * named attribute to an integer and stores the integer in the attr_avd
40835184Sek110237  * portion of the returned attr_t struct. If no parameter string is supplied
40845184Sek110237  * then it defaults to TRUE (1).
40855184Sek110237  */
40865184Sek110237 static attr_t *
40875184Sek110237 get_attr_bool(cmd_t *cmd, int64_t name)
40885184Sek110237 {
40895184Sek110237 	attr_t *attr;
40905184Sek110237 	attr_t *rtn = NULL;
40915184Sek110237 
40925184Sek110237 	for (attr = cmd->cmd_attr_list; attr != NULL;
40935184Sek110237 	    attr = attr->attr_next) {
40945184Sek110237 		if (attr->attr_name == name)
40955184Sek110237 			rtn = attr;
40965184Sek110237 	}
40975184Sek110237 
40985184Sek110237 	if (rtn == NULL)
40995184Sek110237 		return (NULL);
41005184Sek110237 
41015184Sek110237 	if (rtn->attr_param_list) {
41026212Saw148015 		rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
41036212Saw148015 
41046212Saw148015 	} else if (rtn->attr_avd == NULL) {
41056212Saw148015 		rtn->attr_avd = avd_bool_alloc(TRUE);
41066212Saw148015 	}
41076212Saw148015 
41086212Saw148015 	/* boolean attributes cannot point to random variables */
41096212Saw148015 	if (AVD_IS_RANDOM(rtn->attr_avd)) {
41106212Saw148015 		filebench_log(LOG_ERROR,
41116212Saw148015 		    "define flowop: Boolean attr %s cannot be random", name);
41126212Saw148015 		filebench_shutdown(1);
41136212Saw148015 		return (NULL);
41145184Sek110237 	}
41155184Sek110237 
41165184Sek110237 	return (rtn);
41175184Sek110237 }
41185184Sek110237 
41195184Sek110237 /*
41206550Saw148015  * removes the newly allocated local var from the shared local var
41216550Saw148015  * list, then puts it at the head of the private local var list
41226550Saw148015  * supplied as the second argument.
41236550Saw148015  */
41246550Saw148015 static void
41256550Saw148015 add_lvar_to_list(var_t *newlvar, var_t **lvar_list)
41266550Saw148015 {
41276550Saw148015 	var_t *prev;
41286550Saw148015 
41296550Saw148015 	/* remove from shared local list, if there */
41306550Saw148015 	if (newlvar == filebench_shm->shm_var_loc_list) {
41316550Saw148015 		/* on top of list, just grap */
41326550Saw148015 		filebench_shm->shm_var_loc_list = newlvar->var_next;
41336550Saw148015 	} else {
41346550Saw148015 		/* find newvar on list and remove */
41356550Saw148015 		for (prev = filebench_shm->shm_var_loc_list; prev;
41366550Saw148015 		    prev = prev->var_next) {
41376550Saw148015 			if (prev->var_next == newlvar)
41386550Saw148015 				prev->var_next = newlvar->var_next;
41396550Saw148015 		}
41406550Saw148015 	}
41416550Saw148015 	newlvar->var_next = NULL;
41426550Saw148015 
41436550Saw148015 	/* add to flowop private local list at head */
41446550Saw148015 	newlvar->var_next = *lvar_list;
41456550Saw148015 	*lvar_list = newlvar;
41466550Saw148015 }
41476550Saw148015 
41486550Saw148015 /*
41496550Saw148015  * Searches the attribute list for the command for any allocated local
41506550Saw148015  * variables. The attribute list is created by the parser from the list of
41516550Saw148015  * attributes supplied with certain commands, such as the define and flowop
41526550Saw148015  * commands. Places all found local vars onto the flowop's local variable
41536550Saw148015  * list.
41546550Saw148015  */
41556550Saw148015 static void
41566550Saw148015 get_attr_lvars(cmd_t *cmd, flowop_t *flowop)
41576550Saw148015 {
41586550Saw148015 	attr_t *attr;
41596550Saw148015 	var_t *list_tail, *orig_lvar_list;
41606550Saw148015 
41616550Saw148015 	/* save the local var list */
41626550Saw148015 	orig_lvar_list = flowop->fo_lvar_list;
41636550Saw148015 
41646550Saw148015 	for (attr = cmd->cmd_attr_list; attr != NULL;
41656550Saw148015 	    attr = attr->attr_next) {
41666550Saw148015 
41676550Saw148015 		if (attr->attr_name == FSA_LVAR_ASSIGN) {
41686550Saw148015 			var_t *newvar, *prev;
41696550Saw148015 
41706550Saw148015 			if ((newvar = (var_t *)attr->attr_avd) == NULL)
41716550Saw148015 				continue;
41726550Saw148015 
41736550Saw148015 			add_lvar_to_list(newvar, &flowop->fo_lvar_list);
41746550Saw148015 			var_update_comp_lvars(newvar, orig_lvar_list, NULL);
41756550Saw148015 		}
41766550Saw148015 	}
41776550Saw148015 }
41786550Saw148015 
41796550Saw148015 /*
41805184Sek110237  * Allocates memory for a list_t structure, initializes it to zero, and
41815184Sek110237  * returns a pointer to it. On failure, returns NULL.
41825184Sek110237  */
41835184Sek110237 static list_t *
41845184Sek110237 alloc_list()
41855184Sek110237 {
41865184Sek110237 	list_t *list;
41875184Sek110237 
41885184Sek110237 	if ((list = malloc(sizeof (list_t))) == NULL) {
41895184Sek110237 		return (NULL);
41905184Sek110237 	}
41915184Sek110237 
41925184Sek110237 	(void) memset(list, 0, sizeof (list_t));
41935184Sek110237 	return (list);
41945184Sek110237 }
41955184Sek110237 
41965184Sek110237 
41975184Sek110237 #define	USAGE1	\
41985184Sek110237 "Usage:\n" \
41996613Sek110237 "go_filebench: interpret f script and generate file workload\n" \
42005184Sek110237 "Options:\n" \
42015184Sek110237 "   [-h] Display verbose help\n" \
42025184Sek110237 "   [-p] Disable opening /proc to set uacct to enable truss\n"
42035184Sek110237 
42045184Sek110237 #define	PARSER_CMDS \
42055184Sek110237 "create [files|filesets|processes]\n" \
42065184Sek110237 "stats [clear|snap]\n" \
42075184Sek110237 "stats command \"shell command $var1,$var2...\"\n" \
42085184Sek110237 "stats directory <directory>\n" \
42095184Sek110237 "sleep <sleep-value>\n" \
42105184Sek110237 "quit\n\n" \
42115184Sek110237 "Variables:\n" \
42125184Sek110237 "set $var = value\n" \
42135184Sek110237 "    $var   - regular variables\n" \
42145184Sek110237 "    ${var} - internal special variables\n" \
42155184Sek110237 "    $(var) - environment variables\n\n"
42165184Sek110237 
42175184Sek110237 #define	PARSER_EXAMPLE \
42185184Sek110237 "Example:\n\n" \
42196613Sek110237 "#!" FILEBENCHDIR "/bin/go_filebench -f\n" \
42205184Sek110237 "\n" \
42215184Sek110237 "define file name=bigfile,path=bigfile,size=1g,prealloc,reuse\n" \
42225184Sek110237 "define process name=randomizer\n" \
42235184Sek110237 "{\n" \
42245184Sek110237 "  thread random-thread procname=randomizer\n"	\
42255184Sek110237 "  {\n" \
42265184Sek110237 "    flowop read name=random-read,filename=bigfile,iosize=16k,random\n" \
42275184Sek110237 "  }\n" \
42285184Sek110237 "}\n" \
42295184Sek110237 "create files\n" \
42305184Sek110237 "create processes\n" \
42315184Sek110237 "stats clear\n" \
42325184Sek110237 "sleep 30\n" \
42335184Sek110237 "stats snap\n"
42345184Sek110237 
42355184Sek110237 /*
42365184Sek110237  * usage() display brief or verbose help for the filebench(1) command.
42375184Sek110237  */
42385184Sek110237 static void
42395184Sek110237 usage(int help)
42405184Sek110237 {
42415184Sek110237 	if (help >= 1)
42425184Sek110237 		(void) fprintf(stderr, USAGE1, cmdname);
42435184Sek110237 	if (help >= 2) {
42445184Sek110237 
42455184Sek110237 		(void) fprintf(stderr,
42465184Sek110237 		    "\n'f' language definition:\n\n");
42475184Sek110237 		fileset_usage();
42485184Sek110237 		procflow_usage();
42495184Sek110237 		threadflow_usage();
42505184Sek110237 		flowoplib_usage();
42515184Sek110237 		eventgen_usage();
42525184Sek110237 		(void) fprintf(stderr, PARSER_CMDS);
42535184Sek110237 		(void) fprintf(stderr, PARSER_EXAMPLE);
42545184Sek110237 	}
42555184Sek110237 	exit(E_USAGE);
42565184Sek110237 }
42575184Sek110237 
42585184Sek110237 int
42595184Sek110237 yywrap()
42605184Sek110237 {
42615184Sek110237 	char buf[1024];
42625184Sek110237 
42635184Sek110237 	if (parentscript) {
42645184Sek110237 		yyin = parentscript;
42655184Sek110237 		yy_switchfilescript(yyin);
42665184Sek110237 		parentscript = NULL;
42675184Sek110237 		return (0);
42685184Sek110237 	} else
42695184Sek110237 		return (1);
42705184Sek110237 }
4271