summaryrefslogtreecommitdiff
path: root/usr/src/cmd/filebench/common/vars.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/filebench/common/vars.c')
-rw-r--r--usr/src/cmd/filebench/common/vars.c965
1 files changed, 832 insertions, 133 deletions
diff --git a/usr/src/cmd/filebench/common/vars.c b/usr/src/cmd/filebench/common/vars.c
index 6145547cff..ae00ee53f9 100644
--- a/usr/src/cmd/filebench/common/vars.c
+++ b/usr/src/cmd/filebench/common/vars.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -36,84 +36,466 @@
#include "stats.h"
#include "eventgen.h"
#include "filebench.h"
+#include "fb_random.h"
static var_t *var_find_dynamic(char *name);
/*
- * The filebench variables consist of var_integers (var_integer_t)
- * and var_strings (var_string_t), which are pointers to integers and
- * strings respectively, and vars (var_t), which are named, typed
- * entities which contain either an integer or a string and can be
- * placed on a linked list. All three of these objects are allocated
+ * The filebench variables system has attribute value descriptors (avd_t)
+ * where an avd contains a boolean, integer, double, string, random
+ * distribution object ptr, boolean ptr, integer ptr, double ptr,
+ * string ptr, or variable ptr. The system also has the variables
+ * themselves, (var_t), which are named, typed entities which can be
+ * allocated, selected and changed using the "set" command and used in
+ * attribute assignments. The variables contain either a boolean, an
+ * integer, a double, a string or pointer to an associated random
+ * distribution object. Both avd_t and var_t entities are allocated
* from interprocess shared memory space.
*
+ * The attribute descriptors implement delayed binding to variable values,
+ * which is necessary because the values of variables may be changed
+ * between the time the workload file is loaded and it is actually run,
+ * either by further "set" commands in the file or from the command line
+ * interface. For random variables, they actually point to the random
+ * distribution object, allowing FileBench to invoke the appropriate
+ * random distribution function on each access to the attribute. However,
+ * for static attributes, the value is just loaded in the descriptor
+ * directly, avoiding the need to allocate a variable to hold the static
+ * value.
+ *
* The routines in this module are used to allocate, locate, and
- * manipulate the var_integers, var_strings, and vars. Routines are
- * also included to convert between the component strings and integers
- * of vars, and var_strings and var_integers.
+ * manipulate the attribute descriptors, and vars. Routines are
+ * also included to convert between the component strings, doubles
+ * and integers of vars, and said components of avd_t.
*/
/*
- * Returns the int pointed to by the supplied var_integer_t "v".
+ * returns a pointer to a string indicating the type of data contained
+ * in the supplied attribute variable descriptor.
*/
-int
-integer_isset(var_integer_t v)
+static char *
+avd_get_type_string(avd_t avd)
+{
+ switch (avd->avd_type) {
+ case AVD_INVALID:
+ return ("uninitialized");
+
+ case AVD_VAL_BOOL:
+ return ("boolean value");
+
+ case AVD_VARVAL_BOOL:
+ return ("points to boolean in var_t");
+
+ case AVD_VAL_INT:
+ return ("integer value");
+
+ case AVD_VARVAL_INT:
+ return ("points to integer in var_t");
+
+ case AVD_VAL_STR:
+ return ("string");
+
+ case AVD_VARVAL_STR:
+ return ("points to string in var_t");
+
+ case AVD_VAL_DBL:
+ return ("double float value");
+
+ case AVD_VARVAL_DBL:
+ return ("points to double float in var_t");
+
+ case AVD_IND_VAR:
+ return ("points to a var_t");
+
+ case AVD_IND_RANDVAR:
+ return ("points to var_t's random distribution object");
+
+ default:
+ return ("illegal avd type");
+ }
+}
+
+/*
+ * returns a pointer to a string indicating the type of data contained
+ * in the supplied variable.
+ */
+static char *
+var_get_type_string(var_t *ivp)
+{
+ switch (ivp->var_type & VAR_TYPE_SET_MASK) {
+ case VAR_TYPE_BOOL_SET:
+ return ("boolean");
+
+ case VAR_TYPE_INT_SET:
+ return ("integer");
+
+ case VAR_TYPE_STR_SET:
+ return ("string");
+
+ case VAR_TYPE_DBL_SET:
+ return ("double float");
+
+ case VAR_TYPE_RAND_SET:
+ return ("random");
+
+ default:
+ return ("empty");
+ }
+}
+
+/*
+ * Returns the fbint_t pointed to by the supplied avd_t "avd".
+ */
+fbint_t
+avd_get_int(avd_t avd)
+{
+ var_t *ivp;
+ randdist_t *rndp;
+
+ if (avd == NULL)
+ return (0);
+
+ switch (avd->avd_type) {
+ case AVD_VAL_INT:
+ return (avd->avd_val.intval);
+
+ case AVD_VARVAL_INT:
+ if (avd->avd_val.intptr)
+ return (*(avd->avd_val.intptr));
+ else
+ return (0);
+
+ case AVD_IND_VAR:
+ if ((ivp = avd->avd_val.varptr) == NULL)
+ return (0);
+
+ if (VAR_HAS_INTEGER(ivp))
+ return (ivp->var_val.integer);
+
+ if (VAR_HAS_RANDDIST(ivp)) {
+ if ((rndp = ivp->var_val.randptr) != NULL)
+ return ((fbint_t)rndp->rnd_get(rndp));
+ }
+
+ filebench_log(LOG_ERROR,
+ "Attempt to get integer from %s var $%s",
+ var_get_type_string(ivp), ivp->var_name);
+ return (0);
+
+ case AVD_IND_RANDVAR:
+ if ((rndp = avd->avd_val.randptr) == NULL)
+ return (0);
+ else
+ return ((fbint_t)rndp->rnd_get(rndp));
+
+ default:
+ filebench_log(LOG_ERROR,
+ "Attempt to get integer from %s avd",
+ avd_get_type_string(avd));
+ return (0);
+ }
+}
+
+/*
+ * Returns the floating point value of a variable pointed to by the
+ * supplied avd_t "avd". Intended to get the actual (double) value
+ * supplied by the random variable.
+ */
+double
+avd_get_dbl(avd_t avd)
{
- if (v == NULL)
+ var_t *ivp;
+ randdist_t *rndp;
+
+ if (avd == NULL)
+ return (0.0);
+
+ switch (avd->avd_type) {
+ case AVD_VAL_INT:
+ return ((double)avd->avd_val.intval);
+
+ case AVD_VAL_DBL:
+ return (avd->avd_val.dblval);
+
+ case AVD_VARVAL_INT:
+ if (avd->avd_val.intptr)
+ return ((double)(*(avd->avd_val.intptr)));
+ else
+ return (0.0);
+
+ case AVD_VARVAL_DBL:
+ if (avd->avd_val.dblptr)
+ return (*(avd->avd_val.dblptr));
+ else
+ return (0.0);
+
+ case AVD_IND_VAR:
+ ivp = avd->avd_val.varptr;
+
+ if (ivp && VAR_HAS_INTEGER(ivp))
+ return ((double)ivp->var_val.integer);
+
+ if (ivp && VAR_HAS_DOUBLE(ivp))
+ return (ivp->var_val.dbl_flt);
+
+ if (ivp && VAR_HAS_RANDDIST(ivp)) {
+ if ((rndp = ivp->var_val.randptr) != NULL)
+ return (rndp->rnd_get(rndp));
+ }
+ filebench_log(LOG_ERROR,
+ "Attempt to get double float from %s var $%s",
+ var_get_type_string(ivp), ivp->var_name);
+ return (0.0);
+
+ case AVD_IND_RANDVAR:
+ if ((rndp = avd->avd_val.randptr) == NULL) {
+ return (0.0);
+ } else
+ return (rndp->rnd_get(rndp));
+
+ default:
+ filebench_log(LOG_ERROR,
+ "Attempt to get floating point from %s avd",
+ avd_get_type_string(avd));
+ return (0.0);
+ }
+}
+
+/*
+ * Returns the boolean pointed to by the supplied avd_t "avd".
+ */
+boolean_t
+avd_get_bool(avd_t avd)
+{
+ var_t *ivp;
+
+ if (avd == NULL)
return (0);
- return (*v);
+ switch (avd->avd_type) {
+ case AVD_VAL_BOOL:
+ return (avd->avd_val.boolval);
+
+ case AVD_VARVAL_BOOL:
+ if (avd->avd_val.boolptr)
+ return (*(avd->avd_val.boolptr));
+ else
+ return (FALSE);
+
+ /* for backwards compatibility with old workloads */
+ case AVD_VAL_INT:
+ if (avd->avd_val.intval != 0)
+ return (TRUE);
+ else
+ return (FALSE);
+
+ case AVD_VARVAL_INT:
+ if (avd->avd_val.intptr)
+ if (*(avd->avd_val.intptr) != 0)
+ return (TRUE);
+
+ return (FALSE);
+
+ case AVD_IND_VAR:
+ if ((ivp = avd->avd_val.varptr) == NULL)
+ return (0);
+
+ if (VAR_HAS_BOOLEAN(ivp))
+ return (ivp->var_val.boolean);
+
+ if (VAR_HAS_INTEGER(ivp)) {
+ if (ivp->var_val.boolean)
+ return (TRUE);
+ else
+ return (FALSE);
+ }
+
+ filebench_log(LOG_ERROR,
+ "Attempt to get boolean from %s var $%s",
+ var_get_type_string(ivp), ivp->var_name);
+ return (FALSE);
+
+ default:
+ filebench_log(LOG_ERROR,
+ "Attempt to get boolean from %s avd",
+ avd_get_type_string(avd));
+ return (FALSE);
+ }
}
/*
- * Allocates a var_integer_t from ipc memory space and
- * pre-loads it with the vinteger_t "integer". Returns
- * the var_integer_t on success, NULL on failure.
+ * Returns the string pointed to by the supplied avd_t "avd".
*/
-var_integer_t
-integer_alloc(vinteger_t integer)
+char *
+avd_get_str(avd_t avd)
{
- var_integer_t rtn;
+ var_t *ivp;
+
+ if (avd == NULL)
+ return (NULL);
+
+ switch (avd->avd_type) {
+ case AVD_VAL_STR:
+ return (avd->avd_val.strval);
+
+ case AVD_VARVAL_STR:
+ if (avd->avd_val.strptr)
+ return (*avd->avd_val.strptr);
+ else
+ return (NULL);
+
+ case AVD_IND_VAR:
+ ivp = avd->avd_val.varptr;
+
+ if (ivp && VAR_HAS_STRING(ivp))
+ return (ivp->var_val.string);
- if ((rtn = (vinteger_t *)ipc_malloc(FILEBENCH_INTEGER)) == NULL) {
- filebench_log(LOG_ERROR, "Alloc integer failed");
+ filebench_log(LOG_ERROR,
+ "Attempt to get string from %s var $%s",
+ var_get_type_string(ivp), ivp->var_name);
+ return (NULL);
+
+ default:
+ filebench_log(LOG_ERROR,
+ "Attempt to get string from %s avd",
+ avd_get_type_string(avd));
return (NULL);
}
+}
+
+/*
+ * Allocates a avd_t from ipc memory space.
+ * logs an error and returns NULL on failure.
+ */
+static avd_t
+avd_alloc_cmn(void)
+{
+ avd_t rtn;
+
+ if ((rtn = (avd_t)ipc_malloc(FILEBENCH_AVD)) == NULL)
+ filebench_log(LOG_ERROR, "Avd alloc failed");
+
+ return (rtn);
+}
- *rtn = integer;
+/*
+ * pre-loads the allocated avd_t with the boolean_t "bool".
+ * Returns the avd_t on success, NULL on failure.
+ */
+avd_t
+avd_bool_alloc(boolean_t bool)
+{
+ avd_t avd;
+
+ if ((avd = avd_alloc_cmn()) == NULL)
+ return (NULL);
+
+ avd->avd_type = AVD_VAL_BOOL;
+ avd->avd_val.boolval = bool;
+
+ filebench_log(LOG_DEBUG_IMPL, "Alloc boolean %d", bool);
+
+ return (avd);
+}
+
+/*
+ * pre-loads the allocated avd_t with the fbint_t "integer".
+ * Returns the avd_t on success, NULL on failure.
+ */
+avd_t
+avd_int_alloc(fbint_t integer)
+{
+ avd_t avd;
+
+ if ((avd = avd_alloc_cmn()) == NULL)
+ return (NULL);
+
+ avd->avd_type = AVD_VAL_INT;
+ avd->avd_val.intval = integer;
filebench_log(LOG_DEBUG_IMPL, "Alloc integer %lld", integer);
- return (rtn);
+ return (avd);
+}
+
+/*
+ * Gets a avd_t and points it to the var that
+ * it will eventually be filled from
+ */
+static avd_t
+avd_alloc_var_ptr(var_t *var)
+{
+ avd_t avd;
+
+ if (var == NULL)
+ return (NULL);
+
+ if ((avd = avd_alloc_cmn()) == NULL)
+ return (NULL);
+
+ switch (var->var_type & VAR_TYPE_SET_MASK) {
+ case VAR_TYPE_BOOL_SET:
+ avd->avd_type = AVD_VARVAL_BOOL;
+ avd->avd_val.boolptr = (&var->var_val.boolean);
+ break;
+
+ case VAR_TYPE_INT_SET:
+ avd->avd_type = AVD_VARVAL_INT;
+ avd->avd_val.intptr = (&var->var_val.integer);
+ break;
+
+ case VAR_TYPE_STR_SET:
+ avd->avd_type = AVD_VARVAL_STR;
+ avd->avd_val.strptr = &(var->var_val.string);
+ break;
+
+ case VAR_TYPE_DBL_SET:
+ avd->avd_type = AVD_VARVAL_DBL;
+ avd->avd_val.dblptr = &(var->var_val.dbl_flt);
+ break;
+
+ case VAR_TYPE_RAND_SET:
+ avd->avd_type = AVD_IND_RANDVAR;
+ avd->avd_val.randptr = var->var_val.randptr;
+ break;
+
+ default:
+ avd->avd_type = AVD_IND_VAR;
+ avd->avd_val.varptr = var;
+ break;
+ }
+ return (avd);
}
/*
- * Allocates a string pointer in interprocess shared memory,
- * then allocates and initializes a piece of shared string memory,
- * putting the pointer to it into the just allocated string
- * pointer location. The routine returns a pointer to the
- * string pointer location or returns NULL on error.
+ * Gets a avd_t, then allocates and initializes a piece of
+ * shared string memory, putting the pointer to it into the just
+ * allocated string pointer location. The routine returns a pointer
+ * to the string pointer location or returns NULL on error.
*/
-var_string_t
-string_alloc(char *string)
+avd_t
+avd_str_alloc(char *string)
{
- char **rtn;
+ avd_t avd;
- if ((rtn = (char **)ipc_malloc(FILEBENCH_STRING)) == NULL) {
- filebench_log(LOG_ERROR, "Alloc string failed");
+ if (string == NULL) {
+ filebench_log(LOG_ERROR, "No string supplied\n");
return (NULL);
}
- *rtn = ipc_stralloc(string);
+ if ((avd = avd_alloc_cmn()) == NULL)
+ return (NULL);
+
+ avd->avd_type = AVD_VAL_STR;
+ avd->avd_val.strval = ipc_stralloc(string);
filebench_log(LOG_DEBUG_IMPL,
"Alloc string %s ptr %zx",
- string, rtn);
+ string, avd);
- return (rtn);
+ return (avd);
}
-
/*
* Allocates a var (var_t) from interprocess shared memory.
* Places the allocated var on the end of the globally shared
@@ -123,8 +505,9 @@ string_alloc(char *string)
* newly allocated var.
*/
static var_t *
-var_alloc(char *name)
+var_alloc_cmn(char *name, int var_type)
{
+ var_t **var_listp;
var_t *var = NULL;
var_t *prev = NULL;
var_t *newvar;
@@ -134,60 +517,64 @@ var_alloc(char *name)
return (NULL);
}
(void) memset(newvar, 0, sizeof (newvar));
-
- for (var = filebench_shm->var_list; var != NULL; var = var->var_next)
- prev = var; /* Find end of list */
- if (prev != NULL)
- prev->var_next = newvar;
- else
- filebench_shm->var_list = newvar;
+ newvar->var_type = var_type;
if ((newvar->var_name = ipc_stralloc(name)) == NULL) {
filebench_log(LOG_ERROR, "Out of memory for variables");
return (NULL);
}
- return (newvar);
-}
+ switch (var_type & VAR_TYPE_MASK) {
+ case VAR_TYPE_RANDOM:
+ case VAR_TYPE_GLOBAL:
+ var_listp = &filebench_shm->var_list;
+ break;
-/*
- * Allocates a var (var_t) from interprocess shared memory.
- * Places the allocated var on the end of the globally shared
- * var_dyn_list. Finally, the routine allocates a string
- * containing a copy of the supplied "name" string. If any
- * allocations fails, returns NULL, otherwise it returns a
- * pointer to the newly allocated var.
- */
-static var_t *
-var_alloc_dynamic(char *name)
-{
- var_t *var = NULL;
- var_t *prev = NULL;
- var_t *newvar;
+ case VAR_TYPE_DYNAMIC:
+ var_listp = &filebench_shm->var_dyn_list;
+ break;
- if ((newvar = (var_t *)ipc_malloc(FILEBENCH_VARIABLE)) == NULL) {
- filebench_log(LOG_ERROR, "Out of memory for variables");
- return (NULL);
+ default:
+ var_listp = &filebench_shm->var_list;
+ break;
}
- (void) memset(newvar, 0, sizeof (newvar));
- for (var = filebench_shm->var_dyn_list; var != NULL;
- var = var->var_next)
+ /* add to the end of list */
+ for (var = *var_listp; var != NULL; var = var->var_next)
prev = var; /* Find end of list */
if (prev != NULL)
prev->var_next = newvar;
else
- filebench_shm->var_dyn_list = newvar;
-
- if ((newvar->var_name = ipc_stralloc(name)) == NULL) {
- filebench_log(LOG_ERROR, "Out of memory for variables");
- return (NULL);
- }
+ *var_listp = newvar;
return (newvar);
}
/*
+ * Allocates a var (var_t) from interprocess shared memory and
+ * places the allocated var on the end of the globally shared
+ * var_list. If the allocation fails, returns NULL, otherwise
+ * it returns a pointer to the newly allocated var.
+ */
+static var_t *
+var_alloc(char *name)
+{
+ return (var_alloc_cmn(name, VAR_TYPE_GLOBAL));
+}
+
+/*
+ * Allocates a var (var_t) from interprocess shared memory.
+ * Places the allocated var on the end of the globally shared
+ * var_dyn_list. If the allocation fails, returns NULL, otherwise
+ * it returns a pointer to the newly allocated var.
+ */
+static var_t *
+var_alloc_dynamic(char *name)
+{
+ return (var_alloc_cmn(name, VAR_TYPE_DYNAMIC));
+}
+
+/*
* Searches for var_t with name "name" in the master var_list.
* If successful, returns a pointer to the var_t, otherwise
* returns NULL.
@@ -207,21 +594,73 @@ var_find(char *name)
/*
* Searches for the named var, and, if found, sets its
+ * var_val.boolean's value to that of the supplied boolean.
+ * If not found, the routine allocates a new var and sets
+ * its var_val.boolean's value to that of the supplied
+ * boolean. If the named var cannot be found or allocated
+ * the routine returns -1, otherwise it returns 0.
+ */
+int
+var_assign_boolean(char *name, boolean_t bool)
+{
+ var_t *var;
+
+ if (name == NULL) {
+ filebench_log(LOG_ERROR,
+ "var_assign_boolean: Name not supplied");
+ return (0);
+ }
+
+ name += 1;
+
+ if ((var = var_find(name)) == NULL) {
+ var = var_alloc(name);
+ }
+
+ if (var == NULL) {
+ filebench_log(LOG_ERROR, "Cannot assign variable %s",
+ name);
+ return (-1);
+ }
+
+ if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
+ filebench_log(LOG_ERROR,
+ "Cannot assign integer to random variable %s", name);
+ return (-1);
+ }
+
+ VAR_SET_BOOL(var, bool);
+
+ filebench_log(LOG_DEBUG_SCRIPT, "Assign boolean %s=%d",
+ name, bool);
+
+ return (0);
+}
+
+/*
+ * Searches for the named var, and, if found, sets its
* var_integer's value to that of the supplied integer.
* If not found, the routine allocates a new var and sets
* its var_integers's value to that of the supplied
* integer. If the named var cannot be found or allocated
- * the routine returns -1, otherwise it returns 0.
+ * the routine returns -1, otherwise it returns 0.
*/
int
-var_assign_integer(char *name, vinteger_t integer)
+var_assign_integer(char *name, fbint_t integer)
{
var_t *var;
+ if (name == NULL) {
+ filebench_log(LOG_ERROR,
+ "var_assign_integer: Name not supplied");
+ return (0);
+ }
+
name += 1;
- if ((var = var_find(name)) == NULL)
- var = var_alloc(name);
+ if ((var = var_find(name)) == NULL) {
+ var = var_alloc(name);
+ }
if (var == NULL) {
filebench_log(LOG_ERROR, "Cannot assign variable %s",
@@ -229,7 +668,13 @@ var_assign_integer(char *name, vinteger_t integer)
return (-1);
}
- var->var_integer = integer;
+ if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
+ filebench_log(LOG_ERROR,
+ "Cannot assign integer to random variable %s", name);
+ return (-1);
+ }
+
+ VAR_SET_INT(var, integer);
filebench_log(LOG_DEBUG_SCRIPT, "Assign integer %s=%lld",
name, integer);
@@ -238,14 +683,82 @@ var_assign_integer(char *name, vinteger_t integer)
}
/*
- * Searches for the named var, and if found returns a pointer
- * to the var's var_integer. If not found, attempts to allocate
- * a var named "name" and returns a pointer to it's (zeroed)
- * var_integer. If the var cannot be found or allocated, an
+ * Find a variable, and set it to random type.
+ * If it does not have a random extension, allocate one
+ */
+var_t *
+var_find_randvar(char *name)
+{
+ var_t *newvar;
+
+ name += 1;
+
+ if ((newvar = var_find(name)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "failed to locate random variable $%s\n", name);
+ return (NULL);
+ }
+
+ /* set randdist pointer unless it is already set */
+ if (((newvar->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
+ !VAR_HAS_RANDDIST(newvar)) {
+ filebench_log(LOG_ERROR,
+ "Found variable $%s not random\n", name);
+ return (NULL);
+ }
+
+ return (newvar);
+}
+
+/*
+ * Allocate a variable, and set it to random type. Then
+ * allocate a random extension.
+ */
+var_t *
+var_define_randvar(char *name)
+{
+ var_t *newvar;
+ randdist_t *rndp = NULL;
+
+ name += 1;
+
+ /* make sure variable doesn't already exist */
+ if (var_find(name) != NULL) {
+ filebench_log(LOG_ERROR,
+ "variable name already in use\n");
+ return (NULL);
+ }
+
+ /* allocate a random variable */
+ if ((newvar = var_alloc_cmn(name, VAR_TYPE_RANDOM)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "failed to alloc random variable\n");
+ return (NULL);
+ }
+
+ /* set randdist pointer */
+ if ((rndp = randdist_alloc()) == NULL) {
+ filebench_log(LOG_ERROR,
+ "failed to alloc random distribution object\n");
+ return (NULL);
+ }
+
+ rndp->rnd_var = newvar;
+ VAR_SET_RAND(newvar, rndp);
+
+ return (newvar);
+}
+
+/*
+ * Searches for the named var, and if found returns an avd_t
+ * pointing to the var's var_integer, var_string or var_double
+ * as appropriate. If not found, attempts to allocate
+ * a var named "name" and returns an avd_t to it with
+ * no value set. If the var cannot be found or allocated, an
* error is logged and the run is terminated.
*/
-vinteger_t *
-var_ref_integer(char *name)
+avd_t
+var_ref_attr(char *name)
{
var_t *var;
@@ -263,14 +776,16 @@ var_ref_integer(char *name)
filebench_shutdown(1);
}
- return (&var->var_integer);
-
+ /* allocate pointer to var and return */
+ return (avd_alloc_var_ptr(var));
}
+
/*
- * Searches for the named var, and if found copies the var_string,
- * if it exists, or a decimal number string representation of
- * var_integer, into a malloc'd bit of memory using fb_stralloc().
+ * Searches for the named var, and if found copies the var_val.string,
+ * if it exists, a decimal number string representation of
+ * var_val.integer, the state of var_val.boolean, or the type of random
+ * distribution employed, into a malloc'd bit of memory using fb_stralloc().
* Returns a pointer to the created string, or NULL on failure.
*/
char *
@@ -287,20 +802,68 @@ var_to_string(char *name)
if (var == NULL)
return (NULL);
- if (var->var_string)
- return (fb_stralloc(var->var_string));
+ if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
+ switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
+ case RAND_TYPE_UNIFORM:
+ return (fb_stralloc("uniform random var"));
+ case RAND_TYPE_GAMMA:
+ return (fb_stralloc("gamma random var"));
+ case RAND_TYPE_TABLE:
+ return (fb_stralloc("tabular random var"));
+ default:
+ return (fb_stralloc("unitialized random var"));
+ }
+ }
+
+ if (VAR_HAS_STRING(var) && var->var_val.string)
+ return (fb_stralloc(var->var_val.string));
- (void) snprintf(tmp, sizeof (tmp), "%lld", var->var_integer);
+ if (VAR_HAS_BOOLEAN(var)) {
+ if (var->var_val.boolean)
+ return (fb_stralloc("true"));
+ else
+ return (fb_stralloc("false"));
+ }
+
+ if (VAR_HAS_INTEGER(var)) {
+ (void) snprintf(tmp, sizeof (tmp), "%lld",
+ var->var_val.integer);
+ return (fb_stralloc(tmp));
+ }
- return (fb_stralloc(tmp));
+ return (fb_stralloc("No default"));
}
/*
* Searches for the named var, and if found returns the value,
- * of var_integer. If the var is not found, or the var_integer's
- * value is 0, logs an error and returns 0.
+ * of var_val.boolean. If the var is not found, or a boolean
+ * value has not been set, logs an error and returns 0.
*/
-vinteger_t
+boolean_t
+var_to_boolean(char *name)
+{
+ var_t *var;
+
+ name += 1;
+
+ if ((var = var_find(name)) == NULL)
+ var = var_find_dynamic(name);
+
+ if ((var != NULL) && VAR_HAS_BOOLEAN(var))
+ return (var->var_val.boolean);
+
+ filebench_log(LOG_ERROR,
+ "Variable %s referenced before set", name);
+
+ return (0);
+}
+
+/*
+ * Searches for the named var, and if found returns the value,
+ * of var_val.integer. If the var is not found, or the an
+ * integer value has not been set, logs an error and returns 0.
+ */
+fbint_t
var_to_integer(char *name)
{
var_t *var;
@@ -310,8 +873,8 @@ var_to_integer(char *name)
if ((var = var_find(name)) == NULL)
var = var_find_dynamic(name);
- if ((var != NULL) && (var->var_integer))
- return (var->var_integer);
+ if ((var != NULL) && VAR_HAS_INTEGER(var))
+ return (var->var_val.integer);
filebench_log(LOG_ERROR,
"Variable %s referenced before set", name);
@@ -320,6 +883,79 @@ var_to_integer(char *name)
}
/*
+ * Searches for the named random var, and if found, converts the
+ * requested parameter into a string or a decimal number string
+ * representation, into a malloc'd bit of memory using fb_stralloc().
+ * Returns a pointer to the created string, or calls var_to_string()
+ * if a random variable isn't found.
+ */
+char *
+var_randvar_to_string(char *name, int param_name)
+{
+ var_t *var;
+ fbint_t value;
+
+ if ((var = var_find(name + 1)) == NULL)
+ return (var_to_string(name));
+
+ if (((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM) ||
+ !VAR_HAS_RANDDIST(var))
+ return (var_to_string(name));
+
+ switch (param_name) {
+ case RAND_PARAM_TYPE:
+ switch (var->var_val.randptr->rnd_type & RAND_TYPE_MASK) {
+ case RAND_TYPE_UNIFORM:
+ return (fb_stralloc("uniform"));
+ case RAND_TYPE_GAMMA:
+ return (fb_stralloc("gamma"));
+ case RAND_TYPE_TABLE:
+ return (fb_stralloc("tabular"));
+ default:
+ return (fb_stralloc("uninitialized"));
+ }
+
+ case RAND_PARAM_SRC:
+ if (var->var_val.randptr->rnd_type & RAND_SRC_GENERATOR)
+ return (fb_stralloc("rand48"));
+ else
+ return (fb_stralloc("urandom"));
+
+ case RAND_PARAM_SEED:
+ value = avd_get_int(var->var_val.randptr->rnd_seed);
+ break;
+
+ case RAND_PARAM_MIN:
+ value = avd_get_int(var->var_val.randptr->rnd_min);
+ break;
+
+ case RAND_PARAM_MEAN:
+ value = avd_get_int(var->var_val.randptr->rnd_mean);
+ break;
+
+ case RAND_PARAM_GAMMA:
+ value = avd_get_int(var->var_val.randptr->rnd_gamma);
+ break;
+
+ case RAND_PARAM_ROUND:
+ value = avd_get_int(var->var_val.randptr->rnd_round);
+ break;
+
+ default:
+ return (NULL);
+
+ }
+
+ /* just an integer value if we got here */
+ {
+ char tmp[128];
+
+ (void) snprintf(tmp, sizeof (tmp), "%lld", value);
+ return (fb_stralloc(tmp));
+ }
+}
+
+/*
* Searches for the var named "name", and if not found
* allocates it. The then extracts the var_string from
* the var named "string" and copies it into the var_string
@@ -329,31 +965,66 @@ var_to_integer(char *name)
* be found, the routine returns -1, otherwise it returns 0.
*/
int
-var_assign_var(char *name, char *string)
+var_assign_var(char *name, char *src_name)
{
- var_t *var;
- var_string_t str;
+ var_t *dst_var, *src_var;
name += 1;
+ src_name += 1;
- if ((var = var_find(name)) == NULL)
- var = var_alloc(name);
+ if ((src_var = var_find(src_name)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "Cannot find source variable %s", src_name);
+ return (-1);
+ }
- if (var == NULL) {
+ if ((dst_var = var_find(name)) == NULL)
+ dst_var = var_alloc(name);
+
+ if (dst_var == NULL) {
filebench_log(LOG_ERROR, "Cannot assign variable %s",
name);
return (-1);
}
- if ((str = var_ref_string(string)) == NULL)
+ if ((dst_var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
+ filebench_log(LOG_ERROR,
+ "Cannot assign var to Random variable %s", name);
return (-1);
+ }
- if ((var->var_string = ipc_stralloc(*str)) == NULL) {
- filebench_log(LOG_ERROR, "Cannot assign variable %s",
- name);
- return (-1);
+ if (VAR_HAS_BOOLEAN(src_var)) {
+ VAR_SET_BOOL(dst_var, src_var->var_val.boolean);
+ filebench_log(LOG_VERBOSE,
+ "Assign var %s=%d", name, src_var->var_val.boolean);
+ }
+
+ if (VAR_HAS_INTEGER(src_var)) {
+ VAR_SET_INT(dst_var, src_var->var_val.integer);
+ filebench_log(LOG_VERBOSE,
+ "Assign var %s=%lld", name, src_var->var_val.integer);
+ }
+
+ if (VAR_HAS_DOUBLE(src_var)) {
+ VAR_SET_DBL(dst_var, src_var->var_val.dbl_flt);
+ filebench_log(LOG_VERBOSE,
+ "Assign var %s=%lf", name, src_var->var_val.dbl_flt);
+ }
+
+ if (VAR_HAS_STRING(src_var)) {
+ char *strptr;
+
+ if ((strptr =
+ ipc_stralloc(src_var->var_val.string)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "Cannot assign variable %s",
+ name);
+ return (-1);
+ }
+ VAR_SET_STR(dst_var, strptr);
+ filebench_log(LOG_VERBOSE,
+ "Assign var %s=%s", name, src_var->var_val.string);
}
- filebench_log(LOG_VERBOSE, "Assign string %s=%s", name, string);
return (0);
}
@@ -371,6 +1042,7 @@ int
var_assign_string(char *name, char *string)
{
var_t *var;
+ char *strptr;
name += 1;
@@ -383,44 +1055,67 @@ var_assign_string(char *name, char *string)
return (-1);
}
- if ((var->var_string = ipc_stralloc(string)) == NULL) {
+ if ((var->var_type & VAR_TYPE_MASK) == VAR_TYPE_RANDOM) {
+ filebench_log(LOG_ERROR,
+ "Cannot assign string to random variable %s", name);
+ return (-1);
+ }
+
+ if ((strptr = ipc_stralloc(string)) == NULL) {
filebench_log(LOG_ERROR, "Cannot assign variable %s",
name);
return (-1);
}
+ VAR_SET_STR(var, strptr);
- filebench_log(LOG_DEBUG_SCRIPT, "Assign string %s=%s", name, string);
+ filebench_log(LOG_DEBUG_SCRIPT,
+ "Var assign string $%s=%s", name, string);
return (0);
}
/*
- * Searches for the named var, and if found returns a pointer
- * to the var's var_string. If not found, attempts to allocate
- * a var named "name" and returns a pointer to it's (empty)
- * var_string. If the var cannot be found or allocated, an
- * error is logged and the run is terminated.
+ * Tests to see if the supplied variable name without the portion after
+ * the last period is that of a random variable. If it is, it returns
+ * the number of characters to backspace to skip the period and field
+ * name. Otherwise it returns 0.
*/
-char **
-var_ref_string(char *name)
+int
+var_is_set4_randvar(char *name)
{
var_t *var;
+ char varname[128];
+ int namelength;
+ char *sp;
- name += 1;
+ (void) strncpy(varname, name, 128);
+ namelength = strlen(varname);
+ sp = varname + namelength;
- if ((var = var_find(name)) == NULL)
- var = var_find_dynamic(name);
+ while (sp != varname) {
+ int c = *sp;
- if (var == NULL)
- var = var_alloc(name);
+ *sp = 0;
+ if (c == '.')
+ break;
- if (var == NULL) {
- filebench_log(LOG_ERROR, "Cannot reference variable %s",
- name);
- filebench_shutdown(1);
+ sp--;
}
- return (&var->var_string);
+ /* not a variable name + field? */
+ if (sp == varname)
+ return (0);
+
+ /* first part not a variable name? */
+ if ((var = var_find(varname+1)) == NULL)
+ return (0);
+
+ /* Make sure it is a random variable */
+ if ((var->var_type & VAR_TYPE_MASK) != VAR_TYPE_RANDOM)
+ return (0);
+
+ /* calculate offset from end of random variable name */
+ return (namelength - (sp - varname));
}
/*
@@ -468,7 +1163,7 @@ var_find_internal(var_t *var)
/*
* Calls the C library routine getenv() to obtain the value
* for the environment variable specified by var->var_name.
- * If found, the value string is returned in var->var_string.
+ * If found, the value string is returned in var->var_val.string.
* If the requested value is not found, NULL is returned.
*/
static var_t *
@@ -476,14 +1171,18 @@ var_find_environment(var_t *var)
{
char *n = fb_stralloc(var->var_name);
char *name = n;
+ char *strptr;
name++;
- if (name[strlen(name) - 1] != ')')
+ if (name[strlen(name) - 1] != ')') {
+ free(n);
return (NULL);
+ }
name[strlen(name) - 1] = 0;
- if ((var->var_string = getenv(name)) != NULL) {
+ if ((strptr = getenv(name)) != NULL) {
free(n);
+ VAR_SET_STR(var, strptr);
return (var);
} else {
free(n);