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 /* 22*6212Saw148015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235184Sek110237 * Use is subject to license terms. 245184Sek110237 */ 255184Sek110237 265184Sek110237 #pragma ident "%Z%%M% %I% %E% SMI" 275184Sek110237 285184Sek110237 #include <stdlib.h> 295184Sek110237 #include <stdio.h> 305184Sek110237 #include <string.h> 315184Sek110237 #include <errno.h> 325184Sek110237 335184Sek110237 #include "vars.h" 345184Sek110237 #include "misc.h" 355184Sek110237 #include "utils.h" 365184Sek110237 #include "stats.h" 375184Sek110237 #include "eventgen.h" 385184Sek110237 #include "filebench.h" 39*6212Saw148015 #include "fb_random.h" 405184Sek110237 415184Sek110237 static var_t *var_find_dynamic(char *name); 425184Sek110237 435184Sek110237 /* 44*6212Saw148015 * The filebench variables system has attribute value descriptors (avd_t) 45*6212Saw148015 * where an avd contains a boolean, integer, double, string, random 46*6212Saw148015 * distribution object ptr, boolean ptr, integer ptr, double ptr, 47*6212Saw148015 * string ptr, or variable ptr. The system also has the variables 48*6212Saw148015 * themselves, (var_t), which are named, typed entities which can be 49*6212Saw148015 * allocated, selected and changed using the "set" command and used in 50*6212Saw148015 * attribute assignments. The variables contain either a boolean, an 51*6212Saw148015 * integer, a double, a string or pointer to an associated random 52*6212Saw148015 * distribution object. Both avd_t and var_t entities are allocated 535184Sek110237 * from interprocess shared memory space. 545184Sek110237 * 55*6212Saw148015 * The attribute descriptors implement delayed binding to variable values, 56*6212Saw148015 * which is necessary because the values of variables may be changed 57*6212Saw148015 * between the time the workload file is loaded and it is actually run, 58*6212Saw148015 * either by further "set" commands in the file or from the command line 59*6212Saw148015 * interface. For random variables, they actually point to the random 60*6212Saw148015 * distribution object, allowing FileBench to invoke the appropriate 61*6212Saw148015 * random distribution function on each access to the attribute. However, 62*6212Saw148015 * for static attributes, the value is just loaded in the descriptor 63*6212Saw148015 * directly, avoiding the need to allocate a variable to hold the static 64*6212Saw148015 * value. 65*6212Saw148015 * 665184Sek110237 * The routines in this module are used to allocate, locate, and 67*6212Saw148015 * manipulate the attribute descriptors, and vars. Routines are 68*6212Saw148015 * also included to convert between the component strings, doubles 69*6212Saw148015 * and integers of vars, and said components of avd_t. 705184Sek110237 */ 715184Sek110237 725184Sek110237 /* 73*6212Saw148015 * returns a pointer to a string indicating the type of data contained 74*6212Saw148015 * in the supplied attribute variable descriptor. 755184Sek110237 */ 76*6212Saw148015 static char * 77*6212Saw148015 avd_get_type_string(avd_t avd) 785184Sek110237 { 79*6212Saw148015 switch (avd->avd_type) { 80*6212Saw148015 case AVD_INVALID: 81*6212Saw148015 return ("uninitialized"); 82*6212Saw148015 83*6212Saw148015 case AVD_VAL_BOOL: 84*6212Saw148015 return ("boolean value"); 85*6212Saw148015 86*6212Saw148015 case AVD_VARVAL_BOOL: 87*6212Saw148015 return ("points to boolean in var_t"); 88*6212Saw148015 89*6212Saw148015 case AVD_VAL_INT: 90*6212Saw148015 return ("integer value"); 91*6212Saw148015 92*6212Saw148015 case AVD_VARVAL_INT: 93*6212Saw148015 return ("points to integer in var_t"); 94*6212Saw148015 95*6212Saw148015 case AVD_VAL_STR: 96*6212Saw148015 return ("string"); 97*6212Saw148015 98*6212Saw148015 case AVD_VARVAL_STR: 99*6212Saw148015 return ("points to string in var_t"); 100*6212Saw148015 101*6212Saw148015 case AVD_VAL_DBL: 102*6212Saw148015 return ("double float value"); 103*6212Saw148015 104*6212Saw148015 case AVD_VARVAL_DBL: 105*6212Saw148015 return ("points to double float in var_t"); 106*6212Saw148015 107*6212Saw148015 case AVD_IND_VAR: 108*6212Saw148015 return ("points to a var_t"); 109*6212Saw148015 110*6212Saw148015 case AVD_IND_RANDVAR: 111*6212Saw148015 return ("points to var_t's random distribution object"); 112*6212Saw148015 113*6212Saw148015 default: 114*6212Saw148015 return ("illegal avd type"); 115*6212Saw148015 } 116*6212Saw148015 } 117*6212Saw148015 118*6212Saw148015 /* 119*6212Saw148015 * returns a pointer to a string indicating the type of data contained 120*6212Saw148015 * in the supplied variable. 121*6212Saw148015 */ 122*6212Saw148015 static char * 123*6212Saw148015 var_get_type_string(var_t *ivp) 124*6212Saw148015 { 125*6212Saw148015 switch (ivp->var_type & VAR_TYPE_SET_MASK) { 126*6212Saw148015 case VAR_TYPE_BOOL_SET: 127*6212Saw148015 return ("boolean"); 128*6212Saw148015 129*6212Saw148015 case VAR_TYPE_INT_SET: 130*6212Saw148015 return ("integer"); 131*6212Saw148015 132*6212Saw148015 case VAR_TYPE_STR_SET: 133*6212Saw148015 return ("string"); 134*6212Saw148015 135*6212Saw148015 case VAR_TYPE_DBL_SET: 136*6212Saw148015 return ("double float"); 137*6212Saw148015 138*6212Saw148015 case VAR_TYPE_RAND_SET: 139*6212Saw148015 return ("random"); 140*6212Saw148015 141*6212Saw148015 default: 142*6212Saw148015 return ("empty"); 143*6212Saw148015 } 144*6212Saw148015 } 145*6212Saw148015 146*6212Saw148015 /* 147*6212Saw148015 * Returns the fbint_t pointed to by the supplied avd_t "avd". 148*6212Saw148015 */ 149*6212Saw148015 fbint_t 150*6212Saw148015 avd_get_int(avd_t avd) 151*6212Saw148015 { 152*6212Saw148015 var_t *ivp; 153*6212Saw148015 randdist_t *rndp; 154*6212Saw148015 155*6212Saw148015 if (avd == NULL) 1565184Sek110237 return (0); 1575184Sek110237 158*6212Saw148015 switch (avd->avd_type) { 159*6212Saw148015 case AVD_VAL_INT: 160*6212Saw148015 return (avd->avd_val.intval); 161*6212Saw148015 162*6212Saw148015 case AVD_VARVAL_INT: 163*6212Saw148015 if (avd->avd_val.intptr) 164*6212Saw148015 return (*(avd->avd_val.intptr)); 165*6212Saw148015 else 166*6212Saw148015 return (0); 167*6212Saw148015 168*6212Saw148015 case AVD_IND_VAR: 169*6212Saw148015 if ((ivp = avd->avd_val.varptr) == NULL) 170*6212Saw148015 return (0); 171*6212Saw148015 172*6212Saw148015 if (VAR_HAS_INTEGER(ivp)) 173*6212Saw148015 return (ivp->var_val.integer); 174*6212Saw148015 175*6212Saw148015 if (VAR_HAS_RANDDIST(ivp)) { 176*6212Saw148015 if ((rndp = ivp->var_val.randptr) != NULL) 177*6212Saw148015 return ((fbint_t)rndp->rnd_get(rndp)); 178*6212Saw148015 } 179*6212Saw148015 180*6212Saw148015 filebench_log(LOG_ERROR, 181*6212Saw148015 "Attempt to get integer from %s var $%s", 182*6212Saw148015 var_get_type_string(ivp), ivp->var_name); 183*6212Saw148015 return (0); 184*6212Saw148015 185*6212Saw148015 case AVD_IND_RANDVAR: 186*6212Saw148015 if ((rndp = avd->avd_val.randptr) == NULL) 187*6212Saw148015 return (0); 188*6212Saw148015 else 189*6212Saw148015 return ((fbint_t)rndp->rnd_get(rndp)); 190*6212Saw148015 191*6212Saw148015 default: 192*6212Saw148015 filebench_log(LOG_ERROR, 193*6212Saw148015 "Attempt to get integer from %s avd", 194*6212Saw148015 avd_get_type_string(avd)); 195*6212Saw148015 return (0); 196*6212Saw148015 } 1975184Sek110237 } 1985184Sek110237 1995184Sek110237 /* 200*6212Saw148015 * Returns the floating point value of a variable pointed to by the 201*6212Saw148015 * supplied avd_t "avd". Intended to get the actual (double) value 202*6212Saw148015 * supplied by the random variable. 203*6212Saw148015 */ 204*6212Saw148015 double 205*6212Saw148015 avd_get_dbl(avd_t avd) 206*6212Saw148015 { 207*6212Saw148015 var_t *ivp; 208*6212Saw148015 randdist_t *rndp; 209*6212Saw148015 210*6212Saw148015 if (avd == NULL) 211*6212Saw148015 return (0.0); 212*6212Saw148015 213*6212Saw148015 switch (avd->avd_type) { 214*6212Saw148015 case AVD_VAL_INT: 215*6212Saw148015 return ((double)avd->avd_val.intval); 216*6212Saw148015 217*6212Saw148015 case AVD_VAL_DBL: 218*6212Saw148015 return (avd->avd_val.dblval); 219*6212Saw148015 220*6212Saw148015 case AVD_VARVAL_INT: 221*6212Saw148015 if (avd->avd_val.intptr) 222*6212Saw148015 return ((double)(*(avd->avd_val.intptr))); 223*6212Saw148015 else 224*6212Saw148015 return (0.0); 225*6212Saw148015 226*6212Saw148015 case AVD_VARVAL_DBL: 227*6212Saw148015 if (avd->avd_val.dblptr) 228*6212Saw148015 return (*(avd->avd_val.dblptr)); 229*6212Saw148015 else 230*6212Saw148015 return (0.0); 231*6212Saw148015 232*6212Saw148015 case AVD_IND_VAR: 233*6212Saw148015 ivp = avd->avd_val.varptr; 234*6212Saw148015 235*6212Saw148015 if (ivp && VAR_HAS_INTEGER(ivp)) 236*6212Saw148015 return ((double)ivp->var_val.integer); 237*6212Saw148015 238*6212Saw148015 if (ivp && VAR_HAS_DOUBLE(ivp)) 239*6212Saw148015 return (ivp->var_val.dbl_flt); 240*6212Saw148015 241*6212Saw148015 if (ivp && VAR_HAS_RANDDIST(ivp)) { 242*6212Saw148015 if ((rndp = ivp->var_val.randptr) != NULL) 243*6212Saw148015 return (rndp->rnd_get(rndp)); 244*6212Saw148015 } 245*6212Saw148015 filebench_log(LOG_ERROR, 246*6212Saw148015 "Attempt to get double float from %s var $%s", 247*6212Saw148015 var_get_type_string(ivp), ivp->var_name); 248*6212Saw148015 return (0.0); 249*6212Saw148015 250*6212Saw148015 case AVD_IND_RANDVAR: 251*6212Saw148015 if ((rndp = avd->avd_val.randptr) == NULL) { 252*6212Saw148015 return (0.0); 253*6212Saw148015 } else 254*6212Saw148015 return (rndp->rnd_get(rndp)); 255*6212Saw148015 256*6212Saw148015 default: 257*6212Saw148015 filebench_log(LOG_ERROR, 258*6212Saw148015 "Attempt to get floating point from %s avd", 259*6212Saw148015 avd_get_type_string(avd)); 260*6212Saw148015 return (0.0); 261*6212Saw148015 } 262*6212Saw148015 } 263*6212Saw148015 264*6212Saw148015 /* 265*6212Saw148015 * Returns the boolean pointed to by the supplied avd_t "avd". 2665184Sek110237 */ 267*6212Saw148015 boolean_t 268*6212Saw148015 avd_get_bool(avd_t avd) 2695184Sek110237 { 270*6212Saw148015 var_t *ivp; 271*6212Saw148015 272*6212Saw148015 if (avd == NULL) 273*6212Saw148015 return (0); 274*6212Saw148015 275*6212Saw148015 switch (avd->avd_type) { 276*6212Saw148015 case AVD_VAL_BOOL: 277*6212Saw148015 return (avd->avd_val.boolval); 278*6212Saw148015 279*6212Saw148015 case AVD_VARVAL_BOOL: 280*6212Saw148015 if (avd->avd_val.boolptr) 281*6212Saw148015 return (*(avd->avd_val.boolptr)); 282*6212Saw148015 else 283*6212Saw148015 return (FALSE); 284*6212Saw148015 285*6212Saw148015 /* for backwards compatibility with old workloads */ 286*6212Saw148015 case AVD_VAL_INT: 287*6212Saw148015 if (avd->avd_val.intval != 0) 288*6212Saw148015 return (TRUE); 289*6212Saw148015 else 290*6212Saw148015 return (FALSE); 291*6212Saw148015 292*6212Saw148015 case AVD_VARVAL_INT: 293*6212Saw148015 if (avd->avd_val.intptr) 294*6212Saw148015 if (*(avd->avd_val.intptr) != 0) 295*6212Saw148015 return (TRUE); 296*6212Saw148015 297*6212Saw148015 return (FALSE); 298*6212Saw148015 299*6212Saw148015 case AVD_IND_VAR: 300*6212Saw148015 if ((ivp = avd->avd_val.varptr) == NULL) 301*6212Saw148015 return (0); 302*6212Saw148015 303*6212Saw148015 if (VAR_HAS_BOOLEAN(ivp)) 304*6212Saw148015 return (ivp->var_val.boolean); 305*6212Saw148015 306*6212Saw148015 if (VAR_HAS_INTEGER(ivp)) { 307*6212Saw148015 if (ivp->var_val.boolean) 308*6212Saw148015 return (TRUE); 309*6212Saw148015 else 310*6212Saw148015 return (FALSE); 311*6212Saw148015 } 3125184Sek110237 313*6212Saw148015 filebench_log(LOG_ERROR, 314*6212Saw148015 "Attempt to get boolean from %s var $%s", 315*6212Saw148015 var_get_type_string(ivp), ivp->var_name); 316*6212Saw148015 return (FALSE); 317*6212Saw148015 318*6212Saw148015 default: 319*6212Saw148015 filebench_log(LOG_ERROR, 320*6212Saw148015 "Attempt to get boolean from %s avd", 321*6212Saw148015 avd_get_type_string(avd)); 322*6212Saw148015 return (FALSE); 323*6212Saw148015 } 324*6212Saw148015 } 325*6212Saw148015 326*6212Saw148015 /* 327*6212Saw148015 * Returns the string pointed to by the supplied avd_t "avd". 328*6212Saw148015 */ 329*6212Saw148015 char * 330*6212Saw148015 avd_get_str(avd_t avd) 331*6212Saw148015 { 332*6212Saw148015 var_t *ivp; 333*6212Saw148015 334*6212Saw148015 if (avd == NULL) 335*6212Saw148015 return (NULL); 336*6212Saw148015 337*6212Saw148015 switch (avd->avd_type) { 338*6212Saw148015 case AVD_VAL_STR: 339*6212Saw148015 return (avd->avd_val.strval); 340*6212Saw148015 341*6212Saw148015 case AVD_VARVAL_STR: 342*6212Saw148015 if (avd->avd_val.strptr) 343*6212Saw148015 return (*avd->avd_val.strptr); 344*6212Saw148015 else 345*6212Saw148015 return (NULL); 346*6212Saw148015 347*6212Saw148015 case AVD_IND_VAR: 348*6212Saw148015 ivp = avd->avd_val.varptr; 349*6212Saw148015 350*6212Saw148015 if (ivp && VAR_HAS_STRING(ivp)) 351*6212Saw148015 return (ivp->var_val.string); 352*6212Saw148015 353*6212Saw148015 filebench_log(LOG_ERROR, 354*6212Saw148015 "Attempt to get string from %s var $%s", 355*6212Saw148015 var_get_type_string(ivp), ivp->var_name); 356*6212Saw148015 return (NULL); 357*6212Saw148015 358*6212Saw148015 default: 359*6212Saw148015 filebench_log(LOG_ERROR, 360*6212Saw148015 "Attempt to get string from %s avd", 361*6212Saw148015 avd_get_type_string(avd)); 3625184Sek110237 return (NULL); 3635184Sek110237 } 364*6212Saw148015 } 3655184Sek110237 366*6212Saw148015 /* 367*6212Saw148015 * Allocates a avd_t from ipc memory space. 368*6212Saw148015 * logs an error and returns NULL on failure. 369*6212Saw148015 */ 370*6212Saw148015 static avd_t 371*6212Saw148015 avd_alloc_cmn(void) 372*6212Saw148015 { 373*6212Saw148015 avd_t rtn; 3745184Sek110237 375*6212Saw148015 if ((rtn = (avd_t)ipc_malloc(FILEBENCH_AVD)) == NULL) 376*6212Saw148015 filebench_log(LOG_ERROR, "Avd alloc failed"); 3775184Sek110237 3785184Sek110237 return (rtn); 3795184Sek110237 } 3805184Sek110237 3815184Sek110237 /* 382*6212Saw148015 * pre-loads the allocated avd_t with the boolean_t "bool". 383*6212Saw148015 * Returns the avd_t on success, NULL on failure. 384*6212Saw148015 */ 385*6212Saw148015 avd_t 386*6212Saw148015 avd_bool_alloc(boolean_t bool) 387*6212Saw148015 { 388*6212Saw148015 avd_t avd; 389*6212Saw148015 390*6212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 391*6212Saw148015 return (NULL); 392*6212Saw148015 393*6212Saw148015 avd->avd_type = AVD_VAL_BOOL; 394*6212Saw148015 avd->avd_val.boolval = bool; 395*6212Saw148015 396*6212Saw148015 filebench_log(LOG_DEBUG_IMPL, "Alloc boolean %d", bool); 397*6212Saw148015 398*6212Saw148015 return (avd); 399*6212Saw148015 } 400*6212Saw148015 401*6212Saw148015 /* 402*6212Saw148015 * pre-loads the allocated avd_t with the fbint_t "integer". 403*6212Saw148015 * Returns the avd_t on success, NULL on failure. 404*6212Saw148015 */ 405*6212Saw148015 avd_t 406*6212Saw148015 avd_int_alloc(fbint_t integer) 407*6212Saw148015 { 408*6212Saw148015 avd_t avd; 409*6212Saw148015 410*6212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 411*6212Saw148015 return (NULL); 412*6212Saw148015 413*6212Saw148015 avd->avd_type = AVD_VAL_INT; 414*6212Saw148015 avd->avd_val.intval = integer; 415*6212Saw148015 416*6212Saw148015 filebench_log(LOG_DEBUG_IMPL, "Alloc integer %lld", integer); 417*6212Saw148015 418*6212Saw148015 return (avd); 419*6212Saw148015 } 420*6212Saw148015 421*6212Saw148015 /* 422*6212Saw148015 * Gets a avd_t and points it to the var that 423*6212Saw148015 * it will eventually be filled from 4245184Sek110237 */ 425*6212Saw148015 static avd_t 426*6212Saw148015 avd_alloc_var_ptr(var_t *var) 4275184Sek110237 { 428*6212Saw148015 avd_t avd; 429*6212Saw148015 430*6212Saw148015 if (var == NULL) 431*6212Saw148015 return (NULL); 432*6212Saw148015 433*6212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 434*6212Saw148015 return (NULL); 435*6212Saw148015 436*6212Saw148015 switch (var->var_type & VAR_TYPE_SET_MASK) { 437*6212Saw148015 case VAR_TYPE_BOOL_SET: 438*6212Saw148015 avd->avd_type = AVD_VARVAL_BOOL; 439*6212Saw148015 avd->avd_val.boolptr = (&var->var_val.boolean); 440*6212Saw148015 break; 441*6212Saw148015 442*6212Saw148015 case VAR_TYPE_INT_SET: 443*6212Saw148015 avd->avd_type = AVD_VARVAL_INT; 444*6212Saw148015 avd->avd_val.intptr = (&var->var_val.integer); 445*6212Saw148015 break; 446*6212Saw148015 447*6212Saw148015 case VAR_TYPE_STR_SET: 448*6212Saw148015 avd->avd_type = AVD_VARVAL_STR; 449*6212Saw148015 avd->avd_val.strptr = &(var->var_val.string); 450*6212Saw148015 break; 4515184Sek110237 452*6212Saw148015 case VAR_TYPE_DBL_SET: 453*6212Saw148015 avd->avd_type = AVD_VARVAL_DBL; 454*6212Saw148015 avd->avd_val.dblptr = &(var->var_val.dbl_flt); 455*6212Saw148015 break; 456*6212Saw148015 457*6212Saw148015 case VAR_TYPE_RAND_SET: 458*6212Saw148015 avd->avd_type = AVD_IND_RANDVAR; 459*6212Saw148015 avd->avd_val.randptr = var->var_val.randptr; 460*6212Saw148015 break; 461*6212Saw148015 462*6212Saw148015 default: 463*6212Saw148015 avd->avd_type = AVD_IND_VAR; 464*6212Saw148015 avd->avd_val.varptr = var; 465*6212Saw148015 break; 466*6212Saw148015 } 467*6212Saw148015 return (avd); 468*6212Saw148015 } 469*6212Saw148015 470*6212Saw148015 /* 471*6212Saw148015 * Gets a avd_t, then allocates and initializes a piece of 472*6212Saw148015 * shared string memory, putting the pointer to it into the just 473*6212Saw148015 * allocated string pointer location. The routine returns a pointer 474*6212Saw148015 * to the string pointer location or returns NULL on error. 475*6212Saw148015 */ 476*6212Saw148015 avd_t 477*6212Saw148015 avd_str_alloc(char *string) 478*6212Saw148015 { 479*6212Saw148015 avd_t avd; 480*6212Saw148015 481*6212Saw148015 if (string == NULL) { 482*6212Saw148015 filebench_log(LOG_ERROR, "No string supplied\n"); 4835184Sek110237 return (NULL); 4845184Sek110237 } 4855184Sek110237 486*6212Saw148015 if ((avd = avd_alloc_cmn()) == NULL) 487*6212Saw148015 return (NULL); 488*6212Saw148015 489*6212Saw148015 avd->avd_type = AVD_VAL_STR; 490*6212Saw148015 avd->avd_val.strval = ipc_stralloc(string); 4915184Sek110237 4925184Sek110237 filebench_log(LOG_DEBUG_IMPL, 4935184Sek110237 "Alloc string %s ptr %zx", 494*6212Saw148015 string, avd); 4955184Sek110237 496*6212Saw148015 return (avd); 4975184Sek110237 } 4985184Sek110237 4995184Sek110237 /* 5005184Sek110237 * Allocates a var (var_t) from interprocess shared memory. 5015184Sek110237 * Places the allocated var on the end of the globally shared 5025184Sek110237 * var_list. Finally, the routine allocates a string containing 5035184Sek110237 * a copy of the supplied "name" string. If any allocations 5045184Sek110237 * fails, returns NULL, otherwise it returns a pointer to the 5055184Sek110237 * newly allocated var. 5065184Sek110237 */ 5075184Sek110237 static var_t * 508*6212Saw148015 var_alloc_cmn(char *name, int var_type) 5095184Sek110237 { 510*6212Saw148015 var_t **var_listp; 5115184Sek110237 var_t *var = NULL; 5125184Sek110237 var_t *prev = NULL; 5135184Sek110237 var_t *newvar; 5145184Sek110237 5155184Sek110237 if ((newvar = (var_t *)ipc_malloc(FILEBENCH_VARIABLE)) == NULL) { 5165184Sek110237 filebench_log(LOG_ERROR, "Out of memory for variables"); 5175184Sek110237 return (NULL); 5185184Sek110237 } 5195184Sek110237 (void) memset(newvar, 0, sizeof (newvar)); 520*6212Saw148015 newvar->var_type = var_type; 5215184Sek110237 5225184Sek110237 if ((newvar->var_name = ipc_stralloc(name)) == NULL) { 5235184Sek110237 filebench_log(LOG_ERROR, "Out of memory for variables"); 5245184Sek110237 return (NULL); 5255184Sek110237 } 5265184Sek110237 527*6212Saw148015 switch (var_type & VAR_TYPE_MASK) { 528*6212Saw148015 case VAR_TYPE_RANDOM: 529*6212Saw148015 case VAR_TYPE_GLOBAL: 530*6212Saw148015 var_listp = &filebench_shm->var_list; 531*6212Saw148015 break; 532*6212Saw148015 533*6212Saw148015 case VAR_TYPE_DYNAMIC: 534*6212Saw148015 var_listp = &filebench_shm->var_dyn_list; 535*6212Saw148015 break; 536*6212Saw148015 537*6212Saw148015 default: 538*6212Saw148015 var_listp = &filebench_shm->var_list; 539*6212Saw148015 break; 540*6212Saw148015 } 541*6212Saw148015 542*6212Saw148015 /* add to the end of list */ 543*6212Saw148015 for (var = *var_listp; var != NULL; var = var->var_next) 544*6212Saw148015 prev = var; /* Find end of list */ 545*6212Saw148015 if (prev != NULL) 546*6212Saw148015 prev->var_next = newvar; 547*6212Saw148015 else 548*6212Saw148015 *var_listp = newvar; 549*6212Saw148015 5505184Sek110237 return (newvar); 5515184Sek110237 } 5525184Sek110237 5535184Sek110237 /* 554*6212Saw148015 * Allocates a var (var_t) from interprocess shared memory and 555*6212Saw148015 * places the allocated var on the end of the globally shared 556*6212Saw148015 * var_list. If the allocation fails, returns NULL, otherwise 557*6212Saw148015 * it returns a pointer to the newly allocated var. 558*6212Saw148015 */ 559*6212Saw148015 static var_t * 560*6212Saw148015 var_alloc(char *name) 561*6212Saw148015 { 562*6212Saw148015 return (var_alloc_cmn(name, VAR_TYPE_GLOBAL)); 563*6212Saw148015 } 564*6212Saw148015 565*6212Saw148015 /* 5665184Sek110237 * Allocates a var (var_t) from interprocess shared memory. 5675184Sek110237 * Places the allocated var on the end of the globally shared 568*6212Saw148015 * var_dyn_list. If the allocation fails, returns NULL, otherwise 569*6212Saw148015 * it returns a pointer to the newly allocated var. 5705184Sek110237 */ 5715184Sek110237 static var_t * 5725184Sek110237 var_alloc_dynamic(char *name) 5735184Sek110237 { 574*6212Saw148015 return (var_alloc_cmn(name, VAR_TYPE_DYNAMIC)); 5755184Sek110237 } 5765184Sek110237 5775184Sek110237 /* 5785184Sek110237 * Searches for var_t with name "name" in the master var_list. 5795184Sek110237 * If successful, returns a pointer to the var_t, otherwise 5805184Sek110237 * returns NULL. 5815184Sek110237 */ 5825184Sek110237 static var_t * 5835184Sek110237 var_find(char *name) 5845184Sek110237 { 5855184Sek110237 var_t *var; 5865184Sek110237 5875184Sek110237 for (var = filebench_shm->var_list; var != NULL; var = var->var_next) { 5885184Sek110237 if (strcmp(var->var_name, name) == 0) 5895184Sek110237 return (var); 5905184Sek110237 } 5915184Sek110237 5925184Sek110237 return (NULL); 5935184Sek110237 } 5945184Sek110237 5955184Sek110237 /* 5965184Sek110237 * Searches for the named var, and, if found, sets its 597*6212Saw148015 * var_val.boolean's value to that of the supplied boolean. 5985184Sek110237 * If not found, the routine allocates a new var and sets 599*6212Saw148015 * its var_val.boolean's value to that of the supplied 600*6212Saw148015 * boolean. If the named var cannot be found or allocated 601*6212Saw148015 * the routine returns -1, otherwise it returns 0. 6025184Sek110237 */ 6035184Sek110237 int 604*6212Saw148015 var_assign_boolean(char *name, boolean_t bool) 6055184Sek110237 { 6065184Sek110237 var_t *var; 6075184Sek110237 608*6212Saw148015 if (name == NULL) { 609*6212Saw148015 filebench_log(LOG_ERROR, 610*6212Saw148015 "var_assign_boolean: Name not supplied"); 611*6212Saw148015 return (0); 612*6212Saw148015 } 613*6212Saw148015 6145184Sek110237 name += 1; 6155184Sek110237 616*6212Saw148015 if ((var = var_find(name)) == NULL) { 617*6212Saw148015 var = var_alloc(name); 618*6212Saw148015 } 6195184Sek110237 6205184Sek110237 if (var == NULL) { 6215184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 6225184Sek110237 name); 6235184Sek110237 return (-1); 6245184Sek110237 } 6255184Sek110237 626*6212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 627*6212Saw148015 filebench_log(LOG_ERROR, 628*6212Saw148015 "Cannot assign integer to random variable %s", name); 629*6212Saw148015 return (-1); 630*6212Saw148015 } 631*6212Saw148015 632*6212Saw148015 VAR_SET_BOOL(var, bool); 633*6212Saw148015 634*6212Saw148015 filebench_log(LOG_DEBUG_SCRIPT, "Assign boolean %s=%d", 635*6212Saw148015 name, bool); 636*6212Saw148015 637*6212Saw148015 return (0); 638*6212Saw148015 } 639*6212Saw148015 640*6212Saw148015 /* 641*6212Saw148015 * Searches for the named var, and, if found, sets its 642*6212Saw148015 * var_integer's value to that of the supplied integer. 643*6212Saw148015 * If not found, the routine allocates a new var and sets 644*6212Saw148015 * its var_integers's value to that of the supplied 645*6212Saw148015 * integer. If the named var cannot be found or allocated 646*6212Saw148015 * the routine returns -1, otherwise it returns 0. 647*6212Saw148015 */ 648*6212Saw148015 int 649*6212Saw148015 var_assign_integer(char *name, fbint_t integer) 650*6212Saw148015 { 651*6212Saw148015 var_t *var; 652*6212Saw148015 653*6212Saw148015 if (name == NULL) { 654*6212Saw148015 filebench_log(LOG_ERROR, 655*6212Saw148015 "var_assign_integer: Name not supplied"); 656*6212Saw148015 return (0); 657*6212Saw148015 } 658*6212Saw148015 659*6212Saw148015 name += 1; 660*6212Saw148015 661*6212Saw148015 if ((var = var_find(name)) == NULL) { 662*6212Saw148015 var = var_alloc(name); 663*6212Saw148015 } 664*6212Saw148015 665*6212Saw148015 if (var == NULL) { 666*6212Saw148015 filebench_log(LOG_ERROR, "Cannot assign variable %s", 667*6212Saw148015 name); 668*6212Saw148015 return (-1); 669*6212Saw148015 } 670*6212Saw148015 671*6212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 672*6212Saw148015 filebench_log(LOG_ERROR, 673*6212Saw148015 "Cannot assign integer to random variable %s", name); 674*6212Saw148015 return (-1); 675*6212Saw148015 } 676*6212Saw148015 677*6212Saw148015 VAR_SET_INT(var, integer); 6785184Sek110237 6795184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%lld", 6805184Sek110237 name, integer); 6815184Sek110237 6825184Sek110237 return (0); 6835184Sek110237 } 6845184Sek110237 6855184Sek110237 /* 686*6212Saw148015 * Find a variable, and set it to random type. 687*6212Saw148015 * If it does not have a random extension, allocate one 688*6212Saw148015 */ 689*6212Saw148015 var_t * 690*6212Saw148015 var_find_randvar(char *name) 691*6212Saw148015 { 692*6212Saw148015 var_t *newvar; 693*6212Saw148015 694*6212Saw148015 name += 1; 695*6212Saw148015 696*6212Saw148015 if ((newvar = var_find(name)) == NULL) { 697*6212Saw148015 filebench_log(LOG_ERROR, 698*6212Saw148015 "failed to locate random variable $%s\n", name); 699*6212Saw148015 return (NULL); 700*6212Saw148015 } 701*6212Saw148015 702*6212Saw148015 /* set randdist pointer unless it is already set */ 703*6212Saw148015 if (((newvar->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) || 704*6212Saw148015 !VAR_HAS_RANDDIST(newvar)) { 705*6212Saw148015 filebench_log(LOG_ERROR, 706*6212Saw148015 "Found variable $%s not random\n", name); 707*6212Saw148015 return (NULL); 708*6212Saw148015 } 709*6212Saw148015 710*6212Saw148015 return (newvar); 711*6212Saw148015 } 712*6212Saw148015 713*6212Saw148015 /* 714*6212Saw148015 * Allocate a variable, and set it to random type. Then 715*6212Saw148015 * allocate a random extension. 716*6212Saw148015 */ 717*6212Saw148015 var_t * 718*6212Saw148015 var_define_randvar(char *name) 719*6212Saw148015 { 720*6212Saw148015 var_t *newvar; 721*6212Saw148015 randdist_t *rndp = NULL; 722*6212Saw148015 723*6212Saw148015 name += 1; 724*6212Saw148015 725*6212Saw148015 /* make sure variable doesn't already exist */ 726*6212Saw148015 if (var_find(name) != NULL) { 727*6212Saw148015 filebench_log(LOG_ERROR, 728*6212Saw148015 "variable name already in use\n"); 729*6212Saw148015 return (NULL); 730*6212Saw148015 } 731*6212Saw148015 732*6212Saw148015 /* allocate a random variable */ 733*6212Saw148015 if ((newvar = var_alloc_cmn(name, VAR_TYPE_RANDOM)) == NULL) { 734*6212Saw148015 filebench_log(LOG_ERROR, 735*6212Saw148015 "failed to alloc random variable\n"); 736*6212Saw148015 return (NULL); 737*6212Saw148015 } 738*6212Saw148015 739*6212Saw148015 /* set randdist pointer */ 740*6212Saw148015 if ((rndp = randdist_alloc()) == NULL) { 741*6212Saw148015 filebench_log(LOG_ERROR, 742*6212Saw148015 "failed to alloc random distribution object\n"); 743*6212Saw148015 return (NULL); 744*6212Saw148015 } 745*6212Saw148015 746*6212Saw148015 rndp->rnd_var = newvar; 747*6212Saw148015 VAR_SET_RAND(newvar, rndp); 748*6212Saw148015 749*6212Saw148015 return (newvar); 750*6212Saw148015 } 751*6212Saw148015 752*6212Saw148015 /* 753*6212Saw148015 * Searches for the named var, and if found returns an avd_t 754*6212Saw148015 * pointing to the var's var_integer, var_string or var_double 755*6212Saw148015 * as appropriate. If not found, attempts to allocate 756*6212Saw148015 * a var named "name" and returns an avd_t to it with 757*6212Saw148015 * no value set. If the var cannot be found or allocated, an 7585184Sek110237 * error is logged and the run is terminated. 7595184Sek110237 */ 760*6212Saw148015 avd_t 761*6212Saw148015 var_ref_attr(char *name) 7625184Sek110237 { 7635184Sek110237 var_t *var; 7645184Sek110237 7655184Sek110237 name += 1; 7665184Sek110237 7675184Sek110237 if ((var = var_find(name)) == NULL) 7685184Sek110237 var = var_find_dynamic(name); 7695184Sek110237 7705184Sek110237 if (var == NULL) 7715184Sek110237 var = var_alloc(name); 7725184Sek110237 7735184Sek110237 if (var == NULL) { 7745184Sek110237 filebench_log(LOG_ERROR, "Invalid variable $%s", 7755184Sek110237 name); 7765184Sek110237 filebench_shutdown(1); 7775184Sek110237 } 7785184Sek110237 779*6212Saw148015 /* allocate pointer to var and return */ 780*6212Saw148015 return (avd_alloc_var_ptr(var)); 7815184Sek110237 } 7825184Sek110237 783*6212Saw148015 7845184Sek110237 /* 785*6212Saw148015 * Searches for the named var, and if found copies the var_val.string, 786*6212Saw148015 * if it exists, a decimal number string representation of 787*6212Saw148015 * var_val.integer, the state of var_val.boolean, or the type of random 788*6212Saw148015 * distribution employed, into a malloc'd bit of memory using fb_stralloc(). 7895184Sek110237 * Returns a pointer to the created string, or NULL on failure. 7905184Sek110237 */ 7915184Sek110237 char * 7925184Sek110237 var_to_string(char *name) 7935184Sek110237 { 7945184Sek110237 var_t *var; 7955184Sek110237 char tmp[128]; 7965184Sek110237 7975184Sek110237 name += 1; 7985184Sek110237 7995184Sek110237 if ((var = var_find(name)) == NULL) 8005184Sek110237 var = var_find_dynamic(name); 8015184Sek110237 8025184Sek110237 if (var == NULL) 8035184Sek110237 return (NULL); 8045184Sek110237 805*6212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 806*6212Saw148015 switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) { 807*6212Saw148015 case RAND_TYPE_UNIFORM: 808*6212Saw148015 return (fb_stralloc("uniform random var")); 809*6212Saw148015 case RAND_TYPE_GAMMA: 810*6212Saw148015 return (fb_stralloc("gamma random var")); 811*6212Saw148015 case RAND_TYPE_TABLE: 812*6212Saw148015 return (fb_stralloc("tabular random var")); 813*6212Saw148015 default: 814*6212Saw148015 return (fb_stralloc("unitialized random var")); 815*6212Saw148015 } 816*6212Saw148015 } 8175184Sek110237 818*6212Saw148015 if (VAR_HAS_STRING(var) && var->var_val.string) 819*6212Saw148015 return (fb_stralloc(var->var_val.string)); 8205184Sek110237 821*6212Saw148015 if (VAR_HAS_BOOLEAN(var)) { 822*6212Saw148015 if (var->var_val.boolean) 823*6212Saw148015 return (fb_stralloc("true")); 824*6212Saw148015 else 825*6212Saw148015 return (fb_stralloc("false")); 826*6212Saw148015 } 827*6212Saw148015 828*6212Saw148015 if (VAR_HAS_INTEGER(var)) { 829*6212Saw148015 (void) snprintf(tmp, sizeof (tmp), "%lld", 830*6212Saw148015 var->var_val.integer); 831*6212Saw148015 return (fb_stralloc(tmp)); 832*6212Saw148015 } 833*6212Saw148015 834*6212Saw148015 return (fb_stralloc("No default")); 8355184Sek110237 } 8365184Sek110237 8375184Sek110237 /* 8385184Sek110237 * Searches for the named var, and if found returns the value, 839*6212Saw148015 * of var_val.boolean. If the var is not found, or a boolean 840*6212Saw148015 * value has not been set, logs an error and returns 0. 8415184Sek110237 */ 842*6212Saw148015 boolean_t 843*6212Saw148015 var_to_boolean(char *name) 844*6212Saw148015 { 845*6212Saw148015 var_t *var; 846*6212Saw148015 847*6212Saw148015 name += 1; 848*6212Saw148015 849*6212Saw148015 if ((var = var_find(name)) == NULL) 850*6212Saw148015 var = var_find_dynamic(name); 851*6212Saw148015 852*6212Saw148015 if ((var != NULL) && VAR_HAS_BOOLEAN(var)) 853*6212Saw148015 return (var->var_val.boolean); 854*6212Saw148015 855*6212Saw148015 filebench_log(LOG_ERROR, 856*6212Saw148015 "Variable %s referenced before set", name); 857*6212Saw148015 858*6212Saw148015 return (0); 859*6212Saw148015 } 860*6212Saw148015 861*6212Saw148015 /* 862*6212Saw148015 * Searches for the named var, and if found returns the value, 863*6212Saw148015 * of var_val.integer. If the var is not found, or the an 864*6212Saw148015 * integer value has not been set, logs an error and returns 0. 865*6212Saw148015 */ 866*6212Saw148015 fbint_t 8675184Sek110237 var_to_integer(char *name) 8685184Sek110237 { 8695184Sek110237 var_t *var; 8705184Sek110237 8715184Sek110237 name += 1; 8725184Sek110237 8735184Sek110237 if ((var = var_find(name)) == NULL) 8745184Sek110237 var = var_find_dynamic(name); 8755184Sek110237 876*6212Saw148015 if ((var != NULL) && VAR_HAS_INTEGER(var)) 877*6212Saw148015 return (var->var_val.integer); 8785184Sek110237 8795184Sek110237 filebench_log(LOG_ERROR, 8805184Sek110237 "Variable %s referenced before set", name); 8815184Sek110237 8825184Sek110237 return (0); 8835184Sek110237 } 8845184Sek110237 8855184Sek110237 /* 886*6212Saw148015 * Searches for the named random var, and if found, converts the 887*6212Saw148015 * requested parameter into a string or a decimal number string 888*6212Saw148015 * representation, into a malloc'd bit of memory using fb_stralloc(). 889*6212Saw148015 * Returns a pointer to the created string, or calls var_to_string() 890*6212Saw148015 * if a random variable isn't found. 891*6212Saw148015 */ 892*6212Saw148015 char * 893*6212Saw148015 var_randvar_to_string(char *name, int param_name) 894*6212Saw148015 { 895*6212Saw148015 var_t *var; 896*6212Saw148015 fbint_t value; 897*6212Saw148015 898*6212Saw148015 if ((var = var_find(name + 1)) == NULL) 899*6212Saw148015 return (var_to_string(name)); 900*6212Saw148015 901*6212Saw148015 if (((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) || 902*6212Saw148015 !VAR_HAS_RANDDIST(var)) 903*6212Saw148015 return (var_to_string(name)); 904*6212Saw148015 905*6212Saw148015 switch (param_name) { 906*6212Saw148015 case RAND_PARAM_TYPE: 907*6212Saw148015 switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) { 908*6212Saw148015 case RAND_TYPE_UNIFORM: 909*6212Saw148015 return (fb_stralloc("uniform")); 910*6212Saw148015 case RAND_TYPE_GAMMA: 911*6212Saw148015 return (fb_stralloc("gamma")); 912*6212Saw148015 case RAND_TYPE_TABLE: 913*6212Saw148015 return (fb_stralloc("tabular")); 914*6212Saw148015 default: 915*6212Saw148015 return (fb_stralloc("uninitialized")); 916*6212Saw148015 } 917*6212Saw148015 918*6212Saw148015 case RAND_PARAM_SRC: 919*6212Saw148015 if (var->var_val.randptr->rnd_type & RAND_SRC_GENERATOR) 920*6212Saw148015 return (fb_stralloc("rand48")); 921*6212Saw148015 else 922*6212Saw148015 return (fb_stralloc("urandom")); 923*6212Saw148015 924*6212Saw148015 case RAND_PARAM_SEED: 925*6212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_seed); 926*6212Saw148015 break; 927*6212Saw148015 928*6212Saw148015 case RAND_PARAM_MIN: 929*6212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_min); 930*6212Saw148015 break; 931*6212Saw148015 932*6212Saw148015 case RAND_PARAM_MEAN: 933*6212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_mean); 934*6212Saw148015 break; 935*6212Saw148015 936*6212Saw148015 case RAND_PARAM_GAMMA: 937*6212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_gamma); 938*6212Saw148015 break; 939*6212Saw148015 940*6212Saw148015 case RAND_PARAM_ROUND: 941*6212Saw148015 value = avd_get_int(var->var_val.randptr->rnd_round); 942*6212Saw148015 break; 943*6212Saw148015 944*6212Saw148015 default: 945*6212Saw148015 return (NULL); 946*6212Saw148015 947*6212Saw148015 } 948*6212Saw148015 949*6212Saw148015 /* just an integer value if we got here */ 950*6212Saw148015 { 951*6212Saw148015 char tmp[128]; 952*6212Saw148015 953*6212Saw148015 (void) snprintf(tmp, sizeof (tmp), "%lld", value); 954*6212Saw148015 return (fb_stralloc(tmp)); 955*6212Saw148015 } 956*6212Saw148015 } 957*6212Saw148015 958*6212Saw148015 /* 9595184Sek110237 * Searches for the var named "name", and if not found 9605184Sek110237 * allocates it. The then extracts the var_string from 9615184Sek110237 * the var named "string" and copies it into the var_string 9625184Sek110237 * of the var "name", after first allocating a piece of 9635184Sek110237 * interprocess shared string memory. If the var "name" 9645184Sek110237 * cannot be found or allocated, or the var "string" cannot 9655184Sek110237 * be found, the routine returns -1, otherwise it returns 0. 9665184Sek110237 */ 9675184Sek110237 int 968*6212Saw148015 var_assign_var(char *name, char *src_name) 9695184Sek110237 { 970*6212Saw148015 var_t *dst_var, *src_var; 9715184Sek110237 9725184Sek110237 name += 1; 973*6212Saw148015 src_name += 1; 9745184Sek110237 975*6212Saw148015 if ((src_var = var_find(src_name)) == NULL) { 976*6212Saw148015 filebench_log(LOG_ERROR, 977*6212Saw148015 "Cannot find source variable %s", src_name); 978*6212Saw148015 return (-1); 979*6212Saw148015 } 9805184Sek110237 981*6212Saw148015 if ((dst_var = var_find(name)) == NULL) 982*6212Saw148015 dst_var = var_alloc(name); 983*6212Saw148015 984*6212Saw148015 if (dst_var == NULL) { 9855184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 9865184Sek110237 name); 9875184Sek110237 return (-1); 9885184Sek110237 } 9895184Sek110237 990*6212Saw148015 if ((dst_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 991*6212Saw148015 filebench_log(LOG_ERROR, 992*6212Saw148015 "Cannot assign var to Random variable %s", name); 9935184Sek110237 return (-1); 9945184Sek110237 } 995*6212Saw148015 996*6212Saw148015 if (VAR_HAS_BOOLEAN(src_var)) { 997*6212Saw148015 VAR_SET_BOOL(dst_var, src_var->var_val.boolean); 998*6212Saw148015 filebench_log(LOG_VERBOSE, 999*6212Saw148015 "Assign var %s=%d", name, src_var->var_val.boolean); 1000*6212Saw148015 } 1001*6212Saw148015 1002*6212Saw148015 if (VAR_HAS_INTEGER(src_var)) { 1003*6212Saw148015 VAR_SET_INT(dst_var, src_var->var_val.integer); 1004*6212Saw148015 filebench_log(LOG_VERBOSE, 1005*6212Saw148015 "Assign var %s=%lld", name, src_var->var_val.integer); 1006*6212Saw148015 } 1007*6212Saw148015 1008*6212Saw148015 if (VAR_HAS_DOUBLE(src_var)) { 1009*6212Saw148015 VAR_SET_DBL(dst_var, src_var->var_val.dbl_flt); 1010*6212Saw148015 filebench_log(LOG_VERBOSE, 1011*6212Saw148015 "Assign var %s=%lf", name, src_var->var_val.dbl_flt); 1012*6212Saw148015 } 1013*6212Saw148015 1014*6212Saw148015 if (VAR_HAS_STRING(src_var)) { 1015*6212Saw148015 char *strptr; 1016*6212Saw148015 1017*6212Saw148015 if ((strptr = 1018*6212Saw148015 ipc_stralloc(src_var->var_val.string)) == NULL) { 1019*6212Saw148015 filebench_log(LOG_ERROR, 1020*6212Saw148015 "Cannot assign variable %s", 1021*6212Saw148015 name); 1022*6212Saw148015 return (-1); 1023*6212Saw148015 } 1024*6212Saw148015 VAR_SET_STR(dst_var, strptr); 1025*6212Saw148015 filebench_log(LOG_VERBOSE, 1026*6212Saw148015 "Assign var %s=%s", name, src_var->var_val.string); 1027*6212Saw148015 } 10285184Sek110237 return (0); 10295184Sek110237 } 10305184Sek110237 10315184Sek110237 /* 10325184Sek110237 * Like var_assign_integer, only this routine copies the 10335184Sek110237 * supplied "string" into the var named "name". If the var 10345184Sek110237 * named "name" cannot be found then it is first allocated 10355184Sek110237 * before the copy. Space for the string in the var comes 10365184Sek110237 * from interprocess shared memory. If the var "name" 10375184Sek110237 * cannot be found or allocated, or the memory for the 10385184Sek110237 * var_string copy of "string" cannot be allocated, the 10395184Sek110237 * routine returns -1, otherwise it returns 0. 10405184Sek110237 */ 10415184Sek110237 int 10425184Sek110237 var_assign_string(char *name, char *string) 10435184Sek110237 { 10445184Sek110237 var_t *var; 1045*6212Saw148015 char *strptr; 10465184Sek110237 10475184Sek110237 name += 1; 10485184Sek110237 10495184Sek110237 if ((var = var_find(name)) == NULL) 10505184Sek110237 var = var_alloc(name); 10515184Sek110237 10525184Sek110237 if (var == NULL) { 10535184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 10545184Sek110237 name); 10555184Sek110237 return (-1); 10565184Sek110237 } 10575184Sek110237 1058*6212Saw148015 if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) { 1059*6212Saw148015 filebench_log(LOG_ERROR, 1060*6212Saw148015 "Cannot assign string to random variable %s", name); 1061*6212Saw148015 return (-1); 1062*6212Saw148015 } 1063*6212Saw148015 1064*6212Saw148015 if ((strptr = ipc_stralloc(string)) == NULL) { 10655184Sek110237 filebench_log(LOG_ERROR, "Cannot assign variable %s", 10665184Sek110237 name); 10675184Sek110237 return (-1); 10685184Sek110237 } 1069*6212Saw148015 VAR_SET_STR(var, strptr); 10705184Sek110237 1071*6212Saw148015 filebench_log(LOG_DEBUG_SCRIPT, 1072*6212Saw148015 "Var assign string $%s=%s", name, string); 10735184Sek110237 10745184Sek110237 return (0); 10755184Sek110237 } 10765184Sek110237 10775184Sek110237 /* 1078*6212Saw148015 * Tests to see if the supplied variable name without the portion after 1079*6212Saw148015 * the last period is that of a random variable. If it is, it returns 1080*6212Saw148015 * the number of characters to backspace to skip the period and field 1081*6212Saw148015 * name. Otherwise it returns 0. 10825184Sek110237 */ 1083*6212Saw148015 int 1084*6212Saw148015 var_is_set4_randvar(char *name) 10855184Sek110237 { 10865184Sek110237 var_t *var; 1087*6212Saw148015 char varname[128]; 1088*6212Saw148015 int namelength; 1089*6212Saw148015 char *sp; 10905184Sek110237 1091*6212Saw148015 (void) strncpy(varname, name, 128); 1092*6212Saw148015 namelength = strlen(varname); 1093*6212Saw148015 sp = varname + namelength; 10945184Sek110237 1095*6212Saw148015 while (sp != varname) { 1096*6212Saw148015 int c = *sp; 10975184Sek110237 1098*6212Saw148015 *sp = 0; 1099*6212Saw148015 if (c == '.') 1100*6212Saw148015 break; 1101*6212Saw148015 1102*6212Saw148015 sp--; 11035184Sek110237 } 11045184Sek110237 1105*6212Saw148015 /* not a variable name + field? */ 1106*6212Saw148015 if (sp == varname) 1107*6212Saw148015 return (0); 1108*6212Saw148015 1109*6212Saw148015 /* first part not a variable name? */ 1110*6212Saw148015 if ((var = var_find(varname+1)) == NULL) 1111*6212Saw148015 return (0); 1112*6212Saw148015 1113*6212Saw148015 /* Make sure it is a random variable */ 1114*6212Saw148015 if ((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) 1115*6212Saw148015 return (0); 1116*6212Saw148015 1117*6212Saw148015 /* calculate offset from end of random variable name */ 1118*6212Saw148015 return (namelength - (sp - varname)); 11195184Sek110237 } 11205184Sek110237 11215184Sek110237 /* 11225184Sek110237 * Implements a simple path name like scheme for finding values 11235184Sek110237 * to place in certain specially named vars. The first part of 11245184Sek110237 * the name is interpreted as a category of either: stats, 11255184Sek110237 * eventgen, date, script, or host var. If a match is found, 11265184Sek110237 * the appropriate routine is called to fill in the requested 11275184Sek110237 * value in the provided var_t, and a pointer to the supplied 11285184Sek110237 * var_t is returned. If the requested value is not found, NULL 11295184Sek110237 * is returned. 11305184Sek110237 */ 11315184Sek110237 static var_t * 11325184Sek110237 var_find_internal(var_t *var) 11335184Sek110237 { 11345184Sek110237 char *n = fb_stralloc(var->var_name); 11355184Sek110237 char *name = n; 11365184Sek110237 var_t *rtn = NULL; 11375184Sek110237 11385184Sek110237 name++; 11395184Sek110237 if (name[strlen(name) - 1] != '}') 11405184Sek110237 return (NULL); 11415184Sek110237 name[strlen(name) - 1] = 0; 11425184Sek110237 11435184Sek110237 if (strncmp(name, STATS_VAR, strlen(STATS_VAR)) == 0) 11445184Sek110237 rtn = stats_findvar(var, name + strlen(STATS_VAR)); 11455184Sek110237 11465184Sek110237 if (strcmp(name, EVENTGEN_VAR) == 0) 11475184Sek110237 rtn = eventgen_ratevar(var); 11485184Sek110237 11495184Sek110237 if (strcmp(name, DATE_VAR) == 0) 11505184Sek110237 rtn = date_var(var); 11515184Sek110237 11525184Sek110237 if (strcmp(name, SCRIPT_VAR) == 0) 11535184Sek110237 rtn = script_var(var); 11545184Sek110237 11555184Sek110237 if (strcmp(name, HOST_VAR) == 0) 11565184Sek110237 rtn = host_var(var); 11575184Sek110237 11585184Sek110237 free(n); 11595184Sek110237 11605184Sek110237 return (rtn); 11615184Sek110237 } 11625184Sek110237 11635184Sek110237 /* 11645184Sek110237 * Calls the C library routine getenv() to obtain the value 11655184Sek110237 * for the environment variable specified by var->var_name. 1166*6212Saw148015 * If found, the value string is returned in var->var_val.string. 11675184Sek110237 * If the requested value is not found, NULL is returned. 11685184Sek110237 */ 11695184Sek110237 static var_t * 11705184Sek110237 var_find_environment(var_t *var) 11715184Sek110237 { 11725184Sek110237 char *n = fb_stralloc(var->var_name); 11735184Sek110237 char *name = n; 1174*6212Saw148015 char *strptr; 11755184Sek110237 11765184Sek110237 name++; 1177*6212Saw148015 if (name[strlen(name) - 1] != ')') { 1178*6212Saw148015 free(n); 11795184Sek110237 return (NULL); 1180*6212Saw148015 } 11815184Sek110237 name[strlen(name) - 1] = 0; 11825184Sek110237 1183*6212Saw148015 if ((strptr = getenv(name)) != NULL) { 11845184Sek110237 free(n); 1185*6212Saw148015 VAR_SET_STR(var, strptr); 11865184Sek110237 return (var); 11875184Sek110237 } else { 11885184Sek110237 free(n); 11895184Sek110237 return (NULL); 11905184Sek110237 } 11915184Sek110237 } 11925184Sek110237 11935184Sek110237 /* 11945184Sek110237 * Look up special variables. The "name" argument is used to find 11955184Sek110237 * the desired special var and fill it with an appropriate string 11965184Sek110237 * value. Looks for an already allocated var of the same name on 11975184Sek110237 * the var_dyn_list. If not found a new dynamic var is allocated. 11985184Sek110237 * if the name begins with '{', it is an internal variable, and 11995184Sek110237 * var_find_internal() is called. If the name begins with '(' it 12005184Sek110237 * is an environment varable, and var_find_environment() is 12015184Sek110237 * called. On success, a pointer to the var_t is returned, 12025184Sek110237 * otherwise, NULL is returned. 12035184Sek110237 */ 12045184Sek110237 static var_t * 12055184Sek110237 var_find_dynamic(char *name) 12065184Sek110237 { 12075184Sek110237 var_t *var = NULL; 12085184Sek110237 var_t *v = filebench_shm->var_dyn_list; 12095184Sek110237 var_t *rtn; 12105184Sek110237 12115184Sek110237 /* 12125184Sek110237 * Lookup a reference to the var handle for this 12135184Sek110237 * special var 12145184Sek110237 */ 12155184Sek110237 for (v = filebench_shm->var_dyn_list; v != NULL; v = v->var_next) { 12165184Sek110237 if (strcmp(v->var_name, name) == 0) { 12175184Sek110237 var = v; 12185184Sek110237 break; 12195184Sek110237 } 12205184Sek110237 } 12215184Sek110237 12225184Sek110237 if (var == NULL) 12235184Sek110237 var = var_alloc_dynamic(name); 12245184Sek110237 12255184Sek110237 /* Internal system control variable */ 12265184Sek110237 if (*name == '{') { 12275184Sek110237 rtn = var_find_internal(var); 12285184Sek110237 if (rtn == NULL) 12295184Sek110237 filebench_log(LOG_ERROR, 12305184Sek110237 "Cannot find internal variable %s", 12315184Sek110237 var->var_name); 12325184Sek110237 return (rtn); 12335184Sek110237 } 12345184Sek110237 12355184Sek110237 /* Lookup variable in environment */ 12365184Sek110237 if (*name == '(') { 12375184Sek110237 rtn = var_find_environment(var); 12385184Sek110237 if (rtn == NULL) 12395184Sek110237 filebench_log(LOG_ERROR, 12405184Sek110237 "Cannot find environment variable %s", 12415184Sek110237 var->var_name); 12425184Sek110237 return (rtn); 12435184Sek110237 } 12445184Sek110237 12455184Sek110237 return (NULL); 12465184Sek110237 } 1247