Home | History | Annotate | Download | only in common
      1  5184  ek110237 /*
      2  5184  ek110237  * CDDL HEADER START
      3  5184  ek110237  *
      4  5184  ek110237  * The contents of this file are subject to the terms of the
      5  5184  ek110237  * Common Development and Distribution License (the "License").
      6  5184  ek110237  * You may not use this file except in compliance with the License.
      7  5184  ek110237  *
      8  5184  ek110237  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  5184  ek110237  * or http://www.opensolaris.org/os/licensing.
     10  5184  ek110237  * See the License for the specific language governing permissions
     11  5184  ek110237  * and limitations under the License.
     12  5184  ek110237  *
     13  5184  ek110237  * When distributing Covered Code, include this CDDL HEADER in each
     14  5184  ek110237  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  5184  ek110237  * If applicable, add the following below this CDDL HEADER, with the
     16  5184  ek110237  * fields enclosed by brackets "[]" replaced with your own identifying
     17  5184  ek110237  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  5184  ek110237  *
     19  5184  ek110237  * CDDL HEADER END
     20  5184  ek110237  */
     21  5184  ek110237 /*
     22  9801    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  5184  ek110237  * Use is subject to license terms.
     24  6613  ek110237  *
     25  6613  ek110237  * Portions Copyright 2008 Denis Cheng
     26  5184  ek110237  */
     27  5184  ek110237 
     28  5184  ek110237 #include <stdlib.h>
     29  5184  ek110237 #include <stdio.h>
     30  5184  ek110237 #include <string.h>
     31  5184  ek110237 #include <errno.h>
     32  5184  ek110237 
     33  6613  ek110237 #include "filebench.h"
     34  5184  ek110237 #include "vars.h"
     35  5184  ek110237 #include "misc.h"
     36  5184  ek110237 #include "utils.h"
     37  5184  ek110237 #include "stats.h"
     38  5184  ek110237 #include "eventgen.h"
     39  6212  aw148015 #include "fb_random.h"
     40  5184  ek110237 
     41  5184  ek110237 static var_t *var_find_dynamic(char *name);
     42  9801    Andrew static boolean_t var_get_bool(var_t *var);
     43  9801    Andrew static fbint_t var_get_int(var_t *var);
     44  9801    Andrew static double var_get_dbl(var_t *var);
     45  5184  ek110237 
     46  5184  ek110237 /*
     47  6212  aw148015  * The filebench variables system has attribute value descriptors (avd_t)
     48  6212  aw148015  * where an avd contains a boolean, integer, double, string, random
     49  6212  aw148015  * distribution object ptr, boolean ptr, integer ptr, double ptr,
     50  6212  aw148015  * string ptr, or variable ptr. The system also has the variables
     51  6212  aw148015  * themselves, (var_t), which are named, typed entities which can be
     52  6212  aw148015  * allocated, selected and changed using the "set" command and used in
     53  6212  aw148015  * attribute assignments. The variables contain either a boolean, an
     54  6212  aw148015  * integer, a double, a string or pointer to an associated random
     55  6212  aw148015  * distribution object. Both avd_t and var_t entities are allocated
     56  5184  ek110237  * from interprocess shared memory space.
     57  5184  ek110237  *
     58  6212  aw148015  * The attribute descriptors implement delayed binding to variable values,
     59  6212  aw148015  * which is necessary because the values of variables may be changed
     60  6212  aw148015  * between the time the workload file is loaded and it is actually run,
     61  6212  aw148015  * either by further "set" commands in the file or from the command line
     62  6212  aw148015  * interface. For random variables, they actually point to the random
     63  6212  aw148015  * distribution object, allowing FileBench to invoke the appropriate
     64  6212  aw148015  * random distribution function on each access to the attribute. However,
     65  6212  aw148015  * for static attributes, the value is just loaded in the descriptor
     66  6212  aw148015  * directly, avoiding the need to allocate a variable to hold the static
     67  6212  aw148015  * value.
     68  6212  aw148015  *
     69  5184  ek110237  * The routines in this module are used to allocate, locate, and
     70  6212  aw148015  * manipulate the attribute descriptors, and vars. Routines are
     71  6212  aw148015  * also included to convert between the component strings, doubles
     72  6212  aw148015  * and integers of vars, and said components of avd_t.
     73  5184  ek110237  */
     74  6550  aw148015 
     75  5184  ek110237 
     76  5184  ek110237 /*
     77  6212  aw148015  * returns a pointer to a string indicating the type of data contained
     78  6212  aw148015  * in the supplied attribute variable descriptor.
     79  5184  ek110237  */
     80  6212  aw148015 static char *
     81  6212  aw148015 avd_get_type_string(avd_t avd)
     82  5184  ek110237 {
     83  6212  aw148015 	switch (avd->avd_type) {
     84  6212  aw148015 	case AVD_INVALID:
     85  6212  aw148015 		return ("uninitialized");
     86  5184  ek110237 
     87  6212  aw148015 	case AVD_VAL_BOOL:
     88  6212  aw148015 		return ("boolean value");
     89  6212  aw148015 
     90  6212  aw148015 	case AVD_VARVAL_BOOL:
     91  6212  aw148015 		return ("points to boolean in var_t");
     92  6212  aw148015 
     93  6212  aw148015 	case AVD_VAL_INT:
     94  6212  aw148015 		return ("integer value");
     95  6212  aw148015 
     96  6212  aw148015 	case AVD_VARVAL_INT:
     97  6212  aw148015 		return ("points to integer in var_t");
     98  6212  aw148015 
     99  6212  aw148015 	case AVD_VAL_STR:
    100  6212  aw148015 		return ("string");
    101  6212  aw148015 
    102  6212  aw148015 	case AVD_VARVAL_STR:
    103  6212  aw148015 		return ("points to string in var_t");
    104  6212  aw148015 
    105  6212  aw148015 	case AVD_VAL_DBL:
    106  6212  aw148015 		return ("double float value");
    107  6212  aw148015 
    108  6212  aw148015 	case AVD_VARVAL_DBL:
    109  6212  aw148015 		return ("points to double float in var_t");
    110  6212  aw148015 
    111  6212  aw148015 	case AVD_IND_VAR:
    112  6212  aw148015 		return ("points to a var_t");
    113  6212  aw148015 
    114  6212  aw148015 	case AVD_IND_RANDVAR:
    115  6212  aw148015 		return ("points to var_t's random distribution object");
    116  6212  aw148015 
    117  6212  aw148015 	default:
    118  6212  aw148015 		return ("illegal avd type");
    119  6212  aw148015 	}
    120  5184  ek110237 }
    121  5184  ek110237 
    122  5184  ek110237 /*
    123  6212  aw148015  * returns a pointer to a string indicating the type of data contained
    124  6212  aw148015  * in the supplied variable.
    125  5184  ek110237  */
    126  6212  aw148015 static char *
    127  6212  aw148015 var_get_type_string(var_t *ivp)
    128  5184  ek110237 {
    129  6212  aw148015 	switch (ivp->var_type & VAR_TYPE_SET_MASK) {
    130  6212  aw148015 	case VAR_TYPE_BOOL_SET:
    131  6212  aw148015 		return ("boolean");
    132  5184  ek110237 
    133  6212  aw148015 	case VAR_TYPE_INT_SET:
    134  6212  aw148015 		return ("integer");
    135  6212  aw148015 
    136  6212  aw148015 	case VAR_TYPE_STR_SET:
    137  6212  aw148015 		return ("string");
    138  6212  aw148015 
    139  6212  aw148015 	case VAR_TYPE_DBL_SET:
    140  6212  aw148015 		return ("double float");
    141  6212  aw148015 
    142  6212  aw148015 	case VAR_TYPE_RAND_SET:
    143  6212  aw148015 		return ("random");
    144  6212  aw148015 
    145  6212  aw148015 	default:
    146  6212  aw148015 		return ("empty");
    147  6212  aw148015 	}
    148  6212  aw148015 }
    149  6212  aw148015 
    150  6212  aw148015 /*
    151  6212  aw148015  * Returns the fbint_t pointed to by the supplied avd_t "avd".
    152  6212  aw148015  */
    153  6212  aw148015 fbint_t
    154  6212  aw148015 avd_get_int(avd_t avd)
    155  6212  aw148015 {
    156  6212  aw148015 	randdist_t *rndp;
    157  6212  aw148015 
    158  6212  aw148015 	if (avd == NULL)
    159  6212  aw148015 		return (0);
    160  6212  aw148015 
    161  6212  aw148015 	switch (avd->avd_type) {
    162  6212  aw148015 	case AVD_VAL_INT:
    163  6212  aw148015 		return (avd->avd_val.intval);
    164  6212  aw148015 
    165  6212  aw148015 	case AVD_VARVAL_INT:
    166  6212  aw148015 		if (avd->avd_val.intptr)
    167  6212  aw148015 			return (*(avd->avd_val.intptr));
    168  6212  aw148015 		else
    169  6212  aw148015 			return (0);
    170  6212  aw148015 
    171  6212  aw148015 	case AVD_IND_VAR:
    172  9801    Andrew 		return (var_get_int(avd->avd_val.varptr));
    173  6212  aw148015 
    174  6212  aw148015 	case AVD_IND_RANDVAR:
    175  6212  aw148015 		if ((rndp = avd->avd_val.randptr) == NULL)
    176  6212  aw148015 			return (0);
    177  6212  aw148015 		else
    178  6212  aw148015 			return ((fbint_t)rndp->rnd_get(rndp));
    179  6212  aw148015 
    180  6212  aw148015 	default:
    181  6212  aw148015 		filebench_log(LOG_ERROR,
    182  6212  aw148015 		    "Attempt to get integer from %s avd",
    183  6212  aw148015 		    avd_get_type_string(avd));
    184  6212  aw148015 		return (0);
    185  6212  aw148015 	}
    186  6212  aw148015 }
    187  6212  aw148015 
    188  6212  aw148015 /*
    189  6212  aw148015  * Returns the floating point value of a variable pointed to by the
    190  6212  aw148015  * supplied avd_t "avd". Intended to get the actual (double) value
    191  6212  aw148015  * supplied by the random variable.
    192  6212  aw148015  */
    193  6212  aw148015 double
    194  6212  aw148015 avd_get_dbl(avd_t avd)
    195  6212  aw148015 {
    196  6212  aw148015 	randdist_t *rndp;
    197  6212  aw148015 
    198  6212  aw148015 	if (avd == NULL)
    199  6212  aw148015 		return (0.0);
    200  6212  aw148015 
    201  6212  aw148015 	switch (avd->avd_type) {
    202  6212  aw148015 	case AVD_VAL_INT:
    203  6212  aw148015 		return ((double)avd->avd_val.intval);
    204  6212  aw148015 
    205  6212  aw148015 	case AVD_VAL_DBL:
    206  6212  aw148015 		return (avd->avd_val.dblval);
    207  6212  aw148015 
    208  6212  aw148015 	case AVD_VARVAL_INT:
    209  6212  aw148015 		if (avd->avd_val.intptr)
    210  6212  aw148015 			return ((double)(*(avd->avd_val.intptr)));
    211  6212  aw148015 		else
    212  6212  aw148015 			return (0.0);
    213  6212  aw148015 
    214  6212  aw148015 	case AVD_VARVAL_DBL:
    215  6212  aw148015 		if (avd->avd_val.dblptr)
    216  6212  aw148015 			return (*(avd->avd_val.dblptr));
    217  6212  aw148015 		else
    218  6212  aw148015 			return (0.0);
    219  6212  aw148015 
    220  6212  aw148015 	case AVD_IND_VAR:
    221  9801    Andrew 		return (var_get_dbl(avd->avd_val.varptr));
    222  6212  aw148015 
    223  6212  aw148015 	case AVD_IND_RANDVAR:
    224  6212  aw148015 		if ((rndp = avd->avd_val.randptr) == NULL) {
    225  6212  aw148015 			return (0.0);
    226  6212  aw148015 		} else
    227  6212  aw148015 			return (rndp->rnd_get(rndp));
    228  6212  aw148015 
    229  6212  aw148015 	default:
    230  6212  aw148015 		filebench_log(LOG_ERROR,
    231  6212  aw148015 		    "Attempt to get floating point from %s avd",
    232  6212  aw148015 		    avd_get_type_string(avd));
    233  6212  aw148015 		return (0.0);
    234  6212  aw148015 	}
    235  6212  aw148015 }
    236  6212  aw148015 
    237  6212  aw148015 /*
    238  6212  aw148015  * Returns the boolean pointed to by the supplied avd_t "avd".
    239  6212  aw148015  */
    240  6212  aw148015 boolean_t
    241  6212  aw148015 avd_get_bool(avd_t avd)
    242  6212  aw148015 {
    243  6212  aw148015 	if (avd == NULL)
    244  6212  aw148015 		return (0);
    245  6212  aw148015 
    246  6212  aw148015 	switch (avd->avd_type) {
    247  6212  aw148015 	case AVD_VAL_BOOL:
    248  6212  aw148015 		return (avd->avd_val.boolval);
    249  6212  aw148015 
    250  6212  aw148015 	case AVD_VARVAL_BOOL:
    251  6212  aw148015 		if (avd->avd_val.boolptr)
    252  6212  aw148015 			return (*(avd->avd_val.boolptr));
    253  6212  aw148015 		else
    254  6212  aw148015 			return (FALSE);
    255  6212  aw148015 
    256  6212  aw148015 	/* for backwards compatibility with old workloads */
    257  6212  aw148015 	case AVD_VAL_INT:
    258  6212  aw148015 		if (avd->avd_val.intval != 0)
    259  6212  aw148015 			return (TRUE);
    260  6212  aw148015 		else
    261  6212  aw148015 			return (FALSE);
    262  6212  aw148015 
    263  6212  aw148015 	case AVD_VARVAL_INT:
    264  6212  aw148015 		if (avd->avd_val.intptr)
    265  6212  aw148015 			if (*(avd->avd_val.intptr) != 0)
    266  6212  aw148015 				return (TRUE);
    267  6212  aw148015 
    268  6212  aw148015 		return (FALSE);
    269  6212  aw148015 
    270  6212  aw148015 	case AVD_IND_VAR:
    271  9801    Andrew 		return (var_get_bool(avd->avd_val.varptr));
    272  6212  aw148015 
    273  6212  aw148015 	default:
    274  6212  aw148015 		filebench_log(LOG_ERROR,
    275  6212  aw148015 		    "Attempt to get boolean from %s avd",
    276  6212  aw148015 		    avd_get_type_string(avd));
    277  6212  aw148015 		return (FALSE);
    278  6212  aw148015 	}
    279  6212  aw148015 }
    280  6212  aw148015 
    281  6212  aw148015 /*
    282  6212  aw148015  * Returns the string pointed to by the supplied avd_t "avd".
    283  6212  aw148015  */
    284  6212  aw148015 char *
    285  6212  aw148015 avd_get_str(avd_t avd)
    286  6212  aw148015 {
    287  6212  aw148015 	var_t *ivp;
    288  6212  aw148015 
    289  6212  aw148015 	if (avd == NULL)
    290  6212  aw148015 		return (NULL);
    291  6212  aw148015 
    292  6212  aw148015 	switch (avd->avd_type) {
    293  6212  aw148015 	case AVD_VAL_STR:
    294  6212  aw148015 		return (avd->avd_val.strval);
    295  6212  aw148015 
    296  6212  aw148015 	case AVD_VARVAL_STR:
    297  6212  aw148015 		if (avd->avd_val.strptr)
    298  6212  aw148015 			return (*avd->avd_val.strptr);
    299  6212  aw148015 		else
    300  6212  aw148015 			return (NULL);
    301  6212  aw148015 
    302  6212  aw148015 	case AVD_IND_VAR:
    303  6212  aw148015 		ivp = avd->avd_val.varptr;
    304  6212  aw148015 
    305  6212  aw148015 		if (ivp && VAR_HAS_STRING(ivp))
    306  6212  aw148015 			return (ivp->var_val.string);
    307  6212  aw148015 
    308  6212  aw148015 		filebench_log(LOG_ERROR,
    309  6212  aw148015 		    "Attempt to get string from %s var $%s",
    310  6212  aw148015 		    var_get_type_string(ivp), ivp->var_name);
    311  6212  aw148015 		return (NULL);
    312  6212  aw148015 
    313  6212  aw148015 	default:
    314  6212  aw148015 		filebench_log(LOG_ERROR,
    315  6212  aw148015 		    "Attempt to get string from %s avd",
    316  6212  aw148015 		    avd_get_type_string(avd));
    317  5184  ek110237 		return (NULL);
    318  5184  ek110237 	}
    319  6212  aw148015 }
    320  5184  ek110237 
    321  6212  aw148015 /*
    322  6212  aw148015  * Allocates a avd_t from ipc memory space.
    323  6212  aw148015  * logs an error and returns NULL on failure.
    324  6212  aw148015  */
    325  6212  aw148015 static avd_t
    326  6212  aw148015 avd_alloc_cmn(void)
    327  6212  aw148015 {
    328  6212  aw148015 	avd_t rtn;
    329  5184  ek110237 
    330  6212  aw148015 	if ((rtn = (avd_t)ipc_malloc(FILEBENCH_AVD)) == NULL)
    331  6212  aw148015 		filebench_log(LOG_ERROR, "Avd alloc failed");
    332  5184  ek110237 
    333  5184  ek110237 	return (rtn);
    334  5184  ek110237 }
    335  5184  ek110237 
    336  5184  ek110237 /*
    337  6212  aw148015  * pre-loads the allocated avd_t with the boolean_t "bool".
    338  6212  aw148015  * Returns the avd_t on success, NULL on failure.
    339  5184  ek110237  */
    340  6212  aw148015 avd_t
    341  6212  aw148015 avd_bool_alloc(boolean_t bool)
    342  5184  ek110237 {
    343  6212  aw148015 	avd_t avd;
    344  5184  ek110237 
    345  6212  aw148015 	if ((avd = avd_alloc_cmn()) == NULL)
    346  6212  aw148015 		return (NULL);
    347  6212  aw148015 
    348  6212  aw148015 	avd->avd_type = AVD_VAL_BOOL;
    349  6212  aw148015 	avd->avd_val.boolval = bool;
    350  6212  aw148015 
    351  6212  aw148015 	filebench_log(LOG_DEBUG_IMPL, "Alloc boolean %d", bool);
    352  6212  aw148015 
    353  6212  aw148015 	return (avd);
    354  6212  aw148015 }
    355  6212  aw148015 
    356  6212  aw148015 /*
    357  6212  aw148015  * pre-loads the allocated avd_t with the fbint_t "integer".
    358  6212  aw148015  * Returns the avd_t on success, NULL on failure.
    359  6212  aw148015  */
    360  6212  aw148015 avd_t
    361  6212  aw148015 avd_int_alloc(fbint_t integer)
    362  6212  aw148015 {
    363  6212  aw148015 	avd_t avd;
    364  6212  aw148015 
    365  6212  aw148015 	if ((avd = avd_alloc_cmn()) == NULL)
    366  6212  aw148015 		return (NULL);
    367  6212  aw148015 
    368  6212  aw148015 	avd->avd_type = AVD_VAL_INT;
    369  6212  aw148015 	avd->avd_val.intval = integer;
    370  6212  aw148015 
    371  6286  aw148015 	filebench_log(LOG_DEBUG_IMPL, "Alloc integer %llu",
    372  6286  aw148015 	    (u_longlong_t)integer);
    373  6212  aw148015 
    374  6212  aw148015 	return (avd);
    375  6212  aw148015 }
    376  6212  aw148015 
    377  6212  aw148015 /*
    378  6212  aw148015  * Gets a avd_t and points it to the var that
    379  6212  aw148015  * it will eventually be filled from
    380  6212  aw148015  */
    381  6212  aw148015 static avd_t
    382  6212  aw148015 avd_alloc_var_ptr(var_t *var)
    383  6212  aw148015 {
    384  6212  aw148015 	avd_t avd;
    385  6212  aw148015 
    386  6212  aw148015 	if (var == NULL)
    387  6212  aw148015 		return (NULL);
    388  6212  aw148015 
    389  6212  aw148015 	if ((avd = avd_alloc_cmn()) == NULL)
    390  6212  aw148015 		return (NULL);
    391  6212  aw148015 
    392  6212  aw148015 	switch (var->var_type & VAR_TYPE_SET_MASK) {
    393  6212  aw148015 	case VAR_TYPE_BOOL_SET:
    394  6212  aw148015 		avd->avd_type = AVD_VARVAL_BOOL;
    395  6212  aw148015 		avd->avd_val.boolptr = (&var->var_val.boolean);
    396  6212  aw148015 		break;
    397  6212  aw148015 
    398  6212  aw148015 	case VAR_TYPE_INT_SET:
    399  6212  aw148015 		avd->avd_type = AVD_VARVAL_INT;
    400  6212  aw148015 		avd->avd_val.intptr = (&var->var_val.integer);
    401  6212  aw148015 		break;
    402  6212  aw148015 
    403  6212  aw148015 	case VAR_TYPE_STR_SET:
    404  6212  aw148015 		avd->avd_type = AVD_VARVAL_STR;
    405  6212  aw148015 		avd->avd_val.strptr = &(var->var_val.string);
    406  6212  aw148015 		break;
    407  6212  aw148015 
    408  6212  aw148015 	case VAR_TYPE_DBL_SET:
    409  6212  aw148015 		avd->avd_type = AVD_VARVAL_DBL;
    410  6212  aw148015 		avd->avd_val.dblptr = &(var->var_val.dbl_flt);
    411  6212  aw148015 		break;
    412  6212  aw148015 
    413  6212  aw148015 	case VAR_TYPE_RAND_SET:
    414  6212  aw148015 		avd->avd_type = AVD_IND_RANDVAR;
    415  6212  aw148015 		avd->avd_val.randptr = var->var_val.randptr;
    416  6212  aw148015 		break;
    417  6212  aw148015 
    418  6550  aw148015 	case VAR_TYPE_INDVAR_SET:
    419  6550  aw148015 		avd->avd_type = AVD_IND_VAR;
    420  9801    Andrew 		if ((var->var_type & VAR_INDVAR_MASK) == VAR_IND_ASSIGN)
    421  9801    Andrew 			avd->avd_val.varptr = var->var_varptr1;
    422  9801    Andrew 		else
    423  9801    Andrew 			avd->avd_val.varptr = var;
    424  9801    Andrew 
    425  6550  aw148015 		break;
    426  6550  aw148015 
    427  6212  aw148015 	default:
    428  6212  aw148015 		avd->avd_type = AVD_IND_VAR;
    429  6212  aw148015 		avd->avd_val.varptr = var;
    430  6212  aw148015 		break;
    431  6212  aw148015 	}
    432  6212  aw148015 	return (avd);
    433  6212  aw148015 }
    434  6212  aw148015 
    435  6212  aw148015 /*
    436  6212  aw148015  * Gets a avd_t, then allocates and initializes a piece of
    437  6212  aw148015  * shared string memory, putting the pointer to it into the just
    438  6212  aw148015  * allocated string pointer location. The routine returns a pointer
    439  6212  aw148015  * to the string pointer location or returns NULL on error.
    440  6212  aw148015  */
    441  6212  aw148015 avd_t
    442  6212  aw148015 avd_str_alloc(char *string)
    443  6212  aw148015 {
    444  6212  aw148015 	avd_t avd;
    445  6212  aw148015 
    446  6212  aw148015 	if (string == NULL) {
    447  6212  aw148015 		filebench_log(LOG_ERROR, "No string supplied\n");
    448  5184  ek110237 		return (NULL);
    449  5184  ek110237 	}
    450  5184  ek110237 
    451  6212  aw148015 	if ((avd = avd_alloc_cmn()) == NULL)
    452  6212  aw148015 		return (NULL);
    453  6212  aw148015 
    454  6212  aw148015 	avd->avd_type = AVD_VAL_STR;
    455  6212  aw148015 	avd->avd_val.strval = ipc_stralloc(string);
    456  5184  ek110237 
    457  5184  ek110237 	filebench_log(LOG_DEBUG_IMPL,
    458  5184  ek110237 	    "Alloc string %s ptr %zx",
    459  6212  aw148015 	    string, avd);
    460  5184  ek110237 
    461  6212  aw148015 	return (avd);
    462  5184  ek110237 }
    463  5184  ek110237 
    464  5184  ek110237 /*
    465  5184  ek110237  * Allocates a var (var_t) from interprocess shared memory.
    466  5184  ek110237  * Places the allocated var on the end of the globally shared
    467  6550  aw148015  * shm_var_list. Finally, the routine allocates a string containing
    468  5184  ek110237  * a copy of the supplied "name" string. If any allocations
    469  5184  ek110237  * fails, returns NULL, otherwise it returns a pointer to the
    470  5184  ek110237  * newly allocated var.
    471  5184  ek110237  */
    472  5184  ek110237 static var_t *
    473  6212  aw148015 var_alloc_cmn(char *name, int var_type)
    474  5184  ek110237 {
    475  6212  aw148015 	var_t **var_listp;
    476  5184  ek110237 	var_t *var = NULL;
    477  5184  ek110237 	var_t *prev = NULL;
    478  5184  ek110237 	var_t *newvar;
    479  5184  ek110237 
    480  5184  ek110237 	if ((newvar = (var_t *)ipc_malloc(FILEBENCH_VARIABLE)) == NULL) {
    481  5184  ek110237 		filebench_log(LOG_ERROR, "Out of memory for variables");
    482  5184  ek110237 		return (NULL);
    483  5184  ek110237 	}
    484  5184  ek110237 	(void) memset(newvar, 0, sizeof (newvar));
    485  6212  aw148015 	newvar->var_type = var_type;
    486  5184  ek110237 
    487  5184  ek110237 	if ((newvar->var_name = ipc_stralloc(name)) == NULL) {
    488  5184  ek110237 		filebench_log(LOG_ERROR, "Out of memory for variables");
    489  5184  ek110237 		return (NULL);
    490  5184  ek110237 	}
    491  5184  ek110237 
    492  6212  aw148015 	switch (var_type & VAR_TYPE_MASK) {
    493  6212  aw148015 	case VAR_TYPE_RANDOM:
    494  6212  aw148015 	case VAR_TYPE_GLOBAL:
    495  6391  aw148015 		var_listp = &filebench_shm->shm_var_list;
    496  6212  aw148015 		break;
    497  6212  aw148015 
    498  6212  aw148015 	case VAR_TYPE_DYNAMIC:
    499  6391  aw148015 		var_listp = &filebench_shm->shm_var_dyn_list;
    500  6212  aw148015 		break;
    501  6212  aw148015 
    502  6550  aw148015 	case VAR_TYPE_LOCAL:
    503  6550  aw148015 		/* place on head of shared local list */
    504  6550  aw148015 		newvar->var_next = filebench_shm->shm_var_loc_list;
    505  6550  aw148015 		filebench_shm->shm_var_loc_list = newvar;
    506  6550  aw148015 		return (newvar);
    507  6550  aw148015 
    508  6212  aw148015 	default:
    509  6391  aw148015 		var_listp = &filebench_shm->shm_var_list;
    510  6212  aw148015 		break;
    511  6212  aw148015 	}
    512  6212  aw148015 
    513  6212  aw148015 	/* add to the end of list */
    514  6212  aw148015 	for (var = *var_listp; var != NULL; var = var->var_next)
    515  6212  aw148015 		prev = var; /* Find end of list */
    516  6212  aw148015 	if (prev != NULL)
    517  6212  aw148015 		prev->var_next = newvar;
    518  6212  aw148015 	else
    519  6212  aw148015 		*var_listp = newvar;
    520  6212  aw148015 
    521  5184  ek110237 	return (newvar);
    522  6212  aw148015 }
    523  6212  aw148015 
    524  6212  aw148015 /*
    525  6550  aw148015  * Allocates a var (var_t) from interprocess shared memory after
    526  6550  aw148015  * first adjusting the name to elminate the leading $. Places the
    527  6550  aw148015  * allocated var temporarily on the end of the globally
    528  6550  aw148015  * shared var_loc_list. If the allocation fails, returns NULL,
    529  6550  aw148015  * otherwise it returns a pointer to the newly allocated var.
    530  6550  aw148015  */
    531  6550  aw148015 var_t *
    532  6550  aw148015 var_lvar_alloc_local(char *name)
    533  6550  aw148015 {
    534  6550  aw148015 	if (name[0] == '$')
    535  6550  aw148015 		name += 1;
    536  6550  aw148015 
    537  6550  aw148015 	return (var_alloc_cmn(name, VAR_TYPE_LOCAL));
    538  6550  aw148015 }
    539  6550  aw148015 
    540  6550  aw148015 /*
    541  6212  aw148015  * Allocates a var (var_t) from interprocess shared memory and
    542  6212  aw148015  * places the allocated var on the end of the globally shared
    543  6550  aw148015  * shm_var_list. If the allocation fails, returns NULL, otherwise
    544  6212  aw148015  * it returns a pointer to the newly allocated var.
    545  6212  aw148015  */
    546  6212  aw148015 static var_t *
    547  6212  aw148015 var_alloc(char *name)
    548  6212  aw148015 {
    549  6212  aw148015 	return (var_alloc_cmn(name, VAR_TYPE_GLOBAL));
    550  5184  ek110237 }
    551  5184  ek110237 
    552  5184  ek110237 /*
    553  5184  ek110237  * Allocates a var (var_t) from interprocess shared memory.
    554  5184  ek110237  * Places the allocated var on the end of the globally shared
    555  6550  aw148015  * shm_var_dyn_list. If the allocation fails, returns NULL, otherwise
    556  6212  aw148015  * it returns a pointer to the newly allocated var.
    557  5184  ek110237  */
    558  5184  ek110237 static var_t *
    559  5184  ek110237 var_alloc_dynamic(char *name)
    560  5184  ek110237 {
    561  6212  aw148015 	return (var_alloc_cmn(name, VAR_TYPE_DYNAMIC));
    562  5184  ek110237 }
    563  5184  ek110237 
    564  5184  ek110237 /*
    565  6550  aw148015  * Searches for var_t with name "name" in the shm_var_loc_list,
    566  6550  aw148015  * then, if not found, in the global shm_var_list. If a matching
    567  6550  aw148015  * local or global var is found, returns a pointer to the var_t,
    568  6550  aw148015  * otherwise returns NULL.
    569  5184  ek110237  */
    570  5184  ek110237 static var_t *
    571  5184  ek110237 var_find(char *name)
    572  5184  ek110237 {
    573  5184  ek110237 	var_t *var;
    574  6550  aw148015 
    575  6550  aw148015 	for (var = filebench_shm->shm_var_loc_list; var != NULL;
    576  6550  aw148015 	    var = var->var_next) {
    577  6550  aw148015 		if (strcmp(var->var_name, name) == 0)
    578  6550  aw148015 			return (var);
    579  6550  aw148015 	}
    580  5184  ek110237 
    581  6391  aw148015 	for (var = filebench_shm->shm_var_list; var != NULL;
    582  6391  aw148015 	    var = var->var_next) {
    583  5184  ek110237 		if (strcmp(var->var_name, name) == 0)
    584  5184  ek110237 			return (var);
    585  5184  ek110237 	}
    586  5184  ek110237 
    587  5184  ek110237 	return (NULL);
    588  6550  aw148015 }
    589  6550  aw148015 
    590  6550  aw148015 /*
    591  6550  aw148015  * Searches for var_t with name "name" in the supplied shm_var_list.
    592  6550  aw148015  * If not found there, checks the global list. If still
    593  6550  aw148015  * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t.
    594  6550  aw148015  */
    595  6550  aw148015 static var_t *
    596  6550  aw148015 var_find_list_only(char *name, var_t *var_list)
    597  6550  aw148015 {
    598  6550  aw148015 	var_t *var;
    599  6550  aw148015 
    600  6550  aw148015 	for (var = var_list; var != NULL; var = var->var_next) {
    601  6550  aw148015 		if (strcmp(var->var_name, name) == 0)
    602  6550  aw148015 			return (var);
    603  6550  aw148015 	}
    604  6550  aw148015 
    605  6550  aw148015 	return (NULL);
    606  6550  aw148015 }
    607  6550  aw148015 
    608  6550  aw148015 /*
    609  6550  aw148015  * Searches for var_t with name "name" in the supplied shm_var_list.
    610  6550  aw148015  * If not found there, checks the global list. If still
    611  6550  aw148015  * unsuccessful, returns NULL. Otherwise returns a pointer to the var_t.
    612  6550  aw148015  */
    613  6550  aw148015 static var_t *
    614  6550  aw148015 var_find_list(char *name, var_t *var_list)
    615  6550  aw148015 {
    616  6550  aw148015 	var_t *var;
    617  6550  aw148015 
    618  6550  aw148015 	if ((var = var_find_list_only(name, var_list)) != NULL)
    619  6550  aw148015 		return (var);
    620  6550  aw148015 	else
    621  6550  aw148015 		return (var_find(name));
    622  5184  ek110237 }
    623  5184  ek110237 
    624  5184  ek110237 /*
    625  9801    Andrew  * Searches for the named var and returns it if found. If not
    626  9801    Andrew  * found it allocates a new variable
    627  9801    Andrew  */
    628  9801    Andrew static var_t *
    629  9801    Andrew var_find_alloc(char *name)
    630  9801    Andrew {
    631  9801    Andrew 	var_t *var;
    632  9801    Andrew 
    633  9801    Andrew 	if (name == NULL) {
    634  9801    Andrew 		filebench_log(LOG_ERROR,
    635  9801    Andrew 		    "var_find_alloc: Var name not supplied");
    636  9801    Andrew 		return (NULL);
    637  9801    Andrew 	}
    638  9801    Andrew 
    639  9801    Andrew 	name += 1;
    640  9801    Andrew 
    641  9801    Andrew 	if ((var = var_find(name)) == NULL) {
    642  9801    Andrew 			var = var_alloc(name);
    643  9801    Andrew 	}
    644  9801    Andrew 	return (var);
    645  9801    Andrew }
    646  9801    Andrew 
    647  9801    Andrew /*
    648  5184  ek110237  * Searches for the named var, and, if found, sets its
    649  6212  aw148015  * var_val.boolean's value to that of the supplied boolean.
    650  5184  ek110237  * If not found, the routine allocates a new var and sets
    651  6212  aw148015  * its var_val.boolean's value to that of the supplied
    652  6212  aw148015  * boolean. If the named var cannot be found or allocated
    653  6212  aw148015  * the routine returns -1, otherwise it returns 0.
    654  5184  ek110237  */
    655  5184  ek110237 int
    656  6212  aw148015 var_assign_boolean(char *name, boolean_t bool)
    657  5184  ek110237 {
    658  5184  ek110237 	var_t *var;
    659  5184  ek110237 
    660  9801    Andrew 	if ((var = var_find_alloc(name)) == NULL) {
    661  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
    662  5184  ek110237 		    name);
    663  5184  ek110237 		return (-1);
    664  5184  ek110237 	}
    665  5184  ek110237 
    666  6212  aw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
    667  6212  aw148015 		filebench_log(LOG_ERROR,
    668  6212  aw148015 		    "Cannot assign integer to random variable %s", name);
    669  6212  aw148015 		return (-1);
    670  6212  aw148015 	}
    671  6212  aw148015 
    672  6212  aw148015 	VAR_SET_BOOL(var, bool);
    673  6212  aw148015 
    674  6212  aw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign boolean %s=%d",
    675  6212  aw148015 	    name, bool);
    676  6212  aw148015 
    677  6212  aw148015 	return (0);
    678  6212  aw148015 }
    679  6212  aw148015 
    680  6212  aw148015 /*
    681  6212  aw148015  * Searches for the named var, and, if found, sets its
    682  6212  aw148015  * var_integer's value to that of the supplied integer.
    683  6212  aw148015  * If not found, the routine allocates a new var and sets
    684  6212  aw148015  * its var_integers's value to that of the supplied
    685  6212  aw148015  * integer. If the named var cannot be found or allocated
    686  6212  aw148015  * the routine returns -1, otherwise it returns 0.
    687  6212  aw148015  */
    688  6212  aw148015 int
    689  6212  aw148015 var_assign_integer(char *name, fbint_t integer)
    690  6212  aw148015 {
    691  6212  aw148015 	var_t *var;
    692  6212  aw148015 
    693  9801    Andrew 	if ((var = var_find_alloc(name)) == NULL) {
    694  6212  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
    695  6212  aw148015 		    name);
    696  6212  aw148015 		return (-1);
    697  6212  aw148015 	}
    698  6212  aw148015 
    699  6212  aw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
    700  6212  aw148015 		filebench_log(LOG_ERROR,
    701  6212  aw148015 		    "Cannot assign integer to random variable %s", name);
    702  6212  aw148015 		return (-1);
    703  6212  aw148015 	}
    704  6212  aw148015 
    705  6212  aw148015 	VAR_SET_INT(var, integer);
    706  5184  ek110237 
    707  6286  aw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu",
    708  6286  aw148015 	    name, (u_longlong_t)integer);
    709  5184  ek110237 
    710  5184  ek110237 	return (0);
    711  9801    Andrew }
    712  9801    Andrew 
    713  9801    Andrew /*
    714  9801    Andrew  * Add, subtract, multiply or divide two integers based on optype
    715  9801    Andrew  * passed from caller.
    716  9801    Andrew  */
    717  9801    Andrew static fbint_t
    718  9801    Andrew var_binary_integer_op(var_t *var)
    719  9801    Andrew {
    720  9801    Andrew 	fbint_t result;
    721  9801    Andrew 	fbint_t src1, src2;
    722  9801    Andrew 
    723  9801    Andrew 	if (var == NULL)
    724  9801    Andrew 		return (0);
    725  9801    Andrew 
    726  9801    Andrew 	switch (var->var_type & VAR_INDBINOP_MASK) {
    727  9801    Andrew 	case VAR_IND_BINOP_INT:
    728  9801    Andrew 		src2 = var->var_val.integer;
    729  9801    Andrew 		break;
    730  9801    Andrew 
    731  9801    Andrew 	case VAR_IND_BINOP_DBL:
    732  9801    Andrew 		src2 = (fbint_t)var->var_val.dbl_flt;
    733  9801    Andrew 		break;
    734  9801    Andrew 
    735  9801    Andrew 	case VAR_IND_BINOP_VAR:
    736  9801    Andrew 		if (var->var_val.varptr2 != NULL)
    737  9801    Andrew 			src2 = var_get_int(var->var_val.varptr2);
    738  9801    Andrew 		else
    739  9801    Andrew 			src2 = 0;
    740  9801    Andrew 		break;
    741  9801    Andrew 	}
    742  9801    Andrew 
    743  9801    Andrew 	if (var->var_varptr1 != NULL)
    744  9801    Andrew 		src1 = var_get_int(var->var_varptr1);
    745  9801    Andrew 	else
    746  9801    Andrew 		src1 = 0;
    747  9801    Andrew 
    748  9801    Andrew 	switch (var->var_type & VAR_INDVAR_MASK) {
    749  9801    Andrew 	case VAR_IND_VAR_SUM_VC:
    750  9801    Andrew 		result = src1 + src2;
    751  9801    Andrew 		break;
    752  9801    Andrew 
    753  9801    Andrew 	case VAR_IND_VAR_DIF_VC:
    754  9801    Andrew 		result = src1 - src2;
    755  9801    Andrew 		break;
    756  9801    Andrew 
    757  9801    Andrew 	case VAR_IND_C_DIF_VAR:
    758  9801    Andrew 		result = src2 - src1;
    759  9801    Andrew 		break;
    760  9801    Andrew 
    761  9801    Andrew 	case VAR_IND_VAR_MUL_VC:
    762  9801    Andrew 		result = src1 * src2;
    763  9801    Andrew 		break;
    764  9801    Andrew 
    765  9801    Andrew 	case VAR_IND_VAR_DIV_VC:
    766  9801    Andrew 		result = src1 / src2;
    767  9801    Andrew 		break;
    768  9801    Andrew 
    769  9801    Andrew 	case VAR_IND_C_DIV_VAR:
    770  9801    Andrew 		result = src2 / src1;
    771  9801    Andrew 		break;
    772  9801    Andrew 
    773  9801    Andrew 	default:
    774  9801    Andrew 		filebench_log(LOG_DEBUG_IMPL,
    775  9801    Andrew 		    "var_binary_integer_op: Called with unknown IND_TYPE");
    776  9801    Andrew 		result = 0;
    777  9801    Andrew 		break;
    778  9801    Andrew 	}
    779  9801    Andrew 	return (result);
    780  9801    Andrew }
    781  9801    Andrew 
    782  9801    Andrew /*
    783  9801    Andrew  * Add, subtract, multiply or divide two double precision floating point
    784  9801    Andrew  * numbers based on optype passed from caller.
    785  9801    Andrew  */
    786  9801    Andrew static double
    787  9801    Andrew var_binary_dbl_flt_op(var_t *var)
    788  9801    Andrew {
    789  9801    Andrew 	double result;
    790  9801    Andrew 	double src1, src2;
    791  9801    Andrew 
    792  9801    Andrew 	if (var == NULL)
    793  9801    Andrew 		return (0.0);
    794  9801    Andrew 
    795  9801    Andrew 	switch (var->var_type & VAR_INDBINOP_MASK) {
    796  9801    Andrew 	case VAR_IND_BINOP_INT:
    797  9801    Andrew 		src2 = (double)var->var_val.integer;
    798  9801    Andrew 		break;
    799  9801    Andrew 
    800  9801    Andrew 	case VAR_IND_BINOP_DBL:
    801  9801    Andrew 		src2 = var->var_val.dbl_flt;
    802  9801    Andrew 		break;
    803  9801    Andrew 
    804  9801    Andrew 	case VAR_IND_BINOP_VAR:
    805  9801    Andrew 		if (var->var_val.varptr2 != NULL)
    806  9801    Andrew 			src2 = var_get_dbl(var->var_val.varptr2);
    807  9801    Andrew 		else
    808  9801    Andrew 			src2 = 0;
    809  9801    Andrew 		break;
    810  9801    Andrew 	}
    811  9801    Andrew 
    812  9801    Andrew 	if (var->var_varptr1 != NULL)
    813  9801    Andrew 		src1 = var_get_dbl(var->var_varptr1);
    814  9801    Andrew 	else
    815  9801    Andrew 		src1 = 0;
    816  9801    Andrew 
    817  9801    Andrew 	switch (var->var_type & VAR_INDVAR_MASK) {
    818  9801    Andrew 	case VAR_IND_VAR_SUM_VC:
    819  9801    Andrew 		result = src1 + src2;
    820  9801    Andrew 		break;
    821  9801    Andrew 
    822  9801    Andrew 	case VAR_IND_VAR_DIF_VC:
    823  9801    Andrew 		result = src1 - src2;
    824  9801    Andrew 		break;
    825  9801    Andrew 
    826  9801    Andrew 	case VAR_IND_C_DIF_VAR:
    827  9801    Andrew 		result = src2 - src1;
    828  9801    Andrew 		break;
    829  9801    Andrew 
    830  9801    Andrew 	case VAR_IND_VAR_MUL_VC:
    831  9801    Andrew 		result = src1 * src2;
    832  9801    Andrew 		break;
    833  9801    Andrew 
    834  9801    Andrew 	case VAR_IND_C_DIV_VAR:
    835  9801    Andrew 		result = src2 / src1;
    836  9801    Andrew 		break;
    837  9801    Andrew 
    838  9801    Andrew 	case VAR_IND_VAR_DIV_VC:
    839  9801    Andrew 		result = src1 / src2;
    840  9801    Andrew 		break;
    841  9801    Andrew 
    842  9801    Andrew 	default:
    843  9801    Andrew 		filebench_log(LOG_DEBUG_IMPL,
    844  9801    Andrew 		    "var_binary_dbl_flt_op: Called with unknown IND_TYPE");
    845  9801    Andrew 		result = 0;
    846  9801    Andrew 		break;
    847  9801    Andrew 	}
    848  9801    Andrew 	return (result);
    849  9801    Andrew }
    850  9801    Andrew 
    851  9801    Andrew /*
    852  9801    Andrew  * Perform a binary operation on a variable and an integer
    853  9801    Andrew  */
    854  9801    Andrew int
    855  9801    Andrew var_assign_op_var_int(char *name, int optype, char *src1, fbint_t src2)
    856  9801    Andrew {
    857  9801    Andrew 	var_t *var;
    858  9801    Andrew 	var_t *var_src1;
    859  9801    Andrew 
    860  9801    Andrew 	if ((var_src1 = var_find(src1+1)) == NULL)
    861  9801    Andrew 		return (FILEBENCH_ERROR);
    862  9801    Andrew 
    863  9801    Andrew 	if ((var = var_find_alloc(name)) == NULL)
    864  9801    Andrew 		return (FILEBENCH_ERROR);
    865  9801    Andrew 
    866  9801    Andrew 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
    867  9801    Andrew 		filebench_log(LOG_ERROR,
    868  9801    Andrew 		    "Cannot assign integer to random variable %s", name);
    869  9801    Andrew 		return (FILEBENCH_ERROR);
    870  9801    Andrew 	}
    871  9801    Andrew 
    872  9801    Andrew 	VAR_SET_BINOP_INDVAR(var, var_src1, optype);
    873  9801    Andrew 
    874  9801    Andrew 	var->var_val.integer = src2;
    875  9801    Andrew 
    876  9801    Andrew 	return (FILEBENCH_OK);
    877  9801    Andrew }
    878  9801    Andrew 
    879  9801    Andrew int
    880  9801    Andrew var_assign_op_var_var(char *name, int optype, char *src1, char *src2)
    881  9801    Andrew {
    882  9801    Andrew 	var_t *var;
    883  9801    Andrew 	var_t *var_src1;
    884  9801    Andrew 	var_t *var_src2;
    885  9801    Andrew 
    886  9801    Andrew 	if ((var_src1 = var_find(src1+1)) == NULL)
    887  9801    Andrew 		return (FILEBENCH_ERROR);
    888  9801    Andrew 
    889  9801    Andrew 	if ((var_src2 = var_find(src2+1)) == NULL)
    890  9801    Andrew 		return (FILEBENCH_ERROR);
    891  9801    Andrew 
    892  9801    Andrew 	if ((var = var_find_alloc(name)) == NULL)
    893  9801    Andrew 		return (FILEBENCH_ERROR);
    894  9801    Andrew 
    895  9801    Andrew 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
    896  9801    Andrew 		filebench_log(LOG_ERROR,
    897  9801    Andrew 		    "Cannot assign integer to random variable %s", name);
    898  9801    Andrew 		return (FILEBENCH_ERROR);
    899  9801    Andrew 	}
    900  9801    Andrew 
    901  9801    Andrew 	VAR_SET_BINOP_INDVAR(var, var_src1, optype);
    902  9801    Andrew 
    903  9801    Andrew 	var->var_val.varptr2 = var_src2;
    904  9801    Andrew 
    905  9801    Andrew 	return (FILEBENCH_OK);
    906  5184  ek110237 }
    907  5184  ek110237 
    908  5184  ek110237 /*
    909  6212  aw148015  * Find a variable, and set it to random type.
    910  6212  aw148015  * If it does not have a random extension, allocate one
    911  6212  aw148015  */
    912  6212  aw148015 var_t *
    913  6212  aw148015 var_find_randvar(char *name)
    914  6212  aw148015 {
    915  6212  aw148015 	var_t *newvar;
    916  6212  aw148015 
    917  6212  aw148015 	name += 1;
    918  6212  aw148015 
    919  6212  aw148015 	if ((newvar = var_find(name)) == NULL) {
    920  6212  aw148015 		filebench_log(LOG_ERROR,
    921  6212  aw148015 		    "failed to locate random variable $%s\n", name);
    922  6212  aw148015 		return (NULL);
    923  6212  aw148015 	}
    924  6212  aw148015 
    925  6212  aw148015 	/* set randdist pointer unless it is already set */
    926  6212  aw148015 	if (((newvar->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
    927  6212  aw148015 	    !VAR_HAS_RANDDIST(newvar)) {
    928  6212  aw148015 		filebench_log(LOG_ERROR,
    929  6212  aw148015 		    "Found variable $%s not random\n", name);
    930  6212  aw148015 		return (NULL);
    931  6212  aw148015 	}
    932  6212  aw148015 
    933  6212  aw148015 	return (newvar);
    934  6212  aw148015 }
    935  6212  aw148015 
    936  6212  aw148015 /*
    937  6212  aw148015  * Allocate a variable, and set it to random type. Then
    938  6212  aw148015  * allocate a random extension.
    939  6212  aw148015  */
    940  6212  aw148015 var_t *
    941  6212  aw148015 var_define_randvar(char *name)
    942  6212  aw148015 {
    943  6212  aw148015 	var_t *newvar;
    944  6212  aw148015 	randdist_t *rndp = NULL;
    945  6212  aw148015 
    946  6212  aw148015 	name += 1;
    947  6212  aw148015 
    948  6212  aw148015 	/* make sure variable doesn't already exist */
    949  6212  aw148015 	if (var_find(name) != NULL) {
    950  6212  aw148015 		filebench_log(LOG_ERROR,
    951  6212  aw148015 		    "variable name already in use\n");
    952  6212  aw148015 		return (NULL);
    953  6212  aw148015 	}
    954  6212  aw148015 
    955  6212  aw148015 	/* allocate a random variable */
    956  6212  aw148015 	if ((newvar = var_alloc_cmn(name, VAR_TYPE_RANDOM)) == NULL) {
    957  6212  aw148015 		filebench_log(LOG_ERROR,
    958  6212  aw148015 		    "failed to alloc random variable\n");
    959  6212  aw148015 		return (NULL);
    960  6212  aw148015 	}
    961  6212  aw148015 
    962  6212  aw148015 	/* set randdist pointer */
    963  6212  aw148015 	if ((rndp = randdist_alloc()) == NULL) {
    964  6212  aw148015 		filebench_log(LOG_ERROR,
    965  6212  aw148015 		    "failed to alloc random distribution object\n");
    966  6212  aw148015 		return (NULL);
    967  6212  aw148015 	}
    968  6212  aw148015 
    969  6212  aw148015 	rndp->rnd_var = newvar;
    970  6212  aw148015 	VAR_SET_RAND(newvar, rndp);
    971  6212  aw148015 
    972  6212  aw148015 	return (newvar);
    973  6212  aw148015 }
    974  6212  aw148015 
    975  6212  aw148015 /*
    976  6212  aw148015  * Searches for the named var, and if found returns an avd_t
    977  6212  aw148015  * pointing to the var's var_integer, var_string or var_double
    978  6212  aw148015  * as appropriate. If not found, attempts to allocate
    979  6212  aw148015  * a var named "name" and returns an avd_t to it with
    980  6212  aw148015  * no value set. If the var cannot be found or allocated, an
    981  5184  ek110237  * error is logged and the run is terminated.
    982  5184  ek110237  */
    983  6212  aw148015 avd_t
    984  6212  aw148015 var_ref_attr(char *name)
    985  5184  ek110237 {
    986  5184  ek110237 	var_t *var;
    987  5184  ek110237 
    988  5184  ek110237 	name += 1;
    989  5184  ek110237 
    990  5184  ek110237 	if ((var = var_find(name)) == NULL)
    991  5184  ek110237 		var = var_find_dynamic(name);
    992  5184  ek110237 
    993  5184  ek110237 	if (var == NULL)
    994  5184  ek110237 		var = var_alloc(name);
    995  5184  ek110237 
    996  5184  ek110237 	if (var == NULL) {
    997  5184  ek110237 		filebench_log(LOG_ERROR, "Invalid variable $%s",
    998  5184  ek110237 		    name);
    999  5184  ek110237 		filebench_shutdown(1);
   1000  5184  ek110237 	}
   1001  5184  ek110237 
   1002  6212  aw148015 	/* allocate pointer to var and return */
   1003  6212  aw148015 	return (avd_alloc_var_ptr(var));
   1004  5184  ek110237 }
   1005  5184  ek110237 
   1006  5184  ek110237 /*
   1007  9801    Andrew  * Converts the contents of a var to a string
   1008  5184  ek110237  */
   1009  9801    Andrew static char *
   1010  9801    Andrew var_get_string(var_t *var)
   1011  5184  ek110237 {
   1012  5184  ek110237 
   1013  6212  aw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
   1014  6212  aw148015 		switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
   1015  6212  aw148015 		case RAND_TYPE_UNIFORM:
   1016  6212  aw148015 			return (fb_stralloc("uniform random var"));
   1017  6212  aw148015 		case RAND_TYPE_GAMMA:
   1018  6212  aw148015 			return (fb_stralloc("gamma random var"));
   1019  6212  aw148015 		case RAND_TYPE_TABLE:
   1020  6212  aw148015 			return (fb_stralloc("tabular random var"));
   1021  6212  aw148015 		default:
   1022  6212  aw148015 			return (fb_stralloc("unitialized random var"));
   1023  6212  aw148015 		}
   1024  6212  aw148015 	}
   1025  5184  ek110237 
   1026  6212  aw148015 	if (VAR_HAS_STRING(var) && var->var_val.string)
   1027  6212  aw148015 		return (fb_stralloc(var->var_val.string));
   1028  5184  ek110237 
   1029  6212  aw148015 	if (VAR_HAS_BOOLEAN(var)) {
   1030  6212  aw148015 		if (var->var_val.boolean)
   1031  6212  aw148015 			return (fb_stralloc("true"));
   1032  6212  aw148015 		else
   1033  6212  aw148015 			return (fb_stralloc("false"));
   1034  6212  aw148015 	}
   1035  6212  aw148015 
   1036  6212  aw148015 	if (VAR_HAS_INTEGER(var)) {
   1037  9801    Andrew 		char tmp[128];
   1038  9801    Andrew 
   1039  6286  aw148015 		(void) snprintf(tmp, sizeof (tmp), "%llu",
   1040  6286  aw148015 		    (u_longlong_t)var->var_val.integer);
   1041  6212  aw148015 		return (fb_stralloc(tmp));
   1042  6212  aw148015 	}
   1043  6212  aw148015 
   1044  9801    Andrew 	if (VAR_HAS_INDVAR(var)) {
   1045  9801    Andrew 		var_t *ivp;
   1046  9801    Andrew 
   1047  9801    Andrew 		if ((ivp = var->var_varptr1) != NULL) {
   1048  9801    Andrew 			return (var_get_string(ivp));
   1049  9801    Andrew 		}
   1050  9801    Andrew 	}
   1051  9801    Andrew 
   1052  9801    Andrew 	if (VAR_HAS_BINOP(var)) {
   1053  9801    Andrew 		char tmp[128];
   1054  9801    Andrew 
   1055  9801    Andrew 		(void) snprintf(tmp, sizeof (tmp), "%llu",
   1056  9801    Andrew 		    var_binary_integer_op(var));
   1057  9801    Andrew 		return (fb_stralloc(tmp));
   1058  9801    Andrew 	}
   1059  9801    Andrew 
   1060  6212  aw148015 	return (fb_stralloc("No default"));
   1061  9801    Andrew }
   1062  9801    Andrew 
   1063  9801    Andrew /*
   1064  9801    Andrew  * Searches for the named var, and if found copies the var_val.string,
   1065  9801    Andrew  * if it exists, a decimal number string representation of
   1066  9801    Andrew  * var_val.integer, the state of var_val.boolean, or the type of random
   1067  9801    Andrew  * distribution employed, into a malloc'd bit of memory using fb_stralloc().
   1068  9801    Andrew  * Returns a pointer to the created string, or NULL on failure.
   1069  9801    Andrew  */
   1070  9801    Andrew char *
   1071  9801    Andrew var_to_string(char *name)
   1072  9801    Andrew {
   1073  9801    Andrew 	var_t *var;
   1074  9801    Andrew 
   1075  9801    Andrew 	name += 1;
   1076  9801    Andrew 
   1077  9801    Andrew 	if ((var = var_find(name)) == NULL)
   1078  9801    Andrew 		var = var_find_dynamic(name);
   1079  9801    Andrew 
   1080  9801    Andrew 	if (var == NULL)
   1081  9801    Andrew 		return (NULL);
   1082  9801    Andrew 
   1083  9801    Andrew 	return (var_get_string(var));
   1084  9801    Andrew }
   1085  9801    Andrew 
   1086  9801    Andrew /*
   1087  9801    Andrew  * Returns the boolean from the supplied var_t "var".
   1088  9801    Andrew  */
   1089  9801    Andrew static boolean_t
   1090  9801    Andrew var_get_bool(var_t *var)
   1091  9801    Andrew {
   1092  9801    Andrew 	if (var == NULL)
   1093  9801    Andrew 		return (0);
   1094  9801    Andrew 
   1095  9801    Andrew 	if (VAR_HAS_BOOLEAN(var))
   1096  9801    Andrew 		return (var->var_val.boolean);
   1097  9801    Andrew 
   1098  9801    Andrew 	if (VAR_HAS_INTEGER(var)) {
   1099  9801    Andrew 		if (var->var_val.integer == 0)
   1100  9801    Andrew 			return (FALSE);
   1101  9801    Andrew 		else
   1102  9801    Andrew 			return (TRUE);
   1103  9801    Andrew 	}
   1104  9801    Andrew 
   1105  9801    Andrew 	filebench_log(LOG_ERROR,
   1106  9801    Andrew 	    "Attempt to get boolean from %s var $%s",
   1107  9801    Andrew 	    var_get_type_string(var), var->var_name);
   1108  9801    Andrew 	return (FALSE);
   1109  9801    Andrew }
   1110  9801    Andrew 
   1111  9801    Andrew /*
   1112  9801    Andrew  * Returns the fbint_t from the supplied var_t "var".
   1113  9801    Andrew  */
   1114  9801    Andrew static fbint_t
   1115  9801    Andrew var_get_int(var_t *var)
   1116  9801    Andrew {
   1117  9801    Andrew 	randdist_t *rndp;
   1118  9801    Andrew 
   1119  9801    Andrew 	if (var == NULL)
   1120  9801    Andrew 		return (0);
   1121  9801    Andrew 
   1122  9801    Andrew 	if (VAR_HAS_INTEGER(var))
   1123  9801    Andrew 		return (var->var_val.integer);
   1124  9801    Andrew 
   1125  9801    Andrew 	if (VAR_HAS_RANDDIST(var)) {
   1126  9801    Andrew 		if ((rndp = var->var_val.randptr) != NULL)
   1127  9801    Andrew 			return ((fbint_t)rndp->rnd_get(rndp));
   1128  9801    Andrew 	}
   1129  9801    Andrew 
   1130  9801    Andrew 	if (VAR_HAS_BINOP(var))
   1131  9801    Andrew 		return (var_binary_integer_op(var));
   1132  9801    Andrew 
   1133  9801    Andrew 	filebench_log(LOG_ERROR,
   1134  9801    Andrew 	    "Attempt to get integer from %s var $%s",
   1135  9801    Andrew 	    var_get_type_string(var), var->var_name);
   1136  9801    Andrew 	return (0);
   1137  9801    Andrew }
   1138  9801    Andrew 
   1139  9801    Andrew /*
   1140  9801    Andrew  * Returns the floating point value of a variable pointed to by the
   1141  9801    Andrew  * supplied var_t "var". Intended to get the actual (double) value
   1142  9801    Andrew  * supplied by the random variable.
   1143  9801    Andrew  */
   1144  9801    Andrew static double
   1145  9801    Andrew var_get_dbl(var_t *var)
   1146  9801    Andrew {
   1147  9801    Andrew 	randdist_t *rndp;
   1148  9801    Andrew 
   1149  9801    Andrew 	if (var == NULL)
   1150  9801    Andrew 		return (0.0);
   1151  9801    Andrew 
   1152  9801    Andrew 	if (VAR_HAS_INTEGER(var))
   1153  9801    Andrew 		return ((double)var->var_val.integer);
   1154  9801    Andrew 
   1155  9801    Andrew 	if (VAR_HAS_DOUBLE(var))
   1156  9801    Andrew 		return (var->var_val.dbl_flt);
   1157  9801    Andrew 
   1158  9801    Andrew 	if (VAR_HAS_RANDDIST(var)) {
   1159  9801    Andrew 		if ((rndp = var->var_val.randptr) != NULL)
   1160  9801    Andrew 			return (rndp->rnd_get(rndp));
   1161  9801    Andrew 	}
   1162  9801    Andrew 
   1163  9801    Andrew 	if (VAR_HAS_BINOP(var))
   1164  9801    Andrew 		return (var_binary_dbl_flt_op(var));
   1165  9801    Andrew 
   1166  9801    Andrew 	filebench_log(LOG_ERROR,
   1167  9801    Andrew 	    "Attempt to get double float from %s var $%s",
   1168  9801    Andrew 	    var_get_type_string(var), var->var_name);
   1169  9801    Andrew 	return (0.0);
   1170  5184  ek110237 }
   1171  5184  ek110237 
   1172  5184  ek110237 /*
   1173  5184  ek110237  * Searches for the named var, and if found returns the value,
   1174  6212  aw148015  * of var_val.boolean. If the var is not found, or a boolean
   1175  6212  aw148015  * value has not been set, logs an error and returns 0.
   1176  5184  ek110237  */
   1177  6212  aw148015 boolean_t
   1178  6212  aw148015 var_to_boolean(char *name)
   1179  6212  aw148015 {
   1180  6212  aw148015 	var_t *var;
   1181  6212  aw148015 
   1182  6212  aw148015 	name += 1;
   1183  6212  aw148015 
   1184  6212  aw148015 	if ((var = var_find(name)) == NULL)
   1185  6212  aw148015 		var = var_find_dynamic(name);
   1186  6212  aw148015 
   1187  9801    Andrew 	if (var != NULL)
   1188  9801    Andrew 		return (var_get_bool(var));
   1189  6212  aw148015 
   1190  6212  aw148015 	filebench_log(LOG_ERROR,
   1191  6212  aw148015 	    "Variable %s referenced before set", name);
   1192  6212  aw148015 
   1193  9801    Andrew 	return (FALSE);
   1194  6212  aw148015 }
   1195  6212  aw148015 
   1196  6212  aw148015 /*
   1197  6212  aw148015  * Searches for the named var, and if found returns the value,
   1198  6212  aw148015  * of var_val.integer. If the var is not found, or the an
   1199  6212  aw148015  * integer value has not been set, logs an error and returns 0.
   1200  6212  aw148015  */
   1201  6212  aw148015 fbint_t
   1202  5184  ek110237 var_to_integer(char *name)
   1203  5184  ek110237 {
   1204  5184  ek110237 	var_t *var;
   1205  5184  ek110237 
   1206  5184  ek110237 	name += 1;
   1207  5184  ek110237 
   1208  5184  ek110237 	if ((var = var_find(name)) == NULL)
   1209  5184  ek110237 		var = var_find_dynamic(name);
   1210  5184  ek110237 
   1211  9801    Andrew 	if (var != NULL)
   1212  9801    Andrew 		return (var_get_int(var));
   1213  5184  ek110237 
   1214  5184  ek110237 	filebench_log(LOG_ERROR,
   1215  5184  ek110237 	    "Variable %s referenced before set", name);
   1216  5184  ek110237 
   1217  5184  ek110237 	return (0);
   1218  9801    Andrew }
   1219  9801    Andrew 
   1220  9801    Andrew /*
   1221  9801    Andrew  * Searches for the named var, and if found returns the value,
   1222  9801    Andrew  * of var_val.dbl_flt. If the var is not found, or the
   1223  9801    Andrew  * floating value has not been set, logs an error and returns 0.0.
   1224  9801    Andrew  */
   1225  9801    Andrew double
   1226  9801    Andrew var_to_double(char *name)
   1227  9801    Andrew {
   1228  9801    Andrew 	var_t *var;
   1229  9801    Andrew 
   1230  9801    Andrew 	name += 1;
   1231  9801    Andrew 
   1232  9801    Andrew 	if ((var = var_find(name)) == NULL)
   1233  9801    Andrew 		var = var_find_dynamic(name);
   1234  9801    Andrew 
   1235  9801    Andrew 	if (var != NULL)
   1236  9801    Andrew 		return (var_get_dbl(var));
   1237  9801    Andrew 
   1238  9801    Andrew 	filebench_log(LOG_ERROR,
   1239  9801    Andrew 	    "Variable %s referenced before set", name);
   1240  9801    Andrew 
   1241  9801    Andrew 	return (0.0);
   1242  6212  aw148015 }
   1243  6212  aw148015 
   1244  6212  aw148015 /*
   1245  6212  aw148015  * Searches for the named random var, and if found, converts the
   1246  6212  aw148015  * requested parameter into a string or a decimal number string
   1247  6212  aw148015  * representation, into a malloc'd bit of memory using fb_stralloc().
   1248  6212  aw148015  * Returns a pointer to the created string, or calls var_to_string()
   1249  6212  aw148015  * if a random variable isn't found.
   1250  6212  aw148015  */
   1251  6212  aw148015 char *
   1252  6212  aw148015 var_randvar_to_string(char *name, int param_name)
   1253  6212  aw148015 {
   1254  6212  aw148015 	var_t *var;
   1255  6212  aw148015 	fbint_t value;
   1256  6212  aw148015 
   1257  6212  aw148015 	if ((var = var_find(name + 1)) == NULL)
   1258  6212  aw148015 		return (var_to_string(name));
   1259  6212  aw148015 
   1260  6212  aw148015 	if (((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
   1261  6212  aw148015 	    !VAR_HAS_RANDDIST(var))
   1262  6212  aw148015 		return (var_to_string(name));
   1263  6212  aw148015 
   1264  6212  aw148015 	switch (param_name) {
   1265  6212  aw148015 	case RAND_PARAM_TYPE:
   1266  6212  aw148015 		switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
   1267  6212  aw148015 		case RAND_TYPE_UNIFORM:
   1268  6212  aw148015 			return (fb_stralloc("uniform"));
   1269  6212  aw148015 		case RAND_TYPE_GAMMA:
   1270  6212  aw148015 			return (fb_stralloc("gamma"));
   1271  6212  aw148015 		case RAND_TYPE_TABLE:
   1272  6212  aw148015 			return (fb_stralloc("tabular"));
   1273  6212  aw148015 		default:
   1274  6212  aw148015 			return (fb_stralloc("uninitialized"));
   1275  6212  aw148015 		}
   1276  6212  aw148015 
   1277  6212  aw148015 	case RAND_PARAM_SRC:
   1278  6212  aw148015 		if (var->var_val.randptr->rnd_type & RAND_SRC_GENERATOR)
   1279  6212  aw148015 			return (fb_stralloc("rand48"));
   1280  6212  aw148015 		else
   1281  6212  aw148015 			return (fb_stralloc("urandom"));
   1282  6212  aw148015 
   1283  6212  aw148015 	case RAND_PARAM_SEED:
   1284  6212  aw148015 		value = avd_get_int(var->var_val.randptr->rnd_seed);
   1285  6212  aw148015 		break;
   1286  6212  aw148015 
   1287  6212  aw148015 	case RAND_PARAM_MIN:
   1288  6212  aw148015 		value = avd_get_int(var->var_val.randptr->rnd_min);
   1289  6212  aw148015 		break;
   1290  6212  aw148015 
   1291  6212  aw148015 	case RAND_PARAM_MEAN:
   1292  6212  aw148015 		value = avd_get_int(var->var_val.randptr->rnd_mean);
   1293  6212  aw148015 		break;
   1294  6212  aw148015 
   1295  6212  aw148015 	case RAND_PARAM_GAMMA:
   1296  6212  aw148015 		value = avd_get_int(var->var_val.randptr->rnd_gamma);
   1297  6212  aw148015 		break;
   1298  6212  aw148015 
   1299  6212  aw148015 	case RAND_PARAM_ROUND:
   1300  6212  aw148015 		value = avd_get_int(var->var_val.randptr->rnd_round);
   1301  6212  aw148015 		break;
   1302  6212  aw148015 
   1303  6212  aw148015 	default:
   1304  6212  aw148015 		return (NULL);
   1305  6212  aw148015 
   1306  6212  aw148015 	}
   1307  6212  aw148015 
   1308  6212  aw148015 	/* just an integer value if we got here */
   1309  6212  aw148015 	{
   1310  6212  aw148015 		char tmp[128];
   1311  6212  aw148015 
   1312  6286  aw148015 		(void) snprintf(tmp, sizeof (tmp), "%llu",
   1313  6286  aw148015 		    (u_longlong_t)value);
   1314  6212  aw148015 		return (fb_stralloc(tmp));
   1315  6212  aw148015 	}
   1316  5184  ek110237 }
   1317  5184  ek110237 
   1318  5184  ek110237 /*
   1319  6550  aw148015  * Copies the value stored in the source string into the destination
   1320  6550  aw148015  * string. Returns -1 if any problems encountered, 0 otherwise.
   1321  6550  aw148015  */
   1322  6550  aw148015 static int
   1323  6550  aw148015 var_copy(var_t *dst_var, var_t *src_var) {
   1324  6550  aw148015 
   1325  6550  aw148015 	if (VAR_HAS_BOOLEAN(src_var)) {
   1326  6550  aw148015 		VAR_SET_BOOL(dst_var, src_var->var_val.boolean);
   1327  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1328  6550  aw148015 		    "Assign var %s=%s", dst_var->var_name,
   1329  6550  aw148015 		    dst_var->var_val.boolean?"true":"false");
   1330  6550  aw148015 	}
   1331  6550  aw148015 
   1332  6550  aw148015 	if (VAR_HAS_INTEGER(src_var)) {
   1333  6550  aw148015 		VAR_SET_INT(dst_var, src_var->var_val.integer);
   1334  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1335  6550  aw148015 		    "Assign var %s=%llu", dst_var->var_name,
   1336  6550  aw148015 		    (u_longlong_t)dst_var->var_val.integer);
   1337  6550  aw148015 	}
   1338  6550  aw148015 
   1339  6550  aw148015 	if (VAR_HAS_DOUBLE(src_var)) {
   1340  6550  aw148015 		VAR_SET_DBL(dst_var, src_var->var_val.dbl_flt);
   1341  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1342  6550  aw148015 		    "Assign var %s=%lf", dst_var->var_name,
   1343  6550  aw148015 		    dst_var->var_val.dbl_flt);
   1344  6550  aw148015 	}
   1345  6550  aw148015 
   1346  6550  aw148015 	if (VAR_HAS_STRING(src_var)) {
   1347  6550  aw148015 		char *strptr;
   1348  6550  aw148015 
   1349  6550  aw148015 		if ((strptr =
   1350  6550  aw148015 		    ipc_stralloc(src_var->var_val.string)) == NULL) {
   1351  6550  aw148015 			filebench_log(LOG_ERROR,
   1352  6550  aw148015 			    "Cannot assign string for variable %s",
   1353  6550  aw148015 			    dst_var->var_name);
   1354  6550  aw148015 			return (-1);
   1355  6550  aw148015 		}
   1356  6550  aw148015 		VAR_SET_STR(dst_var, strptr);
   1357  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1358  6550  aw148015 		    "Assign var %s=%s", dst_var->var_name,
   1359  6550  aw148015 		    dst_var->var_val.string);
   1360  6550  aw148015 	}
   1361  6550  aw148015 
   1362  6550  aw148015 	if (VAR_HAS_INDVAR(src_var)) {
   1363  9801    Andrew 		VAR_SET_INDVAR(dst_var, src_var->var_varptr1);
   1364  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1365  6550  aw148015 		    "Assign var %s to var %s", dst_var->var_name,
   1366  6550  aw148015 		    src_var->var_name);
   1367  6550  aw148015 	}
   1368  6550  aw148015 	return (0);
   1369  6550  aw148015 }
   1370  6550  aw148015 
   1371  6550  aw148015 /*
   1372  5184  ek110237  * Searches for the var named "name", and if not found
   1373  6550  aw148015  * allocates it. The then copies the value from
   1374  6550  aw148015  * the src_var into the destination var "name"
   1375  6550  aw148015  * If the var "name" cannot be found or allocated, or the var "src_name"
   1376  6550  aw148015  * cannot be found, the routine returns -1, otherwise it returns 0.
   1377  5184  ek110237  */
   1378  5184  ek110237 int
   1379  6212  aw148015 var_assign_var(char *name, char *src_name)
   1380  5184  ek110237 {
   1381  6212  aw148015 	var_t *dst_var, *src_var;
   1382  5184  ek110237 
   1383  5184  ek110237 	name += 1;
   1384  6212  aw148015 	src_name += 1;
   1385  5184  ek110237 
   1386  6212  aw148015 	if ((src_var = var_find(src_name)) == NULL) {
   1387  6212  aw148015 		filebench_log(LOG_ERROR,
   1388  6212  aw148015 		    "Cannot find source variable %s", src_name);
   1389  6212  aw148015 		return (-1);
   1390  6212  aw148015 	}
   1391  5184  ek110237 
   1392  6212  aw148015 	if ((dst_var = var_find(name)) == NULL)
   1393  6212  aw148015 		dst_var = var_alloc(name);
   1394  6212  aw148015 
   1395  6212  aw148015 	if (dst_var == NULL) {
   1396  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1397  5184  ek110237 		    name);
   1398  5184  ek110237 		return (-1);
   1399  5184  ek110237 	}
   1400  5184  ek110237 
   1401  6212  aw148015 	if ((dst_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
   1402  6212  aw148015 		filebench_log(LOG_ERROR,
   1403  6212  aw148015 		    "Cannot assign var to Random variable %s", name);
   1404  5184  ek110237 		return (-1);
   1405  5184  ek110237 	}
   1406  6212  aw148015 
   1407  6550  aw148015 	return (var_copy(dst_var, src_var));
   1408  5184  ek110237 }
   1409  5184  ek110237 
   1410  5184  ek110237 /*
   1411  5184  ek110237  * Like var_assign_integer, only this routine copies the
   1412  5184  ek110237  * supplied "string" into the var named "name". If the var
   1413  5184  ek110237  * named "name" cannot be found then it is first allocated
   1414  5184  ek110237  * before the copy. Space for the string in the var comes
   1415  5184  ek110237  * from interprocess shared memory. If the var "name"
   1416  5184  ek110237  * cannot be found or allocated, or the memory for the
   1417  6550  aw148015  * var_val.string copy of "string" cannot be allocated, the
   1418  5184  ek110237  * routine returns -1, otherwise it returns 0.
   1419  5184  ek110237  */
   1420  5184  ek110237 int
   1421  5184  ek110237 var_assign_string(char *name, char *string)
   1422  5184  ek110237 {
   1423  5184  ek110237 	var_t *var;
   1424  6212  aw148015 	char *strptr;
   1425  5184  ek110237 
   1426  5184  ek110237 	name += 1;
   1427  5184  ek110237 
   1428  5184  ek110237 	if ((var = var_find(name)) == NULL)
   1429  5184  ek110237 		var = var_alloc(name);
   1430  5184  ek110237 
   1431  5184  ek110237 	if (var == NULL) {
   1432  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1433  5184  ek110237 		    name);
   1434  5184  ek110237 		return (-1);
   1435  5184  ek110237 	}
   1436  5184  ek110237 
   1437  6212  aw148015 	if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
   1438  6212  aw148015 		filebench_log(LOG_ERROR,
   1439  6212  aw148015 		    "Cannot assign string to random variable %s", name);
   1440  6212  aw148015 		return (-1);
   1441  6212  aw148015 	}
   1442  6212  aw148015 
   1443  6212  aw148015 	if ((strptr = ipc_stralloc(string)) == NULL) {
   1444  5184  ek110237 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1445  5184  ek110237 		    name);
   1446  5184  ek110237 		return (-1);
   1447  5184  ek110237 	}
   1448  6212  aw148015 	VAR_SET_STR(var, strptr);
   1449  5184  ek110237 
   1450  6212  aw148015 	filebench_log(LOG_DEBUG_SCRIPT,
   1451  6212  aw148015 	    "Var assign string $%s=%s", name, string);
   1452  5184  ek110237 
   1453  5184  ek110237 	return (0);
   1454  6550  aw148015 }
   1455  6550  aw148015 
   1456  6550  aw148015 /*
   1457  6550  aw148015  * Allocates a local var. The then extracts the var_string from
   1458  6550  aw148015  * the var named "string" and copies it into the var_string
   1459  6550  aw148015  * of the var "name", after first allocating a piece of
   1460  6550  aw148015  * interprocess shared string memory. Returns a pointer to the
   1461  6550  aw148015  * newly allocated local var or NULL on error.
   1462  6550  aw148015  */
   1463  6550  aw148015 var_t *
   1464  6550  aw148015 var_lvar_assign_var(char *name, char *src_name)
   1465  6550  aw148015 {
   1466  6550  aw148015 	var_t *dst_var, *src_var;
   1467  6550  aw148015 
   1468  6550  aw148015 	src_name += 1;
   1469  6550  aw148015 
   1470  6550  aw148015 	if ((src_var = var_find(src_name)) == NULL) {
   1471  6550  aw148015 		filebench_log(LOG_ERROR,
   1472  6550  aw148015 		    "Cannot find source variable %s", src_name);
   1473  6550  aw148015 		return (NULL);
   1474  6550  aw148015 	}
   1475  6550  aw148015 
   1476  6550  aw148015 	dst_var = var_lvar_alloc_local(name);
   1477  6550  aw148015 
   1478  6550  aw148015 	if (dst_var == NULL) {
   1479  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1480  6550  aw148015 		    name);
   1481  6550  aw148015 		return (NULL);
   1482  6550  aw148015 	}
   1483  6550  aw148015 
   1484  6550  aw148015 	/*
   1485  6550  aw148015 	 * if referencing another local var which is currently
   1486  6550  aw148015 	 * empty, indirect to it
   1487  6550  aw148015 	 */
   1488  6550  aw148015 	if ((src_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_LOCAL) {
   1489  6550  aw148015 		VAR_SET_INDVAR(dst_var, src_var);
   1490  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1491  6550  aw148015 		    "Assign local var %s to %s", name, src_name);
   1492  6550  aw148015 		return (dst_var);
   1493  6550  aw148015 	}
   1494  6550  aw148015 
   1495  6550  aw148015 	if (VAR_HAS_BOOLEAN(src_var)) {
   1496  6550  aw148015 		VAR_SET_BOOL(dst_var, src_var->var_val.boolean);
   1497  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1498  6550  aw148015 		    "Assign var (%s, %p)=%s", name,
   1499  6550  aw148015 		    dst_var, src_var->var_val.boolean?"true":"false");
   1500  6550  aw148015 	} else if (VAR_HAS_INTEGER(src_var)) {
   1501  6550  aw148015 		VAR_SET_INT(dst_var, src_var->var_val.integer);
   1502  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1503  6550  aw148015 		    "Assign var (%s, %p)=%llu", name,
   1504  6550  aw148015 		    dst_var, (u_longlong_t)src_var->var_val.integer);
   1505  6550  aw148015 	} else if (VAR_HAS_STRING(src_var)) {
   1506  6550  aw148015 		char *strptr;
   1507  6550  aw148015 
   1508  6550  aw148015 		if ((strptr = ipc_stralloc(src_var->var_val.string)) == NULL) {
   1509  6550  aw148015 			filebench_log(LOG_ERROR,
   1510  6550  aw148015 			    "Cannot assign variable %s",
   1511  6550  aw148015 			    name);
   1512  6550  aw148015 			return (NULL);
   1513  6550  aw148015 		}
   1514  6550  aw148015 		VAR_SET_STR(dst_var, strptr);
   1515  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1516  6550  aw148015 		    "Assign var (%s, %p)=%s", name,
   1517  6550  aw148015 		    dst_var, src_var->var_val.string);
   1518  6550  aw148015 	} else if (VAR_HAS_DOUBLE(src_var)) {
   1519  6550  aw148015 		/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
   1520  6550  aw148015 		VAR_SET_INT(dst_var, src_var->var_val.dbl_flt);
   1521  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1522  6550  aw148015 		    "Assign var (%s, %p)=%8.2f", name,
   1523  6550  aw148015 		    dst_var, src_var->var_val.dbl_flt);
   1524  6550  aw148015 	} else if (VAR_HAS_RANDDIST(src_var)) {
   1525  6550  aw148015 		VAR_SET_RAND(dst_var, src_var->var_val.randptr);
   1526  6550  aw148015 		filebench_log(LOG_DEBUG_SCRIPT,
   1527  6550  aw148015 		    "Assign var (%s, %p)=%llu", name,
   1528  6550  aw148015 		    dst_var, (u_longlong_t)src_var->var_val.integer);
   1529  6550  aw148015 	}
   1530  6550  aw148015 
   1531  6550  aw148015 	return (dst_var);
   1532  6550  aw148015 }
   1533  6550  aw148015 
   1534  6550  aw148015 /*
   1535  6550  aw148015  * the routine allocates a new local var and sets
   1536  6550  aw148015  * its var_boolean's value to that of the supplied
   1537  6550  aw148015  * boolean. It returns a pointer to the new local var
   1538  6550  aw148015  */
   1539  6550  aw148015 var_t *
   1540  6550  aw148015 var_lvar_assign_boolean(char *name, boolean_t bool)
   1541  6550  aw148015 {
   1542  6550  aw148015 	var_t *var;
   1543  6550  aw148015 
   1544  6550  aw148015 	var = var_lvar_alloc_local(name);
   1545  6550  aw148015 
   1546  6550  aw148015 	if (var == NULL) {
   1547  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1548  6550  aw148015 		    name);
   1549  6550  aw148015 		return (NULL);
   1550  6550  aw148015 	}
   1551  6550  aw148015 
   1552  6550  aw148015 	VAR_SET_BOOL(var, bool);
   1553  6550  aw148015 
   1554  6550  aw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%s",
   1555  6550  aw148015 	    name, bool ? "true" : "false");
   1556  6550  aw148015 
   1557  6550  aw148015 	return (var);
   1558  6550  aw148015 }
   1559  6550  aw148015 
   1560  6550  aw148015 /*
   1561  6550  aw148015  * the routine allocates a new local var and sets
   1562  6550  aw148015  * its var_integers's value to that of the supplied
   1563  6550  aw148015  * integer. It returns a pointer to the new local var
   1564  6550  aw148015  */
   1565  6550  aw148015 var_t *
   1566  6550  aw148015 var_lvar_assign_integer(char *name, fbint_t integer)
   1567  6550  aw148015 {
   1568  6550  aw148015 	var_t *var;
   1569  6550  aw148015 
   1570  6550  aw148015 	var = var_lvar_alloc_local(name);
   1571  6550  aw148015 
   1572  6550  aw148015 	if (var == NULL) {
   1573  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1574  6550  aw148015 		    name);
   1575  6550  aw148015 		return (NULL);
   1576  6550  aw148015 	}
   1577  6550  aw148015 
   1578  6550  aw148015 	VAR_SET_INT(var, integer);
   1579  6550  aw148015 
   1580  6550  aw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%llu",
   1581  6550  aw148015 	    name, (u_longlong_t)integer);
   1582  6550  aw148015 
   1583  6550  aw148015 	return (var);
   1584  6550  aw148015 }
   1585  6550  aw148015 
   1586  6550  aw148015 /*
   1587  6550  aw148015  * the routine allocates a new local var and sets
   1588  6550  aw148015  * its var_dbl_flt value to that of the supplied
   1589  6550  aw148015  * double precission floating point number. It returns
   1590  6550  aw148015  * a pointer to the new local var
   1591  6550  aw148015  */
   1592  6550  aw148015 var_t *
   1593  6550  aw148015 var_lvar_assign_double(char *name, double dbl)
   1594  6550  aw148015 {
   1595  6550  aw148015 	var_t *var;
   1596  6550  aw148015 
   1597  6550  aw148015 	var = var_lvar_alloc_local(name);
   1598  6550  aw148015 
   1599  6550  aw148015 	if (var == NULL) {
   1600  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1601  6550  aw148015 		    name);
   1602  6550  aw148015 		return (NULL);
   1603  6550  aw148015 	}
   1604  6550  aw148015 
   1605  6550  aw148015 	VAR_SET_DBL(var, dbl);
   1606  6550  aw148015 
   1607  6550  aw148015 	filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%8.2f", name, dbl);
   1608  6550  aw148015 
   1609  6550  aw148015 	return (var);
   1610  6550  aw148015 }
   1611  6550  aw148015 
   1612  6550  aw148015 /*
   1613  6550  aw148015  * Like var_lvar_assign_integer, only this routine copies the
   1614  6550  aw148015  * supplied "string" into the var named "name". If the var
   1615  6550  aw148015  * named "name" cannot be found then it is first allocated
   1616  6550  aw148015  * before the copy. Space for the string in the var comes
   1617  6550  aw148015  * from interprocess shared memory. The allocated local var
   1618  6550  aw148015  * is returned at as a char *, or NULL on error.
   1619  6550  aw148015  */
   1620  6550  aw148015 var_t *
   1621  6550  aw148015 var_lvar_assign_string(char *name, char *string)
   1622  6550  aw148015 {
   1623  6550  aw148015 	var_t *var;
   1624  6550  aw148015 	char *strptr;
   1625  6550  aw148015 
   1626  6550  aw148015 	var = var_lvar_alloc_local(name);
   1627  6550  aw148015 
   1628  6550  aw148015 	if (var == NULL) {
   1629  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1630  6550  aw148015 		    name);
   1631  6550  aw148015 		return (NULL);
   1632  6550  aw148015 	}
   1633  6550  aw148015 
   1634  6550  aw148015 	if ((strptr = ipc_stralloc(string)) == NULL) {
   1635  6550  aw148015 		filebench_log(LOG_ERROR, "Cannot assign variable %s",
   1636  6550  aw148015 		    name);
   1637  6550  aw148015 		return (NULL);
   1638  6550  aw148015 	}
   1639  6550  aw148015 	VAR_SET_STR(var, strptr);
   1640  6550  aw148015 
   1641  6550  aw148015 	filebench_log(LOG_DEBUG_SCRIPT,
   1642  6550  aw148015 	    "Lvar_assign_string (%s, %p)=%s", name, var, string);
   1643  6550  aw148015 
   1644  6550  aw148015 	return (var);
   1645  5184  ek110237 }
   1646  5184  ek110237 
   1647  5184  ek110237 /*
   1648  6212  aw148015  * Tests to see if the supplied variable name without the portion after
   1649  6212  aw148015  * the last period is that of a random variable. If it is, it returns
   1650  6212  aw148015  * the number of characters to backspace to skip the period and field
   1651  6212  aw148015  * name. Otherwise it returns 0.
   1652  5184  ek110237  */
   1653  6212  aw148015 int
   1654  6212  aw148015 var_is_set4_randvar(char *name)
   1655  5184  ek110237 {
   1656  5184  ek110237 	var_t *var;
   1657  6212  aw148015 	char varname[128];
   1658  6212  aw148015 	int namelength;
   1659  6212  aw148015 	char *sp;
   1660  5184  ek110237 
   1661  6212  aw148015 	(void) strncpy(varname, name, 128);
   1662  6212  aw148015 	namelength = strlen(varname);
   1663  6212  aw148015 	sp = varname + namelength;
   1664  5184  ek110237 
   1665  6212  aw148015 	while (sp != varname) {
   1666  6212  aw148015 		int c = *sp;
   1667  5184  ek110237 
   1668  6212  aw148015 		*sp = 0;
   1669  6212  aw148015 		if (c == '.')
   1670  6212  aw148015 			break;
   1671  5184  ek110237 
   1672  6212  aw148015 		sp--;
   1673  5184  ek110237 	}
   1674  5184  ek110237 
   1675  6212  aw148015 	/* not a variable name + field? */
   1676  6212  aw148015 	if (sp == varname)
   1677  6212  aw148015 		return (0);
   1678  6212  aw148015 
   1679  6212  aw148015 	/* first part not a variable name? */
   1680  6212  aw148015 	if ((var = var_find(varname+1)) == NULL)
   1681  6212  aw148015 		return (0);
   1682  6212  aw148015 
   1683  6212  aw148015 	/* Make sure it is a random variable */
   1684  6212  aw148015 	if ((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM)
   1685  6212  aw148015 		return (0);
   1686  6212  aw148015 
   1687  6212  aw148015 	/* calculate offset from end of random variable name */
   1688  6212  aw148015 	return (namelength - (sp - varname));
   1689  5184  ek110237 }
   1690  5184  ek110237 
   1691  5184  ek110237 /*
   1692  5184  ek110237  * Implements a simple path name like scheme for finding values
   1693  5184  ek110237  * to place in certain specially named vars. The first part of
   1694  5184  ek110237  * the name is interpreted as a category of either: stats,
   1695  5184  ek110237  * eventgen, date, script, or host var. If a match is found,
   1696  5184  ek110237  * the appropriate routine is called to fill in the requested
   1697  5184  ek110237  * value in the provided var_t, and a pointer to the supplied
   1698  5184  ek110237  * var_t is returned. If the requested value is not found, NULL
   1699  5184  ek110237  * is returned.
   1700  5184  ek110237  */
   1701  5184  ek110237 static var_t *
   1702  5184  ek110237 var_find_internal(var_t *var)
   1703  5184  ek110237 {
   1704  5184  ek110237 	char *n = fb_stralloc(var->var_name);
   1705  5184  ek110237 	char *name = n;
   1706  5184  ek110237 	var_t *rtn = NULL;
   1707  5184  ek110237 
   1708  5184  ek110237 	name++;
   1709  5184  ek110237 	if (name[strlen(name) - 1] != '}')
   1710  5184  ek110237 		return (NULL);
   1711  5184  ek110237 	name[strlen(name) - 1] = 0;
   1712  5184  ek110237 
   1713  5184  ek110237 	if (strncmp(name, STATS_VAR, strlen(STATS_VAR)) == 0)
   1714  5184  ek110237 		rtn = stats_findvar(var, name + strlen(STATS_VAR));
   1715  5184  ek110237 
   1716  5184  ek110237 	if (strcmp(name, EVENTGEN_VAR) == 0)
   1717  5184  ek110237 		rtn = eventgen_ratevar(var);
   1718  5184  ek110237 
   1719  5184  ek110237 	if (strcmp(name, DATE_VAR) == 0)
   1720  5184  ek110237 		rtn = date_var(var);
   1721  5184  ek110237 
   1722  5184  ek110237 	if (strcmp(name, SCRIPT_VAR) == 0)
   1723  5184  ek110237 		rtn = script_var(var);
   1724  5184  ek110237 
   1725  5184  ek110237 	if (strcmp(name, HOST_VAR) == 0)
   1726  5184  ek110237 		rtn = host_var(var);
   1727  5184  ek110237 
   1728  5184  ek110237 	free(n);
   1729  5184  ek110237 
   1730  5184  ek110237 	return (rtn);
   1731  5184  ek110237 }
   1732  5184  ek110237 
   1733  5184  ek110237 /*
   1734  5184  ek110237  * Calls the C library routine getenv() to obtain the value
   1735  5184  ek110237  * for the environment variable specified by var->var_name.
   1736  6212  aw148015  * If found, the value string is returned in var->var_val.string.
   1737  5184  ek110237  * If the requested value is not found, NULL is returned.
   1738  5184  ek110237  */
   1739  5184  ek110237 static var_t *
   1740  5184  ek110237 var_find_environment(var_t *var)
   1741  5184  ek110237 {
   1742  5184  ek110237 	char *n = fb_stralloc(var->var_name);
   1743  5184  ek110237 	char *name = n;
   1744  6212  aw148015 	char *strptr;
   1745  5184  ek110237 
   1746  5184  ek110237 	name++;
   1747  6212  aw148015 	if (name[strlen(name) - 1] != ')') {
   1748  6212  aw148015 		free(n);
   1749  5184  ek110237 		return (NULL);
   1750  6212  aw148015 	}
   1751  5184  ek110237 	name[strlen(name) - 1] = 0;
   1752  5184  ek110237 
   1753  6212  aw148015 	if ((strptr = getenv(name)) != NULL) {
   1754  5184  ek110237 		free(n);
   1755  6212  aw148015 		VAR_SET_STR(var, strptr);
   1756  5184  ek110237 		return (var);
   1757  5184  ek110237 	} else {
   1758  5184  ek110237 		free(n);
   1759  5184  ek110237 		return (NULL);
   1760  5184  ek110237 	}
   1761  5184  ek110237 }
   1762  5184  ek110237 
   1763  5184  ek110237 /*
   1764  5184  ek110237  * Look up special variables. The "name" argument is used to find
   1765  5184  ek110237  * the desired special var and fill it with an appropriate string
   1766  5184  ek110237  * value. Looks for an already allocated var of the same name on
   1767  6550  aw148015  * the shm_var_dyn_list. If not found a new dynamic var is allocated.
   1768  5184  ek110237  * if the name begins with '{', it is an internal variable, and
   1769  5184  ek110237  * var_find_internal() is called. If the name begins with '(' it
   1770  5184  ek110237  * is an environment varable, and var_find_environment() is
   1771  5184  ek110237  * called. On success, a pointer to the var_t is returned,
   1772  5184  ek110237  * otherwise, NULL is returned.
   1773  5184  ek110237  */
   1774  5184  ek110237 static var_t *
   1775  5184  ek110237 var_find_dynamic(char *name)
   1776  5184  ek110237 {
   1777  5184  ek110237 	var_t *var = NULL;
   1778  6391  aw148015 	var_t *v = filebench_shm->shm_var_dyn_list;
   1779  5184  ek110237 	var_t *rtn;
   1780  5184  ek110237 
   1781  5184  ek110237 	/*
   1782  5184  ek110237 	 * Lookup a reference to the var handle for this
   1783  5184  ek110237 	 * special var
   1784  5184  ek110237 	 */
   1785  6391  aw148015 	for (v = filebench_shm->shm_var_dyn_list; v != NULL; v = v->var_next) {
   1786  5184  ek110237 		if (strcmp(v->var_name, name) == 0) {
   1787  5184  ek110237 			var = v;
   1788  5184  ek110237 			break;
   1789  5184  ek110237 		}
   1790  5184  ek110237 	}
   1791  5184  ek110237 
   1792  5184  ek110237 	if (var == NULL)
   1793  5184  ek110237 		var = var_alloc_dynamic(name);
   1794  5184  ek110237 
   1795  5184  ek110237 	/* Internal system control variable */
   1796  5184  ek110237 	if (*name == '{') {
   1797  5184  ek110237 		rtn = var_find_internal(var);
   1798  5184  ek110237 		if (rtn == NULL)
   1799  5184  ek110237 			filebench_log(LOG_ERROR,
   1800  5184  ek110237 			    "Cannot find internal variable %s",
   1801  5184  ek110237 			    var->var_name);
   1802  5184  ek110237 		return (rtn);
   1803  5184  ek110237 	}
   1804  5184  ek110237 
   1805  5184  ek110237 	/* Lookup variable in environment */
   1806  5184  ek110237 	if (*name == '(') {
   1807  5184  ek110237 		rtn = var_find_environment(var);
   1808  5184  ek110237 		if (rtn == NULL)
   1809  5184  ek110237 			filebench_log(LOG_ERROR,
   1810  5184  ek110237 			    "Cannot find environment variable %s",
   1811  5184  ek110237 			    var->var_name);
   1812  5184  ek110237 		return (rtn);
   1813  5184  ek110237 	}
   1814  5184  ek110237 
   1815  5184  ek110237 	return (NULL);
   1816  5184  ek110237 }
   1817  6550  aw148015 
   1818  6550  aw148015 /*
   1819  6550  aw148015  * replace the avd_t attribute value descriptor in the new FLOW_MASTER flowop
   1820  6550  aw148015  * that points to a local variable with a new avd_t containing
   1821  6550  aw148015  * the actual value from the local variable.
   1822  6550  aw148015  */
   1823  6550  aw148015 void
   1824  6550  aw148015 avd_update(avd_t *avdp, var_t *lvar_list)
   1825  6550  aw148015 {
   1826  6550  aw148015 	var_t *old_lvar, *new_lvar;
   1827  6550  aw148015 
   1828  6550  aw148015 	if ((*avdp)->avd_type == AVD_IND_VAR) {
   1829  6550  aw148015 
   1830  6550  aw148015 		/* Make sure there is a local var */
   1831  6550  aw148015 		if ((old_lvar = (*avdp)->avd_val.varptr) == NULL) {
   1832  6550  aw148015 			filebench_log(LOG_ERROR,
   1833  6550  aw148015 			    "avd_update: local var not found");
   1834  6550  aw148015 			return;
   1835  6550  aw148015 		}
   1836  6550  aw148015 	} else {
   1837  6550  aw148015 		/* Empty or not indirect, so no update needed */
   1838  6550  aw148015 		return;
   1839  6550  aw148015 	}
   1840  6550  aw148015 
   1841  6550  aw148015 	/*  allocate a new avd using the new or old lvar contents */
   1842  6550  aw148015 	if ((new_lvar =
   1843  6550  aw148015 	    var_find_list(old_lvar->var_name, lvar_list)) != NULL)
   1844  6550  aw148015 		(*avdp) = avd_alloc_var_ptr(new_lvar);
   1845  6550  aw148015 	else
   1846  6550  aw148015 		(*avdp) = avd_alloc_var_ptr(old_lvar);
   1847  6550  aw148015 }
   1848  6550  aw148015 
   1849  6550  aw148015 void
   1850  6550  aw148015 var_update_comp_lvars(var_t *newlvar, var_t *proto_comp_vars,
   1851  6550  aw148015     var_t *mstr_lvars)
   1852  6550  aw148015 {
   1853  6550  aw148015 	var_t *proto_lvar;
   1854  6550  aw148015 
   1855  6550  aw148015 	/* find the prototype lvar from the inherited list */
   1856  6550  aw148015 	proto_lvar = var_find_list_only(newlvar->var_name, proto_comp_vars);
   1857  6550  aw148015 
   1858  6550  aw148015 	if (proto_lvar == NULL)
   1859  6550  aw148015 		return;
   1860  6550  aw148015 
   1861  6550  aw148015 	/*
   1862  6550  aw148015 	 * if the new local variable has not already been assigned
   1863  6550  aw148015 	 * a value, try to copy a value from the prototype local variable
   1864  6550  aw148015 	 */
   1865  6550  aw148015 	if ((newlvar->var_type & VAR_TYPE_SET_MASK) == 0) {
   1866  6550  aw148015 
   1867  6550  aw148015 		/* copy value from prototype lvar to new lvar */
   1868  6550  aw148015 		(void) var_copy(newlvar, proto_lvar);
   1869  6550  aw148015 	}
   1870  6550  aw148015 
   1871  6550  aw148015 	/* If proto lvar is indirect, see if we can colapse indirection */
   1872  6550  aw148015 	if (VAR_HAS_INDVAR(proto_lvar)) {
   1873  6550  aw148015 		var_t *uplvp;
   1874  6550  aw148015 
   1875  9801    Andrew 		uplvp = (var_t *)proto_lvar->var_varptr1;
   1876  6550  aw148015 
   1877  6550  aw148015 		/* search for more current uplvar on comp master list */
   1878  6550  aw148015 		if (mstr_lvars) {
   1879  6550  aw148015 			uplvp = var_find_list_only(
   1880  6550  aw148015 			    uplvp->var_name, mstr_lvars);
   1881  6550  aw148015 			VAR_SET_INDVAR(newlvar, uplvp);
   1882  6550  aw148015 		}
   1883  6550  aw148015 
   1884  6550  aw148015 		if (VAR_HAS_INDVAR(uplvp))
   1885  9801    Andrew 			VAR_SET_INDVAR(newlvar, uplvp->var_varptr1);
   1886  6550  aw148015 	}
   1887  6550  aw148015 }
   1888