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 /*
226212Saw148015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235184Sek110237  * Use is subject to license terms.
245184Sek110237  */
255184Sek110237 
265184Sek110237 #pragma ident	"%Z%%M%	%I%	%E% SMI"
275184Sek110237 
285184Sek110237 #include <stdlib.h>
295184Sek110237 #include <stdio.h>
305184Sek110237 #include <string.h>
315184Sek110237 #include <errno.h>
325184Sek110237 
335184Sek110237 #include "vars.h"
345184Sek110237 #include "misc.h"
355184Sek110237 #include "utils.h"
365184Sek110237 #include "stats.h"
375184Sek110237 #include "eventgen.h"
385184Sek110237 #include "filebench.h"
396212Saw148015 #include "fb_random.h"
405184Sek110237 
415184Sek110237 static var_t *var_find_dynamic(char *name);
425184Sek110237 
435184Sek110237 /*
446212Saw148015  * The filebench variables system has attribute value descriptors (avd_t)
456212Saw148015  * where an avd contains a boolean, integer, double, string, random
466212Saw148015  * distribution object ptr, boolean ptr, integer ptr, double ptr,
476212Saw148015  * string ptr, or variable ptr. The system also has the variables
486212Saw148015  * themselves, (var_t), which are named, typed entities which can be
496212Saw148015  * allocated, selected and changed using the "set" command and used in
506212Saw148015  * attribute assignments. The variables contain either a boolean, an
516212Saw148015  * integer, a double, a string or pointer to an associated random
526212Saw148015  * distribution object. Both avd_t and var_t entities are allocated
535184Sek110237  * from interprocess shared memory space.
545184Sek110237  *
556212Saw148015  * The attribute descriptors implement delayed binding to variable values,
566212Saw148015  * which is necessary because the values of variables may be changed
576212Saw148015  * between the time the workload file is loaded and it is actually run,
586212Saw148015  * either by further "set" commands in the file or from the command line
596212Saw148015  * interface. For random variables, they actually point to the random
606212Saw148015  * distribution object, allowing FileBench to invoke the appropriate
616212Saw148015  * random distribution function on each access to the attribute. However,
626212Saw148015  * for static attributes, the value is just loaded in the descriptor
636212Saw148015  * directly, avoiding the need to allocate a variable to hold the static
646212Saw148015  * value.
656212Saw148015  *
665184Sek110237  * The routines in this module are used to allocate, locate, and
676212Saw148015  * manipulate the attribute descriptors, and vars. Routines are
686212Saw148015  * also included to convert between the component strings, doubles
696212Saw148015  * and integers of vars, and said components of avd_t.
705184Sek110237  */
715184Sek110237 
72*6550Saw148015 
735184Sek110237 /*
746212Saw148015  * returns a pointer to a string indicating the type of data contained
756212Saw148015  * in the supplied attribute variable descriptor.
765184Sek110237  */
776212Saw148015 static char *
786212Saw148015 avd_get_type_string(avd_t avd)
795184Sek110237 {
806212Saw148015 	switch (avd->avd_type) {
816212Saw148015 	case AVD_INVALID:
826212Saw148015 		return ("uninitialized");
836212Saw148015 
846212Saw148015 	case AVD_VAL_BOOL:
856212Saw148015 		return ("boolean value");
866212Saw148015 
876212Saw148015 	case AVD_VARVAL_BOOL:
886212Saw148015 		return ("points to boolean in var_t");
896212Saw148015 
906212Saw148015 	case AVD_VAL_INT:
916212Saw148015 		return ("integer value");
926212Saw148015 
936212Saw148015 	case AVD_VARVAL_INT:
946212Saw148015 		return ("points to integer in var_t");
956212Saw148015 
966212Saw148015 	case AVD_VAL_STR:
976212Saw148015 		return ("string");
986212Saw148015 
996212Saw148015 	case AVD_VARVAL_STR:
1006212Saw148015 		return ("points to string in var_t");
1016212Saw148015 
1026212Saw148015 	case AVD_VAL_DBL:
1036212Saw148015 		return ("double float value");
1046212Saw148015 
1056212Saw148015 	case AVD_VARVAL_DBL:
1066212Saw148015 		return ("points to double float in var_t");
1076212Saw148015 
1086212Saw148015 	case AVD_IND_VAR:
1096212Saw148015 		return ("points to a var_t");
1106212Saw148015 
1116212Saw148015 	case AVD_IND_RANDVAR:
1126212Saw148015 		return ("points to var_t's random distribution object");
1136212Saw148015 
1146212Saw148015 	default:
1156212Saw148015 		return ("illegal avd type");
1166212Saw148015 	}
1176212Saw148015 }
1186212Saw148015 
1196212Saw148015 /*
1206212Saw148015  * returns a pointer to a string indicating the type of data contained
1216212Saw148015  * in the supplied variable.
1226212Saw148015  */
1236212Saw148015 static char *
1246212Saw148015 var_get_type_string(var_t *ivp)
1256212Saw148015 {
1266212Saw148015 	switch (ivp->var_type & VAR_TYPE_SET_MASK) {
1276212Saw148015 	case VAR_TYPE_BOOL_SET:
1286212Saw148015 		return ("boolean");
1296212Saw148015 
1306212Saw148015 	case VAR_TYPE_INT_SET:
1316212Saw148015 		return ("integer");
1326212Saw148015 
1336212Saw148015 	case VAR_TYPE_STR_SET:
1346212Saw148015 		return ("string");
1356212Saw148015 
1366212Saw148015 	case VAR_TYPE_DBL_SET:
1376212Saw148015 		return ("double float");
1386212Saw148015 
1396212Saw148015 	case VAR_TYPE_RAND_SET:
1406212Saw148015 		return ("random");
1416212Saw148015 
1426212Saw148015 	default:
1436212Saw148015 		return ("empty");
1446212Saw148015 	}
1456212Saw148015 }
1466212Saw148015 
1476212Saw148015 /*
1486212Saw148015  * Returns the fbint_t pointed to by the supplied avd_t "avd".
1496212Saw148015  */
1506212Saw148015 fbint_t
1516212Saw148015 avd_get_int(avd_t avd)
1526212Saw148015 {
1536212Saw148015 	var_t *ivp;
1546212Saw148015 	randdist_t *rndp;
1556212Saw148015 
1566212Saw148015 	if (avd == NULL)
1575184Sek110237 		return (0);
1585184Sek110237 
1596212Saw148015 	switch (avd->avd_type) {
1606212Saw148015 	case AVD_VAL_INT:
1616212Saw148015 		return (avd->avd_val.intval);
1626212Saw148015 
1636212Saw148015 	case AVD_VARVAL_INT:
1646212Saw148015 		if (avd->avd_val.intptr)
1656212Saw148015 			return (*(avd->avd_val.intptr));
1666212Saw148015 		else
1676212Saw148015 			return (0);
1686212Saw148015 
1696212Saw148015 	case AVD_IND_VAR:
1706212Saw148015 		if ((ivp = avd->avd_val.varptr) == NULL)
1716212Saw148015 			return (0);
1726212Saw148015 
1736212Saw148015 		if (VAR_HAS_INTEGER(ivp))
1746212Saw148015 			return (ivp->var_val.integer);
1756212Saw148015 
1766212Saw148015 		if (VAR_HAS_RANDDIST(ivp)) {
1776212Saw148015 			if ((rndp = ivp->var_val.randptr) != NULL)
1786212Saw148015 				return ((fbint_t)rndp->rnd_get(rndp));
1796212Saw148015 		}
1806212Saw148015 
1816212Saw148015 		filebench_log(LOG_ERROR,
1826212Saw148015 		    "Attempt to get integer from %s var $%s",
1836212Saw148015 		    var_get_type_string(ivp), ivp->var_name);
1846212Saw148015 		return (0);
1856212Saw148015 
1866212Saw148015 	case AVD_IND_RANDVAR:
1876212Saw148015 		if ((rndp = avd->avd_val.randptr) == NULL)
1886212Saw148015 			return (0);
1896212Saw148015 		else
1906212Saw148015 			return ((fbint_t)rndp->rnd_get(rndp));
1916212Saw148015 
1926212Saw148015 	default:
1936212Saw148015 		filebench_log(LOG_ERROR,
1946212Saw148015 		    "Attempt to get integer from %s avd",
1956212Saw148015 		    avd_get_type_string(avd));
1966212Saw148015 		return (0);
1976212Saw148015 	}
1985184Sek110237 }
1995184Sek110237 
2005184Sek110237 /*
2016212Saw148015  * Returns the floating point value of a variable pointed to by the
2026212Saw148015  * supplied avd_t "avd". Intended to get the actual (double) value
2036212Saw148015  * supplied by the random variable.
2046212Saw148015  */
2056212Saw148015 double
2066212Saw148015 avd_get_dbl(avd_t avd)
2076212Saw148015 {
2086212Saw148015 	var_t *ivp;
2096212Saw148015 	randdist_t *rndp;
2106212Saw148015 
2116212Saw148015 	if (avd == NULL)
2126212Saw148015 		return (0.0);
2136212Saw148015 
2146212Saw148015 	switch (avd->avd_type) {
2156212Saw148015 	case AVD_VAL_INT:
2166212Saw148015 		return ((double)avd->avd_val.intval);
2176212Saw148015 
2186212Saw148015 	case AVD_VAL_DBL:
2196212Saw148015 		return (avd->avd_val.dblval);
2206212Saw148015 
2216212Saw148015 	case AVD_VARVAL_INT:
2226212Saw148015 		if (avd->avd_val.intptr)
2236212Saw148015 			return ((double)(*(avd->avd_val.intptr)));
2246212Saw148015 		else
2256212Saw148015 			return (0.0);
2266212Saw148015 
2276212Saw148015 	case AVD_VARVAL_DBL:
2286212Saw148015 		if (avd->avd_val.dblptr)
2296212Saw148015 			return (*(avd->avd_val.dblptr));
2306212Saw148015 		else
2316212Saw148015 			return (0.0);
2326212Saw148015 
2336212Saw148015 	case AVD_IND_VAR:
2346212Saw148015 		ivp = avd->avd_val.varptr;
2356212Saw148015 
2366212Saw148015 		if (ivp && VAR_HAS_INTEGER(ivp))
2376212Saw148015 			return ((double)ivp->var_val.integer);
2386212Saw148015 
2396212Saw148015 		if (ivp && VAR_HAS_DOUBLE(ivp))
2406212Saw148015 			return (ivp->var_val.dbl_flt);
2416212Saw148015 
2426212Saw148015 		if (ivp && VAR_HAS_RANDDIST(ivp)) {
2436212Saw148015 			if ((rndp = ivp->var_val.randptr) != NULL)
2446212Saw148015 				return (rndp->rnd_get(rndp));
2456212Saw148015 		}
2466212Saw148015 		filebench_log(LOG_ERROR,
2476212Saw148015 		    "Attempt to get double float from %s var $%s",
2486212Saw148015 		    var_get_type_string(ivp), ivp->var_name);
2496212Saw148015 		return (0.0);
2506212Saw148015 
2516212Saw148015 	case AVD_IND_RANDVAR:
2526212Saw148015 		if ((rndp = avd->avd_val.randptr) == NULL) {
2536212Saw148015 			return (0.0);
2546212Saw148015 		} else
2556212Saw148015 			return (rndp->rnd_get(rndp));
2566212Saw148015 
2576212Saw148015 	default:
2586212Saw148015 		filebench_log(LOG_ERROR,
2596212Saw148015 		    "Attempt to get floating point from %s avd",
2606212Saw148015 		    avd_get_type_string(avd));
2616212Saw148015 		return (0.0);
2626212Saw148015 	}
2636212Saw148015 }
2646212Saw148015 
2656212Saw148015 /*
2666212Saw148015  * Returns the boolean pointed to by the supplied avd_t "avd".
2675184Sek110237  */
2686212Saw148015 boolean_t
2696212Saw148015 avd_get_bool(avd_t avd)
2705184Sek110237 {
2716212Saw148015 	var_t *ivp;
2726212Saw148015 
2736212Saw148015 	if (avd == NULL)
2746212Saw148015 		return (0);
2756212Saw148015 
2766212Saw148015 	switch (avd->avd_type) {
2776212Saw148015 	case AVD_VAL_BOOL:
2786212Saw148015 		return (avd->avd_val.boolval);
2796212Saw148015 
2806212Saw148015 	case AVD_VARVAL_BOOL:
2816212Saw148015 		if (avd->avd_val.boolptr)
2826212Saw148015 			return (*(avd->avd_val.boolptr));
2836212Saw148015 		else
2846212Saw148015 			return (FALSE);
2856212Saw148015 
2866212Saw148015 	/* for backwards compatibility with old workloads */
2876212Saw148015 	case AVD_VAL_INT:
2886212Saw148015 		if (avd->avd_val.intval != 0)
2896212Saw148015 			return (TRUE);
2906212Saw148015 		else
2916212Saw148015 			return (FALSE);
2926212Saw148015 
2936212Saw148015 	case AVD_VARVAL_INT:
2946212Saw148015 		if (avd->avd_val.intptr)
2956212Saw148015 			if (*(avd->avd_val.intptr) != 0)
2966212Saw148015 				return (TRUE);
2976212Saw148015 
2986212Saw148015 		return (FALSE);
2996212Saw148015 
3006212Saw148015 	case AVD_IND_VAR:
3016212Saw148015 		if ((ivp = avd->avd_val.varptr) == NULL)
3026212Saw148015 			return (0);
3036212Saw148015 
3046212Saw148015 		if (VAR_HAS_BOOLEAN(ivp))
3056212Saw148015 			return (ivp->var_val.boolean);
3066212Saw148015 
3076212Saw148015 		if (VAR_HAS_INTEGER(ivp)) {
3086212Saw148015 			if (ivp->var_val.boolean)
3096212Saw148015 				return (TRUE);
3106212Saw148015 			else
3116212Saw148015 				return (FALSE);
3126212Saw148015 		}
3135184Sek110237 
3146212Saw148015 		filebench_log(LOG_ERROR,
3156212Saw148015 		    "Attempt to get boolean from %s var $%s",
3166212Saw148015 		    var_get_type_string(ivp), ivp->var_name);
3176212Saw148015 		return (FALSE);
3186212Saw148015 
3196212Saw148015 	default:
3206212Saw148015 		filebench_log(LOG_ERROR,
3216212Saw148015 		    "Attempt to get boolean from %s avd",
3226212Saw148015 		    avd_get_type_string(avd));
3236212Saw148015 		return (FALSE);
3246212Saw148015 	}
3256212Saw148015 }
3266212Saw148015 
3276212Saw148015 /*
3286212Saw148015  * Returns the string pointed to by the supplied avd_t "avd".
3296212Saw148015  */
3306212Saw148015 char *
3316212Saw148015 avd_get_str(avd_t avd)
3326212Saw148015 {
3336212Saw148015 	var_t *ivp;
3346212Saw148015 
3356212Saw148015 	if (avd == NULL)
3366212Saw148015 		return (NULL);
3376212Saw148015 
3386212Saw148015 	switch (avd->avd_type) {
3396212Saw148015 	case AVD_VAL_STR:
3406212Saw148015 		return (avd->avd_val.strval);
3416212Saw148015 
3426212Saw148015 	case AVD_VARVAL_STR:
3436212Saw148015 		if (avd->avd_val.strptr)
3446212Saw148015 			return (*avd->avd_val.strptr);
3456212Saw148015 		else
3466212Saw148015 			return (NULL);
3476212Saw148015 
3486212Saw148015 	case AVD_IND_VAR:
3496212Saw148015 		ivp = avd->avd_val.varptr;
3506212Saw148015 
3516212Saw148015 		if (ivp && VAR_HAS_STRING(ivp))
3526212Saw148015 			return (ivp->var_val.string);
3536212Saw148015 
3546212Saw148015 		filebench_log(LOG_ERROR,
3556212Saw148015 		    "Attempt to get string from %s var $%s",
3566212Saw148015 		    var_get_type_string(ivp), ivp->var_name);
3576212Saw148015 		return (NULL);
3586212Saw148015 
3596212Saw148015 	default:
3606212Saw148015 		filebench_log(LOG_ERROR,
3616212Saw148015 		    "Attempt to get string from %s avd",
3626212Saw148015 		    avd_get_type_string(avd));
3635184Sek110237 		return (NULL);
3645184Sek110237 	}
3656212Saw148015 }
3665184Sek110237 
3676212Saw148015 /*
3686212Saw148015  * Allocates a avd_t from ipc memory space.
3696212Saw148015  * logs an error and returns NULL on failure.
3706212Saw148015  */
3716212Saw148015 static avd_t
3726212Saw148015 avd_alloc_cmn(void)
3736212Saw148015 {
3746212Saw148015 	avd_t rtn;
3755184Sek110237 
3766212Saw148015 	if ((rtn = (avd_t)ipc_malloc(FILEBENCH_AVD)) == NULL)
3776212Saw148015 		filebench_log(LOG_ERROR, "Avd alloc failed");
3785184Sek110237 
3795184Sek110237 	return (rtn);
3805184Sek110237 }
3815184Sek110237 
3825184Sek110237 /*
3836212Saw148015  * pre-loads the allocated avd_t with the boolean_t "bool".
3846212Saw148015  * Returns the avd_t on success, NULL on failure.
3856212Saw148015  */
3866212Saw148015 avd_t
3876212Saw148015 avd_bool_alloc(boolean_t bool)
3886212Saw148015 {
3896212Saw148015 	avd_t avd;
3906212Saw148015 
3916212Saw148015 	if ((avd = avd_alloc_cmn()) == NULL)
3926212Saw148015 		return (NULL);
3936212Saw148015 
3946212Saw148015 	avd->avd_type = AVD_VAL_BOOL;
3956212Saw148015 	avd->avd_val.boolval = bool;
3966212Saw148015 
3976212Saw148015 	filebench_log(LOG_DEBUG_IMPL, "Alloc boolean %d", bool);
3986212Saw148015 
3996212Saw148015 	return (avd);
4006212Saw148015 }
4016212Saw148015 
4026212Saw148015 /*
4036212Saw148015  * pre-loads the allocated avd_t with the fbint_t "integer".
4046212Saw148015  * Returns the avd_t on success, NULL on failure.
4056212Saw148015  */
4066212Saw148015 avd_t
4076212Saw148015 avd_int_alloc(fbint_t integer)
4086212Saw148015 {
4096212Saw148015 	avd_t avd;
4106212Saw148015 
4116212Saw148015 	if ((avd = avd_alloc_cmn()) == NULL)
4126212Saw148015 		return (NULL);
4136212Saw148015 
4146212Saw148015 	avd->avd_type = AVD_VAL_INT;
4156212Saw148015 	avd->avd_val.intval = integer;
4166212Saw148015 
4176286Saw148015 	filebench_log(LOG_DEBUG_IMPL, "Alloc integer %llu",
4186286Saw148015 	    (u_longlong_t)integer);
4196212Saw148015 
4206212Saw148015 	return (avd);
4216212Saw148015 }
4226212Saw148015 
4236212Saw148015 /*
4246212Saw148015  * Gets a avd_t and points it to the var that
4256212Saw148015  * it will eventually be filled from
4265184Sek110237  */
4276212Saw148015 static avd_t
4286212Saw148015 avd_alloc_var_ptr(var_t *var)
4295184Sek110237 {
4306212Saw148015 	avd_t avd;
4316212Saw148015 
4326212Saw148015 	if (var == NULL)
4336212Saw148015 		return (NULL);
4346212Saw148015 
4356212Saw148015 	if ((avd = avd_alloc_cmn()) == NULL)
4366212Saw148015 		return (NULL);
4376212Saw148015 
4386212Saw148015 	switch (var->var_type & VAR_TYPE_SET_MASK) {
4396212Saw148015 	case VAR_TYPE_BOOL_SET:
4406212Saw148015 		avd->avd_type = AVD_VARVAL_BOOL;
4416212Saw148015 		avd->avd_val.boolptr = (&var->var_val.boolean);
4426212Saw148015 		break;
4436212Saw148015 
4446212Saw148015 	case VAR_TYPE_INT_SET:
4456212Saw148015 		avd->avd_type = AVD_VARVAL_INT;
4466212Saw148015 		avd->avd_val.intptr = (&var->var_val.integer);
4476212Saw148015 		break;
4486212Saw148015 
4496212Saw148015 	case VAR_TYPE_STR_SET:
4506212Saw148015 		avd->avd_type = AVD_VARVAL_STR;
4516212Saw148015 		avd->avd_val.strptr = &(var->var_val.string);
4526212Saw148015 		break;
4535184Sek110237 
4546212Saw148015 	case VAR_TYPE_DBL_SET:
4556212Saw148015 		avd->avd_type = AVD_VARVAL_DBL;
4566212Saw148015 		avd->avd_val.dblptr = &(var->var_val.dbl_flt);
4576212Saw148015 		break;
4586212Saw148015 
4596212Saw148015 	case VAR_TYPE_RAND_SET:
4606212Saw148015 		avd->avd_type = AVD_IND_RANDVAR;
4616212Saw148015 		avd->avd_val.randptr = var->var_val.randptr;
4626212Saw148015 		break;
4636212Saw148015 
464*6550Saw148015 	case VAR_TYPE_INDVAR_SET:
465*6550Saw148015 		avd->avd_type = AVD_IND_VAR;
466*6550Saw148015 		avd->avd_val.varptr = var->var_val.varptr;
467*6550Saw148015 		break;
468*6550Saw148015 
4696212Saw148015 	default:
4706212Saw148015 		avd->avd_type = AVD_IND_VAR;
4716212Saw148015 		avd->avd_val.varptr = var;
4726212Saw148015 		break;
4736212Saw148015 	}
4746212Saw148015 	return (avd);
4756212Saw148015 }
4766212Saw148015 
4776212Saw148015 /*
4786212Saw148015  * Gets a avd_t, then allocates and initializes a piece of
4796212Saw148015  * shared string memory, putting the pointer to it into the just
4806212Saw148015  * allocated string pointer location. The routine returns a pointer
4816212Saw148015  * to the string pointer location or returns NULL on error.
4826212Saw148015  */
4836212Saw148015 avd_t
4846212Saw148015 avd_str_alloc(char *string)
4856212Saw148015 {
4866212Saw148015 	avd_t avd;
4876212Saw148015 
4886212Saw148015 	if (string == NULL) {
4896212Saw148015 		filebench_log(LOG_ERROR, "No string supplied\n");
4905184Sek110237 		return (NULL);
4915184Sek110237 	}
4925184Sek110237 
4936212Saw148015 	if ((avd = avd_alloc_cmn()) == NULL)
4946212Saw148015 		return (NULL);
4956212Saw148015 
4966212Saw148015 	avd->avd_type = AVD_VAL_STR;
4976212Saw148015 	avd->avd_val.strval = ipc_stralloc(string);
4985184Sek110237 
4995184Sek110237 	filebench_log(LOG_DEBUG_IMPL,
5005184Sek110237 	    "Alloc string %s ptr %zx",
5016212Saw148015 	    string, avd);
5025184Sek110237 
5036212Saw148015 	return (avd);
5045184Sek110237 }
5055184Sek110237 
5065184Sek110237 /*
5075184Sek110237  * Allocates a var (var_t) from interprocess shared memory.
5085184Sek110237  * Places the allocated var on the end of the globally shared
509*6550Saw148015  * shm_var_list. Finally, the routine allocates a string containing
5105184Sek110237  * a copy of the supplied "name" string. If any allocations
5115184Sek110237  * fails, returns NULL, otherwise it returns a pointer to the
5125184Sek110237  * newly allocated var.
5135184Sek110237  */
5145184Sek110237 static var_t *
5156212Saw148015 var_alloc_cmn(char *name, int var_type)
5165184Sek110237 {
5176212Saw148015 	var_t **var_listp;
5185184Sek110237 	var_t *var = NULL;
5195184Sek110237 	var_t *prev = NULL;
5205184Sek110237 	var_t *newvar;
5215184Sek110237 
5225184Sek110237 	if ((newvar = (var_t *)ipc_malloc(FILEBENCH_VARIABLE)) == NULL) {
5235184Sek110237 		filebench_log(LOG_ERROR, "Out of memory for variables");
5245184Sek110237 		return (NULL);
5255184Sek110237 	}
5265184Sek110237 	(void) memset(newvar, 0, sizeof (newvar));
5276212Saw148015 	newvar->var_type = var_type;
5285184Sek110237 
5295184Sek110237 	if ((newvar->var_name = ipc_stralloc(name)) == NULL) {
5305184Sek110237 		filebench_log(LOG_ERROR, "Out of memory for variables");
5315184Sek110237 		return (NULL);
5325184Sek110237 	}
5335184Sek110237 
5346212Saw148015 	switch (var_type & VAR_TYPE_MASK) {
5356212Saw148015 	case VAR_TYPE_RANDOM:
5366212Saw148015 	case VAR_TYPE_GLOBAL:
5376391Saw148015 		var_listp = &filebench_shm->shm_var_list;
5386212Saw148015 		break;
5396212Saw148015 
5406212Saw148015 	case VAR_TYPE_DYNAMIC:
5416391Saw148015 		var_listp = &filebench_shm->shm_var_dyn_list;
5426212Saw148015 		break;
5436212Saw148015 
544*6550Saw148015 	case VAR_TYPE_LOCAL:
545*6550Saw148015 		/* place on head of shared local list */
546*6550Saw148015 		newvar->var_next = filebench_shm->shm_var_loc_list;
547*6550Saw148015 		filebench_shm->shm_var_loc_list = newvar;
548*6550Saw148015 		return (newvar);
549*6550Saw148015 
5506212Saw148015 	default:
5516391Saw148015 		var_listp = &filebench_shm->shm_var_list;
5526212Saw148015 		break;
5536212Saw148015 	}
5546212Saw148015 
5556212Saw148015 	/* add to the end of list */
5566212Saw148015 	for (var = *var_listp; var != NULL; var = var->var_next)
5576212Saw148015 		prev = var; /* Find end of list */
5586212Saw148015 	if (prev != NULL)
5596212Saw148015 		prev->var_next = newvar;
5606212Saw148015 	else
5616212Saw148015 		*var_listp = newvar;
5626212Saw148015 
5635184Sek110237 	return (newvar);
5645184Sek110237 }
5655184Sek110237 
5665184Sek110237 /*
567*6550Saw148015  * Allocates a var (var_t) from interprocess shared memory after
568*6550Saw148015  * first adjusting the name to elminate the leading $. Places the
569*6550Saw148015  * allocated var temporarily on the end of the globally
570*6550Saw148015  * shared var_loc_list. If the allocation fails, returns NULL,
571*6550Saw148015  * otherwise it returns a pointer to the newly allocated var.
572*6550Saw148015  */
573*6550Saw148015 var_t *
574*6550Saw148015 var_lvar_alloc_local(char *name)
575*6550Saw148015 {
576*6550Saw148015 	if (name[0] == '$')
577*6550Saw148015 		name += 1;
578*6550Saw148015 
579*6550Saw148015 	return (var_alloc_cmn(name, VAR_TYPE_LOCAL));
580*6550Saw148015 }
581*6550Saw148015 
582*6550Saw148015 /*
5836212Saw148015  * Allocates a var (var_t) from interprocess shared memory and
5846212Saw148015  * places the allocated var on the end of the globally shared
585*6550Saw148015  * shm_var_list. If the allocation fails, returns NULL, otherwise
5866212Saw148015  * it returns a pointer to the newly allocated var.
5876212Saw148015  */
5886212Saw148015 static var_t *
5896212Saw148015 var_alloc(char *name)
5906212Saw148015 {
5916212Saw148015 	return (var_alloc_cmn(name, VAR_TYPE_GLOBAL));
5926212Saw148015 }
5936212Saw148015 
5946212Saw148015 /*
5955184Sek110237  * Allocates a var (var_t) from interprocess shared memory.
5965184Sek110237  * Places the allocated var on the end of the globally shared
597*6550Saw148015  * shm_var_dyn_list. If the allocation fails, returns NULL, otherwise
5986212Saw148015  * it returns a pointer to the newly allocated var.
5995184Sek110237  */
6005184Sek110237 static var_t *
6015184Sek110237 var_alloc_dynamic(char *name)
6025184Sek110237 {
6036212Saw148015 	return (var_alloc_cmn(name, VAR_TYPE_DYNAMIC));
6045184Sek110237 }
6055184Sek110237 
6065184Sek110237 /*
607*6550Saw148015  * Searches for var_t with name "name" in the shm_var_loc_list,
608*6550Saw148015  * then, if not found, in the global shm_var_list. If a matching
609*6550Saw148015  * local or global var is found, returns a pointer to the var_t,
610*6550Saw148015  * otherwise returns NULL.
6115184Sek110237  */
6125184Sek110237 static var_t *
6135184Sek110237 var_find(char *name)
6145184Sek110237 {
6155184Sek110237 	var_t *var;
6165184Sek110237 
617*6550Saw148015 	for (var = filebench_shm->shm_var_loc_list; var != NULL;
618*6550Saw148015 	    var = var->var_next) {
619*6550Saw148015 		if (strcmp(var->var_name, name) == 0)
620*6550Saw148015 			return (var);
621*6550Saw148015 	}
622*6550Saw148015 
6236391Saw148015 	for (var = filebench_shm->shm_var_list; var != NULL;
6246391Saw148015 	    var = var->var_next) {
6255184Sek110237 		if (strcmp(var->var_name, name) == 0)
6265184Sek110237 			return (var);
6275184Sek110237 	}
6285184Sek110237 
6295184Sek110237 	return (NULL);
6305184Sek110237 }
6315184Sek110237 
6325184Sek110237 /*
633*6550Saw148015  * Searches for var_t with name "name" in the supplied shm_var_list.
634*6550Saw148015  * If not found there, checks the global list. If still
635*6550Saw148015  * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t.
636*6550Saw148015  */
637*6550Saw148015 static var_t *
638*6550Saw148015 var_find_list_only(char *name, var_t *var_list)
639*6550Saw148015 {
640*6550Saw148015 	var_t *var;
641*6550Saw148015 
642*6550Saw148015 	for (var = var_list; var != NULL; var = var->var_next) {
643*6550Saw148015 		if (strcmp(var->var_name, name) == 0)
644*6550Saw148015 			return (var);
645*6550Saw148015 	}
646*6550Saw148015 
647*6550Saw148015 	return (NULL);
648*6550Saw148015 }
649*6550Saw148015 
650*6550Saw148015 /*
651*6550Saw148015  * Searches for var_t with name "name" in the supplied shm_var_list.
652*6550Saw148015  * If not found there, checks the global list. If still
653*6550Saw148015  * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t.
654*6550Saw148015  */
655*6550Saw148015 static var_t *
656*6550Saw148015 var_find_list(char *name, var_t *var_list)
657*6550Saw148015 {
658*6550Saw148015 	var_t *var;
659*6550Saw148015 
660*6550Saw148015 	if ((var = var_find_list_only(name, var_list)) != NULL)
661*6550Saw148015 		return (var);
662*6550Saw148015 	else
663*6550Saw148015 		return (var_find(name));
664*6550Saw148015 }
665*6550Saw148015 
666*6550Saw148015 /*
6675184Sek110237  * Searches for the named var, and, if found, sets its
6686212Saw148015  * var_val.boolean's value to that of the supplied boolean.
6695184Sek110237  * If not found, the routine allocates a new var and sets
6706212Saw148015  * its var_val.boolean's value to that of the supplied
6716212Saw148015  * boolean. If the named var cannot be found or allocated
6726212Saw148015  * the routine returns -1, otherwise it returns 0.
6735184Sek110237  */
6745184Sek110237 int
6756212Saw148015 var_assign_boolean(char *name, boolean_t bool)
6765184Sek110237 {
6775184Sek110237 	var_t *var;
6785184Sek110237 
6796212Saw148015 	if (name == NULL) {
6806212Saw148015 		filebench_log(LOG_ERROR,
6816212Saw148015 		    "var_assign_boolean: Name not supplied");
6826212Saw148015 		return (0);
6836212Saw148015 	}
6846212Saw148015 
6855184Sek110237 	name += 1;
6865184Sek110237 
6876212Saw148015 	if ((var = var_find(name)) == NULL) {
6886212Saw148015 			var = var_alloc(name);
6896212Saw148015 	}
6905184Sek110237 
6915184Sek110237 	if (var == NULL) {
6925184Sek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
6935184Sek110237 		    name);
6945184Sek110237 		return (-1);
6955184Sek110237 	}
6965184Sek110237 
6976212Saw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
6986212Saw148015 		filebench_log(LOG_ERROR,
6996212Saw148015 		    "Cannot assign integer to random variable %s", name);
7006212Saw148015 		return (-1);
7016212Saw148015 	}
7026212Saw148015 
7036212Saw148015 	VAR_SET_BOOL(var, bool);
7046212Saw148015 
7056212Saw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign boolean %s=%d",
7066212Saw148015 	    name, bool);
7076212Saw148015 
7086212Saw148015 	return (0);
7096212Saw148015 }
7106212Saw148015 
7116212Saw148015 /*
7126212Saw148015  * Searches for the named var, and, if found, sets its
7136212Saw148015  * var_integer's value to that of the supplied integer.
7146212Saw148015  * If not found, the routine allocates a new var and sets
7156212Saw148015  * its var_integers's value to that of the supplied
7166212Saw148015  * integer. If the named var cannot be found or allocated
7176212Saw148015  * the routine returns -1, otherwise it returns 0.
7186212Saw148015  */
7196212Saw148015 int
7206212Saw148015 var_assign_integer(char *name, fbint_t integer)
7216212Saw148015 {
7226212Saw148015 	var_t *var;
7236212Saw148015 
7246212Saw148015 	if (name == NULL) {
7256212Saw148015 		filebench_log(LOG_ERROR,
7266212Saw148015 		    "var_assign_integer: Name not supplied");
7276212Saw148015 		return (0);
7286212Saw148015 	}
7296212Saw148015 
7306212Saw148015 	name += 1;
7316212Saw148015 
7326212Saw148015 	if ((var = var_find(name)) == NULL) {
7336212Saw148015 			var = var_alloc(name);
7346212Saw148015 	}
7356212Saw148015 
7366212Saw148015 	if (var == NULL) {
7376212Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
7386212Saw148015 		    name);
7396212Saw148015 		return (-1);
7406212Saw148015 	}
7416212Saw148015 
7426212Saw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
7436212Saw148015 		filebench_log(LOG_ERROR,
7446212Saw148015 		    "Cannot assign integer to random variable %s", name);
7456212Saw148015 		return (-1);
7466212Saw148015 	}
7476212Saw148015 
7486212Saw148015 	VAR_SET_INT(var, integer);
7495184Sek110237 
7506286Saw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu",
7516286Saw148015 	    name, (u_longlong_t)integer);
7525184Sek110237 
7535184Sek110237 	return (0);
7545184Sek110237 }
7555184Sek110237 
7565184Sek110237 /*
7576212Saw148015  * Find a variable, and set it to random type.
7586212Saw148015  * If it does not have a random extension, allocate one
7596212Saw148015  */
7606212Saw148015 var_t *
7616212Saw148015 var_find_randvar(char *name)
7626212Saw148015 {
7636212Saw148015 	var_t *newvar;
7646212Saw148015 
7656212Saw148015 	name += 1;
7666212Saw148015 
7676212Saw148015 	if ((newvar = var_find(name)) == NULL) {
7686212Saw148015 		filebench_log(LOG_ERROR,
7696212Saw148015 		    "failed to locate random variable $%s\n", name);
7706212Saw148015 		return (NULL);
7716212Saw148015 	}
7726212Saw148015 
7736212Saw148015 	/* set randdist pointer unless it is already set */
7746212Saw148015 	if (((newvar->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
7756212Saw148015 	    !VAR_HAS_RANDDIST(newvar)) {
7766212Saw148015 		filebench_log(LOG_ERROR,
7776212Saw148015 		    "Found variable $%s not random\n", name);
7786212Saw148015 		return (NULL);
7796212Saw148015 	}
7806212Saw148015 
7816212Saw148015 	return (newvar);
7826212Saw148015 }
7836212Saw148015 
7846212Saw148015 /*
7856212Saw148015  * Allocate a variable, and set it to random type. Then
7866212Saw148015  * allocate a random extension.
7876212Saw148015  */
7886212Saw148015 var_t *
7896212Saw148015 var_define_randvar(char *name)
7906212Saw148015 {
7916212Saw148015 	var_t *newvar;
7926212Saw148015 	randdist_t *rndp = NULL;
7936212Saw148015 
7946212Saw148015 	name += 1;
7956212Saw148015 
7966212Saw148015 	/* make sure variable doesn't already exist */
7976212Saw148015 	if (var_find(name) != NULL) {
7986212Saw148015 		filebench_log(LOG_ERROR,
7996212Saw148015 		    "variable name already in use\n");
8006212Saw148015 		return (NULL);
8016212Saw148015 	}
8026212Saw148015 
8036212Saw148015 	/* allocate a random variable */
8046212Saw148015 	if ((newvar = var_alloc_cmn(name, VAR_TYPE_RANDOM)) == NULL) {
8056212Saw148015 		filebench_log(LOG_ERROR,
8066212Saw148015 		    "failed to alloc random variable\n");
8076212Saw148015 		return (NULL);
8086212Saw148015 	}
8096212Saw148015 
8106212Saw148015 	/* set randdist pointer */
8116212Saw148015 	if ((rndp = randdist_alloc()) == NULL) {
8126212Saw148015 		filebench_log(LOG_ERROR,
8136212Saw148015 		    "failed to alloc random distribution object\n");
8146212Saw148015 		return (NULL);
8156212Saw148015 	}
8166212Saw148015 
8176212Saw148015 	rndp->rnd_var = newvar;
8186212Saw148015 	VAR_SET_RAND(newvar, rndp);
8196212Saw148015 
8206212Saw148015 	return (newvar);
8216212Saw148015 }
8226212Saw148015 
8236212Saw148015 /*
8246212Saw148015  * Searches for the named var, and if found returns an avd_t
8256212Saw148015  * pointing to the var's var_integer, var_string or var_double
8266212Saw148015  * as appropriate. If not found, attempts to allocate
8276212Saw148015  * a var named "name" and returns an avd_t to it with
8286212Saw148015  * no value set. If the var cannot be found or allocated, an
8295184Sek110237  * error is logged and the run is terminated.
8305184Sek110237  */
8316212Saw148015 avd_t
8326212Saw148015 var_ref_attr(char *name)
8335184Sek110237 {
8345184Sek110237 	var_t *var;
8355184Sek110237 
8365184Sek110237 	name += 1;
8375184Sek110237 
8385184Sek110237 	if ((var = var_find(name)) == NULL)
8395184Sek110237 		var = var_find_dynamic(name);
8405184Sek110237 
8415184Sek110237 	if (var == NULL)
8425184Sek110237 		var = var_alloc(name);
8435184Sek110237 
8445184Sek110237 	if (var == NULL) {
8455184Sek110237 		filebench_log(LOG_ERROR, "Invalid variable $%s",
8465184Sek110237 		    name);
8475184Sek110237 		filebench_shutdown(1);
8485184Sek110237 	}
8495184Sek110237 
8506212Saw148015 	/* allocate pointer to var and return */
8516212Saw148015 	return (avd_alloc_var_ptr(var));
8525184Sek110237 }
8535184Sek110237 
8546212Saw148015 
8555184Sek110237 /*
8566212Saw148015  * Searches for the named var, and if found copies the var_val.string,
8576212Saw148015  * if it exists, a decimal number string representation of
8586212Saw148015  * var_val.integer, the state of var_val.boolean, or the type of random
8596212Saw148015  * distribution employed, into a malloc'd bit of memory using fb_stralloc().
8605184Sek110237  * Returns a pointer to the created string, or NULL on failure.
8615184Sek110237  */
8625184Sek110237 char *
8635184Sek110237 var_to_string(char *name)
8645184Sek110237 {
8655184Sek110237 	var_t *var;
8665184Sek110237 	char tmp[128];
8675184Sek110237 
8685184Sek110237 	name += 1;
8695184Sek110237 
8705184Sek110237 	if ((var = var_find(name)) == NULL)
8715184Sek110237 		var = var_find_dynamic(name);
8725184Sek110237 
8735184Sek110237 	if (var == NULL)
8745184Sek110237 		return (NULL);
8755184Sek110237 
8766212Saw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
8776212Saw148015 		switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
8786212Saw148015 		case RAND_TYPE_UNIFORM:
8796212Saw148015 			return (fb_stralloc("uniform random var"));
8806212Saw148015 		case RAND_TYPE_GAMMA:
8816212Saw148015 			return (fb_stralloc("gamma random var"));
8826212Saw148015 		case RAND_TYPE_TABLE:
8836212Saw148015 			return (fb_stralloc("tabular random var"));
8846212Saw148015 		default:
8856212Saw148015 			return (fb_stralloc("unitialized random var"));
8866212Saw148015 		}
8876212Saw148015 	}
8885184Sek110237 
8896212Saw148015 	if (VAR_HAS_STRING(var) && var->var_val.string)
8906212Saw148015 		return (fb_stralloc(var->var_val.string));
8915184Sek110237 
8926212Saw148015 	if (VAR_HAS_BOOLEAN(var)) {
8936212Saw148015 		if (var->var_val.boolean)
8946212Saw148015 			return (fb_stralloc("true"));
8956212Saw148015 		else
8966212Saw148015 			return (fb_stralloc("false"));
8976212Saw148015 	}
8986212Saw148015 
8996212Saw148015 	if (VAR_HAS_INTEGER(var)) {
9006286Saw148015 		(void) snprintf(tmp, sizeof (tmp), "%llu",
9016286Saw148015 		    (u_longlong_t)var->var_val.integer);
9026212Saw148015 		return (fb_stralloc(tmp));
9036212Saw148015 	}
9046212Saw148015 
9056212Saw148015 	return (fb_stralloc("No default"));
9065184Sek110237 }
9075184Sek110237 
9085184Sek110237 /*
9095184Sek110237  * Searches for the named var, and if found returns the value,
9106212Saw148015  * of var_val.boolean. If the var is not found, or a boolean
9116212Saw148015  * value has not been set, logs an error and returns 0.
9125184Sek110237  */
9136212Saw148015 boolean_t
9146212Saw148015 var_to_boolean(char *name)
9156212Saw148015 {
9166212Saw148015 	var_t *var;
9176212Saw148015 
9186212Saw148015 	name += 1;
9196212Saw148015 
9206212Saw148015 	if ((var = var_find(name)) == NULL)
9216212Saw148015 		var = var_find_dynamic(name);
9226212Saw148015 
9236212Saw148015 	if ((var != NULL) && VAR_HAS_BOOLEAN(var))
9246212Saw148015 		return (var->var_val.boolean);
9256212Saw148015 
9266212Saw148015 	filebench_log(LOG_ERROR,
9276212Saw148015 	    "Variable %s referenced before set", name);
9286212Saw148015 
9296212Saw148015 	return (0);
9306212Saw148015 }
9316212Saw148015 
9326212Saw148015 /*
9336212Saw148015  * Searches for the named var, and if found returns the value,
9346212Saw148015  * of var_val.integer. If the var is not found, or the an
9356212Saw148015  * integer value has not been set, logs an error and returns 0.
9366212Saw148015  */
9376212Saw148015 fbint_t
9385184Sek110237 var_to_integer(char *name)
9395184Sek110237 {
9405184Sek110237 	var_t *var;
9415184Sek110237 
9425184Sek110237 	name += 1;
9435184Sek110237 
9445184Sek110237 	if ((var = var_find(name)) == NULL)
9455184Sek110237 		var = var_find_dynamic(name);
9465184Sek110237 
9476212Saw148015 	if ((var != NULL) && VAR_HAS_INTEGER(var))
9486212Saw148015 		return (var->var_val.integer);
9495184Sek110237 
9505184Sek110237 	filebench_log(LOG_ERROR,
9515184Sek110237 	    "Variable %s referenced before set", name);
9525184Sek110237 
9535184Sek110237 	return (0);
9545184Sek110237 }
9555184Sek110237 
9565184Sek110237 /*
9576212Saw148015  * Searches for the named random var, and if found, converts the
9586212Saw148015  * requested parameter into a string or a decimal number string
9596212Saw148015  * representation, into a malloc'd bit of memory using fb_stralloc().
9606212Saw148015  * Returns a pointer to the created string, or calls var_to_string()
9616212Saw148015  * if a random variable isn't found.
9626212Saw148015  */
9636212Saw148015 char *
9646212Saw148015 var_randvar_to_string(char *name, int param_name)
9656212Saw148015 {
9666212Saw148015 	var_t *var;
9676212Saw148015 	fbint_t value;
9686212Saw148015 
9696212Saw148015 	if ((var = var_find(name + 1)) == NULL)
9706212Saw148015 		return (var_to_string(name));
9716212Saw148015 
9726212Saw148015 	if (((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
9736212Saw148015 	    !VAR_HAS_RANDDIST(var))
9746212Saw148015 		return (var_to_string(name));
9756212Saw148015 
9766212Saw148015 	switch (param_name) {
9776212Saw148015 	case RAND_PARAM_TYPE:
9786212Saw148015 		switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
9796212Saw148015 		case RAND_TYPE_UNIFORM:
9806212Saw148015 			return (fb_stralloc("uniform"));
9816212Saw148015 		case RAND_TYPE_GAMMA:
9826212Saw148015 			return (fb_stralloc("gamma"));
9836212Saw148015 		case RAND_TYPE_TABLE:
9846212Saw148015 			return (fb_stralloc("tabular"));
9856212Saw148015 		default:
9866212Saw148015 			return (fb_stralloc("uninitialized"));
9876212Saw148015 		}
9886212Saw148015 
9896212Saw148015 	case RAND_PARAM_SRC:
9906212Saw148015 		if (var->var_val.randptr->rnd_type & RAND_SRC_GENERATOR)
9916212Saw148015 			return (fb_stralloc("rand48"));
9926212Saw148015 		else
9936212Saw148015 			return (fb_stralloc("urandom"));
9946212Saw148015 
9956212Saw148015 	case RAND_PARAM_SEED:
9966212Saw148015 		value = avd_get_int(var->var_val.randptr->rnd_seed);
9976212Saw148015 		break;
9986212Saw148015 
9996212Saw148015 	case RAND_PARAM_MIN:
10006212Saw148015 		value = avd_get_int(var->var_val.randptr->rnd_min);
10016212Saw148015 		break;
10026212Saw148015 
10036212Saw148015 	case RAND_PARAM_MEAN:
10046212Saw148015 		value = avd_get_int(var->var_val.randptr->rnd_mean);
10056212Saw148015 		break;
10066212Saw148015 
10076212Saw148015 	case RAND_PARAM_GAMMA:
10086212Saw148015 		value = avd_get_int(var->var_val.randptr->rnd_gamma);
10096212Saw148015 		break;
10106212Saw148015 
10116212Saw148015 	case RAND_PARAM_ROUND:
10126212Saw148015 		value = avd_get_int(var->var_val.randptr->rnd_round);
10136212Saw148015 		break;
10146212Saw148015 
10156212Saw148015 	default:
10166212Saw148015 		return (NULL);
10176212Saw148015 
10186212Saw148015 	}
10196212Saw148015 
10206212Saw148015 	/* just an integer value if we got here */
10216212Saw148015 	{
10226212Saw148015 		char tmp[128];
10236212Saw148015 
10246286Saw148015 		(void) snprintf(tmp, sizeof (tmp), "%llu",
10256286Saw148015 		    (u_longlong_t)value);
10266212Saw148015 		return (fb_stralloc(tmp));
10276212Saw148015 	}
10286212Saw148015 }
10296212Saw148015 
10306212Saw148015 /*
1031*6550Saw148015  * Copies the value stored in the source string into the destination
1032*6550Saw148015  * string. Returns -1 if any problems encountered, 0 otherwise.
1033*6550Saw148015  */
1034*6550Saw148015 static int
1035*6550Saw148015 var_copy(var_t *dst_var, var_t *src_var) {
1036*6550Saw148015 
1037*6550Saw148015 	if (VAR_HAS_BOOLEAN(src_var)) {
1038*6550Saw148015 		VAR_SET_BOOL(dst_var, src_var->var_val.boolean);
1039*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1040*6550Saw148015 		    "Assign var %s=%s", dst_var->var_name,
1041*6550Saw148015 		    dst_var->var_val.boolean?"true":"false");
1042*6550Saw148015 	}
1043*6550Saw148015 
1044*6550Saw148015 	if (VAR_HAS_INTEGER(src_var)) {
1045*6550Saw148015 		VAR_SET_INT(dst_var, src_var->var_val.integer);
1046*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1047*6550Saw148015 		    "Assign var %s=%llu", dst_var->var_name,
1048*6550Saw148015 		    (u_longlong_t)dst_var->var_val.integer);
1049*6550Saw148015 	}
1050*6550Saw148015 
1051*6550Saw148015 	if (VAR_HAS_DOUBLE(src_var)) {
1052*6550Saw148015 		VAR_SET_DBL(dst_var, src_var->var_val.dbl_flt);
1053*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1054*6550Saw148015 		    "Assign var %s=%lf", dst_var->var_name,
1055*6550Saw148015 		    dst_var->var_val.dbl_flt);
1056*6550Saw148015 	}
1057*6550Saw148015 
1058*6550Saw148015 	if (VAR_HAS_STRING(src_var)) {
1059*6550Saw148015 		char *strptr;
1060*6550Saw148015 
1061*6550Saw148015 		if ((strptr =
1062*6550Saw148015 		    ipc_stralloc(src_var->var_val.string)) == NULL) {
1063*6550Saw148015 			filebench_log(LOG_ERROR,
1064*6550Saw148015 			    "Cannot assign string for variable %s",
1065*6550Saw148015 			    dst_var->var_name);
1066*6550Saw148015 			return (-1);
1067*6550Saw148015 		}
1068*6550Saw148015 		VAR_SET_STR(dst_var, strptr);
1069*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1070*6550Saw148015 		    "Assign var %s=%s", dst_var->var_name,
1071*6550Saw148015 		    dst_var->var_val.string);
1072*6550Saw148015 	}
1073*6550Saw148015 
1074*6550Saw148015 	if (VAR_HAS_INDVAR(src_var)) {
1075*6550Saw148015 		VAR_SET_INDVAR(dst_var, src_var->var_val.varptr);
1076*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1077*6550Saw148015 		    "Assign var %s to var %s", dst_var->var_name,
1078*6550Saw148015 		    src_var->var_name);
1079*6550Saw148015 	}
1080*6550Saw148015 	return (0);
1081*6550Saw148015 }
1082*6550Saw148015 
1083*6550Saw148015 /*
10845184Sek110237  * Searches for the var named "name", and if not found
1085*6550Saw148015  * allocates it. The then copies the value from
1086*6550Saw148015  * the src_var into the destination var "name"
1087*6550Saw148015  * If the var "name" cannot be found or allocated, or the var "src_name"
1088*6550Saw148015  * cannot be found, the routine returns -1, otherwise it returns 0.
10895184Sek110237  */
10905184Sek110237 int
10916212Saw148015 var_assign_var(char *name, char *src_name)
10925184Sek110237 {
10936212Saw148015 	var_t *dst_var, *src_var;
10945184Sek110237 
10955184Sek110237 	name += 1;
10966212Saw148015 	src_name += 1;
10975184Sek110237 
10986212Saw148015 	if ((src_var = var_find(src_name)) == NULL) {
10996212Saw148015 		filebench_log(LOG_ERROR,
11006212Saw148015 		    "Cannot find source variable %s", src_name);
11016212Saw148015 		return (-1);
11026212Saw148015 	}
11035184Sek110237 
11046212Saw148015 	if ((dst_var = var_find(name)) == NULL)
11056212Saw148015 		dst_var = var_alloc(name);
11066212Saw148015 
11076212Saw148015 	if (dst_var == NULL) {
11085184Sek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
11095184Sek110237 		    name);
11105184Sek110237 		return (-1);
11115184Sek110237 	}
11125184Sek110237 
11136212Saw148015 	if ((dst_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
11146212Saw148015 		filebench_log(LOG_ERROR,
11156212Saw148015 		    "Cannot assign var to Random variable %s", name);
11165184Sek110237 		return (-1);
11175184Sek110237 	}
11186212Saw148015 
1119*6550Saw148015 	return (var_copy(dst_var, src_var));
11205184Sek110237 }
11215184Sek110237 
11225184Sek110237 /*
11235184Sek110237  * Like var_assign_integer, only this routine copies the
11245184Sek110237  * supplied "string" into the var named "name". If the var
11255184Sek110237  * named "name" cannot be found then it is first allocated
11265184Sek110237  * before the copy. Space for the string in the var comes
11275184Sek110237  * from interprocess shared memory. If the var "name"
11285184Sek110237  * cannot be found or allocated, or the memory for the
1129*6550Saw148015  * var_val.string copy of "string" cannot be allocated, the
11305184Sek110237  * routine returns -1, otherwise it returns 0.
11315184Sek110237  */
11325184Sek110237 int
11335184Sek110237 var_assign_string(char *name, char *string)
11345184Sek110237 {
11355184Sek110237 	var_t *var;
11366212Saw148015 	char *strptr;
11375184Sek110237 
11385184Sek110237 	name += 1;
11395184Sek110237 
11405184Sek110237 	if ((var = var_find(name)) == NULL)
11415184Sek110237 		var = var_alloc(name);
11425184Sek110237 
11435184Sek110237 	if (var == NULL) {
11445184Sek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
11455184Sek110237 		    name);
11465184Sek110237 		return (-1);
11475184Sek110237 	}
11485184Sek110237 
11496212Saw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
11506212Saw148015 		filebench_log(LOG_ERROR,
11516212Saw148015 		    "Cannot assign string to random variable %s", name);
11526212Saw148015 		return (-1);
11536212Saw148015 	}
11546212Saw148015 
11556212Saw148015 	if ((strptr = ipc_stralloc(string)) == NULL) {
11565184Sek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
11575184Sek110237 		    name);
11585184Sek110237 		return (-1);
11595184Sek110237 	}
11606212Saw148015 	VAR_SET_STR(var, strptr);
11615184Sek110237 
11626212Saw148015 	filebench_log(LOG_DEBUG_SCRIPT,
11636212Saw148015 	    "Var assign string $%s=%s", name, string);
11645184Sek110237 
11655184Sek110237 	return (0);
11665184Sek110237 }
11675184Sek110237 
11685184Sek110237 /*
1169*6550Saw148015  * Allocates a local var. The then extracts the var_string from
1170*6550Saw148015  * the var named "string" and copies it into the var_string
1171*6550Saw148015  * of the var "name", after first allocating a piece of
1172*6550Saw148015  * interprocess shared string memory. Returns a pointer to the
1173*6550Saw148015  * newly allocated local var or NULL on error.
1174*6550Saw148015  */
1175*6550Saw148015 var_t *
1176*6550Saw148015 var_lvar_assign_var(char *name, char *src_name)
1177*6550Saw148015 {
1178*6550Saw148015 	var_t *dst_var, *src_var;
1179*6550Saw148015 
1180*6550Saw148015 	src_name += 1;
1181*6550Saw148015 
1182*6550Saw148015 	if ((src_var = var_find(src_name)) == NULL) {
1183*6550Saw148015 		filebench_log(LOG_ERROR,
1184*6550Saw148015 		    "Cannot find source variable %s", src_name);
1185*6550Saw148015 		return (NULL);
1186*6550Saw148015 	}
1187*6550Saw148015 
1188*6550Saw148015 	dst_var = var_lvar_alloc_local(name);
1189*6550Saw148015 
1190*6550Saw148015 	if (dst_var == NULL) {
1191*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1192*6550Saw148015 		    name);
1193*6550Saw148015 		return (NULL);
1194*6550Saw148015 	}
1195*6550Saw148015 
1196*6550Saw148015 	/*
1197*6550Saw148015 	 * if referencing another local var which is currently
1198*6550Saw148015 	 * empty, indirect to it
1199*6550Saw148015 	 */
1200*6550Saw148015 	if ((src_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_LOCAL) {
1201*6550Saw148015 		VAR_SET_INDVAR(dst_var, src_var);
1202*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1203*6550Saw148015 		    "Assign local var %s to %s", name, src_name);
1204*6550Saw148015 		return (dst_var);
1205*6550Saw148015 	}
1206*6550Saw148015 
1207*6550Saw148015 	if (VAR_HAS_BOOLEAN(src_var)) {
1208*6550Saw148015 		VAR_SET_BOOL(dst_var, src_var->var_val.boolean);
1209*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1210*6550Saw148015 		    "Assign var (%s, %p)=%s", name,
1211*6550Saw148015 		    dst_var, src_var->var_val.boolean?"true":"false");
1212*6550Saw148015 	} else if (VAR_HAS_INTEGER(src_var)) {
1213*6550Saw148015 		VAR_SET_INT(dst_var, src_var->var_val.integer);
1214*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1215*6550Saw148015 		    "Assign var (%s, %p)=%llu", name,
1216*6550Saw148015 		    dst_var, (u_longlong_t)src_var->var_val.integer);
1217*6550Saw148015 	} else if (VAR_HAS_STRING(src_var)) {
1218*6550Saw148015 		char *strptr;
1219*6550Saw148015 
1220*6550Saw148015 		if ((strptr = ipc_stralloc(src_var->var_val.string)) == NULL) {
1221*6550Saw148015 			filebench_log(LOG_ERROR,
1222*6550Saw148015 			    "Cannot assign variable %s",
1223*6550Saw148015 			    name);
1224*6550Saw148015 			return (NULL);
1225*6550Saw148015 		}
1226*6550Saw148015 		VAR_SET_STR(dst_var, strptr);
1227*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1228*6550Saw148015 		    "Assign var (%s, %p)=%s", name,
1229*6550Saw148015 		    dst_var, src_var->var_val.string);
1230*6550Saw148015 	} else if (VAR_HAS_DOUBLE(src_var)) {
1231*6550Saw148015 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
1232*6550Saw148015 		VAR_SET_INT(dst_var, src_var->var_val.dbl_flt);
1233*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1234*6550Saw148015 		    "Assign var (%s, %p)=%8.2f", name,
1235*6550Saw148015 		    dst_var, src_var->var_val.dbl_flt);
1236*6550Saw148015 	} else if (VAR_HAS_RANDDIST(src_var)) {
1237*6550Saw148015 		VAR_SET_RAND(dst_var, src_var->var_val.randptr);
1238*6550Saw148015 		filebench_log(LOG_DEBUG_SCRIPT,
1239*6550Saw148015 		    "Assign var (%s, %p)=%llu", name,
1240*6550Saw148015 		    dst_var, (u_longlong_t)src_var->var_val.integer);
1241*6550Saw148015 	}
1242*6550Saw148015 
1243*6550Saw148015 	return (dst_var);
1244*6550Saw148015 }
1245*6550Saw148015 
1246*6550Saw148015 /*
1247*6550Saw148015  * the routine allocates a new local var and sets
1248*6550Saw148015  * its var_boolean's value to that of the supplied
1249*6550Saw148015  * boolean. It returns a pointer to the new local var
1250*6550Saw148015  */
1251*6550Saw148015 var_t *
1252*6550Saw148015 var_lvar_assign_boolean(char *name, boolean_t bool)
1253*6550Saw148015 {
1254*6550Saw148015 	var_t *var;
1255*6550Saw148015 
1256*6550Saw148015 	var = var_lvar_alloc_local(name);
1257*6550Saw148015 
1258*6550Saw148015 	if (var == NULL) {
1259*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1260*6550Saw148015 		    name);
1261*6550Saw148015 		return (NULL);
1262*6550Saw148015 	}
1263*6550Saw148015 
1264*6550Saw148015 	VAR_SET_BOOL(var, bool);
1265*6550Saw148015 
1266*6550Saw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%s",
1267*6550Saw148015 	    name, bool ? "true" : "false");
1268*6550Saw148015 
1269*6550Saw148015 	return (var);
1270*6550Saw148015 }
1271*6550Saw148015 
1272*6550Saw148015 /*
1273*6550Saw148015  * the routine allocates a new local var and sets
1274*6550Saw148015  * its var_integers's value to that of the supplied
1275*6550Saw148015  * integer. It returns a pointer to the new local var
1276*6550Saw148015  */
1277*6550Saw148015 var_t *
1278*6550Saw148015 var_lvar_assign_integer(char *name, fbint_t integer)
1279*6550Saw148015 {
1280*6550Saw148015 	var_t *var;
1281*6550Saw148015 
1282*6550Saw148015 	var = var_lvar_alloc_local(name);
1283*6550Saw148015 
1284*6550Saw148015 	if (var == NULL) {
1285*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1286*6550Saw148015 		    name);
1287*6550Saw148015 		return (NULL);
1288*6550Saw148015 	}
1289*6550Saw148015 
1290*6550Saw148015 	VAR_SET_INT(var, integer);
1291*6550Saw148015 
1292*6550Saw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu",
1293*6550Saw148015 	    name, (u_longlong_t)integer);
1294*6550Saw148015 
1295*6550Saw148015 	return (var);
1296*6550Saw148015 }
1297*6550Saw148015 
1298*6550Saw148015 /*
1299*6550Saw148015  * the routine allocates a new local var and sets
1300*6550Saw148015  * its var_dbl_flt value to that of the supplied
1301*6550Saw148015  * double precission floating point number. It returns
1302*6550Saw148015  * a pointer to the new local var
1303*6550Saw148015  */
1304*6550Saw148015 var_t *
1305*6550Saw148015 var_lvar_assign_double(char *name, double dbl)
1306*6550Saw148015 {
1307*6550Saw148015 	var_t *var;
1308*6550Saw148015 
1309*6550Saw148015 	var = var_lvar_alloc_local(name);
1310*6550Saw148015 
1311*6550Saw148015 	if (var == NULL) {
1312*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1313*6550Saw148015 		    name);
1314*6550Saw148015 		return (NULL);
1315*6550Saw148015 	}
1316*6550Saw148015 
1317*6550Saw148015 	VAR_SET_DBL(var, dbl);
1318*6550Saw148015 
1319*6550Saw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%8.2f", name, dbl);
1320*6550Saw148015 
1321*6550Saw148015 	return (var);
1322*6550Saw148015 }
1323*6550Saw148015 
1324*6550Saw148015 /*
1325*6550Saw148015  * Like var_lvar_assign_integer, only this routine copies the
1326*6550Saw148015  * supplied "string" into the var named "name". If the var
1327*6550Saw148015  * named "name" cannot be found then it is first allocated
1328*6550Saw148015  * before the copy. Space for the string in the var comes
1329*6550Saw148015  * from interprocess shared memory. The allocated local var
1330*6550Saw148015  * is returned at as a char *, or NULL on error.
1331*6550Saw148015  */
1332*6550Saw148015 var_t *
1333*6550Saw148015 var_lvar_assign_string(char *name, char *string)
1334*6550Saw148015 {
1335*6550Saw148015 	var_t *var;
1336*6550Saw148015 	char *strptr;
1337*6550Saw148015 
1338*6550Saw148015 	var = var_lvar_alloc_local(name);
1339*6550Saw148015 
1340*6550Saw148015 	if (var == NULL) {
1341*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1342*6550Saw148015 		    name);
1343*6550Saw148015 		return (NULL);
1344*6550Saw148015 	}
1345*6550Saw148015 
1346*6550Saw148015 	if ((strptr = ipc_stralloc(string)) == NULL) {
1347*6550Saw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
1348*6550Saw148015 		    name);
1349*6550Saw148015 		return (NULL);
1350*6550Saw148015 	}
1351*6550Saw148015 	VAR_SET_STR(var, strptr);
1352*6550Saw148015 
1353*6550Saw148015 	filebench_log(LOG_DEBUG_SCRIPT,
1354*6550Saw148015 	    "Lvar_assign_string (%s, %p)=%s", name, var, string);
1355*6550Saw148015 
1356*6550Saw148015 	return (var);
1357*6550Saw148015 }
1358*6550Saw148015 
1359*6550Saw148015 /*
13606212Saw148015  * Tests to see if the supplied variable name without the portion after
13616212Saw148015  * the last period is that of a random variable. If it is, it returns
13626212Saw148015  * the number of characters to backspace to skip the period and field
13636212Saw148015  * name. Otherwise it returns 0.
13645184Sek110237  */
13656212Saw148015 int
13666212Saw148015 var_is_set4_randvar(char *name)
13675184Sek110237 {
13685184Sek110237 	var_t *var;
13696212Saw148015 	char varname[128];
13706212Saw148015 	int namelength;
13716212Saw148015 	char *sp;
13725184Sek110237 
13736212Saw148015 	(void) strncpy(varname, name, 128);
13746212Saw148015 	namelength = strlen(varname);
13756212Saw148015 	sp = varname + namelength;
13765184Sek110237 
13776212Saw148015 	while (sp != varname) {
13786212Saw148015 		int c = *sp;
13795184Sek110237 
13806212Saw148015 		*sp = 0;
13816212Saw148015 		if (c == '.')
13826212Saw148015 			break;
13836212Saw148015 
13846212Saw148015 		sp--;
13855184Sek110237 	}
13865184Sek110237 
13876212Saw148015 	/* not a variable name + field? */
13886212Saw148015 	if (sp == varname)
13896212Saw148015 		return (0);
13906212Saw148015 
13916212Saw148015 	/* first part not a variable name? */
13926212Saw148015 	if ((var = var_find(varname+1)) == NULL)
13936212Saw148015 		return (0);
13946212Saw148015 
13956212Saw148015 	/* Make sure it is a random variable */
13966212Saw148015 	if ((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM)
13976212Saw148015 		return (0);
13986212Saw148015 
13996212Saw148015 	/* calculate offset from end of random variable name */
14006212Saw148015 	return (namelength - (sp - varname));
14015184Sek110237 }
14025184Sek110237 
14035184Sek110237 /*
14045184Sek110237  * Implements a simple path name like scheme for finding values
14055184Sek110237  * to place in certain specially named vars. The first part of
14065184Sek110237  * the name is interpreted as a category of either: stats,
14075184Sek110237  * eventgen, date, script, or host var. If a match is found,
14085184Sek110237  * the appropriate routine is called to fill in the requested
14095184Sek110237  * value in the provided var_t, and a pointer to the supplied
14105184Sek110237  * var_t is returned. If the requested value is not found, NULL
14115184Sek110237  * is returned.
14125184Sek110237  */
14135184Sek110237 static var_t *
14145184Sek110237 var_find_internal(var_t *var)
14155184Sek110237 {
14165184Sek110237 	char *n = fb_stralloc(var->var_name);
14175184Sek110237 	char *name = n;
14185184Sek110237 	var_t *rtn = NULL;
14195184Sek110237 
14205184Sek110237 	name++;
14215184Sek110237 	if (name[strlen(name) - 1] != '}')
14225184Sek110237 		return (NULL);
14235184Sek110237 	name[strlen(name) - 1] = 0;
14245184Sek110237 
14255184Sek110237 	if (strncmp(name, STATS_VAR, strlen(STATS_VAR)) == 0)
14265184Sek110237 		rtn = stats_findvar(var, name + strlen(STATS_VAR));
14275184Sek110237 
14285184Sek110237 	if (strcmp(name, EVENTGEN_VAR) == 0)
14295184Sek110237 		rtn = eventgen_ratevar(var);
14305184Sek110237 
14315184Sek110237 	if (strcmp(name, DATE_VAR) == 0)
14325184Sek110237 		rtn = date_var(var);
14335184Sek110237 
14345184Sek110237 	if (strcmp(name, SCRIPT_VAR) == 0)
14355184Sek110237 		rtn = script_var(var);
14365184Sek110237 
14375184Sek110237 	if (strcmp(name, HOST_VAR) == 0)
14385184Sek110237 		rtn = host_var(var);
14395184Sek110237 
14405184Sek110237 	free(n);
14415184Sek110237 
14425184Sek110237 	return (rtn);
14435184Sek110237 }
14445184Sek110237 
14455184Sek110237 /*
14465184Sek110237  * Calls the C library routine getenv() to obtain the value
14475184Sek110237  * for the environment variable specified by var->var_name.
14486212Saw148015  * If found, the value string is returned in var->var_val.string.
14495184Sek110237  * If the requested value is not found, NULL is returned.
14505184Sek110237  */
14515184Sek110237 static var_t *
14525184Sek110237 var_find_environment(var_t *var)
14535184Sek110237 {
14545184Sek110237 	char *n = fb_stralloc(var->var_name);
14555184Sek110237 	char *name = n;
14566212Saw148015 	char *strptr;
14575184Sek110237 
14585184Sek110237 	name++;
14596212Saw148015 	if (name[strlen(name) - 1] != ')') {
14606212Saw148015 		free(n);
14615184Sek110237 		return (NULL);
14626212Saw148015 	}
14635184Sek110237 	name[strlen(name) - 1] = 0;
14645184Sek110237 
14656212Saw148015 	if ((strptr = getenv(name)) != NULL) {
14665184Sek110237 		free(n);
14676212Saw148015 		VAR_SET_STR(var, strptr);
14685184Sek110237 		return (var);
14695184Sek110237 	} else {
14705184Sek110237 		free(n);
14715184Sek110237 		return (NULL);
14725184Sek110237 	}
14735184Sek110237 }
14745184Sek110237 
14755184Sek110237 /*
14765184Sek110237  * Look up special variables. The "name" argument is used to find
14775184Sek110237  * the desired special var and fill it with an appropriate string
14785184Sek110237  * value. Looks for an already allocated var of the same name on
1479*6550Saw148015  * the shm_var_dyn_list. If not found a new dynamic var is allocated.
14805184Sek110237  * if the name begins with '{', it is an internal variable, and
14815184Sek110237  * var_find_internal() is called. If the name begins with '(' it
14825184Sek110237  * is an environment varable, and var_find_environment() is
14835184Sek110237  * called. On success, a pointer to the var_t is returned,
14845184Sek110237  * otherwise, NULL is returned.
14855184Sek110237  */
14865184Sek110237 static var_t *
14875184Sek110237 var_find_dynamic(char *name)
14885184Sek110237 {
14895184Sek110237 	var_t *var = NULL;
14906391Saw148015 	var_t *v = filebench_shm->shm_var_dyn_list;
14915184Sek110237 	var_t *rtn;
14925184Sek110237 
14935184Sek110237 	/*
14945184Sek110237 	 * Lookup a reference to the var handle for this
14955184Sek110237 	 * special var
14965184Sek110237 	 */
14976391Saw148015 	for (v = filebench_shm->shm_var_dyn_list; v != NULL; v = v->var_next) {
14985184Sek110237 		if (strcmp(v->var_name, name) == 0) {
14995184Sek110237 			var = v;
15005184Sek110237 			break;
15015184Sek110237 		}
15025184Sek110237 	}
15035184Sek110237 
15045184Sek110237 	if (var == NULL)
15055184Sek110237 		var = var_alloc_dynamic(name);
15065184Sek110237 
15075184Sek110237 	/* Internal system control variable */
15085184Sek110237 	if (*name == '{') {
15095184Sek110237 		rtn = var_find_internal(var);
15105184Sek110237 		if (rtn == NULL)
15115184Sek110237 			filebench_log(LOG_ERROR,
15125184Sek110237 			    "Cannot find internal variable %s",
15135184Sek110237 			    var->var_name);
15145184Sek110237 		return (rtn);
15155184Sek110237 	}
15165184Sek110237 
15175184Sek110237 	/* Lookup variable in environment */
15185184Sek110237 	if (*name == '(') {
15195184Sek110237 		rtn = var_find_environment(var);
15205184Sek110237 		if (rtn == NULL)
15215184Sek110237 			filebench_log(LOG_ERROR,
15225184Sek110237 			    "Cannot find environment variable %s",
15235184Sek110237 			    var->var_name);
15245184Sek110237 		return (rtn);
15255184Sek110237 	}
15265184Sek110237 
15275184Sek110237 	return (NULL);
15285184Sek110237 }
1529*6550Saw148015 
1530*6550Saw148015 /*
1531*6550Saw148015  * replace the avd_t attribute value descriptor in the new FLOW_MASTER flowop
1532*6550Saw148015  * that points to a local variable with a new avd_t containing
1533*6550Saw148015  * the actual value from the local variable.
1534*6550Saw148015  */
1535*6550Saw148015 void
1536*6550Saw148015 avd_update(avd_t *avdp, var_t *lvar_list)
1537*6550Saw148015 {
1538*6550Saw148015 	var_t *old_lvar, *new_lvar;
1539*6550Saw148015 
1540*6550Saw148015 	if ((*avdp)->avd_type == AVD_IND_VAR) {
1541*6550Saw148015 
1542*6550Saw148015 		/* Make sure there is a local var */
1543*6550Saw148015 		if ((old_lvar = (*avdp)->avd_val.varptr) == NULL) {
1544*6550Saw148015 			filebench_log(LOG_ERROR,
1545*6550Saw148015 			    "avd_update: local var not found");
1546*6550Saw148015 			return;
1547*6550Saw148015 		}
1548*6550Saw148015 	} else {
1549*6550Saw148015 		/* Empty or not indirect, so no update needed */
1550*6550Saw148015 		return;
1551*6550Saw148015 	}
1552*6550Saw148015 
1553*6550Saw148015 	/*  allocate a new avd using the new or old lvar contents */
1554*6550Saw148015 	if ((new_lvar =
1555*6550Saw148015 	    var_find_list(old_lvar->var_name, lvar_list)) != NULL)
1556*6550Saw148015 		(*avdp) = avd_alloc_var_ptr(new_lvar);
1557*6550Saw148015 	else
1558*6550Saw148015 		(*avdp) = avd_alloc_var_ptr(old_lvar);
1559*6550Saw148015 }
1560*6550Saw148015 
1561*6550Saw148015 void
1562*6550Saw148015 var_update_comp_lvars(var_t *newlvar, var_t *proto_comp_vars,
1563*6550Saw148015     var_t *mstr_lvars)
1564*6550Saw148015 {
1565*6550Saw148015 	var_t *proto_lvar;
1566*6550Saw148015 
1567*6550Saw148015 	/* find the prototype lvar from the inherited list */
1568*6550Saw148015 	proto_lvar = var_find_list_only(newlvar->var_name, proto_comp_vars);
1569*6550Saw148015 
1570*6550Saw148015 	if (proto_lvar == NULL)
1571*6550Saw148015 		return;
1572*6550Saw148015 
1573*6550Saw148015 	/*
1574*6550Saw148015 	 * if the new local variable has not already been assigned
1575*6550Saw148015 	 * a value, try to copy a value from the prototype local variable
1576*6550Saw148015 	 */
1577*6550Saw148015 	if ((newlvar->var_type & VAR_TYPE_SET_MASK) == 0) {
1578*6550Saw148015 
1579*6550Saw148015 		/* copy value from prototype lvar to new lvar */
1580*6550Saw148015 		(void) var_copy(newlvar, proto_lvar);
1581*6550Saw148015 	}
1582*6550Saw148015 
1583*6550Saw148015 	/* If proto lvar is indirect, see if we can colapse indirection */
1584*6550Saw148015 	if (VAR_HAS_INDVAR(proto_lvar)) {
1585*6550Saw148015 		var_t *uplvp;
1586*6550Saw148015 
1587*6550Saw148015 		uplvp = (var_t *)proto_lvar->var_val.varptr;
1588*6550Saw148015 
1589*6550Saw148015 		/* search for more current uplvar on comp master list */
1590*6550Saw148015 		if (mstr_lvars) {
1591*6550Saw148015 			uplvp = var_find_list_only(
1592*6550Saw148015 			    uplvp->var_name, mstr_lvars);
1593*6550Saw148015 			VAR_SET_INDVAR(newlvar, uplvp);
1594*6550Saw148015 		}
1595*6550Saw148015 
1596*6550Saw148015 		if (VAR_HAS_INDVAR(uplvp))
1597*6550Saw148015 			VAR_SET_INDVAR(newlvar, uplvp->var_val.varptr);
1598*6550Saw148015 	}
1599*6550Saw148015 }
1600