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. 24*6613Sek110237 * 25*6613Sek110237 * Portions Copyright 2008 Denis Cheng 265184Sek110237 */ 275184Sek110237 285184Sek110237 #pragma ident "%Z%%M% %I% %E% SMI" 295184Sek110237 305184Sek110237 #include <stdlib.h> 315184Sek110237 #include <stdio.h> 325184Sek110237 #include <string.h> 335184Sek110237 #include <errno.h> 345184Sek110237 35*6613Sek110237 #include "filebench.h" 365184Sek110237 #include "vars.h" 375184Sek110237 #include "misc.h" 385184Sek110237 #include "utils.h" 395184Sek110237 #include "stats.h" 405184Sek110237 #include "eventgen.h" 416212Saw148015 #include "fb_random.h" 425184Sek110237 435184Sek110237 static var_t *var_find_dynamic(char *name); 445184Sek110237 455184Sek110237 /* 466212Saw148015 * The filebench variables system has attribute value descriptors (avd_t) 476212Saw148015 * where an avd contains a boolean, integer, double, string, random 486212Saw148015 * distribution object ptr, boolean ptr, integer ptr, double ptr, 496212Saw148015 * string ptr, or variable ptr. The system also has the variables 506212Saw148015 * themselves, (var_t), which are named, typed entities which can be 516212Saw148015 * allocated, selected and changed using the "set" command and used in 526212Saw148015 * attribute assignments. The variables contain either a boolean, an 536212Saw148015 * integer, a double, a string or pointer to an associated random 546212Saw148015 * distribution object. Both avd_t and var_t entities are allocated 555184Sek110237 * from interprocess shared memory space. 565184Sek110237 * 576212Saw148015 * The attribute descriptors implement delayed binding to variable values, 586212Saw148015 * which is necessary because the values of variables may be changed 596212Saw148015 * between the time the workload file is loaded and it is actually run, 606212Saw148015 * either by further "set" commands in the file or from the command line 616212Saw148015 * interface. For random variables, they actually point to the random 626212Saw148015 * distribution object, allowing FileBench to invoke the appropriate 636212Saw148015 * random distribution function on each access to the attribute. However, 646212Saw148015 * for static attributes, the value is just loaded in the descriptor 656212Saw148015 * directly, avoiding the need to allocate a variable to hold the static 666212Saw148015 * value. 676212Saw148015 * 685184Sek110237 * The routines in this module are used to allocate, locate, and 696212Saw148015 * manipulate the attribute descriptors, and vars. Routines are 706212Saw148015 * also included to convert between the component strings, doubles 716212Saw148015 * and integers of vars, and said components of avd_t. 725184Sek110237 */ 735184Sek110237 746550Saw148015 755184Sek110237 /* 766212Saw148015 * returns a pointer to a string indicating the type of data contained 776212Saw148015 * in the supplied attribute variable descriptor. 785184Sek110237 */ 796212Saw148015 static char * 806212Saw148015 avd_get_type_string(avd_t avd) 815184Sek110237 { 826212Saw148015 switch (avd->avd_type) { 836212Saw148015 case AVD_INVALID: 846212Saw148015 return ("uninitialized"); 856212Saw148015 866212Saw148015 case AVD_VAL_BOOL: 876212Saw148015 return ("boolean value"); 886212Saw148015 896212Saw148015 case AVD_VARVAL_BOOL: 906212Saw148015 return ("points to boolean in var_t"); 916212Saw148015 926212Saw148015 case AVD_VAL_INT: 936212Saw148015 return ("integer value"); 946212Saw148015 956212Saw148015 case AVD_VARVAL_INT: 966212Saw148015 return ("points to integer in var_t"); 976212Saw148015 986212Saw148015 case AVD_VAL_STR: 996212Saw148015 return ("string"); 1006212Saw148015 1016212Saw148015 case AVD_VARVAL_STR: 1026212Saw148015 return ("points to string in var_t"); 1036212Saw148015 1046212Saw148015 case AVD_VAL_DBL: 1056212Saw148015 return ("double float value"); 1066212Saw148015 1076212Saw148015 case AVD_VARVAL_DBL: 1086212Saw148015 return ("points to double float in var_t"); 1096212Saw148015 1106212Saw148015 case AVD_IND_VAR: 1116212Saw148015 return ("points to a var_t"); 1126212Saw148015 1136212Saw148015 case AVD_IND_RANDVAR: 1146212Saw148015 return ("points to var_t's random distribution object"); 1156212Saw148015 1166212Saw148015 default: 1176212Saw148015 return ("illegal avd type"); 1186212Saw148015 } 1196212Saw148015 } 1206212Saw148015 1216212Saw148015 /* 1226212Saw148015 * returns a pointer to a string indicating the type of data contained 1236212Saw148015 * in the supplied variable. 1246212Saw148015 */ 1256212Saw148015 static char * 1266212Saw148015 var_get_type_string(var_t *ivp) 1276212Saw148015 { 1286212Saw148015 switch (ivp->var_type & VAR_TYPE_SET_MASK) { 1296212Saw148015 case VAR_TYPE_BOOL_SET: 1306212Saw148015 return ("boolean"); 1316212Saw148015 1326212Saw148015 case VAR_TYPE_INT_SET: 1336212Saw148015 return ("integer"); 1346212Saw148015 1356212Saw148015 case VAR_TYPE_STR_SET: 1366212Saw148015 return ("string"); 1376212Saw148015 1386212Saw148015 case VAR_TYPE_DBL_SET: 1396212Saw148015 return ("double float"); 1406212Saw148015 1416212Saw148015 case VAR_TYPE_RAND_SET: 1426212Saw148015 return ("random"); 1436212Saw148015 1446212Saw148015 default: 1456212Saw148015 return ("empty"); 1466212Saw148015 } 1476212Saw148015 } 1486212Saw148015 1496212Saw148015 /* 1506212Saw148015 * Returns the fbint_t pointed to by the supplied avd_t "avd". 1516212Saw148015 */ 1526212Saw148015 fbint_t 1536212Saw148015 avd_get_int(avd_t avd) 1546212Saw148015 { 1556212Saw148015 var_t *ivp; 1566212Saw148015 randdist_t *rndp; 1576212Saw148015 1586212Saw148015 if (avd == NULL) 1595184Sek110237 return (0); 1605184Sek110237 1616212Saw148015 switch (avd->avd_type) { 1626212Saw148015 case AVD_VAL_INT: 1636212Saw148015 return (avd->avd_val.intval); 1646212Saw148015 1656212Saw148015 case AVD_VARVAL_INT: 1666212Saw148015 if (avd->avd_val.intptr) 1676212Saw148015 return (*(avd->avd_val.intptr)); 1686212Saw148015 else 1696212Saw148015 return (0); 1706212Saw148015 1716212Saw148015 case AVD_IND_VAR: 1726212Saw148015 if ((ivp = avd->avd_val.varptr) == NULL) 1736212Saw148015 return (0); 1746212Saw148015 1756212Saw148015 if (VAR_HAS_INTEGER(ivp)) 1766212Saw148015 return (ivp->var_val.integer); 1776212Saw148015 1786212Saw148015 if (VAR_HAS_RANDDIST(ivp)) { 1796212Saw148015 if ((rndp = ivp->var_val.randptr) != NULL) 1806212Saw148015 return ((fbint_t)rndp->rnd_get(rndp)); 1816212Saw148015 } 1826212Saw148015 1836212Saw148015 filebench_log(LOG_ERROR, 1846212Saw148015 "Attempt to get integer from %s var $%s", 1856212Saw148015 var_get_type_string(ivp), ivp->var_name); 1866212Saw148015 return (0); 1876212Saw148015 1886212Saw148015 case AVD_IND_RANDVAR: 1896212Saw148015 if ((rndp = avd->avd_val.randptr) == NULL) 1906212Saw148015 return (0); 1916212Saw148015 else 1926212Saw148015 return ((fbint_t)rndp->rnd_get(rndp)); 1936212Saw148015 1946212Saw148015 default: 1956212Saw148015 filebench_log(LOG_ERROR, 1966212Saw148015 "Attempt to get integer from %s avd", 1976212Saw148015 avd_get_type_string(avd)); 1986212Saw148015 return (0); 1996212Saw148015 } 2005184Sek110237 } 2015184Sek110237 2025184Sek110237 /* 2036212Saw148015 * Returns the floating point value of a variable pointed to by the 2046212Saw148015 * supplied avd_t "avd". Intended to get the actual (double) value 2056212Saw148015 * supplied by the random variable. 2066212Saw148015 */ 2076212Saw148015 double 2086212Saw148015 avd_get_dbl(avd_t avd) 2096212Saw148015 { 2106212Saw148015 var_t *ivp; 2116212Saw148015 randdist_t *rndp; 2126212Saw148015 2136212Saw148015 if (avd == NULL) 2146212Saw148015 return (0.0); 2156212Saw148015 2166212Saw148015 switch (avd->avd_type) { 2176212Saw148015 case AVD_VAL_INT: 2186212Saw148015 return ((double)avd->avd_val.intval); 2196212Saw148015 2206212Saw148015 case AVD_VAL_DBL: 2216212Saw148015 return (avd->avd_val.dblval); 2226212Saw148015 2236212Saw148015 case AVD_VARVAL_INT: 2246212Saw148015 if (avd->avd_val.intptr) 2256212Saw148015 return ((double)(*(avd->avd_val.intptr))); 2266212Saw148015 else 2276212Saw148015 return (0.0); 2286212Saw148015 2296212Saw148015 case AVD_VARVAL_DBL: 2306212Saw148015 if (avd->avd_val.dblptr) 2316212Saw148015 return (*(avd->avd_val.dblptr)); 2326212Saw148015 else 2336212Saw148015 return (0.0); 2346212Saw148015 2356212Saw148015 case AVD_IND_VAR: 2366212Saw148015 ivp = avd->avd_val.varptr; 2376212Saw148015 2386212Saw148015 if (ivp && VAR_HAS_INTEGER(ivp)) 2396212Saw148015 return ((double)ivp->var_val.integer); 2406212Saw148015 2416212Saw148015 if (ivp && VAR_HAS_DOUBLE(ivp)) 2426212Saw148015 return (ivp->var_val.dbl_flt); 2436212Saw148015 2446212Saw148015 if (ivp && VAR_HAS_RANDDIST(ivp)) { 2456212Saw148015 if ((rndp = ivp->var_val.randptr) != NULL) 2466212Saw148015 return (rndp->rnd_get(rndp)); 2476212Saw148015 } 2486212Saw148015 filebench_log(LOG_ERROR, 2496212Saw148015 "Attempt to get double float from %s var $%s", 2506212Saw148015 var_get_type_string(ivp), ivp->var_name); 2516212Saw148015 return (0.0); 2526212Saw148015 2536212Saw148015 case AVD_IND_RANDVAR: 2546212Saw148015 if ((rndp = avd->avd_val.randptr) == NULL) { 2556212Saw148015 return (0.0); 2566212Saw148015 } else 2576212Saw148015 return (rndp->rnd_get(rndp)); 2586212Saw148015 2596212Saw148015 default: 2606212Saw148015 filebench_log(LOG_ERROR, 2616212Saw148015 "Attempt to get floating point from %s avd", 2626212Saw148015 avd_get_type_string(avd)); 2636212Saw148015 return (0.0); 2646212Saw148015 } 2656212Saw148015 } 2666212Saw148015 2676212Saw148015 /* 2686212Saw148015 * Returns the boolean pointed to by the supplied avd_t "avd". 2695184Sek110237 */ 2706212Saw148015 boolean_t 2716212Saw148015 avd_get_bool(avd_t avd) 2725184Sek110237 { 2736212Saw148015 var_t *ivp; 2746212Saw148015 2756212Saw148015 if (avd == NULL) 2766212Saw148015 return (0); 2776212Saw148015 2786212Saw148015 switch (avd->avd_type) { 2796212Saw148015 case AVD_VAL_BOOL: 2806212Saw148015 return (avd->avd_val.boolval); 2816212Saw148015 2826212Saw148015 case AVD_VARVAL_BOOL: 2836212Saw148015 if (avd->avd_val.boolptr) 2846212Saw148015 return (*(avd->avd_val.boolptr)); 2856212Saw148015 else 2866212Saw148015 return (FALSE); 2876212Saw148015 2886212Saw148015 /* for backwards compatibility with old workloads */ 2896212Saw148015 case AVD_VAL_INT: 2906212Saw148015 if (avd->avd_val.intval != 0) 2916212Saw148015 return (TRUE); 2926212Saw148015 else 2936212Saw148015 return (FALSE); 2946212Saw148015 2956212Saw148015 case AVD_VARVAL_INT: 2966212Saw148015 if (avd->avd_val.intptr) 2976212Saw148015 if (*(avd->avd_val.intptr) != 0) 2986212Saw148015 return (TRUE); 2996212Saw148015 3006212Saw148015 return (FALSE); 3016212Saw148015 3026212Saw148015 case AVD_IND_VAR: 3036212Saw148015 if ((ivp = avd->avd_val.varptr) == NULL) 3046212Saw148015 return (0); 3056212Saw148015 3066212Saw148015 if (VAR_HAS_BOOLEAN(ivp)) 3076212Saw148015 return (ivp->var_val.boolean); 3086212Saw148015 3096212Saw148015 if (VAR_HAS_INTEGER(ivp)) { 3106212Saw148015 if (ivp->var_val.boolean) 3116212Saw148015 return (TRUE); 3126212Saw148015 else 3136212Saw148015 return (FALSE); 3146212Saw148015 } 3155184Sek110237 3166212Saw148015 filebench_log(LOG_ERROR, 3176212Saw148015 "Attempt to get boolean from %s var $%s", 3186212Saw148015 var_get_type_string(ivp), ivp->var_name); 3196212Saw148015 return (FALSE); 3206212Saw148015 3216212Saw148015 default: 3226212Saw148015 filebench_log(LOG_ERROR, 3236212Saw148015 "Attempt to get boolean from %s avd", 3246212Saw148015 avd_get_type_string(avd)); 3256212Saw148015 return (FALSE); 3266212Saw148015 } 3276212Saw148015 } 3286212Saw148015 3296212Saw148015 /* 3306212Saw148015 * Returns the string pointed to by the supplied avd_t "avd". 3316212Saw148015 */ 3326212Saw148015 char * 3336212Saw148015 avd_get_str(avd_t avd) 3346212Saw148015 { 3356212Saw148015 var_t *ivp; 3366212Saw148015 3376212Saw148015 if (avd == NULL) 3386212Saw148015 return (NULL); 3396212Saw148015 3406212Saw148015 switch (avd->avd_type) { 3416212Saw148015 case AVD_VAL_STR: 3426212Saw148015 return (avd->avd_val.strval); 3436212Saw148015 3446212Saw148015 case AVD_VARVAL_STR: 3456212Saw148015 if (avd->avd_val.strptr) 3466212Saw148015 return (*avd->avd_val.strptr); 3476212Saw148015 else 3486212Saw148015 return (NULL); 3496212Saw148015 3506212Saw148015 case AVD_IND_VAR: 3516212Saw148015 ivp = avd->avd_val.varptr; 3526212Saw148015 3536212Saw148015 if (ivp && VAR_HAS_STRING(ivp)) 3546212Saw148015 return (ivp->var_val.string); 3556212Saw148015 3566212Saw148015 filebench_log(LOG_ERROR, 3576212Saw148015 "Attempt to get string from %s var $%s", 3586212Saw148015 var_get_type_string(ivp), ivp->var_name); 3596212Saw148015 return (NULL); 3606212Saw148015 3616212Saw148015 default: 3626212Saw148015 filebench_log(LOG_ERROR, 3636212Saw148015 "Attempt to get string from %s avd", 3646212Saw148015 avd_get_type_string(avd)); 3655184Sek110237 return (NULL); 3665184Sek110237 } 3676212Saw148015 } 3685184Sek110237 3696212Saw148015 /* 3706212Saw148015 * Allocates a avd_t from ipc memory space. 3716212Saw148015 * logs an error and returns NULL on failure. 3726212Saw148015 */ 3736212Saw148015 static avd_t 3746212Saw148015 avd_alloc_cmn(void) 3756212Saw148015 { 3766212Saw148015 avd_t rtn; 3775184Sek110237 3786212Saw148015 if ((rtn = (avd_t)ipc_malloc(FILEBENCH_AVD)) == NULL) 3796212Saw148015 filebench_log(LOG_ERROR, "Avd alloc failed"); 3805184Sek110237 3815184Sek110237 return (rtn); 3825184Sek110237 } 3835184Sek110237 3845184Sek110237 /* 3856212Saw148015 * pre-loads the allocated avd_t with the boolean_t "bool". 3866212Saw148015 * Returns the avd_t on success, NULL on failure. 3876212Saw148015 */ 3886212Saw148015 avd_t 3896212Saw148015 avd_bool_alloc(boolean_t bool) 3906212Saw148015 { 3916212Saw148015 avd_t avd; 3926212Saw148015 3936212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 3946212Saw148015 return (NULL); 3956212Saw148015 3966212Saw148015 avd->avd_type = AVD_VAL_BOOL; 3976212Saw148015 avd->avd_val.boolval = bool; 3986212Saw148015 3996212Saw148015 filebench_log(LOG_DEBUG_IMPL, "Alloc boolean %d", bool); 4006212Saw148015 4016212Saw148015 return (avd); 4026212Saw148015 } 4036212Saw148015 4046212Saw148015 /* 4056212Saw148015 * pre-loads the allocated avd_t with the fbint_t "integer". 4066212Saw148015 * Returns the avd_t on success, NULL on failure. 4076212Saw148015 */ 4086212Saw148015 avd_t 4096212Saw148015 avd_int_alloc(fbint_t integer) 4106212Saw148015 { 4116212Saw148015 avd_t avd; 4126212Saw148015 4136212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 4146212Saw148015 return (NULL); 4156212Saw148015 4166212Saw148015 avd->avd_type = AVD_VAL_INT; 4176212Saw148015 avd->avd_val.intval = integer; 4186212Saw148015 4196286Saw148015 filebench_log(LOG_DEBUG_IMPL, "Alloc integer %llu", 4206286Saw148015 (u_longlong_t)integer); 4216212Saw148015 4226212Saw148015 return (avd); 4236212Saw148015 } 4246212Saw148015 4256212Saw148015 /* 4266212Saw148015 * Gets a avd_t and points it to the var that 4276212Saw148015 * it will eventually be filled from 4285184Sek110237 */ 4296212Saw148015 static avd_t 4306212Saw148015 avd_alloc_var_ptr(var_t *var) 4315184Sek110237 { 4326212Saw148015 avd_t avd; 4336212Saw148015 4346212Saw148015 if (var == NULL) 4356212Saw148015 return (NULL); 4366212Saw148015 4376212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 4386212Saw148015 return (NULL); 4396212Saw148015 4406212Saw148015 switch (var->var_type & VAR_TYPE_SET_MASK) { 4416212Saw148015 case VAR_TYPE_BOOL_SET: 4426212Saw148015 avd->avd_type = AVD_VARVAL_BOOL; 4436212Saw148015 avd->avd_val.boolptr = (&var->var_val.boolean); 4446212Saw148015 break; 4456212Saw148015 4466212Saw148015 case VAR_TYPE_INT_SET: 4476212Saw148015 avd->avd_type = AVD_VARVAL_INT; 4486212Saw148015 avd->avd_val.intptr = (&var->var_val.integer); 4496212Saw148015 break; 4506212Saw148015 4516212Saw148015 case VAR_TYPE_STR_SET: 4526212Saw148015 avd->avd_type = AVD_VARVAL_STR; 4536212Saw148015 avd->avd_val.strptr = &(var->var_val.string); 4546212Saw148015 break; 4555184Sek110237 4566212Saw148015 case VAR_TYPE_DBL_SET: 4576212Saw148015 avd->avd_type = AVD_VARVAL_DBL; 4586212Saw148015 avd->avd_val.dblptr = &(var->var_val.dbl_flt); 4596212Saw148015 break; 4606212Saw148015 4616212Saw148015 case VAR_TYPE_RAND_SET: 4626212Saw148015 avd->avd_type = AVD_IND_RANDVAR; 4636212Saw148015 avd->avd_val.randptr = var->var_val.randptr; 4646212Saw148015 break; 4656212Saw148015 4666550Saw148015 case VAR_TYPE_INDVAR_SET: 4676550Saw148015 avd->avd_type = AVD_IND_VAR; 4686550Saw148015 avd->avd_val.varptr = var->var_val.varptr; 4696550Saw148015 break; 4706550Saw148015 4716212Saw148015 default: 4726212Saw148015 avd->avd_type = AVD_IND_VAR; 4736212Saw148015 avd->avd_val.varptr = var; 4746212Saw148015 break; 4756212Saw148015 } 4766212Saw148015 return (avd); 4776212Saw148015 } 4786212Saw148015 4796212Saw148015 /* 4806212Saw148015 * Gets a avd_t, then allocates and initializes a piece of 4816212Saw148015 * shared string memory, putting the pointer to it into the just 4826212Saw148015 * allocated string pointer location. The routine returns a pointer 4836212Saw148015 * to the string pointer location or returns NULL on error. 4846212Saw148015 */ 4856212Saw148015 avd_t 4866212Saw148015 avd_str_alloc(char *string) 4876212Saw148015 { 4886212Saw148015 avd_t avd; 4896212Saw148015 4906212Saw148015 if (string == NULL) { 4916212Saw148015 filebench_log(LOG_ERROR, "No string supplied\n"); 4925184Sek110237 return (NULL); 4935184Sek110237 } 4945184Sek110237 4956212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 4966212Saw148015 return (NULL); 4976212Saw148015 4986212Saw148015 avd->avd_type = AVD_VAL_STR; 4996212Saw148015 avd->avd_val.strval = ipc_stralloc(string); 5005184Sek110237 5015184Sek110237 filebench_log(LOG_DEBUG_IMPL, 5025184Sek110237 "Alloc string %s ptr %zx", 5036212Saw148015 string, avd); 5045184Sek110237 5056212Saw148015 return (avd); 5065184Sek110237 } 5075184Sek110237 5085184Sek110237 /* 5095184Sek110237 * Allocates a var (var_t) from interprocess shared memory. 5105184Sek110237 * Places the allocated var on the end of the globally shared 5116550Saw148015 * shm_var_list. Finally, the routine allocates a string containing 5125184Sek110237 * a copy of the supplied "name" string. If any allocations 5135184Sek110237 * fails, returns NULL, otherwise it returns a pointer to the 5145184Sek110237 * newly allocated var. 5155184Sek110237 */ 5165184Sek110237 static var_t * 5176212Saw148015 var_alloc_cmn(char *name, int var_type) 5185184Sek110237 { 5196212Saw148015 var_t **var_listp; 5205184Sek110237 var_t *var = NULL; 5215184Sek110237 var_t *prev = NULL; 5225184Sek110237 var_t *newvar; 5235184Sek110237 5245184Sek110237 if ((newvar = (var_t *)ipc_malloc(FILEBENCH_VARIABLE)) == NULL) { 5255184Sek110237 filebench_log(LOG_ERROR, "Out of memory for variables"); 5265184Sek110237 return (NULL); 5275184Sek110237 } 5285184Sek110237 (void) memset(newvar, 0, sizeof (newvar)); 5296212Saw148015 newvar->var_type = var_type; 5305184Sek110237 5315184Sek110237 if ((newvar->var_name = ipc_stralloc(name)) == NULL) { 5325184Sek110237 filebench_log(LOG_ERROR, "Out of memory for variables"); 5335184Sek110237 return (NULL); 5345184Sek110237 } 5355184Sek110237 5366212Saw148015 switch (var_type & VAR_TYPE_MASK) { 5376212Saw148015 case VAR_TYPE_RANDOM: 5386212Saw148015 case VAR_TYPE_GLOBAL: 5396391Saw148015 var_listp = &filebench_shm->shm_var_list; 5406212Saw148015 break; 5416212Saw148015 5426212Saw148015 case VAR_TYPE_DYNAMIC: 5436391Saw148015 var_listp = &filebench_shm->shm_var_dyn_list; 5446212Saw148015 break; 5456212Saw148015 5466550Saw148015 case VAR_TYPE_LOCAL: 5476550Saw148015 /* place on head of shared local list */ 5486550Saw148015 newvar->var_next = filebench_shm->shm_var_loc_list; 5496550Saw148015 filebench_shm->shm_var_loc_list = newvar; 5506550Saw148015 return (newvar); 5516550Saw148015 5526212Saw148015 default: 5536391Saw148015 var_listp = &filebench_shm->shm_var_list; 5546212Saw148015 break; 5556212Saw148015 } 5566212Saw148015 5576212Saw148015 /* add to the end of list */ 5586212Saw148015 for (var = *var_listp; var != NULL; var = var->var_next) 5596212Saw148015 prev = var; /* Find end of list */ 5606212Saw148015 if (prev != NULL) 5616212Saw148015 prev->var_next = newvar; 5626212Saw148015 else 5636212Saw148015 *var_listp = newvar; 5646212Saw148015 5655184Sek110237 return (newvar); 5665184Sek110237 } 5675184Sek110237 5685184Sek110237 /* 5696550Saw148015 * Allocates a var (var_t) from interprocess shared memory after 5706550Saw148015 * first adjusting the name to elminate the leading $. Places the 5716550Saw148015 * allocated var temporarily on the end of the globally 5726550Saw148015 * shared var_loc_list. If the allocation fails, returns NULL, 5736550Saw148015 * otherwise it returns a pointer to the newly allocated var. 5746550Saw148015 */ 5756550Saw148015 var_t * 5766550Saw148015 var_lvar_alloc_local(char *name) 5776550Saw148015 { 5786550Saw148015 if (name[0] == '$') 5796550Saw148015 name += 1; 5806550Saw148015 5816550Saw148015 return (var_alloc_cmn(name, VAR_TYPE_LOCAL)); 5826550Saw148015 } 5836550Saw148015 5846550Saw148015 /* 5856212Saw148015 * Allocates a var (var_t) from interprocess shared memory and 5866212Saw148015 * places the allocated var on the end of the globally shared 5876550Saw148015 * shm_var_list. If the allocation fails, returns NULL, otherwise 5886212Saw148015 * it returns a pointer to the newly allocated var. 5896212Saw148015 */ 5906212Saw148015 static var_t * 5916212Saw148015 var_alloc(char *name) 5926212Saw148015 { 5936212Saw148015 return (var_alloc_cmn(name, VAR_TYPE_GLOBAL)); 5946212Saw148015 } 5956212Saw148015 5966212Saw148015 /* 5975184Sek110237 * Allocates a var (var_t) from interprocess shared memory. 5985184Sek110237 * Places the allocated var on the end of the globally shared 5996550Saw148015 * shm_var_dyn_list. If the allocation fails, returns NULL, otherwise 6006212Saw148015 * it returns a pointer to the newly allocated var. 6015184Sek110237 */ 6025184Sek110237 static var_t * 6035184Sek110237 var_alloc_dynamic(char *name) 6045184Sek110237 { 6056212Saw148015 return (var_alloc_cmn(name, VAR_TYPE_DYNAMIC)); 6065184Sek110237 } 6075184Sek110237 6085184Sek110237 /* 6096550Saw148015 * Searches for var_t with name "name" in the shm_var_loc_list, 6106550Saw148015 * then, if not found, in the global shm_var_list. If a matching 6116550Saw148015 * local or global var is found, returns a pointer to the var_t, 6126550Saw148015 * otherwise returns NULL. 6135184Sek110237 */ 6145184Sek110237 static var_t * 6155184Sek110237 var_find(char *name) 6165184Sek110237 { 6175184Sek110237 var_t *var; 6185184Sek110237 6196550Saw148015 for (var = filebench_shm->shm_var_loc_list; var != NULL; 6206550Saw148015 var = var->var_next) { 6216550Saw148015 if (strcmp(var->var_name, name) == 0) 6226550Saw148015 return (var); 6236550Saw148015 } 6246550Saw148015 6256391Saw148015 for (var = filebench_shm->shm_var_list; var != NULL; 6266391Saw148015 var = var->var_next) { 6275184Sek110237 if (strcmp(var->var_name, name) == 0) 6285184Sek110237 return (var); 6295184Sek110237 } 6305184Sek110237 6315184Sek110237 return (NULL); 6325184Sek110237 } 6335184Sek110237 6345184Sek110237 /* 6356550Saw148015 * Searches for var_t with name "name" in the supplied shm_var_list. 6366550Saw148015 * If not found there, checks the global list. If still 6376550Saw148015 * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t. 6386550Saw148015 */ 6396550Saw148015 static var_t * 6406550Saw148015 var_find_list_only(char *name, var_t *var_list) 6416550Saw148015 { 6426550Saw148015 var_t *var; 6436550Saw148015 6446550Saw148015 for (var = var_list; var != NULL; var = var->var_next) { 6456550Saw148015 if (strcmp(var->var_name, name) == 0) 6466550Saw148015 return (var); 6476550Saw148015 } 6486550Saw148015 6496550Saw148015 return (NULL); 6506550Saw148015 } 6516550Saw148015 6526550Saw148015 /* 6536550Saw148015 * Searches for var_t with name "name" in the supplied shm_var_list. 6546550Saw148015 * If not found there, checks the global list. If still 6556550Saw148015 * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t. 6566550Saw148015 */ 6576550Saw148015 static var_t * 6586550Saw148015 var_find_list(char *name, var_t *var_list) 6596550Saw148015 { 6606550Saw148015 var_t *var; 6616550Saw148015 6626550Saw148015 if ((var = var_find_list_only(name, var_list)) != NULL) 6636550Saw148015 return (var); 6646550Saw148015 else 6656550Saw148015 return (var_find(name)); 6666550Saw148015 } 6676550Saw148015 6686550Saw148015 /* 6695184Sek110237 * Searches for the named var, and, if found, sets its 6706212Saw148015 * var_val.boolean's value to that of the supplied boolean. 6715184Sek110237 * If not found, the routine allocates a new var and sets 6726212Saw148015 * its var_val.boolean's value to that of the supplied 6736212Saw148015 * boolean. If the named var cannot be found or allocated 6746212Saw148015 * the routine returns -1, otherwise it returns 0. 6755184Sek110237 */ 6765184Sek110237 int 6776212Saw148015 var_assign_boolean(char *name, boolean_t bool) 6785184Sek110237 { 6795184Sek110237 var_t *var; 6805184Sek110237 6816212Saw148015 if (name == NULL) { 6826212Saw148015 filebench_log(LOG_ERROR, 6836212Saw148015 "var_assign_boolean: Name not supplied"); 6846212Saw148015 return (0); 6856212Saw148015 } 6866212Saw148015 6875184Sek110237 name += 1; 6885184Sek110237 6896212Saw148015 if ((var = var_find(name)) == NULL) { 6906212Saw148015 var = var_alloc(name); 6916212Saw148015 } 6925184Sek110237 6935184Sek110237 if (var == NULL) { 6945184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 6955184Sek110237 name); 6965184Sek110237 return (-1); 6975184Sek110237 } 6985184Sek110237 6996212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 7006212Saw148015 filebench_log(LOG_ERROR, 7016212Saw148015 "Cannot assign integer to random variable %s", name); 7026212Saw148015 return (-1); 7036212Saw148015 } 7046212Saw148015 7056212Saw148015 VAR_SET_BOOL(var, bool); 7066212Saw148015 7076212Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign boolean %s=%d", 7086212Saw148015 name, bool); 7096212Saw148015 7106212Saw148015 return (0); 7116212Saw148015 } 7126212Saw148015 7136212Saw148015 /* 7146212Saw148015 * Searches for the named var, and, if found, sets its 7156212Saw148015 * var_integer's value to that of the supplied integer. 7166212Saw148015 * If not found, the routine allocates a new var and sets 7176212Saw148015 * its var_integers's value to that of the supplied 7186212Saw148015 * integer. If the named var cannot be found or allocated 7196212Saw148015 * the routine returns -1, otherwise it returns 0. 7206212Saw148015 */ 7216212Saw148015 int 7226212Saw148015 var_assign_integer(char *name, fbint_t integer) 7236212Saw148015 { 7246212Saw148015 var_t *var; 7256212Saw148015 7266212Saw148015 if (name == NULL) { 7276212Saw148015 filebench_log(LOG_ERROR, 7286212Saw148015 "var_assign_integer: Name not supplied"); 7296212Saw148015 return (0); 7306212Saw148015 } 7316212Saw148015 7326212Saw148015 name += 1; 7336212Saw148015 7346212Saw148015 if ((var = var_find(name)) == NULL) { 7356212Saw148015 var = var_alloc(name); 7366212Saw148015 } 7376212Saw148015 7386212Saw148015 if (var == NULL) { 7396212Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 7406212Saw148015 name); 7416212Saw148015 return (-1); 7426212Saw148015 } 7436212Saw148015 7446212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 7456212Saw148015 filebench_log(LOG_ERROR, 7466212Saw148015 "Cannot assign integer to random variable %s", name); 7476212Saw148015 return (-1); 7486212Saw148015 } 7496212Saw148015 7506212Saw148015 VAR_SET_INT(var, integer); 7515184Sek110237 7526286Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu", 7536286Saw148015 name, (u_longlong_t)integer); 7545184Sek110237 7555184Sek110237 return (0); 7565184Sek110237 } 7575184Sek110237 7585184Sek110237 /* 7596212Saw148015 * Find a variable, and set it to random type. 7606212Saw148015 * If it does not have a random extension, allocate one 7616212Saw148015 */ 7626212Saw148015 var_t * 7636212Saw148015 var_find_randvar(char *name) 7646212Saw148015 { 7656212Saw148015 var_t *newvar; 7666212Saw148015 7676212Saw148015 name += 1; 7686212Saw148015 7696212Saw148015 if ((newvar = var_find(name)) == NULL) { 7706212Saw148015 filebench_log(LOG_ERROR, 7716212Saw148015 "failed to locate random variable $%s\n", name); 7726212Saw148015 return (NULL); 7736212Saw148015 } 7746212Saw148015 7756212Saw148015 /* set randdist pointer unless it is already set */ 7766212Saw148015 if (((newvar->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) || 7776212Saw148015 !VAR_HAS_RANDDIST(newvar)) { 7786212Saw148015 filebench_log(LOG_ERROR, 7796212Saw148015 "Found variable $%s not random\n", name); 7806212Saw148015 return (NULL); 7816212Saw148015 } 7826212Saw148015 7836212Saw148015 return (newvar); 7846212Saw148015 } 7856212Saw148015 7866212Saw148015 /* 7876212Saw148015 * Allocate a variable, and set it to random type. Then 7886212Saw148015 * allocate a random extension. 7896212Saw148015 */ 7906212Saw148015 var_t * 7916212Saw148015 var_define_randvar(char *name) 7926212Saw148015 { 7936212Saw148015 var_t *newvar; 7946212Saw148015 randdist_t *rndp = NULL; 7956212Saw148015 7966212Saw148015 name += 1; 7976212Saw148015 7986212Saw148015 /* make sure variable doesn't already exist */ 7996212Saw148015 if (var_find(name) != NULL) { 8006212Saw148015 filebench_log(LOG_ERROR, 8016212Saw148015 "variable name already in use\n"); 8026212Saw148015 return (NULL); 8036212Saw148015 } 8046212Saw148015 8056212Saw148015 /* allocate a random variable */ 8066212Saw148015 if ((newvar = var_alloc_cmn(name, VAR_TYPE_RANDOM)) == NULL) { 8076212Saw148015 filebench_log(LOG_ERROR, 8086212Saw148015 "failed to alloc random variable\n"); 8096212Saw148015 return (NULL); 8106212Saw148015 } 8116212Saw148015 8126212Saw148015 /* set randdist pointer */ 8136212Saw148015 if ((rndp = randdist_alloc()) == NULL) { 8146212Saw148015 filebench_log(LOG_ERROR, 8156212Saw148015 "failed to alloc random distribution object\n"); 8166212Saw148015 return (NULL); 8176212Saw148015 } 8186212Saw148015 8196212Saw148015 rndp->rnd_var = newvar; 8206212Saw148015 VAR_SET_RAND(newvar, rndp); 8216212Saw148015 8226212Saw148015 return (newvar); 8236212Saw148015 } 8246212Saw148015 8256212Saw148015 /* 8266212Saw148015 * Searches for the named var, and if found returns an avd_t 8276212Saw148015 * pointing to the var's var_integer, var_string or var_double 8286212Saw148015 * as appropriate. If not found, attempts to allocate 8296212Saw148015 * a var named "name" and returns an avd_t to it with 8306212Saw148015 * no value set. If the var cannot be found or allocated, an 8315184Sek110237 * error is logged and the run is terminated. 8325184Sek110237 */ 8336212Saw148015 avd_t 8346212Saw148015 var_ref_attr(char *name) 8355184Sek110237 { 8365184Sek110237 var_t *var; 8375184Sek110237 8385184Sek110237 name += 1; 8395184Sek110237 8405184Sek110237 if ((var = var_find(name)) == NULL) 8415184Sek110237 var = var_find_dynamic(name); 8425184Sek110237 8435184Sek110237 if (var == NULL) 8445184Sek110237 var = var_alloc(name); 8455184Sek110237 8465184Sek110237 if (var == NULL) { 8475184Sek110237 filebench_log(LOG_ERROR, "Invalid variable $%s", 8485184Sek110237 name); 8495184Sek110237 filebench_shutdown(1); 8505184Sek110237 } 8515184Sek110237 8526212Saw148015 /* allocate pointer to var and return */ 8536212Saw148015 return (avd_alloc_var_ptr(var)); 8545184Sek110237 } 8555184Sek110237 8566212Saw148015 8575184Sek110237 /* 8586212Saw148015 * Searches for the named var, and if found copies the var_val.string, 8596212Saw148015 * if it exists, a decimal number string representation of 8606212Saw148015 * var_val.integer, the state of var_val.boolean, or the type of random 8616212Saw148015 * distribution employed, into a malloc'd bit of memory using fb_stralloc(). 8625184Sek110237 * Returns a pointer to the created string, or NULL on failure. 8635184Sek110237 */ 8645184Sek110237 char * 8655184Sek110237 var_to_string(char *name) 8665184Sek110237 { 8675184Sek110237 var_t *var; 8685184Sek110237 char tmp[128]; 8695184Sek110237 8705184Sek110237 name += 1; 8715184Sek110237 8725184Sek110237 if ((var = var_find(name)) == NULL) 8735184Sek110237 var = var_find_dynamic(name); 8745184Sek110237 8755184Sek110237 if (var == NULL) 8765184Sek110237 return (NULL); 8775184Sek110237 8786212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 8796212Saw148015 switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) { 8806212Saw148015 case RAND_TYPE_UNIFORM: 8816212Saw148015 return (fb_stralloc("uniform random var")); 8826212Saw148015 case RAND_TYPE_GAMMA: 8836212Saw148015 return (fb_stralloc("gamma random var")); 8846212Saw148015 case RAND_TYPE_TABLE: 8856212Saw148015 return (fb_stralloc("tabular random var")); 8866212Saw148015 default: 8876212Saw148015 return (fb_stralloc("unitialized random var")); 8886212Saw148015 } 8896212Saw148015 } 8905184Sek110237 8916212Saw148015 if (VAR_HAS_STRING(var) && var->var_val.string) 8926212Saw148015 return (fb_stralloc(var->var_val.string)); 8935184Sek110237 8946212Saw148015 if (VAR_HAS_BOOLEAN(var)) { 8956212Saw148015 if (var->var_val.boolean) 8966212Saw148015 return (fb_stralloc("true")); 8976212Saw148015 else 8986212Saw148015 return (fb_stralloc("false")); 8996212Saw148015 } 9006212Saw148015 9016212Saw148015 if (VAR_HAS_INTEGER(var)) { 9026286Saw148015 (void) snprintf(tmp, sizeof (tmp), "%llu", 9036286Saw148015 (u_longlong_t)var->var_val.integer); 9046212Saw148015 return (fb_stralloc(tmp)); 9056212Saw148015 } 9066212Saw148015 9076212Saw148015 return (fb_stralloc("No default")); 9085184Sek110237 } 9095184Sek110237 9105184Sek110237 /* 9115184Sek110237 * Searches for the named var, and if found returns the value, 9126212Saw148015 * of var_val.boolean. If the var is not found, or a boolean 9136212Saw148015 * value has not been set, logs an error and returns 0. 9145184Sek110237 */ 9156212Saw148015 boolean_t 9166212Saw148015 var_to_boolean(char *name) 9176212Saw148015 { 9186212Saw148015 var_t *var; 9196212Saw148015 9206212Saw148015 name += 1; 9216212Saw148015 9226212Saw148015 if ((var = var_find(name)) == NULL) 9236212Saw148015 var = var_find_dynamic(name); 9246212Saw148015 9256212Saw148015 if ((var != NULL) && VAR_HAS_BOOLEAN(var)) 9266212Saw148015 return (var->var_val.boolean); 9276212Saw148015 9286212Saw148015 filebench_log(LOG_ERROR, 9296212Saw148015 "Variable %s referenced before set", name); 9306212Saw148015 9316212Saw148015 return (0); 9326212Saw148015 } 9336212Saw148015 9346212Saw148015 /* 9356212Saw148015 * Searches for the named var, and if found returns the value, 9366212Saw148015 * of var_val.integer. If the var is not found, or the an 9376212Saw148015 * integer value has not been set, logs an error and returns 0. 9386212Saw148015 */ 9396212Saw148015 fbint_t 9405184Sek110237 var_to_integer(char *name) 9415184Sek110237 { 9425184Sek110237 var_t *var; 9435184Sek110237 9445184Sek110237 name += 1; 9455184Sek110237 9465184Sek110237 if ((var = var_find(name)) == NULL) 9475184Sek110237 var = var_find_dynamic(name); 9485184Sek110237 9496212Saw148015 if ((var != NULL) && VAR_HAS_INTEGER(var)) 9506212Saw148015 return (var->var_val.integer); 9515184Sek110237 9525184Sek110237 filebench_log(LOG_ERROR, 9535184Sek110237 "Variable %s referenced before set", name); 9545184Sek110237 9555184Sek110237 return (0); 9565184Sek110237 } 9575184Sek110237 9585184Sek110237 /* 9596212Saw148015 * Searches for the named random var, and if found, converts the 9606212Saw148015 * requested parameter into a string or a decimal number string 9616212Saw148015 * representation, into a malloc'd bit of memory using fb_stralloc(). 9626212Saw148015 * Returns a pointer to the created string, or calls var_to_string() 9636212Saw148015 * if a random variable isn't found. 9646212Saw148015 */ 9656212Saw148015 char * 9666212Saw148015 var_randvar_to_string(char *name, int param_name) 9676212Saw148015 { 9686212Saw148015 var_t *var; 9696212Saw148015 fbint_t value; 9706212Saw148015 9716212Saw148015 if ((var = var_find(name + 1)) == NULL) 9726212Saw148015 return (var_to_string(name)); 9736212Saw148015 9746212Saw148015 if (((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) || 9756212Saw148015 !VAR_HAS_RANDDIST(var)) 9766212Saw148015 return (var_to_string(name)); 9776212Saw148015 9786212Saw148015 switch (param_name) { 9796212Saw148015 case RAND_PARAM_TYPE: 9806212Saw148015 switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) { 9816212Saw148015 case RAND_TYPE_UNIFORM: 9826212Saw148015 return (fb_stralloc("uniform")); 9836212Saw148015 case RAND_TYPE_GAMMA: 9846212Saw148015 return (fb_stralloc("gamma")); 9856212Saw148015 case RAND_TYPE_TABLE: 9866212Saw148015 return (fb_stralloc("tabular")); 9876212Saw148015 default: 9886212Saw148015 return (fb_stralloc("uninitialized")); 9896212Saw148015 } 9906212Saw148015 9916212Saw148015 case RAND_PARAM_SRC: 9926212Saw148015 if (var->var_val.randptr->rnd_type & RAND_SRC_GENERATOR) 9936212Saw148015 return (fb_stralloc("rand48")); 9946212Saw148015 else 9956212Saw148015 return (fb_stralloc("urandom")); 9966212Saw148015 9976212Saw148015 case RAND_PARAM_SEED: 9986212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_seed); 9996212Saw148015 break; 10006212Saw148015 10016212Saw148015 case RAND_PARAM_MIN: 10026212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_min); 10036212Saw148015 break; 10046212Saw148015 10056212Saw148015 case RAND_PARAM_MEAN: 10066212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_mean); 10076212Saw148015 break; 10086212Saw148015 10096212Saw148015 case RAND_PARAM_GAMMA: 10106212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_gamma); 10116212Saw148015 break; 10126212Saw148015 10136212Saw148015 case RAND_PARAM_ROUND: 10146212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_round); 10156212Saw148015 break; 10166212Saw148015 10176212Saw148015 default: 10186212Saw148015 return (NULL); 10196212Saw148015 10206212Saw148015 } 10216212Saw148015 10226212Saw148015 /* just an integer value if we got here */ 10236212Saw148015 { 10246212Saw148015 char tmp[128]; 10256212Saw148015 10266286Saw148015 (void) snprintf(tmp, sizeof (tmp), "%llu", 10276286Saw148015 (u_longlong_t)value); 10286212Saw148015 return (fb_stralloc(tmp)); 10296212Saw148015 } 10306212Saw148015 } 10316212Saw148015 10326212Saw148015 /* 10336550Saw148015 * Copies the value stored in the source string into the destination 10346550Saw148015 * string. Returns -1 if any problems encountered, 0 otherwise. 10356550Saw148015 */ 10366550Saw148015 static int 10376550Saw148015 var_copy(var_t *dst_var, var_t *src_var) { 10386550Saw148015 10396550Saw148015 if (VAR_HAS_BOOLEAN(src_var)) { 10406550Saw148015 VAR_SET_BOOL(dst_var, src_var->var_val.boolean); 10416550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 10426550Saw148015 "Assign var %s=%s", dst_var->var_name, 10436550Saw148015 dst_var->var_val.boolean?"true":"false"); 10446550Saw148015 } 10456550Saw148015 10466550Saw148015 if (VAR_HAS_INTEGER(src_var)) { 10476550Saw148015 VAR_SET_INT(dst_var, src_var->var_val.integer); 10486550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 10496550Saw148015 "Assign var %s=%llu", dst_var->var_name, 10506550Saw148015 (u_longlong_t)dst_var->var_val.integer); 10516550Saw148015 } 10526550Saw148015 10536550Saw148015 if (VAR_HAS_DOUBLE(src_var)) { 10546550Saw148015 VAR_SET_DBL(dst_var, src_var->var_val.dbl_flt); 10556550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 10566550Saw148015 "Assign var %s=%lf", dst_var->var_name, 10576550Saw148015 dst_var->var_val.dbl_flt); 10586550Saw148015 } 10596550Saw148015 10606550Saw148015 if (VAR_HAS_STRING(src_var)) { 10616550Saw148015 char *strptr; 10626550Saw148015 10636550Saw148015 if ((strptr = 10646550Saw148015 ipc_stralloc(src_var->var_val.string)) == NULL) { 10656550Saw148015 filebench_log(LOG_ERROR, 10666550Saw148015 "Cannot assign string for variable %s", 10676550Saw148015 dst_var->var_name); 10686550Saw148015 return (-1); 10696550Saw148015 } 10706550Saw148015 VAR_SET_STR(dst_var, strptr); 10716550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 10726550Saw148015 "Assign var %s=%s", dst_var->var_name, 10736550Saw148015 dst_var->var_val.string); 10746550Saw148015 } 10756550Saw148015 10766550Saw148015 if (VAR_HAS_INDVAR(src_var)) { 10776550Saw148015 VAR_SET_INDVAR(dst_var, src_var->var_val.varptr); 10786550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 10796550Saw148015 "Assign var %s to var %s", dst_var->var_name, 10806550Saw148015 src_var->var_name); 10816550Saw148015 } 10826550Saw148015 return (0); 10836550Saw148015 } 10846550Saw148015 10856550Saw148015 /* 10865184Sek110237 * Searches for the var named "name", and if not found 10876550Saw148015 * allocates it. The then copies the value from 10886550Saw148015 * the src_var into the destination var "name" 10896550Saw148015 * If the var "name" cannot be found or allocated, or the var "src_name" 10906550Saw148015 * cannot be found, the routine returns -1, otherwise it returns 0. 10915184Sek110237 */ 10925184Sek110237 int 10936212Saw148015 var_assign_var(char *name, char *src_name) 10945184Sek110237 { 10956212Saw148015 var_t *dst_var, *src_var; 10965184Sek110237 10975184Sek110237 name += 1; 10986212Saw148015 src_name += 1; 10995184Sek110237 11006212Saw148015 if ((src_var = var_find(src_name)) == NULL) { 11016212Saw148015 filebench_log(LOG_ERROR, 11026212Saw148015 "Cannot find source variable %s", src_name); 11036212Saw148015 return (-1); 11046212Saw148015 } 11055184Sek110237 11066212Saw148015 if ((dst_var = var_find(name)) == NULL) 11076212Saw148015 dst_var = var_alloc(name); 11086212Saw148015 11096212Saw148015 if (dst_var == NULL) { 11105184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 11115184Sek110237 name); 11125184Sek110237 return (-1); 11135184Sek110237 } 11145184Sek110237 11156212Saw148015 if ((dst_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 11166212Saw148015 filebench_log(LOG_ERROR, 11176212Saw148015 "Cannot assign var to Random variable %s", name); 11185184Sek110237 return (-1); 11195184Sek110237 } 11206212Saw148015 11216550Saw148015 return (var_copy(dst_var, src_var)); 11225184Sek110237 } 11235184Sek110237 11245184Sek110237 /* 11255184Sek110237 * Like var_assign_integer, only this routine copies the 11265184Sek110237 * supplied "string" into the var named "name". If the var 11275184Sek110237 * named "name" cannot be found then it is first allocated 11285184Sek110237 * before the copy. Space for the string in the var comes 11295184Sek110237 * from interprocess shared memory. If the var "name" 11305184Sek110237 * cannot be found or allocated, or the memory for the 11316550Saw148015 * var_val.string copy of "string" cannot be allocated, the 11325184Sek110237 * routine returns -1, otherwise it returns 0. 11335184Sek110237 */ 11345184Sek110237 int 11355184Sek110237 var_assign_string(char *name, char *string) 11365184Sek110237 { 11375184Sek110237 var_t *var; 11386212Saw148015 char *strptr; 11395184Sek110237 11405184Sek110237 name += 1; 11415184Sek110237 11425184Sek110237 if ((var = var_find(name)) == NULL) 11435184Sek110237 var = var_alloc(name); 11445184Sek110237 11455184Sek110237 if (var == NULL) { 11465184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 11475184Sek110237 name); 11485184Sek110237 return (-1); 11495184Sek110237 } 11505184Sek110237 11516212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 11526212Saw148015 filebench_log(LOG_ERROR, 11536212Saw148015 "Cannot assign string to random variable %s", name); 11546212Saw148015 return (-1); 11556212Saw148015 } 11566212Saw148015 11576212Saw148015 if ((strptr = ipc_stralloc(string)) == NULL) { 11585184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 11595184Sek110237 name); 11605184Sek110237 return (-1); 11615184Sek110237 } 11626212Saw148015 VAR_SET_STR(var, strptr); 11635184Sek110237 11646212Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 11656212Saw148015 "Var assign string $%s=%s", name, string); 11665184Sek110237 11675184Sek110237 return (0); 11685184Sek110237 } 11695184Sek110237 11705184Sek110237 /* 11716550Saw148015 * Allocates a local var. The then extracts the var_string from 11726550Saw148015 * the var named "string" and copies it into the var_string 11736550Saw148015 * of the var "name", after first allocating a piece of 11746550Saw148015 * interprocess shared string memory. Returns a pointer to the 11756550Saw148015 * newly allocated local var or NULL on error. 11766550Saw148015 */ 11776550Saw148015 var_t * 11786550Saw148015 var_lvar_assign_var(char *name, char *src_name) 11796550Saw148015 { 11806550Saw148015 var_t *dst_var, *src_var; 11816550Saw148015 11826550Saw148015 src_name += 1; 11836550Saw148015 11846550Saw148015 if ((src_var = var_find(src_name)) == NULL) { 11856550Saw148015 filebench_log(LOG_ERROR, 11866550Saw148015 "Cannot find source variable %s", src_name); 11876550Saw148015 return (NULL); 11886550Saw148015 } 11896550Saw148015 11906550Saw148015 dst_var = var_lvar_alloc_local(name); 11916550Saw148015 11926550Saw148015 if (dst_var == NULL) { 11936550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 11946550Saw148015 name); 11956550Saw148015 return (NULL); 11966550Saw148015 } 11976550Saw148015 11986550Saw148015 /* 11996550Saw148015 * if referencing another local var which is currently 12006550Saw148015 * empty, indirect to it 12016550Saw148015 */ 12026550Saw148015 if ((src_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_LOCAL) { 12036550Saw148015 VAR_SET_INDVAR(dst_var, src_var); 12046550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12056550Saw148015 "Assign local var %s to %s", name, src_name); 12066550Saw148015 return (dst_var); 12076550Saw148015 } 12086550Saw148015 12096550Saw148015 if (VAR_HAS_BOOLEAN(src_var)) { 12106550Saw148015 VAR_SET_BOOL(dst_var, src_var->var_val.boolean); 12116550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12126550Saw148015 "Assign var (%s, %p)=%s", name, 12136550Saw148015 dst_var, src_var->var_val.boolean?"true":"false"); 12146550Saw148015 } else if (VAR_HAS_INTEGER(src_var)) { 12156550Saw148015 VAR_SET_INT(dst_var, src_var->var_val.integer); 12166550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12176550Saw148015 "Assign var (%s, %p)=%llu", name, 12186550Saw148015 dst_var, (u_longlong_t)src_var->var_val.integer); 12196550Saw148015 } else if (VAR_HAS_STRING(src_var)) { 12206550Saw148015 char *strptr; 12216550Saw148015 12226550Saw148015 if ((strptr = ipc_stralloc(src_var->var_val.string)) == NULL) { 12236550Saw148015 filebench_log(LOG_ERROR, 12246550Saw148015 "Cannot assign variable %s", 12256550Saw148015 name); 12266550Saw148015 return (NULL); 12276550Saw148015 } 12286550Saw148015 VAR_SET_STR(dst_var, strptr); 12296550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12306550Saw148015 "Assign var (%s, %p)=%s", name, 12316550Saw148015 dst_var, src_var->var_val.string); 12326550Saw148015 } else if (VAR_HAS_DOUBLE(src_var)) { 12336550Saw148015 /* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */ 12346550Saw148015 VAR_SET_INT(dst_var, src_var->var_val.dbl_flt); 12356550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12366550Saw148015 "Assign var (%s, %p)=%8.2f", name, 12376550Saw148015 dst_var, src_var->var_val.dbl_flt); 12386550Saw148015 } else if (VAR_HAS_RANDDIST(src_var)) { 12396550Saw148015 VAR_SET_RAND(dst_var, src_var->var_val.randptr); 12406550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 12416550Saw148015 "Assign var (%s, %p)=%llu", name, 12426550Saw148015 dst_var, (u_longlong_t)src_var->var_val.integer); 12436550Saw148015 } 12446550Saw148015 12456550Saw148015 return (dst_var); 12466550Saw148015 } 12476550Saw148015 12486550Saw148015 /* 12496550Saw148015 * the routine allocates a new local var and sets 12506550Saw148015 * its var_boolean's value to that of the supplied 12516550Saw148015 * boolean. It returns a pointer to the new local var 12526550Saw148015 */ 12536550Saw148015 var_t * 12546550Saw148015 var_lvar_assign_boolean(char *name, boolean_t bool) 12556550Saw148015 { 12566550Saw148015 var_t *var; 12576550Saw148015 12586550Saw148015 var = var_lvar_alloc_local(name); 12596550Saw148015 12606550Saw148015 if (var == NULL) { 12616550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 12626550Saw148015 name); 12636550Saw148015 return (NULL); 12646550Saw148015 } 12656550Saw148015 12666550Saw148015 VAR_SET_BOOL(var, bool); 12676550Saw148015 12686550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%s", 12696550Saw148015 name, bool ? "true" : "false"); 12706550Saw148015 12716550Saw148015 return (var); 12726550Saw148015 } 12736550Saw148015 12746550Saw148015 /* 12756550Saw148015 * the routine allocates a new local var and sets 12766550Saw148015 * its var_integers's value to that of the supplied 12776550Saw148015 * integer. It returns a pointer to the new local var 12786550Saw148015 */ 12796550Saw148015 var_t * 12806550Saw148015 var_lvar_assign_integer(char *name, fbint_t integer) 12816550Saw148015 { 12826550Saw148015 var_t *var; 12836550Saw148015 12846550Saw148015 var = var_lvar_alloc_local(name); 12856550Saw148015 12866550Saw148015 if (var == NULL) { 12876550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 12886550Saw148015 name); 12896550Saw148015 return (NULL); 12906550Saw148015 } 12916550Saw148015 12926550Saw148015 VAR_SET_INT(var, integer); 12936550Saw148015 12946550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu", 12956550Saw148015 name, (u_longlong_t)integer); 12966550Saw148015 12976550Saw148015 return (var); 12986550Saw148015 } 12996550Saw148015 13006550Saw148015 /* 13016550Saw148015 * the routine allocates a new local var and sets 13026550Saw148015 * its var_dbl_flt value to that of the supplied 13036550Saw148015 * double precission floating point number. It returns 13046550Saw148015 * a pointer to the new local var 13056550Saw148015 */ 13066550Saw148015 var_t * 13076550Saw148015 var_lvar_assign_double(char *name, double dbl) 13086550Saw148015 { 13096550Saw148015 var_t *var; 13106550Saw148015 13116550Saw148015 var = var_lvar_alloc_local(name); 13126550Saw148015 13136550Saw148015 if (var == NULL) { 13146550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 13156550Saw148015 name); 13166550Saw148015 return (NULL); 13176550Saw148015 } 13186550Saw148015 13196550Saw148015 VAR_SET_DBL(var, dbl); 13206550Saw148015 13216550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%8.2f", name, dbl); 13226550Saw148015 13236550Saw148015 return (var); 13246550Saw148015 } 13256550Saw148015 13266550Saw148015 /* 13276550Saw148015 * Like var_lvar_assign_integer, only this routine copies the 13286550Saw148015 * supplied "string" into the var named "name". If the var 13296550Saw148015 * named "name" cannot be found then it is first allocated 13306550Saw148015 * before the copy. Space for the string in the var comes 13316550Saw148015 * from interprocess shared memory. The allocated local var 13326550Saw148015 * is returned at as a char *, or NULL on error. 13336550Saw148015 */ 13346550Saw148015 var_t * 13356550Saw148015 var_lvar_assign_string(char *name, char *string) 13366550Saw148015 { 13376550Saw148015 var_t *var; 13386550Saw148015 char *strptr; 13396550Saw148015 13406550Saw148015 var = var_lvar_alloc_local(name); 13416550Saw148015 13426550Saw148015 if (var == NULL) { 13436550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 13446550Saw148015 name); 13456550Saw148015 return (NULL); 13466550Saw148015 } 13476550Saw148015 13486550Saw148015 if ((strptr = ipc_stralloc(string)) == NULL) { 13496550Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 13506550Saw148015 name); 13516550Saw148015 return (NULL); 13526550Saw148015 } 13536550Saw148015 VAR_SET_STR(var, strptr); 13546550Saw148015 13556550Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 13566550Saw148015 "Lvar_assign_string (%s, %p)=%s", name, var, string); 13576550Saw148015 13586550Saw148015 return (var); 13596550Saw148015 } 13606550Saw148015 13616550Saw148015 /* 13626212Saw148015 * Tests to see if the supplied variable name without the portion after 13636212Saw148015 * the last period is that of a random variable. If it is, it returns 13646212Saw148015 * the number of characters to backspace to skip the period and field 13656212Saw148015 * name. Otherwise it returns 0. 13665184Sek110237 */ 13676212Saw148015 int 13686212Saw148015 var_is_set4_randvar(char *name) 13695184Sek110237 { 13705184Sek110237 var_t *var; 13716212Saw148015 char varname[128]; 13726212Saw148015 int namelength; 13736212Saw148015 char *sp; 13745184Sek110237 13756212Saw148015 (void) strncpy(varname, name, 128); 13766212Saw148015 namelength = strlen(varname); 13776212Saw148015 sp = varname + namelength; 13785184Sek110237 13796212Saw148015 while (sp != varname) { 13806212Saw148015 int c = *sp; 13815184Sek110237 13826212Saw148015 *sp = 0; 13836212Saw148015 if (c == '.') 13846212Saw148015 break; 13856212Saw148015 13866212Saw148015 sp--; 13875184Sek110237 } 13885184Sek110237 13896212Saw148015 /* not a variable name + field? */ 13906212Saw148015 if (sp == varname) 13916212Saw148015 return (0); 13926212Saw148015 13936212Saw148015 /* first part not a variable name? */ 13946212Saw148015 if ((var = var_find(varname+1)) == NULL) 13956212Saw148015 return (0); 13966212Saw148015 13976212Saw148015 /* Make sure it is a random variable */ 13986212Saw148015 if ((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) 13996212Saw148015 return (0); 14006212Saw148015 14016212Saw148015 /* calculate offset from end of random variable name */ 14026212Saw148015 return (namelength - (sp - varname)); 14035184Sek110237 } 14045184Sek110237 14055184Sek110237 /* 14065184Sek110237 * Implements a simple path name like scheme for finding values 14075184Sek110237 * to place in certain specially named vars. The first part of 14085184Sek110237 * the name is interpreted as a category of either: stats, 14095184Sek110237 * eventgen, date, script, or host var. If a match is found, 14105184Sek110237 * the appropriate routine is called to fill in the requested 14115184Sek110237 * value in the provided var_t, and a pointer to the supplied 14125184Sek110237 * var_t is returned. If the requested value is not found, NULL 14135184Sek110237 * is returned. 14145184Sek110237 */ 14155184Sek110237 static var_t * 14165184Sek110237 var_find_internal(var_t *var) 14175184Sek110237 { 14185184Sek110237 char *n = fb_stralloc(var->var_name); 14195184Sek110237 char *name = n; 14205184Sek110237 var_t *rtn = NULL; 14215184Sek110237 14225184Sek110237 name++; 14235184Sek110237 if (name[strlen(name) - 1] != '}') 14245184Sek110237 return (NULL); 14255184Sek110237 name[strlen(name) - 1] = 0; 14265184Sek110237 14275184Sek110237 if (strncmp(name, STATS_VAR, strlen(STATS_VAR)) == 0) 14285184Sek110237 rtn = stats_findvar(var, name + strlen(STATS_VAR)); 14295184Sek110237 14305184Sek110237 if (strcmp(name, EVENTGEN_VAR) == 0) 14315184Sek110237 rtn = eventgen_ratevar(var); 14325184Sek110237 14335184Sek110237 if (strcmp(name, DATE_VAR) == 0) 14345184Sek110237 rtn = date_var(var); 14355184Sek110237 14365184Sek110237 if (strcmp(name, SCRIPT_VAR) == 0) 14375184Sek110237 rtn = script_var(var); 14385184Sek110237 14395184Sek110237 if (strcmp(name, HOST_VAR) == 0) 14405184Sek110237 rtn = host_var(var); 14415184Sek110237 14425184Sek110237 free(n); 14435184Sek110237 14445184Sek110237 return (rtn); 14455184Sek110237 } 14465184Sek110237 14475184Sek110237 /* 14485184Sek110237 * Calls the C library routine getenv() to obtain the value 14495184Sek110237 * for the environment variable specified by var->var_name. 14506212Saw148015 * If found, the value string is returned in var->var_val.string. 14515184Sek110237 * If the requested value is not found, NULL is returned. 14525184Sek110237 */ 14535184Sek110237 static var_t * 14545184Sek110237 var_find_environment(var_t *var) 14555184Sek110237 { 14565184Sek110237 char *n = fb_stralloc(var->var_name); 14575184Sek110237 char *name = n; 14586212Saw148015 char *strptr; 14595184Sek110237 14605184Sek110237 name++; 14616212Saw148015 if (name[strlen(name) - 1] != ')') { 14626212Saw148015 free(n); 14635184Sek110237 return (NULL); 14646212Saw148015 } 14655184Sek110237 name[strlen(name) - 1] = 0; 14665184Sek110237 14676212Saw148015 if ((strptr = getenv(name)) != NULL) { 14685184Sek110237 free(n); 14696212Saw148015 VAR_SET_STR(var, strptr); 14705184Sek110237 return (var); 14715184Sek110237 } else { 14725184Sek110237 free(n); 14735184Sek110237 return (NULL); 14745184Sek110237 } 14755184Sek110237 } 14765184Sek110237 14775184Sek110237 /* 14785184Sek110237 * Look up special variables. The "name" argument is used to find 14795184Sek110237 * the desired special var and fill it with an appropriate string 14805184Sek110237 * value. Looks for an already allocated var of the same name on 14816550Saw148015 * the shm_var_dyn_list. If not found a new dynamic var is allocated. 14825184Sek110237 * if the name begins with '{', it is an internal variable, and 14835184Sek110237 * var_find_internal() is called. If the name begins with '(' it 14845184Sek110237 * is an environment varable, and var_find_environment() is 14855184Sek110237 * called. On success, a pointer to the var_t is returned, 14865184Sek110237 * otherwise, NULL is returned. 14875184Sek110237 */ 14885184Sek110237 static var_t * 14895184Sek110237 var_find_dynamic(char *name) 14905184Sek110237 { 14915184Sek110237 var_t *var = NULL; 14926391Saw148015 var_t *v = filebench_shm->shm_var_dyn_list; 14935184Sek110237 var_t *rtn; 14945184Sek110237 14955184Sek110237 /* 14965184Sek110237 * Lookup a reference to the var handle for this 14975184Sek110237 * special var 14985184Sek110237 */ 14996391Saw148015 for (v = filebench_shm->shm_var_dyn_list; v != NULL; v = v->var_next) { 15005184Sek110237 if (strcmp(v->var_name, name) == 0) { 15015184Sek110237 var = v; 15025184Sek110237 break; 15035184Sek110237 } 15045184Sek110237 } 15055184Sek110237 15065184Sek110237 if (var == NULL) 15075184Sek110237 var = var_alloc_dynamic(name); 15085184Sek110237 15095184Sek110237 /* Internal system control variable */ 15105184Sek110237 if (*name == '{') { 15115184Sek110237 rtn = var_find_internal(var); 15125184Sek110237 if (rtn == NULL) 15135184Sek110237 filebench_log(LOG_ERROR, 15145184Sek110237 "Cannot find internal variable %s", 15155184Sek110237 var->var_name); 15165184Sek110237 return (rtn); 15175184Sek110237 } 15185184Sek110237 15195184Sek110237 /* Lookup variable in environment */ 15205184Sek110237 if (*name == '(') { 15215184Sek110237 rtn = var_find_environment(var); 15225184Sek110237 if (rtn == NULL) 15235184Sek110237 filebench_log(LOG_ERROR, 15245184Sek110237 "Cannot find environment variable %s", 15255184Sek110237 var->var_name); 15265184Sek110237 return (rtn); 15275184Sek110237 } 15285184Sek110237 15295184Sek110237 return (NULL); 15305184Sek110237 } 15316550Saw148015 15326550Saw148015 /* 15336550Saw148015 * replace the avd_t attribute value descriptor in the new FLOW_MASTER flowop 15346550Saw148015 * that points to a local variable with a new avd_t containing 15356550Saw148015 * the actual value from the local variable. 15366550Saw148015 */ 15376550Saw148015 void 15386550Saw148015 avd_update(avd_t *avdp, var_t *lvar_list) 15396550Saw148015 { 15406550Saw148015 var_t *old_lvar, *new_lvar; 15416550Saw148015 15426550Saw148015 if ((*avdp)->avd_type == AVD_IND_VAR) { 15436550Saw148015 15446550Saw148015 /* Make sure there is a local var */ 15456550Saw148015 if ((old_lvar = (*avdp)->avd_val.varptr) == NULL) { 15466550Saw148015 filebench_log(LOG_ERROR, 15476550Saw148015 "avd_update: local var not found"); 15486550Saw148015 return; 15496550Saw148015 } 15506550Saw148015 } else { 15516550Saw148015 /* Empty or not indirect, so no update needed */ 15526550Saw148015 return; 15536550Saw148015 } 15546550Saw148015 15556550Saw148015 /* allocate a new avd using the new or old lvar contents */ 15566550Saw148015 if ((new_lvar = 15576550Saw148015 var_find_list(old_lvar->var_name, lvar_list)) != NULL) 15586550Saw148015 (*avdp) = avd_alloc_var_ptr(new_lvar); 15596550Saw148015 else 15606550Saw148015 (*avdp) = avd_alloc_var_ptr(old_lvar); 15616550Saw148015 } 15626550Saw148015 15636550Saw148015 void 15646550Saw148015 var_update_comp_lvars(var_t *newlvar, var_t *proto_comp_vars, 15656550Saw148015 var_t *mstr_lvars) 15666550Saw148015 { 15676550Saw148015 var_t *proto_lvar; 15686550Saw148015 15696550Saw148015 /* find the prototype lvar from the inherited list */ 15706550Saw148015 proto_lvar = var_find_list_only(newlvar->var_name, proto_comp_vars); 15716550Saw148015 15726550Saw148015 if (proto_lvar == NULL) 15736550Saw148015 return; 15746550Saw148015 15756550Saw148015 /* 15766550Saw148015 * if the new local variable has not already been assigned 15776550Saw148015 * a value, try to copy a value from the prototype local variable 15786550Saw148015 */ 15796550Saw148015 if ((newlvar->var_type & VAR_TYPE_SET_MASK) == 0) { 15806550Saw148015 15816550Saw148015 /* copy value from prototype lvar to new lvar */ 15826550Saw148015 (void) var_copy(newlvar, proto_lvar); 15836550Saw148015 } 15846550Saw148015 15856550Saw148015 /* If proto lvar is indirect, see if we can colapse indirection */ 15866550Saw148015 if (VAR_HAS_INDVAR(proto_lvar)) { 15876550Saw148015 var_t *uplvp; 15886550Saw148015 15896550Saw148015 uplvp = (var_t *)proto_lvar->var_val.varptr; 15906550Saw148015 15916550Saw148015 /* search for more current uplvar on comp master list */ 15926550Saw148015 if (mstr_lvars) { 15936550Saw148015 uplvp = var_find_list_only( 15946550Saw148015 uplvp->var_name, mstr_lvars); 15956550Saw148015 VAR_SET_INDVAR(newlvar, uplvp); 15966550Saw148015 } 15976550Saw148015 15986550Saw148015 if (VAR_HAS_INDVAR(uplvp)) 15996550Saw148015 VAR_SET_INDVAR(newlvar, uplvp->var_val.varptr); 16006550Saw148015 } 16016550Saw148015 } 1602