summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authoraw148015 <none@none>2008-03-18 13:52:42 -0700
committeraw148015 <none@none>2008-03-18 13:52:42 -0700
commit1b24378ce424258d555f0363de97728c68c862ce (patch)
treebbe79ddba7d5a5756ae39cbb3069307df2fa962e /usr/src
parent334edc4840d12dfd25a5559468cdd15a375cd111 (diff)
downloadillumos-joyent-1b24378ce424258d555f0363de97728c68c862ce.tar.gz
6627653 FileBench needs to support random variables
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/filebench/Makefile.com3
-rw-r--r--usr/src/cmd/filebench/common/eventgen.c10
-rw-r--r--usr/src/cmd/filebench/common/eventgen.h4
-rw-r--r--usr/src/cmd/filebench/common/fb_random.c435
-rw-r--r--usr/src/cmd/filebench/common/fb_random.h116
-rw-r--r--usr/src/cmd/filebench/common/filebench.h12
-rw-r--r--usr/src/cmd/filebench/common/fileset.c256
-rw-r--r--usr/src/cmd/filebench/common/fileset.h42
-rw-r--r--usr/src/cmd/filebench/common/flowop.c89
-rw-r--r--usr/src/cmd/filebench/common/flowop.h32
-rw-r--r--usr/src/cmd/filebench/common/flowop_library.c341
-rw-r--r--usr/src/cmd/filebench/common/gamma_dist.c65
-rw-r--r--usr/src/cmd/filebench/common/gamma_dist.h4
-rw-r--r--usr/src/cmd/filebench/common/ipc.c50
-rw-r--r--usr/src/cmd/filebench/common/ipc.h25
-rw-r--r--usr/src/cmd/filebench/common/misc.c159
-rw-r--r--usr/src/cmd/filebench/common/parser_gram.y1380
-rw-r--r--usr/src/cmd/filebench/common/parser_lex.l59
-rw-r--r--usr/src/cmd/filebench/common/parsertypes.h14
-rw-r--r--usr/src/cmd/filebench/common/procflow.c15
-rw-r--r--usr/src/cmd/filebench/common/procflow.h9
-rw-r--r--usr/src/cmd/filebench/common/stats.c72
-rw-r--r--usr/src/cmd/filebench/common/threadflow.c23
-rw-r--r--usr/src/cmd/filebench/common/threadflow.h9
-rw-r--r--usr/src/cmd/filebench/common/vars.c965
-rw-r--r--usr/src/cmd/filebench/common/vars.h134
-rw-r--r--usr/src/cmd/filebench/workloads/filemicro_rread.f14
-rw-r--r--usr/src/cmd/filebench/workloads/filemicro_seqwrite.f14
-rw-r--r--usr/src/cmd/filebench/workloads/filemicro_seqwriterandvargam.f63
-rw-r--r--usr/src/cmd/filebench/workloads/filemicro_seqwriterandvartab.f66
30 files changed, 3551 insertions, 929 deletions
diff --git a/usr/src/cmd/filebench/Makefile.com b/usr/src/cmd/filebench/Makefile.com
index 8902b2cd68..dbd3114a43 100644
--- a/usr/src/cmd/filebench/Makefile.com
+++ b/usr/src/cmd/filebench/Makefile.com
@@ -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.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -32,6 +32,7 @@ include ../../Makefile.targ
SRCS = \
auto_comp.c \
eventgen.c \
+ fb_random.c \
fileset.c \
flowop.c \
flowop_library.c \
diff --git a/usr/src/cmd/filebench/common/eventgen.c b/usr/src/cmd/filebench/common/eventgen.c
index bff586e17d..a8ec68286b 100644
--- a/usr/src/cmd/filebench/common/eventgen.c
+++ b/usr/src/cmd/filebench/common/eventgen.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.
*/
@@ -149,18 +149,18 @@ eventgen_init(void)
var_t *
eventgen_ratevar(var_t *var)
{
- var->var_integer = filebench_shm->eventgen_hz;
+ VAR_SET_INT(var, filebench_shm->eventgen_hz);
return (var);
}
/*
* Sets the event generator rate to that supplied by
- * vinteger_t rate.
+ * fbint_t rate.
*/
void
-eventgen_setrate(vinteger_t rate)
+eventgen_setrate(fbint_t rate)
{
- filebench_shm->eventgen_hz = rate;
+ filebench_shm->eventgen_hz = (int)rate;
}
/*
diff --git a/usr/src/cmd/filebench/common/eventgen.h b/usr/src/cmd/filebench/common/eventgen.h
index 21296614e6..51d80f9aed 100644
--- a/usr/src/cmd/filebench/common/eventgen.h
+++ b/usr/src/cmd/filebench/common/eventgen.h
@@ -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,7 +36,7 @@ extern "C" {
#endif
void eventgen_init(void);
-void eventgen_setrate(vinteger_t rate);
+void eventgen_setrate(fbint_t rate);
var_t *eventgen_ratevar(var_t *var);
void eventgen_usage(void);
void eventgen_reset(void);
diff --git a/usr/src/cmd/filebench/common/fb_random.c b/usr/src/cmd/filebench/common/fb_random.c
new file mode 100644
index 0000000000..a086185772
--- /dev/null
+++ b/usr/src/cmd/filebench/common/fb_random.c
@@ -0,0 +1,435 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <math.h>
+#include "filebench.h"
+#include "ipc.h"
+#include "gamma_dist.h"
+
+static int urandomfd;
+
+/*
+ * Reads a 64 bit random number from the urandom "file".
+ * Shuts down the run if the read fails. Otherwise returns
+ * the random number after rounding it off by "round".
+ * Returns 0 on success, -1 on failure.
+ */
+int
+filebench_randomno64(uint64_t *randp, uint64_t max,
+ uint64_t round, avd_t avd)
+{
+ uint64_t random;
+
+ /* check for round value too large */
+ if (max <= round) {
+ *randp = 0;
+
+ /* if it just fits, its ok, otherwise error */
+ if (max == round)
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (avd) {
+
+ /* get it from the variable */
+ random = avd_get_int(avd);
+
+ } else {
+
+ /* get it from urandom */
+ if (read(urandomfd, &random,
+ sizeof (uint64_t)) != sizeof (uint64_t)) {
+ filebench_log(LOG_ERROR,
+ "read /dev/urandom failed: %s", strerror(errno));
+ filebench_shutdown(1);
+ }
+ }
+
+ /* clip with max and optionally round */
+ max -= round;
+ random = random / (FILEBENCH_RANDMAX64 / max);
+ if (round) {
+ random = random / round;
+ random *= round;
+ }
+ if (random > max)
+ random = max;
+
+ *randp = random;
+ return (0);
+}
+
+
+/*
+ * Reads a 32 bit random number from the urandom "file".
+ * Shuts down the run if the read fails. Otherwise returns
+ * the random number after rounding it off by "round".
+ * Returns 0 on success, -1 on failure.
+ */
+int
+filebench_randomno32(uint32_t *randp, uint32_t max,
+ uint32_t round, avd_t avd)
+{
+ uint32_t random;
+
+ /* check for round value too large */
+ if (max <= round) {
+ *randp = 0;
+
+ /* if it just fits, its ok, otherwise error */
+ if (max == round)
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (avd) {
+
+ /* get it from the variable */
+ random = (uint32_t)avd_get_int(avd);
+
+ } else {
+
+ /* get it from urandom */
+ if (read(urandomfd, &random,
+ sizeof (uint32_t)) != sizeof (uint32_t)) {
+ filebench_log(LOG_ERROR,
+ "read /dev/urandom failed: %s", strerror(errno));
+ filebench_shutdown(1);
+ }
+ }
+
+ /* clip with max and optionally round */
+ max -= round;
+ random = random / (FILEBENCH_RANDMAX32 / max);
+ if (round) {
+ random = random / round;
+ random *= round;
+ }
+ if (random > max)
+ random = max;
+
+ *randp = random;
+ return (0);
+}
+
+/*
+ * fetch a source random number from the pseudo random number generator:
+ * erand48()
+ */
+static double
+rand_src_rand48(unsigned short *xi)
+{
+ return (erand48(xi));
+}
+
+/*
+ * fetch a source random number from the hardware random number device:
+ * urandomfd. Convert it to a floating point probability.
+ */
+/* ARGSUSED */
+static double
+rand_src_urandom(unsigned short *xi)
+{
+ fbint_t randnum;
+
+ if (read(urandomfd, &randnum,
+ sizeof (fbint_t)) != sizeof (fbint_t)) {
+ filebench_log(LOG_ERROR,
+ "read /dev/urandom failed: %s", strerror(errno));
+ filebench_shutdown(1);
+ return (0.0);
+ }
+
+ /* convert to 0-1 probability */
+ return ((double)randnum / (double)(FILEBENCH_RANDMAX64));
+}
+
+/*
+ * fetch a uniformly distributed random number from the supplied
+ * random object.
+ */
+static double
+rand_uniform_get(randdist_t *rndp)
+{
+ double dprob, dmin, dres, dround;
+
+ dmin = (double)rndp->rnd_vint_min;
+ dround = (double)rndp->rnd_vint_round;
+
+ dprob = (*rndp->rnd_src)(rndp->rnd_xi);
+
+ dres = (dprob * (2.0 * (rndp->rnd_dbl_mean - dmin))) + dmin;
+
+ if (dround == 0.0)
+ return (dres);
+ else
+ return (round(dres / dround) * dround);
+}
+
+/*
+ * fetch a gamma distributed random number from the supplied
+ * random object.
+ */
+static double
+rand_gamma_get(randdist_t *rndp)
+{
+ double dmult, dres, dmin, dround;
+
+ dmin = (double)rndp->rnd_vint_min;
+ dround = (double)rndp->rnd_vint_round;
+
+ dmult = (rndp->rnd_dbl_mean - dmin) / rndp->rnd_dbl_gamma;
+
+ dres = gamma_dist_knuth_src(rndp->rnd_dbl_gamma,
+ dmult, rndp->rnd_src, rndp->rnd_xi) + dmin;
+
+ if (dround == 0.0)
+ return (dres);
+ else
+ return (round(dres / dround) * dround);
+}
+
+/*
+ * fetch a table driven random number from the supplied
+ * random object.
+ */
+static double
+rand_table_get(randdist_t *rndp)
+{
+ double dprob, dprcnt, dtabres, dsclres, dmin, dround;
+ int idx;
+
+ dmin = (double)rndp->rnd_vint_min;
+ dround = (double)rndp->rnd_vint_round;
+
+ dprob = (*rndp->rnd_src)(rndp->rnd_xi);
+
+ dprcnt = (dprob * (double)(PF_TAB_SIZE));
+ idx = (int)dprcnt;
+
+ dtabres = (rndp->rnd_rft[idx].rf_base +
+ (rndp->rnd_rft[idx].rf_range * (dprcnt - (double)idx)));
+
+ dsclres = (dtabres * (rndp->rnd_dbl_mean - dmin)) + dmin;
+
+ if (dround == 0.0)
+ return (dsclres);
+ else
+ return (round(dsclres / dround) * dround);
+}
+
+/*
+ * Set the random seed in the supplied random object.
+ */
+static void
+rand_seed_set(randdist_t *rndp)
+{
+ union {
+ uint64_t ll;
+ uint16_t w[4];
+ } temp1;
+ int idx;
+
+ temp1.ll = (uint64_t)avd_get_int(rndp->rnd_seed);
+
+ for (idx = 0; idx < 3; idx++) {
+
+#ifdef _BIG_ENDIAN
+ rndp->rnd_xi[idx] = temp1.w[3-idx];
+#else
+ rndp->rnd_xi[idx] = temp1.w[idx];
+#endif
+ }
+}
+
+/*
+ * Define a random entity which will contain the parameters of a random
+ * distribution.
+ */
+randdist_t *
+randdist_alloc(void)
+{
+ randdist_t *rndp;
+
+ if ((rndp = (randdist_t *)ipc_malloc(FILEBENCH_RANDDIST)) == NULL) {
+ filebench_log(LOG_ERROR, "Out of memory for random dist");
+ return (NULL);
+ }
+
+ /* place on global list */
+ rndp->rnd_next = filebench_shm->shm_rand_list;
+ filebench_shm->shm_rand_list = rndp;
+
+ return (rndp);
+}
+
+/*
+ * Initializes a random distribution entity, converting avd_t
+ * parameters to doubles, and converting the list of probability density
+ * function table entries, if supplied, into a probablilty function table
+ */
+static void
+randdist_init_one(randdist_t *rndp)
+{
+ probtabent_t *rdte_hdp, *ptep;
+ double tablemean, tablemin;
+ int pteidx;
+
+ /* convert parameters to doubles */
+ rndp->rnd_dbl_mean = (double)avd_get_int(rndp->rnd_mean);
+ rndp->rnd_dbl_gamma = (double)avd_get_int(rndp->rnd_gamma) / 1000.0;
+
+ rndp->rnd_vint_min = avd_get_int(rndp->rnd_min);
+ rndp->rnd_vint_round = avd_get_int(rndp->rnd_round);
+
+ filebench_log(LOG_DEBUG_IMPL,
+ "init random var %s: Mean = %6.0llf, Gamma = %6.3llf, Min = %lld",
+ rndp->rnd_var->var_name, rndp->rnd_dbl_mean, rndp->rnd_dbl_gamma,
+ rndp->rnd_vint_min);
+
+ /* initialize distribution to apply */
+ switch (rndp->rnd_type & RAND_TYPE_MASK) {
+ case RAND_TYPE_UNIFORM:
+ rndp->rnd_get = rand_uniform_get;
+ break;
+
+ case RAND_TYPE_GAMMA:
+ rndp->rnd_get = rand_gamma_get;
+ break;
+
+ case RAND_TYPE_TABLE:
+ rndp->rnd_get = rand_table_get;
+ break;
+
+ default:
+ filebench_log(LOG_DEBUG_IMPL, "Random Type not Specified");
+ filebench_shutdown(1);
+ return;
+ }
+
+ /* initialize source of random numbers */
+ if (rndp->rnd_type & RAND_SRC_GENERATOR) {
+ rndp->rnd_src = rand_src_rand48;
+ rand_seed_set(rndp);
+ } else {
+ rndp->rnd_src = rand_src_urandom;
+ }
+
+ /* any random distribution table to convert? */
+ if ((rdte_hdp = rndp->rnd_probtabs) == NULL)
+ return;
+
+ /* determine random distribution max and mins and initialize table */
+ pteidx = 0;
+ tablemean = 0.0;
+ for (ptep = rdte_hdp; ptep; ptep = ptep->pte_next) {
+ double dmin, dmax;
+ int entcnt;
+
+ dmax = (double)avd_get_int(ptep->pte_segmax);
+ dmin = (double)avd_get_int(ptep->pte_segmin);
+
+ /* initialize table minimum on first pass */
+ if (pteidx == 0)
+ tablemin = dmin;
+
+ /* update table minimum */
+ if (tablemin > dmin)
+ tablemin = dmin;
+
+ entcnt = (int)avd_get_int(ptep->pte_percent);
+ tablemean += (((dmin + dmax)/2.0) * (double)entcnt);
+
+ /* populate the lookup table */
+
+ for (; entcnt > 0; entcnt--) {
+ rndp->rnd_rft[pteidx].rf_base = dmin;
+ rndp->rnd_rft[pteidx].rf_range = dmax - dmin;
+ pteidx++;
+ }
+ }
+
+ /* check to see if probability equals 100% */
+ if (pteidx != PF_TAB_SIZE)
+ filebench_log(LOG_ERROR,
+ "Prob table only totals %d%%", pteidx);
+
+ /* If table is not supplied with a mean value, set it to table mean */
+ if (rndp->rnd_dbl_mean == 0.0)
+ rndp->rnd_dbl_mean = (double)tablemean / (double)PF_TAB_SIZE;
+
+ /* now normalize the entries for a min value of 0, mean of 1 */
+ tablemean = (tablemean / 100.0) - tablemin;
+
+ /* special case if really a constant value */
+ if (tablemean == 0.0) {
+ for (pteidx = 0; pteidx < PF_TAB_SIZE; pteidx++) {
+ rndp->rnd_rft[pteidx].rf_base = 0.0;
+ rndp->rnd_rft[pteidx].rf_range = 0.0;
+ }
+ return;
+ }
+
+ for (pteidx = 0; pteidx < PF_TAB_SIZE; pteidx++) {
+
+ rndp->rnd_rft[pteidx].rf_base =
+ ((rndp->rnd_rft[pteidx].rf_base - tablemin) / tablemean);
+ rndp->rnd_rft[pteidx].rf_range =
+ (rndp->rnd_rft[pteidx].rf_range / tablemean);
+ }
+}
+
+/*
+ * initialize all the random distribution entities
+ */
+void
+randdist_init(void)
+{
+ randdist_t *rndp;
+
+ for (rndp = filebench_shm->shm_rand_list; rndp; rndp = rndp->rnd_next)
+ randdist_init_one(rndp);
+}
+
+/*
+ * Initialize the urandom random number source
+ */
+void
+fb_random_init(void)
+{
+ /* open the "urandom" random number device file */
+ if ((urandomfd = open("/dev/urandom", O_RDONLY)) < 0) {
+ filebench_log(LOG_ERROR, "open /dev/urandom failed: %s",
+ strerror(errno));
+ filebench_shutdown(1);
+ }
+}
diff --git a/usr/src/cmd/filebench/common/fb_random.h b/usr/src/cmd/filebench/common/fb_random.h
new file mode 100644
index 0000000000..027b299d26
--- /dev/null
+++ b/usr/src/cmd/filebench/common/fb_random.h
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FB_RANDOM_H
+#define _FB_RANDOM_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "config.h"
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * probability table entry, used while parsing the supplied
+ * probability table
+ */
+typedef struct probtabent {
+ struct probtabent *pte_next;
+ avd_t pte_percent;
+ avd_t pte_segmin;
+ avd_t pte_segmax;
+} probtabent_t;
+
+/*
+ * The supplied probability table is converted into a probability funtion
+ * lookup table at initialization time. This is the definition for each
+ * entry in the table.
+ */
+typedef struct randfunc {
+ double rf_base;
+ double rf_range;
+} randfunc_t;
+
+/* Number of entries in the probability function table */
+#define PF_TAB_SIZE 100
+
+/*
+ * Random Distribution definition object. Includes a pointer to the
+ * appropriate function to access the distribution defined by the object,
+ * as well as a function pointer to the specified source of random
+ * numbers.
+ */
+typedef struct randdist {
+ double (*rnd_get)(struct randdist *);
+ double (*rnd_src)(unsigned short *);
+ struct randdist *rnd_next;
+ struct var *rnd_var;
+ avd_t rnd_seed;
+ avd_t rnd_mean;
+ avd_t rnd_gamma;
+ avd_t rnd_min;
+ avd_t rnd_round;
+ double rnd_dbl_mean;
+ double rnd_dbl_gamma;
+ fbint_t rnd_vint_min;
+ fbint_t rnd_vint_round;
+ probtabent_t *rnd_probtabs;
+ randfunc_t rnd_rft[PF_TAB_SIZE];
+ uint16_t rnd_xi[3];
+ uint16_t rnd_type;
+} randdist_t;
+
+#define RAND_TYPE_UNIFORM 0x1
+#define RAND_TYPE_GAMMA 0x2
+#define RAND_TYPE_TABLE 0x3
+#define RAND_TYPE_MASK 0x0fff
+#define RAND_SRC_URANDOM 0x0000
+#define RAND_SRC_GENERATOR 0x1000
+
+#define RAND_PARAM_TYPE 1
+#define RAND_PARAM_SRC 2
+#define RAND_PARAM_SEED 3
+#define RAND_PARAM_MIN 4
+#define RAND_PARAM_MEAN 5
+#define RAND_PARAM_GAMMA 6
+#define RAND_PARAM_ROUND 7
+
+randdist_t *randdist_alloc(void);
+void randdist_init(void);
+int filebench_randomno32(uint32_t *, uint32_t, uint32_t, avd_t);
+int filebench_randomno64(uint64_t *, uint64_t, uint64_t, avd_t);
+void fb_random_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FB_RANDOM_H */
diff --git a/usr/src/cmd/filebench/common/filebench.h b/usr/src/cmd/filebench/common/filebench.h
index ae710b587b..e41813f529 100644
--- a/usr/src/cmd/filebench/common/filebench.h
+++ b/usr/src/cmd/filebench/common/filebench.h
@@ -66,6 +66,14 @@
extern "C" {
#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
extern pid_t my_pid; /* this process' process id */
extern procflow_t *my_procflow; /* if slave process, procflow pointer */
extern int errno;
@@ -90,8 +98,6 @@ void filebench_shutdown(int error);
#define filebench_randomno filebench_randomno32
#define FILEBENCH_RANDMAX FILEBENCH_RANDMAX32
#endif
-int filebench_randomno32(uint32_t *, uint32_t, uint32_t);
-int filebench_randomno64(uint64_t *, uint64_t, uint64_t);
#define KB (1024LL)
#define MB (KB * KB)
@@ -103,7 +109,7 @@ int filebench_randomno64(uint64_t *, uint64_t, uint64_t);
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
-#define FILEBENCH_VERSION "1.1.1"
+#define FILEBENCH_VERSION "1.2.0"
#define FILEBENCHDIR "/usr/benchmarks/filebench"
#define FILEBENCH_PROMPT "filebench> "
#define MAX_LINE_LEN 1024
diff --git a/usr/src/cmd/filebench/common/fileset.c b/usr/src/cmd/filebench/common/fileset.c
index 0148ff0894..72d6bc856e 100644
--- a/usr/src/cmd/filebench/common/fileset.c
+++ b/usr/src/cmd/filebench/common/fileset.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.
*/
@@ -41,7 +41,7 @@
* information about collections of files and subdirectories in Filebench.
* The fileset, once populated, consists of a tree of fileset entries of
* type filesetentry_t which specify files and directories. The fileset
- * is rooted in a directory specified by fs_path, and once the populated
+ * is rooted in a directory specified by fileset_path, and once the populated
* fileset has been created, has a tree of directories and files
* corresponding to the fileset's filesetentry tree.
*/
@@ -97,8 +97,12 @@ fileset_usage(void)
"define [file name=<name> | fileset name=<name>],path=<pathname>,"
",entries=<number>\n");
(void) fprintf(stderr,
+ " [,filesize=[size]]\n");
+ (void) fprintf(stderr,
" [,dirwidth=[width]]\n");
(void) fprintf(stderr,
+ " [,dirdepthrv=$random_variable_name]\n");
+ (void) fprintf(stderr,
" [,dirgamma=[100-10000]] "
"(Gamma * 1000)\n");
(void) fprintf(stderr,
@@ -263,9 +267,9 @@ fileset_alloc_file(filesetentry_t *entry)
int fd;
*path = 0;
- (void) strcpy(path, *entry->fse_fileset->fs_path);
+ (void) strcpy(path, avd_get_str(entry->fse_fileset->fs_path));
(void) strcat(path, "/");
- (void) strcat(path, entry->fse_fileset->fs_name);
+ (void) strcat(path, avd_get_str(entry->fse_fileset->fs_name));
pathtmp = fileset_resolvepath(entry);
(void) strcat(path, pathtmp);
@@ -284,7 +288,7 @@ fileset_alloc_file(filesetentry_t *entry)
filebench_log(LOG_INFO,
"Re-using file %s", path);
- if (!integer_isset(entry->fse_fileset->fs_cached))
+ if (!avd_get_bool(entry->fse_fileset->fs_cached))
(void) fileset_freemem(fd,
entry->fse_size);
@@ -300,7 +304,7 @@ fileset_alloc_file(filesetentry_t *entry)
(void) ftruncate64(fd,
(off64_t)entry->fse_size);
- if (!integer_isset(entry->fse_fileset->fs_cached))
+ if (!avd_get_bool(entry->fse_fileset->fs_cached))
(void) fileset_freemem(fd,
entry->fse_size);
@@ -347,7 +351,7 @@ fileset_alloc_file(filesetentry_t *entry)
seek += wsize;
}
- if (!integer_isset(entry->fse_fileset->fs_cached))
+ if (!avd_get_bool(entry->fse_fileset->fs_cached))
(void) fileset_freemem(fd, entry->fse_size);
(void) close(fd);
@@ -403,9 +407,9 @@ fileset_openfile(fileset_t *fileset,
int open_attrs = 0;
*path = 0;
- (void) strcpy(path, *fileset->fs_path);
+ (void) strcpy(path, avd_get_str(fileset->fs_path));
(void) strcat(path, "/");
- (void) strcat(path, fileset->fs_name);
+ (void) strcat(path, avd_get_str(fileset->fs_name));
pathtmp = fileset_resolvepath(entry);
(void) strcat(path, pathtmp);
(void) strcpy(dir, path);
@@ -557,14 +561,14 @@ empty:
/*
* Given a fileset "fileset", create the associated files as
* specified in the attributes of the fileset. The fileset is
- * rooted in a directory whose pathname is in fs_path. If the
+ * rooted in a directory whose pathname is in fileset_path. If the
* directory exists, meaning that there is already a fileset,
- * and the fs_reuse attribute is false, then remove it and all
+ * and the fileset_reuse attribute is false, then remove it and all
* its contained files and subdirectories. Next, the routine
* creates a root directory for the fileset. All the file type
* filesetentries are cycled through creating as needed
* their containing subdirectory trees in the filesystem and
- * creating actual files for fs_preallocpercent of them. The
+ * creating actual files for fileset_preallocpercent of them. The
* created files are filled with fse_size bytes of unitialized
* data. The routine returns -1 on errors, 0 on success.
*/
@@ -576,15 +580,24 @@ fileset_create(fileset_t *fileset)
struct stat64 sb;
int pickflags = FILESET_PICKUNIQUE | FILESET_PICKRESET;
hrtime_t start = gethrtime();
+ char *fileset_path;
+ char *fileset_name;
+ int randno;
int preallocated = 0;
int reusing = 0;
- if (*fileset->fs_path == NULL) {
+ if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) {
filebench_log(LOG_ERROR, "%s path not set",
fileset_entity_name(fileset));
return (-1);
}
+ if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) {
+ filebench_log(LOG_ERROR, "%s name not set",
+ fileset_entity_name(fileset));
+ return (-1);
+ }
+
#ifdef HAVE_RAW_SUPPORT
/* treat raw device as special case */
if (fileset->fs_attrs & FILESET_IS_RAW_DEV)
@@ -594,19 +607,19 @@ fileset_create(fileset_t *fileset)
/* XXX Add check to see if there is enough space */
/* Remove existing */
- (void) strcpy(path, *fileset->fs_path);
+ (void) strcpy(path, fileset_path);
(void) strcat(path, "/");
- (void) strcat(path, fileset->fs_name);
+ (void) strcat(path, fileset_name);
if ((stat64(path, &sb) == 0) && (strlen(path) > 3) &&
- (strlen(*fileset->fs_path) > 2)) {
- if (!integer_isset(fileset->fs_reuse)) {
+ (strlen(avd_get_str(fileset->fs_path)) > 2)) {
+ if (!avd_get_bool(fileset->fs_reuse)) {
char cmd[MAXPATHLEN];
(void) snprintf(cmd, sizeof (cmd), "rm -rf %s", path);
(void) system(cmd);
filebench_log(LOG_VERBOSE,
"Removed any existing %s %s in %lld seconds",
- fileset_entity_name(fileset), fileset->fs_name,
+ fileset_entity_name(fileset), fileset_name,
((gethrtime() - start) / 1000000000) + 1);
} else {
/* we are re-using */
@@ -614,7 +627,7 @@ fileset_create(fileset_t *fileset)
filebench_log(LOG_VERBOSE,
"Re-using %s %s on %s file system.",
fileset_entity_name(fileset),
- fileset->fs_name, sb.st_fstype);
+ fileset_name, sb.st_fstype);
}
}
(void) mkdir(path, 0755);
@@ -626,22 +639,21 @@ fileset_create(fileset_t *fileset)
start = gethrtime();
filebench_log(LOG_VERBOSE, "Creating %s %s...",
- fileset_entity_name(fileset), fileset->fs_name);
+ fileset_entity_name(fileset), fileset_name);
- if (!integer_isset(fileset->fs_prealloc))
+ if (!avd_get_bool(fileset->fs_prealloc))
goto exit;
+ randno = ((RAND_MAX * (100
+ - avd_get_int(fileset->fs_preallocpercent))) / 100);
+
while (entry = fileset_pick(fileset, pickflags, 0)) {
- int randno;
pthread_t tid;
pickflags = FILESET_PICKUNIQUE;
entry->fse_flags &= ~FSE_EXISTS;
- randno = ((RAND_MAX * (100 - *(fileset->fs_preallocpercent)))
- / 100);
-
/* entry doesn't need to be locked during initialization */
(void) ipc_mutex_unlock(&entry->fse_lock);
@@ -655,7 +667,7 @@ fileset_create(fileset_t *fileset)
else
entry->fse_flags &= (~FSE_REUSING);
- if (integer_isset(fileset->fs_paralloc)) {
+ if (avd_get_bool(fileset->fs_paralloc)) {
/* fire off a separate allocation thread */
(void) pthread_mutex_lock(&paralloc_lock);
@@ -690,9 +702,8 @@ exit:
filebench_log(LOG_VERBOSE,
"Preallocated %d of %lld of %s %s in %lld seconds",
preallocated,
- *(fileset->fs_entries),
- fileset_entity_name(fileset),
- fileset->fs_name,
+ fileset->fs_constentries,
+ fileset_entity_name(fileset), fileset_name,
((gethrtime() - start) / 1000000000) + 1);
return (0);
@@ -733,9 +744,9 @@ fileset_insdirlist(fileset_t *fileset, filesetentry_t *entry)
/*
* Obtaines a filesetentry entity for a file to be placed in a
* (sub)directory of a fileset. The size of the file may be
- * specified by fs_meansize, or calculated from a gamma
- * distribution of parameter fs_sizegamma and of mean size
- * fs_meansize. The filesetentry entity is placed on the file
+ * specified by fileset_meansize, or calculated from a gamma
+ * distribution of parameter fileset_sizegamma and of mean size
+ * fileset_meansize. The filesetentry entity is placed on the file
* list in the specified parent filesetentry entity, which may
* be a directory filesetentry, or the root filesetentry in the
* fileset. It is also placed on the fileset's list of all
@@ -748,7 +759,6 @@ fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial)
char tmpname[16];
filesetentry_t *entry;
double drand;
- double gamma;
if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY))
== NULL) {
@@ -770,13 +780,20 @@ fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial)
return (-1);
}
- gamma = *(fileset->fs_sizegamma) / 1000.0;
-
- if (gamma > 0) {
- drand = gamma_dist_knuth(gamma, fileset->fs_meansize / gamma);
- entry->fse_size = (off64_t)drand;
+ /* see if random variable was supplied for file size */
+ if (fileset->fs_meansize == -1) {
+ entry->fse_size = (off64_t)avd_get_int(fileset->fs_size);
} else {
- entry->fse_size = (off64_t)fileset->fs_meansize;
+ double gamma;
+
+ gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0;
+ if (gamma > 0) {
+ drand = gamma_dist_knuth(gamma,
+ fileset->fs_meansize / gamma);
+ entry->fse_size = (off64_t)drand;
+ } else {
+ entry->fse_size = (off64_t)fileset->fs_meansize;
+ }
}
fileset->fs_bytes += entry->fse_size;
@@ -808,7 +825,7 @@ static int
fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent,
int serial, double depth)
{
- double randepth, drand, ranwidth, gamma;
+ double randepth, drand, ranwidth;
int isleaf = 0;
char tmpname[16];
filesetentry_t *entry;
@@ -837,21 +854,34 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent,
entry->fse_flags |= FSE_DIR | FSE_FREE;
fileset_insdirlist(fileset, entry);
- gamma = *(fileset->fs_dirgamma) / 1000.0;
- if (gamma > 0) {
- drand = gamma_dist_knuth(gamma, fileset->fs_meandepth / gamma);
- randepth = (int)drand;
+ if (fileset->fs_dirdepthrv) {
+ randepth = (int)avd_get_int(fileset->fs_dirdepthrv);
} else {
- randepth = (int)fileset->fs_meandepth;
- }
+ double gamma;
- gamma = *(fileset->fs_sizegamma) / 1000.0;
+ gamma = avd_get_int(fileset->fs_dirgamma) / 1000.0;
+ if (gamma > 0) {
+ drand = gamma_dist_knuth(gamma,
+ fileset->fs_meandepth / gamma);
+ randepth = (int)drand;
+ } else {
+ randepth = (int)fileset->fs_meandepth;
+ }
+ }
- if (gamma > 0) {
- drand = gamma_dist_knuth(gamma, fileset->fs_meanwidth / gamma);
- ranwidth = drand;
+ if (fileset->fs_meanwidth == -1) {
+ ranwidth = avd_get_dbl(fileset->fs_dirwidth);
} else {
- ranwidth = fileset->fs_meanwidth;
+ double gamma;
+
+ gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0;
+ if (gamma > 0) {
+ drand = gamma_dist_knuth(gamma,
+ fileset->fs_meanwidth / gamma);
+ ranwidth = drand;
+ } else {
+ ranwidth = fileset->fs_meanwidth;
+ }
}
if (randepth == 0)
@@ -865,9 +895,9 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent,
* Create directory of random width according to distribution, or
* if root directory, continue until #files required
*/
- for (i = 1;
- ((parent == NULL) || (i < ranwidth + 1)) &&
- (fileset->fs_realfiles < *(fileset->fs_entries)); i++) {
+ for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) &&
+ (fileset->fs_realfiles < fileset->fs_constentries);
+ i++) {
int ret = 0;
if (parent && isleaf)
@@ -883,9 +913,9 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent,
/*
* Populates a fileset with files and subdirectory entries. Uses
- * the supplied fs_dirwidth and fs_entries (number of files) to
- * calculate the required fs_meandepth (of subdirectories) and
- * initialize the fs_meanwidth and fs_meansize variables. Then
+ * the supplied fileset_dirwidth and fileset_entries (number of files) to
+ * calculate the required fileset_meandepth (of subdirectories) and
+ * initialize the fileset_meanwidth and fileset_meansize variables. Then
* calls fileset_populate_subdir() to do the recursive
* subdirectory entry creation and leaf file entry creation. All
* of the above is skipped if the fileset has already been
@@ -895,8 +925,8 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent,
static int
fileset_populate(fileset_t *fileset)
{
- int nfiles;
- int meandirwidth = *(fileset->fs_dirwidth);
+ int entries = (int)avd_get_int(fileset->fs_entries);
+ int meandirwidth;
int ret;
/* Skip if already populated */
@@ -909,6 +939,19 @@ fileset_populate(fileset_t *fileset)
return (0);
#endif /* HAVE_RAW_SUPPORT */
+ /* save value of entries obtained for later, in case it was random */
+ fileset->fs_constentries = entries;
+
+ /* is dirwidth a random variable? */
+ if (AVD_IS_RANDOM(fileset->fs_dirwidth)) {
+ meandirwidth =
+ (int)fileset->fs_dirwidth->avd_val.randptr->rnd_dbl_mean;
+ fileset->fs_meanwidth = -1;
+ } else {
+ meandirwidth = (int)avd_get_int(fileset->fs_dirwidth);
+ fileset->fs_meanwidth = (double)meandirwidth;
+ }
+
/*
* Input params are:
* # of files
@@ -917,10 +960,20 @@ fileset_populate(fileset_t *fileset)
* # ave size of file
* max size of file
*/
- nfiles = *(fileset->fs_entries);
- fileset->fs_meandepth = log(nfiles) / log(meandirwidth);
- fileset->fs_meanwidth = meandirwidth;
- fileset->fs_meansize = *(fileset->fs_size);
+ fileset->fs_meandepth = log(entries) / log(meandirwidth);
+
+ /* Has a random variable been supplied for dirdepth? */
+ if (fileset->fs_dirdepthrv) {
+ /* yes, so set the random variable's mean value to meandepth */
+ fileset->fs_dirdepthrv->avd_val.randptr->rnd_dbl_mean =
+ fileset->fs_meandepth;
+ }
+
+ /* test for random size variable */
+ if (AVD_IS_RANDOM(fileset->fs_size))
+ fileset->fs_meansize = -1;
+ else
+ fileset->fs_meansize = avd_get_int(fileset->fs_size);
if ((ret = fileset_populate_subdir(fileset, NULL, 1, 0)) != 0)
return (ret);
@@ -929,14 +982,13 @@ fileset_populate(fileset_t *fileset)
exists:
if (fileset->fs_attrs & FILESET_IS_FILE) {
filebench_log(LOG_VERBOSE, "File %s: mbytes=%lld",
- fileset->fs_name,
+ avd_get_str(fileset->fs_name),
fileset->fs_bytes / 1024UL / 1024UL);
} else {
filebench_log(LOG_VERBOSE, "Fileset %s: %lld files, "
- "avg dir = %.1lf, avg depth = %.1lf, mbytes=%lld",
- fileset->fs_name,
- *(fileset->fs_entries),
- fileset->fs_meanwidth,
+ "avg dir = %d, avg depth = %.1lf, mbytes=%lld",
+ avd_get_str(fileset->fs_name), entries,
+ meandirwidth,
fileset->fs_meandepth,
fileset->fs_bytes / 1024UL / 1024UL);
}
@@ -944,13 +996,13 @@ exists:
}
/*
- * Allocates a fileset instance, initializes fs_dirgamma and
- * fs_sizegamma default values, and sets the fileset name to the
+ * Allocates a fileset instance, initializes fileset_dirgamma and
+ * fileset_sizegamma default values, and sets the fileset name to the
* supplied name string. Puts the allocated fileset on the
* master fileset list and returns a pointer to it.
*/
fileset_t *
-fileset_define(char *name)
+fileset_define(avd_t name)
{
fileset_t *fileset;
@@ -963,12 +1015,13 @@ fileset_define(char *name)
return (NULL);
}
- filebench_log(LOG_DEBUG_IMPL, "Defining file %s", name);
+ filebench_log(LOG_DEBUG_IMPL,
+ "Defining file %s", avd_get_str(name));
(void) ipc_mutex_lock(&filebench_shm->fileset_lock);
- fileset->fs_dirgamma = integer_alloc(1500);
- fileset->fs_sizegamma = integer_alloc(1500);
+ fileset->fs_dirgamma = avd_int_alloc(1500);
+ fileset->fs_sizegamma = avd_int_alloc(1500);
/* Add fileset to global list */
if (filebench_shm->filesetlist == NULL) {
@@ -981,14 +1034,14 @@ fileset_define(char *name)
(void) ipc_mutex_unlock(&filebench_shm->fileset_lock);
- (void) strcpy(fileset->fs_name, name);
+ fileset->fs_name = name;
return (fileset);
}
/*
* If supplied with a pointer to a fileset and the fileset's
- * fs_prealloc flag is set, calls fileset_populate() to populate
+ * fileset_prealloc flag is set, calls fileset_populate() to populate
* the fileset with filesetentries, then calls fileset_create()
* to make actual directories and files for the filesetentries.
* Otherwise, it applies fileset_populate() and fileset_create()
@@ -1008,11 +1061,12 @@ fileset_createset(fileset_t *fileset)
/* set up for possible parallel allocate */
paralloc_count = 0;
- if (fileset && integer_isset(fileset->fs_prealloc)) {
+ if (fileset && avd_get_bool(fileset->fs_prealloc)) {
filebench_log(LOG_INFO,
"creating/pre-allocating %s %s",
- fileset_entity_name(fileset), fileset->fs_name);
+ fileset_entity_name(fileset),
+ avd_get_str(fileset->fs_name));
if ((ret = fileset_populate(fileset)) != 0)
return (ret);
@@ -1061,7 +1115,7 @@ fileset_find(char *name)
(void) ipc_mutex_lock(&filebench_shm->fileset_lock);
while (fileset) {
- if (strcmp(name, fileset->fs_name) == 0) {
+ if (strcmp(name, avd_get_str(fileset->fs_name)) == 0) {
(void) ipc_mutex_unlock(&filebench_shm->fileset_lock);
return (fileset);
}
@@ -1103,9 +1157,24 @@ fileset_iter(int (*cmd)(fileset_t *fileset, int first))
int
fileset_print(fileset_t *fileset, int first)
{
- int pathlength = strlen(*fileset->fs_path) + strlen(fileset->fs_name);
- /* 30 spaces */
- char pad[] = " ";
+ int pathlength;
+ char *fileset_path;
+ char *fileset_name;
+ static char pad[] = " "; /* 30 spaces */
+
+ if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) {
+ filebench_log(LOG_ERROR, "%s path not set",
+ fileset_entity_name(fileset));
+ return (-1);
+ }
+
+ if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) {
+ filebench_log(LOG_ERROR, "%s name not set",
+ fileset_entity_name(fileset));
+ return (-1);
+ }
+
+ pathlength = strlen(fileset_path) + strlen(fileset_name);
if (pathlength > 29)
pathlength = 29;
@@ -1121,25 +1190,20 @@ fileset_print(fileset_t *fileset, int first)
if (fileset->fs_attrs & FILESET_IS_RAW_DEV) {
filebench_log(LOG_INFO,
"%s/%s%s (Raw Device)",
- *fileset->fs_path,
- fileset->fs_name,
- &pad[pathlength]);
+ fileset_path, fileset_name, &pad[pathlength]);
} else {
filebench_log(LOG_INFO,
"%s/%s%s%9lld (Single File)",
- *fileset->fs_path,
- fileset->fs_name,
- &pad[pathlength],
- *fileset->fs_size);
+ fileset_path, fileset_name, &pad[pathlength],
+ avd_get_int(fileset->fs_size));
}
} else {
filebench_log(LOG_INFO, "%s/%s%s%9lld%12lld%10lld",
- *fileset->fs_path,
- fileset->fs_name,
+ fileset_path, fileset_name,
&pad[pathlength],
- *fileset->fs_size,
- *fileset->fs_dirwidth,
- *fileset->fs_entries);
+ avd_get_int(fileset->fs_size),
+ avd_get_int(fileset->fs_dirwidth),
+ fileset->fs_constentries);
}
return (0);
}
@@ -1159,9 +1223,9 @@ fileset_checkraw(fileset_t *fileset)
#ifdef HAVE_RAW_SUPPORT
/* check for raw device */
- (void) strcpy(path, *fileset->fs_path);
+ (void) strcpy(path, avd_get_str(fileset->fs_path));
(void) strcat(path, "/");
- (void) strcat(path, fileset->fs_name);
+ (void) strcat(path, avd_get_str(fileset->fs_name));
if ((stat64(path, &sb) == 0) &&
((sb.st_mode & S_IFMT) == S_IFBLK) && sb.st_rdev) {
fileset->fs_attrs |= FILESET_IS_RAW_DEV;
diff --git a/usr/src/cmd/filebench/common/fileset.h b/usr/src/cmd/filebench/common/fileset.h
index 8f81afaac8..fe0b86ec79 100644
--- a/usr/src/cmd/filebench/common/fileset.h
+++ b/usr/src/cmd/filebench/common/fileset.h
@@ -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.
*/
@@ -92,37 +92,45 @@ typedef struct filesetentry {
typedef struct fileset {
struct fileset *fs_next; /* Next in list */
- char fs_name[128]; /* Name */
- var_string_t fs_path; /* Pathname prefix in fs */
- var_integer_t fs_entries; /* Set size */
- var_integer_t fs_preallocpercent; /* Prealloc size */
+ avd_t fs_name; /* Name */
+ avd_t fs_path; /* Pathname prefix in fileset */
+ avd_t fs_entries; /* Number of entries attr */
+ /* (possibly random) */
+ fbint_t fs_constentries; /* Constant version of enties attr */
+ avd_t fs_preallocpercent; /* Prealloc size */
int fs_attrs; /* Attributes */
- var_integer_t fs_dirwidth; /* Explicit or 0 for distribution */
- var_integer_t fs_size; /* Explicit or 0 for distribution */
- var_integer_t fs_dirgamma; /* Dirwidth Gamma distribution (* 1000) */
- var_integer_t fs_sizegamma; /* Filesize Gamma distribution (* 1000) */
- var_integer_t fs_create; /* Attr */
- var_integer_t fs_prealloc; /* Attr */
- var_integer_t fs_paralloc; /* Attr */
- var_integer_t fs_cached; /* Attr */
- var_integer_t fs_reuse; /* Attr */
+ avd_t fs_dirwidth; /* Explicit or mean for distribution */
+ avd_t fs_dirdepthrv; /* random variable for dir depth */
+ avd_t fs_size; /* Explicit or mean for distribution */
+ avd_t fs_dirgamma; /* Dirdepth Gamma distribution */
+ /* (* 1000) defaults to 1500, set */
+ /* to 0 for explicit depth */
+ avd_t fs_sizegamma; /* Filesize and dirwidth Gamma */
+ /* distribution (* 1000), default */
+ /* is 1500, set to 0 for explicit */
+ avd_t fs_create; /* Attr */
+ avd_t fs_prealloc; /* Attr */
+ avd_t fs_paralloc; /* Attr */
+ avd_t fs_cached; /* Attr */
+ avd_t fs_reuse; /* Attr */
double fs_meandepth; /* Computed mean depth */
double fs_meanwidth; /* Specified mean dir width */
double fs_meansize; /* Specified mean file size */
int fs_realfiles; /* Actual files */
- off64_t fs_bytes; /* Space potentially consumed by all files */
+ off64_t fs_bytes; /* Total space consumed by files */
filesetentry_t *fs_filelist; /* List of files */
filesetentry_t *fs_dirlist; /* List of directories */
filesetentry_t *fs_filefree; /* Ptr to next free file */
filesetentry_t *fs_dirfree; /* Ptr to next free directory */
- filesetentry_t *fs_filerotor[FSE_MAXTID]; /* next file to select */
+ filesetentry_t *fs_filerotor[FSE_MAXTID]; /* next file to */
+ /* select */
filesetentry_t *fs_dirrotor; /* Ptr to next directory to select */
} fileset_t;
int fileset_createset(fileset_t *);
int fileset_openfile(fileset_t *fileset, filesetentry_t *entry,
int flag, int mode, int attrs);
-fileset_t *fileset_define(char *);
+fileset_t *fileset_define(avd_t);
fileset_t *fileset_find(char *name);
filesetentry_t *fileset_pick(fileset_t *fileset, int flags, int tid);
char *fileset_resolvepath(filesetentry_t *entry);
diff --git a/usr/src/cmd/filebench/common/flowop.c b/usr/src/cmd/filebench/common/flowop.c
index 4140234377..1b86a0c8a4 100644
--- a/usr/src/cmd/filebench/common/flowop.c
+++ b/usr/src/cmd/filebench/common/flowop.c
@@ -41,8 +41,7 @@
#endif
static flowop_t *flowop_define_common(threadflow_t *threadflow, char *name,
- flowop_t *inherit, int instance, int type);
-
+ flowop_t *inherit, int instance, int type);
/*
* A collection of flowop support functions. The actual code that
@@ -72,6 +71,22 @@ flowop_printlist(flowop_t *list)
return (0);
}
+/*
+ * Prints the name and instance number of all flowops on
+ * the master flowop list to the console and the filebench log.
+ */
+void
+flowop_printall(void)
+{
+ flowop_t *flowop = filebench_shm->flowoplist;
+
+ while (flowop) {
+ filebench_log(LOG_VERBOSE, "flowop-list %s-%d",
+ flowop->fo_name, flowop->fo_instance);
+ flowop = flowop->fo_next;
+ }
+}
+
#define TIMESPEC_TO_HRTIME(s, e) (((e.tv_sec - s.tv_sec) * 1000000000LL) + \
(e.tv_nsec - s.tv_nsec))
/*
@@ -111,6 +126,7 @@ flowop_beginop(threadflow_t *threadflow, flowop_t *flowop)
}
flowstat_t controlstats;
+pthread_mutex_t controlstats_lock;
static int controlstats_zeroed = 0;
/*
@@ -156,6 +172,7 @@ flowop_endop(threadflow_t *threadflow, flowop_t *flowop, int64_t bytes)
flowop->fo_stats.fs_count++;
flowop->fo_stats.fs_bytes += bytes;
+ (void) ipc_mutex_lock(&controlstats_lock);
if ((flowop->fo_type & FLOW_TYPE_IO) ||
(flowop->fo_type & FLOW_TYPE_AIO)) {
controlstats.fs_count++;
@@ -174,6 +191,7 @@ flowop_endop(threadflow_t *threadflow, flowop_t *flowop, int64_t bytes)
controlstats.fs_wbytes += bytes;
controlstats.fs_wcount++;
}
+ (void) ipc_mutex_unlock(&controlstats_lock);
}
/*
@@ -183,6 +201,13 @@ flowop_endop(threadflow_t *threadflow, flowop_t *flowop, int64_t bytes)
static int
flowop_initflow(flowop_t *flowop)
{
+ /*
+ * save static copies of two items, in case they are supplied
+ * from random variables
+ */
+ flowop->fo_constvalue = avd_get_int(flowop->fo_value);
+ flowop->fo_constwss = avd_get_int(flowop->fo_wss);
+
if ((*flowop->fo_init)(flowop) < 0) {
filebench_log(LOG_ERROR, "flowop %s-%d init failed",
flowop->fo_name, flowop->fo_instance);
@@ -263,10 +288,12 @@ flowop_start(threadflow_t *threadflow)
}
#endif
+ (void) ipc_mutex_lock(&controlstats_lock);
if (!controlstats_zeroed) {
(void) memset(&controlstats, 0, sizeof (controlstats));
controlstats_zeroed = 1;
}
+ (void) ipc_mutex_unlock(&controlstats_lock);
flowop = threadflow->tf_ops;
threadflow->tf_stats.fs_stime = gethrtime();
@@ -316,15 +343,17 @@ flowop_start(threadflow_t *threadflow)
threadflow->tf_abort = 0;
threadflow->tf_running = 1;
+ memsize = (size_t)threadflow->tf_constmemsize;
+
/* If we are going to use ISM, allocate later */
if (threadflow->tf_attrs & THREADFLOW_USEISM) {
threadflow->tf_mem =
- ipc_ismmalloc((size_t)*threadflow->tf_memsize);
+ ipc_ismmalloc(memsize);
} else {
- threadflow->tf_mem = malloc((size_t)*threadflow->tf_memsize);
+ threadflow->tf_mem =
+ malloc(memsize);
}
- memsize = *threadflow->tf_memsize;
(void) memset(threadflow->tf_mem, 0, memsize);
filebench_log(LOG_DEBUG_SCRIPT, "Thread allocated %d bytes", memsize);
@@ -337,7 +366,7 @@ flowop_start(threadflow_t *threadflow)
/* Main filebench worker loop */
/* CONSTCOND */
while (1) {
- int i;
+ int i, count;
/* Abort if asked */
if (threadflow->tf_abort || filebench_shm->f_abort)
@@ -353,26 +382,23 @@ flowop_start(threadflow_t *threadflow)
if (!filebench_shm->shm_running)
(void) sleep(1);
- if (flowop->fo_stats.fs_stime == 0)
- flowop->fo_stats.fs_stime = gethrtime();
-
if (flowop == NULL) {
filebench_log(LOG_ERROR, "flowop_read null flowop");
return;
}
- filebench_log(LOG_DEBUG_SCRIPT, "%s: executing flowop %s-%d",
- threadflow->tf_name, flowop->fo_name, flowop->fo_instance);
+ if (flowop->fo_stats.fs_stime == 0)
+ flowop->fo_stats.fs_stime = gethrtime();
/* Execute the flowop for fo_iters times */
- for (i = 0; i < *flowop->fo_iters; i++) {
+ count = avd_get_int(flowop->fo_iters);
+ for (i = 0; i < count; i++) {
+
filebench_log(LOG_DEBUG_SCRIPT, "%s: executing flowop "
"%s-%d", threadflow->tf_name, flowop->fo_name,
flowop->fo_instance);
+
ret = (*flowop->fo_func)(threadflow, flowop);
- filebench_log(LOG_DEBUG_SCRIPT, "%s: executing flowop "
- "%s-%d", threadflow->tf_name, flowop->fo_name,
- flowop->fo_instance);
/*
* Return value FILEBENCH_ERROR means "flowop
@@ -561,7 +587,7 @@ flowop_delete_all(flowop_t **flowoplist)
filebench_log(LOG_DEBUG_IMPL, "Deleting all flowops...");
while (flowop) {
- filebench_log(LOG_DEBUG_IMPL, "Deleting all flowops (%s-%d)",
+ filebench_log(LOG_DEBUG_IMPL, "Deleting flowop (%s-%d)",
flowop->fo_name, flowop->fo_instance);
flowop = flowop->fo_threadnext;
}
@@ -631,7 +657,7 @@ flowop_define_common(threadflow_t *threadflow, char *name, flowop_t *inherit,
} else {
(void) memset(flowop, 0, sizeof (flowop_t));
flowop->fo_fd = -1;
- flowop->fo_iters = integer_alloc(1);
+ flowop->fo_iters = avd_int_alloc(1);
flowop->fo_type = type;
(void) pthread_mutex_init(&flowop->fo_lock, ipc_mutexattr());
(void) ipc_mutex_lock(&flowop->fo_lock);
@@ -682,7 +708,7 @@ flowop_t *
flowop_define(threadflow_t *threadflow, char *name, flowop_t *inherit,
int instance, int type)
{
- flowop_t *flowop;
+ flowop_t *flowop;
(void) ipc_mutex_lock(&filebench_shm->flowop_lock);
flowop = flowop_define_common(threadflow, name,
@@ -721,13 +747,15 @@ flowop_find_barrier(void)
flowop_t *
flowop_find(char *name)
{
- flowop_t *flowop = filebench_shm->flowoplist;
+ flowop_t *flowop;
flowop_t *result = NULL;
flowop_find_barrier();
(void) ipc_mutex_lock(&filebench_shm->flowop_lock);
+ flowop = filebench_shm->flowoplist;
+
while (flowop) {
if (strcmp(name, flowop->fo_name) == 0) {
@@ -751,21 +779,28 @@ flowop_find(char *name)
/*
* Returns a pointer to the specified instance of flowop
- * "name" from the list returned by flowop_find().
+ * "name" from the supplied list.
*/
flowop_t *
flowop_find_one(char *name, int instance)
{
- flowop_t *result;
+ flowop_t *test_flowop;
+
+ flowop_find_barrier();
+
+ (void) ipc_mutex_lock(&filebench_shm->flowop_lock);
- result = flowop_find(name);
+ test_flowop = filebench_shm->flowoplist;
- while (result) {
- if ((strcmp(name, result->fo_name) == 0) &&
- (instance == result->fo_instance))
+ while (test_flowop) {
+ if ((strcmp(name, test_flowop->fo_name) == 0) &&
+ (instance == test_flowop->fo_instance))
break;
- result = result->fo_next;
+
+ test_flowop = test_flowop->fo_next;
}
- return (result);
+ (void) ipc_mutex_unlock(&filebench_shm->flowop_lock);
+
+ return (test_flowop);
}
diff --git a/usr/src/cmd/filebench/common/flowop.h b/usr/src/cmd/filebench/common/flowop.h
index 8aa9b33440..d98b1d0ff8 100644
--- a/usr/src/cmd/filebench/common/flowop.h
+++ b/usr/src/cmd/filebench/common/flowop.h
@@ -64,28 +64,32 @@ typedef struct flowop {
void (*fo_destruct)(); /* Destructor Method */
int fo_type; /* Type */
int fo_attrs; /* Flow op attribute */
+ avd_t fo_filename; /* file/fileset name */
fileset_t *fo_fileset; /* Fileset for op */
int fo_fd; /* File descriptor */
int fo_fdnumber; /* User specified file descriptor */
int fo_srcfdnumber; /* User specified src file descriptor */
- var_integer_t fo_iosize; /* Size of operation */
- var_integer_t fo_wss; /* Flow op working set size */
+ fbint_t fo_constvalue; /* constant version of fo_value */
+ fbint_t fo_constwss; /* constant version of fo_wss */
+ avd_t fo_iosize; /* Size of operation */
+ avd_t fo_wss; /* Flow op working set size */
char fo_targetname[128]; /* Target, for wakeup etc... */
struct flowop *fo_targets; /* List of targets matching name */
struct flowop *fo_targetnext; /* List of targets matching name */
- var_integer_t fo_iters; /* Number of iterations of op */
- var_integer_t fo_value; /* Attr */
- var_integer_t fo_sequential; /* Attr */
- var_integer_t fo_random; /* Attr */
- var_integer_t fo_stride; /* Attr */
- var_integer_t fo_backwards; /* Attr */
- var_integer_t fo_dsync; /* Attr */
- var_integer_t fo_blocking; /* Attr */
- var_integer_t fo_directio; /* Attr */
- var_integer_t fo_rotatefd; /* Attr */
+ avd_t fo_iters; /* Number of iterations of op */
+ avd_t fo_value; /* Attr */
+ avd_t fo_sequential; /* Attr */
+ avd_t fo_random; /* Attr */
+ avd_t fo_stride; /* Attr */
+ avd_t fo_backwards; /* Attr */
+ avd_t fo_dsync; /* Attr */
+ avd_t fo_blocking; /* Attr */
+ avd_t fo_directio; /* Attr */
+ avd_t fo_rotatefd; /* Attr */
flowstat_t fo_stats; /* Flow statistics */
pthread_cond_t fo_cv; /* Block/wakeup cv */
pthread_mutex_t fo_lock; /* Mutex around flowop */
+ void *fo_private; /* Flowop private scratch pad area */
char *fo_buf; /* Per-flowop buffer */
uint64_t fo_buf_size; /* current size of buffer */
#ifdef HAVE_SYSV_SEM
@@ -94,7 +98,7 @@ typedef struct flowop {
#else
sem_t fo_sem; /* sem_t for posix semaphores */
#endif /* HAVE_SYSV_SEM */
- var_integer_t fo_highwater; /* value of highwater paramter */
+ avd_t fo_highwater; /* value of highwater paramter */
void *fo_idp; /* id, for sems etc */
hrtime_t fo_timestamp; /* for ratecontrol, etc... */
int fo_initted; /* Set to one if initialized */
@@ -125,6 +129,7 @@ typedef struct flowop {
#define FLOW_TYPE_OTHER 4 /* Op is a something else */
extern flowstat_t controlstats;
+extern pthread_mutex_t controlstats_lock;
void flowop_init(void);
flowop_t *flowop_define(threadflow_t *, char *name, flowop_t *inherit,
@@ -137,6 +142,7 @@ void flowop_delete_all(flowop_t **threadlist);
void flowop_endop(threadflow_t *threadflow, flowop_t *flowop, int64_t bytes);
void flowop_beginop(threadflow_t *threadflow, flowop_t *flowop);
void flowop_destruct_all_flows(threadflow_t *threadflow);
+void flowop_printall(void);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/filebench/common/flowop_library.c b/usr/src/cmd/filebench/common/flowop_library.c
index 3124be54b9..cb54bd5c9c 100644
--- a/usr/src/cmd/filebench/common/flowop_library.c
+++ b/usr/src/cmd/filebench/common/flowop_library.c
@@ -37,6 +37,7 @@
#include <sys/time.h>
#include <inttypes.h>
#include <fcntl.h>
+#include <math.h>
#ifdef HAVE_UTILITY_H
#include <utility.h>
@@ -73,6 +74,7 @@
#include "filebench.h"
#include "flowop.h"
#include "fileset.h"
+#include "fb_random.h"
/*
* These routines implement the flowops from the f language. Each
@@ -135,6 +137,9 @@ static int flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop);
static int flowoplib_finishoncount(threadflow_t *threadflow, flowop_t *flowop);
static int flowoplib_finishonbytes(threadflow_t *threadflow, flowop_t *flowop);
static int flowoplib_fsyncset(threadflow_t *threadflow, flowop_t *flowop);
+static int flowoplib_testrandvar(threadflow_t *threadflow, flowop_t *flowop);
+static int flowoplib_testrandvar_init(flowop_t *flowop);
+static void flowoplib_testrandvar_destruct(flowop_t *flowop);
typedef struct flowoplib {
int fl_type;
@@ -201,7 +206,10 @@ static flowoplib_t flowoplib_funcs[] = {
FLOW_TYPE_IO, 0, "deletefile", flowoplib_init_generic,
flowoplib_deletefile, flowoplib_destruct_generic,
FLOW_TYPE_IO, FLOW_ATTR_WRITE, "writewholefile", flowoplib_init_generic,
- flowoplib_writewholefile, flowoplib_destruct_generic
+ flowoplib_writewholefile, flowoplib_destruct_generic,
+ /* routine to calculate mean and stddev for output from a randvar */
+ FLOW_TYPE_OTHER, 0, "testrandvar", flowoplib_testrandvar_init,
+ flowoplib_testrandvar, flowoplib_testrandvar_destruct
};
/*
@@ -279,10 +287,10 @@ flowoplib_fileattrs(flowop_t *flowop)
{
int attrs = 0;
- if (*flowop->fo_directio)
+ if (avd_get_bool(flowop->fo_directio))
attrs |= FLOW_ATTR_DIRECTIO;
- if (*flowop->fo_dsync)
+ if (avd_get_bool(flowop->fo_dsync))
attrs |= FLOW_ATTR_DSYNC;
return (attrs);
@@ -312,19 +320,22 @@ flowoplib_fileattrs(flowop_t *flowop)
static int
flowoplib_fdnum(threadflow_t *threadflow, flowop_t *flowop)
{
+ fbint_t entries;
+
/* If the script sets the fd explicitly */
if (flowop->fo_fdnumber > 0)
return (flowop->fo_fdnumber);
/* If the flowop defaults to persistent fd */
- if (!integer_isset(flowop->fo_rotatefd))
+ if (!avd_get_bool(flowop->fo_rotatefd))
return (flowop->fo_fdnumber);
+ entries = flowop->fo_fileset->fs_constentries;
+
/* Rotate the fd on each flowop invocation */
- if (*(flowop->fo_fileset->fs_entries) > (THREADFLOW_MAXFD / 2)) {
+ if (entries > (THREADFLOW_MAXFD / 2)) {
filebench_log(LOG_ERROR, "Out of file descriptors in flowop %s"
- " (too many files : %d", flowop->fo_name,
- *(flowop->fo_fileset->fs_entries));
+ " (too many files : %d", flowop->fo_name, entries);
return (FILEBENCH_ERROR);
}
@@ -333,8 +344,7 @@ flowoplib_fdnum(threadflow_t *threadflow, flowop_t *flowop)
threadflow->tf_fdrotor = THREADFLOW_MAXFD;
/* One fd for every file in the set */
- if (*(flowop->fo_fileset->fs_entries) ==
- (THREADFLOW_MAXFD - threadflow->tf_fdrotor))
+ if (entries == (THREADFLOW_MAXFD - threadflow->tf_fdrotor))
threadflow->tf_fdrotor = THREADFLOW_MAXFD;
@@ -353,7 +363,7 @@ flowoplib_fdnum(threadflow_t *threadflow, flowop_t *flowop)
*/
static int
flowoplib_filesetup(threadflow_t *threadflow, flowop_t *flowop,
- vinteger_t *wssp, int *filedescp)
+ fbint_t *wssp, int *filedescp)
{
int fd = flowoplib_fdnum(threadflow, flowop);
@@ -373,20 +383,18 @@ flowoplib_filesetup(threadflow_t *threadflow, flowop_t *flowop,
} else {
filebench_log(LOG_DEBUG_IMPL,
"opened device %s/%s",
- flowop->fo_fileset->fs_path,
- flowop->fo_fileset->fs_name);
+ avd_get_str(flowop->fo_fileset->fs_path),
+ avd_get_str(flowop->fo_fileset->fs_name));
}
}
*filedescp = threadflow->tf_fd[fd];
- if (*flowop->fo_wss == 0) {
+ if ((*wssp = flowop->fo_constwss) == 0) {
if (threadflow->tf_fse[fd])
*wssp = threadflow->tf_fse[fd]->fse_size;
else
- *wssp = *flowop->fo_fileset->fs_size;
- } else {
- *wssp = *flowop->fo_wss;
+ *wssp = avd_get_int(flowop->fo_fileset->fs_size);
}
return (FILEBENCH_OK);
@@ -398,7 +406,7 @@ flowoplib_filesetup(threadflow_t *threadflow, flowop_t *flowop,
*/
static int
flowoplib_iobufsetup(threadflow_t *threadflow, flowop_t *flowop,
- caddr_t *iobufp, vinteger_t iosize)
+ caddr_t *iobufp, fbint_t iosize)
{
long memsize;
size_t memoffset;
@@ -409,10 +417,11 @@ flowoplib_iobufsetup(threadflow_t *threadflow, flowop_t *flowop,
return (FILEBENCH_ERROR);
}
- if ((memsize = *threadflow->tf_memsize) != 0) {
+ if ((memsize = threadflow->tf_constmemsize) != 0) {
/* use tf_mem for I/O with random offset */
- if (filebench_randomno(&memoffset, memsize, iosize) == -1) {
+ if (filebench_randomno(&memoffset,
+ memsize, iosize, NULL) == -1) {
filebench_log(LOG_ERROR,
"tf_memsize smaller than IO size for thread %s",
flowop->fo_name);
@@ -424,9 +433,16 @@ flowoplib_iobufsetup(threadflow_t *threadflow, flowop_t *flowop,
/* use private I/O buffer */
if ((flowop->fo_buf != NULL) &&
(flowop->fo_buf_size < iosize)) {
+ /* too small, so free up and re-allocate */
free(flowop->fo_buf);
flowop->fo_buf = NULL;
}
+
+ /*
+ * Allocate memory for the buffer. The memory is freed
+ * by flowop_destruct_generic() or by this routine if more
+ * memory is needed for the buffer.
+ */
if ((flowop->fo_buf == NULL) && ((flowop->fo_buf
= (char *)malloc(iosize)) == NULL))
return (FILEBENCH_ERROR);
@@ -444,7 +460,7 @@ flowoplib_iobufsetup(threadflow_t *threadflow, flowop_t *flowop,
*/
static int
flowoplib_iosetup(threadflow_t *threadflow, flowop_t *flowop,
- vinteger_t *wssp, caddr_t *iobufp, int *filedescp, vinteger_t iosize)
+ fbint_t *wssp, caddr_t *iobufp, int *filedescp, fbint_t iosize)
{
int ret;
@@ -479,19 +495,22 @@ static int
flowoplib_read(threadflow_t *threadflow, flowop_t *flowop)
{
caddr_t iobuf;
- vinteger_t wss;
+ fbint_t wss;
+ fbint_t iosize;
int filedesc;
int ret;
+
+ iosize = avd_get_int(flowop->fo_iosize);
if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf,
- &filedesc, *flowop->fo_iosize)) != FILEBENCH_OK)
+ &filedesc, iosize)) != FILEBENCH_OK)
return (ret);
- if (*flowop->fo_random) {
+ if (avd_get_bool(flowop->fo_random)) {
uint64_t fileoffset;
- if (filebench_randomno64(&fileoffset, wss,
- *flowop->fo_iosize) == -1) {
+ if (filebench_randomno64(&fileoffset,
+ wss, iosize, NULL) == -1) {
filebench_log(LOG_ERROR,
"file size smaller than IO size for thread %s",
flowop->fo_name);
@@ -500,12 +519,12 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop)
(void) flowop_beginop(threadflow, flowop);
if ((ret = pread64(filedesc, iobuf,
- *flowop->fo_iosize, (off64_t)fileoffset)) == -1) {
+ iosize, (off64_t)fileoffset)) == -1) {
(void) flowop_endop(threadflow, flowop, 0);
filebench_log(LOG_ERROR,
"read file %s failed, offset %lld "
"io buffer %zd: %s",
- flowop->fo_fileset->fs_name,
+ avd_get_str(flowop->fo_fileset->fs_name),
fileoffset, iobuf, strerror(errno));
flowop_endop(threadflow, flowop, 0);
return (FILEBENCH_ERROR);
@@ -517,11 +536,11 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop)
} else {
(void) flowop_beginop(threadflow, flowop);
- if ((ret = read(filedesc, iobuf,
- *flowop->fo_iosize)) == -1) {
+ if ((ret = read(filedesc, iobuf, iosize)) == -1) {
+ (void) flowop_endop(threadflow, flowop, 0);
filebench_log(LOG_ERROR,
"read file %s failed, io buffer %zd: %s",
- flowop->fo_fileset->fs_name,
+ avd_get_str(flowop->fo_fileset->fs_name),
iobuf, strerror(errno));
(void) flowop_endop(threadflow, flowop, 0);
return (FILEBENCH_ERROR);
@@ -628,21 +647,24 @@ static int
flowoplib_aiowrite(threadflow_t *threadflow, flowop_t *flowop)
{
caddr_t iobuf;
- vinteger_t wss;
+ fbint_t wss;
+ fbint_t iosize;
int filedesc;
int ret;
+ iosize = avd_get_int(flowop->fo_iosize);
+
if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf,
- &filedesc, *flowop->fo_iosize)) != FILEBENCH_OK)
+ &filedesc, iosize)) != FILEBENCH_OK)
return (ret);
- if (*flowop->fo_random) {
+ if (avd_get_bool(flowop->fo_random)) {
uint64_t fileoffset;
struct aiocb64 *aiocb;
aiolist_t *aiolist;
if (filebench_randomno64(&fileoffset,
- wss, *flowop->fo_iosize) == -1) {
+ wss, iosize, NULL) == -1) {
filebench_log(LOG_ERROR,
"file size smaller than IO size for thread %s",
flowop->fo_name);
@@ -655,13 +677,13 @@ flowoplib_aiowrite(threadflow_t *threadflow, flowop_t *flowop)
aiocb->aio_fildes = filedesc;
aiocb->aio_buf = iobuf;
- aiocb->aio_nbytes = *flowop->fo_iosize;
+ aiocb->aio_nbytes = (size_t)iosize;
aiocb->aio_offset = (off64_t)fileoffset;
aiocb->aio_reqprio = 0;
filebench_log(LOG_DEBUG_IMPL,
"aio fd=%d, bytes=%lld, offset=%lld",
- filedesc, *flowop->fo_iosize, fileoffset);
+ filedesc, iosize, fileoffset);
flowop_beginop(threadflow, flowop);
if (aio_write64(aiocb) < 0) {
@@ -669,7 +691,7 @@ flowoplib_aiowrite(threadflow_t *threadflow, flowop_t *flowop)
strerror(errno));
filebench_shutdown(1);
}
- flowop_endop(threadflow, flowop, *flowop->fo_iosize);
+ flowop_endop(threadflow, flowop, iosize);
} else {
return (FILEBENCH_ERROR);
}
@@ -915,7 +937,7 @@ flowoplib_wakeup(threadflow_t *threadflow, flowop_t *flowop)
static int
flowoplib_hog(threadflow_t *threadflow, flowop_t *flowop)
{
- uint64_t value = *flowop->fo_value;
+ uint64_t value = avd_get_int(flowop->fo_value);
int i;
filebench_log(LOG_DEBUG_IMPL, "hog enter");
@@ -936,7 +958,7 @@ flowoplib_hog(threadflow_t *threadflow, flowop_t *flowop)
static int
flowoplib_delay(threadflow_t *threadflow, flowop_t *flowop)
{
- int value = *flowop->fo_value;
+ int value = avd_get_int(flowop->fo_value);
flowop_beginop(threadflow, flowop);
(void) sleep(value);
@@ -1013,8 +1035,10 @@ flowoplib_iopslimit(threadflow_t *threadflow, flowop_t *flowop)
flowop->fo_initted = 1;
}
+ (void) ipc_mutex_lock(&controlstats_lock);
iops = (controlstats.fs_rcount +
controlstats.fs_wcount);
+ (void) ipc_mutex_unlock(&controlstats_lock);
/* Is this the first time around */
if (flowop->fo_tputlast == 0) {
@@ -1077,7 +1101,9 @@ flowoplib_opslimit(threadflow_t *threadflow, flowop_t *flowop)
flowop->fo_initted = 1;
}
+ (void) ipc_mutex_lock(&controlstats_lock);
ops = controlstats.fs_count;
+ (void) ipc_mutex_unlock(&controlstats_lock);
/* Is this the first time around */
if (flowop->fo_tputlast == 0) {
@@ -1141,8 +1167,10 @@ flowoplib_bwlimit(threadflow_t *threadflow, flowop_t *flowop)
flowop->fo_initted = 1;
}
+ (void) ipc_mutex_lock(&controlstats_lock);
bytes = (controlstats.fs_rbytes +
controlstats.fs_wbytes);
+ (void) ipc_mutex_unlock(&controlstats_lock);
/* Is this the first time around */
if (flowop->fo_tputlast == 0) {
@@ -1193,7 +1221,7 @@ flowoplib_bwlimit(threadflow_t *threadflow, flowop_t *flowop)
/*
* Stop filebench run when specified number of I/O bytes have been
- * transferred. Compares controlstats.fs_bytes with *flowop->value,
+ * transferred. Compares controlstats.fs_bytes with flowop->value,
* and if greater returns 1, stopping the run, if not, returns 0
* to continue running.
*/
@@ -1201,9 +1229,11 @@ static int
flowoplib_finishonbytes(threadflow_t *threadflow, flowop_t *flowop)
{
uint64_t b;
- uint64_t bytes = *flowop->fo_value;
+ uint64_t bytes = flowop->fo_constvalue; /* use constant value */
+ (void) ipc_mutex_lock(&controlstats_lock);
b = controlstats.fs_bytes;
+ (void) ipc_mutex_unlock(&controlstats_lock);
flowop_beginop(threadflow, flowop);
if (b > bytes) {
@@ -1225,9 +1255,11 @@ static int
flowoplib_finishoncount(threadflow_t *threadflow, flowop_t *flowop)
{
uint64_t ops;
- uint64_t count = *flowop->fo_value;
+ uint64_t count = flowop->fo_constvalue; /* use constant value */
+ (void) ipc_mutex_lock(&controlstats_lock);
ops = controlstats.fs_count;
+ (void) ipc_mutex_unlock(&controlstats_lock);
flowop_beginop(threadflow, flowop);
if (ops >= count) {
@@ -1286,12 +1318,12 @@ flowoplib_semblock_init(flowop_t *flowop)
}
if ((highwater = flowop->fo_semid_hw) == 0)
- highwater = *flowop->fo_value;
+ highwater = flowop->fo_constvalue; /* use constant value */
filebench_log(LOG_DEBUG_IMPL, "setting highwater to : %d", highwater);
sbuf[0].sem_num = (short)highwater;
- sbuf[0].sem_op = *flowop->fo_highwater;
+ sbuf[0].sem_op = avd_get_int(flowop->fo_highwater);
sbuf[0].sem_flg = 0;
if ((semop(semid, &sbuf[0], 1) == -1) && errno) {
filebench_log(LOG_ERROR, "semblock init post failed: %s (%d,"
@@ -1306,7 +1338,7 @@ flowoplib_semblock_init(flowop_t *flowop)
sem_init(&flowop->fo_sem, 1, 0);
#endif /* HAVE_SYSV_SEM */
- if (!(*flowop->fo_blocking))
+ if (!(avd_get_bool(flowop->fo_blocking)))
(void) ipc_mutex_unlock(&flowop->fo_lock);
return (FILEBENCH_OK);
@@ -1340,7 +1372,7 @@ flowoplib_semblock(threadflow_t *threadflow, flowop_t *flowop)
#ifdef HAVE_SYSV_SEM
struct sembuf sbuf[2];
- int value = *flowop->fo_value;
+ int value = avd_get_int(flowop->fo_value);
int semid;
struct timespec timeout;
@@ -1366,7 +1398,7 @@ flowoplib_semblock(threadflow_t *threadflow, flowop_t *flowop)
timeout.tv_sec = 600;
timeout.tv_nsec = 0;
- if (*flowop->fo_blocking)
+ if (avd_get_bool(flowop->fo_blocking))
(void) ipc_mutex_unlock(&flowop->fo_lock);
flowop_beginop(threadflow, flowop);
@@ -1379,13 +1411,13 @@ flowoplib_semblock(threadflow_t *threadflow, flowop_t *flowop)
(void) semop(semid, &sbuf[1], 1);
#endif /* HAVE_SEMTIMEDOP */
- if (*flowop->fo_blocking)
+ if (avd_get_bool(flowop->fo_blocking))
(void) ipc_mutex_lock(&flowop->fo_lock);
flowop_endop(threadflow, flowop, 0);
#else
- int value = *flowop->fo_value;
+ int value = avd_get_int(flowop->fo_value);
int i;
filebench_log(LOG_DEBUG_IMPL,
@@ -1471,8 +1503,8 @@ flowoplib_sempost(threadflow_t *threadflow, flowop_t *flowop)
#else
int i;
#endif /* HAVE_SYSV_SEM */
- int value = *flowop->fo_value;
struct timespec timeout;
+ int value = avd_get_int(flowop->fo_value);
if (target->fo_instance == FLOW_MASTER) {
target = target->fo_targetnext;
@@ -1505,7 +1537,7 @@ flowoplib_sempost(threadflow_t *threadflow, flowop_t *flowop)
timeout.tv_sec = 600;
timeout.tv_nsec = 0;
- if (*flowop->fo_blocking)
+ if (avd_get_bool(flowop->fo_blocking))
blocking = 1;
else
blocking = 0;
@@ -1605,13 +1637,21 @@ static int
flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd)
{
filesetentry_t *file;
+ char *fileset_name;
int tid = 0;
+ if ((fileset_name =
+ avd_get_str(flowop->fo_fileset->fs_name)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "flowop %s: fileset has no name", flowop->fo_name);
+ return (FILEBENCH_ERROR);
+ }
+
/*
* If the flowop doesn't default to persistent fd
* then get unique thread ID for use by fileset_pick
*/
- if (integer_isset(flowop->fo_rotatefd))
+ if (avd_get_bool(flowop->fo_rotatefd))
tid = threadflow->tf_utid;
if (threadflow->tf_fd[fd] != 0) {
@@ -1631,11 +1671,12 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd)
int open_attrs = 0;
char name[MAXPATHLEN];
- (void) strcpy(name, *flowop->fo_fileset->fs_path);
+ (void) strcpy(name,
+ avd_get_str(flowop->fo_fileset->fs_path));
(void) strcat(name, "/");
- (void) strcat(name, flowop->fo_fileset->fs_name);
+ (void) strcat(name, fileset_name);
- if (*flowop->fo_dsync) {
+ if (avd_get_bool(flowop->fo_dsync)) {
#ifdef sun
open_attrs |= O_DSYNC;
#else
@@ -1671,8 +1712,7 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd)
FILESET_PICKEXISTS, tid)) == NULL) {
filebench_log(LOG_DEBUG_SCRIPT,
"flowop %s failed to pick file from %s on fd %d",
- flowop->fo_name,
- flowop->fo_fileset->fs_name, fd);
+ flowop->fo_name, fileset_name, fd);
return (FILEBENCH_NORSC);
}
@@ -1684,8 +1724,8 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd)
flowop_endop(threadflow, flowop, 0);
if (threadflow->tf_fd[fd] < 0) {
- filebench_log(LOG_ERROR, "failed to open file %s",
- flowop->fo_name);
+ filebench_log(LOG_ERROR, "flowop %s failed to open file %s",
+ flowop->fo_name, file->fse_path);
return (FILEBENCH_ERROR);
}
@@ -1740,7 +1780,8 @@ flowoplib_createfile(threadflow_t *threadflow, flowop_t *flowop)
FILESET_PICKNOEXIST, 0)) == NULL) {
filebench_log(LOG_DEBUG_SCRIPT,
"flowop %s failed to pick file from fileset %s",
- flowop->fo_name, flowop->fo_fileset->fs_name);
+ flowop->fo_name,
+ avd_get_str(flowop->fo_fileset->fs_name));
return (FILEBENCH_NORSC);
}
@@ -1804,9 +1845,9 @@ flowoplib_deletefile(threadflow_t *threadflow, flowop_t *flowop)
}
*path = 0;
- (void) strcpy(path, *fileset->fs_path);
+ (void) strcpy(path, avd_get_str(fileset->fs_path));
(void) strcat(path, "/");
- (void) strcat(path, fileset->fs_name);
+ (void) strcat(path, avd_get_str(fileset->fs_name));
pathtmp = fileset_resolvepath(file);
(void) strcat(path, pathtmp);
free(pathtmp);
@@ -1962,9 +2003,9 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop)
}
*path = 0;
- (void) strcpy(path, *fileset->fs_path);
+ (void) strcpy(path, avd_get_str(fileset->fs_path));
(void) strcat(path, "/");
- (void) strcat(path, fileset->fs_name);
+ (void) strcat(path, avd_get_str(fileset->fs_name));
pathtmp = fileset_resolvepath(file);
(void) strcat(path, pathtmp);
free(pathtmp);
@@ -2003,9 +2044,10 @@ flowoplib_readwholefile(threadflow_t *threadflow, flowop_t *flowop)
off64_t bytes = 0;
int fd = flowop->fo_fdnumber;
int filedesc;
- int ret;
uint64_t wss;
- vinteger_t iosize = *flowop->fo_iosize;
+ fbint_t iosize;
+ int ret;
+ char zerordbuf;
/* get the file to use */
if ((ret = flowoplib_filesetup(threadflow, flowop, &wss,
@@ -2013,11 +2055,23 @@ flowoplib_readwholefile(threadflow_t *threadflow, flowop_t *flowop)
return (ret);
/* an I/O size of zero means read entire working set with one I/O */
- if (iosize == 0)
+ if ((iosize = avd_get_int(flowop->fo_iosize)) == 0)
iosize = wss;
- if (flowoplib_iobufsetup(threadflow, flowop, &iobuf, iosize) != 0)
- return (FILEBENCH_ERROR);
+ /*
+ * The file may actually be 0 bytes long, in which case skip
+ * the buffer set up call (which would fail) and substitute
+ * a small buffer, which won't really be used.
+ */
+ if (iosize == 0) {
+ iobuf = (caddr_t)&zerordbuf;
+ filebench_log(LOG_DEBUG_SCRIPT,
+ "flowop %s read zero length file", flowop->fo_name);
+ } else {
+ if (flowoplib_iobufsetup(threadflow, flowop, &iobuf,
+ iosize) != 0)
+ return (FILEBENCH_ERROR);
+ }
/* Measure time to read bytes */
flowop_beginop(threadflow, flowop);
@@ -2056,19 +2110,21 @@ static int
flowoplib_write(threadflow_t *threadflow, flowop_t *flowop)
{
caddr_t iobuf;
- vinteger_t wss;
+ fbint_t wss;
+ fbint_t iosize;
int filedesc;
int ret;
+ iosize = avd_get_int(flowop->fo_iosize);
if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf,
- &filedesc, *flowop->fo_iosize)) != FILEBENCH_OK)
+ &filedesc, iosize)) != FILEBENCH_OK)
return (ret);
- if (*flowop->fo_random) {
+ if (avd_get_bool(flowop->fo_random)) {
uint64_t fileoffset;
if (filebench_randomno64(&fileoffset,
- wss, *flowop->fo_iosize) == -1) {
+ wss, iosize, NULL) == -1) {
filebench_log(LOG_ERROR,
"file size smaller than IO size for thread %s",
flowop->fo_name);
@@ -2076,25 +2132,25 @@ flowoplib_write(threadflow_t *threadflow, flowop_t *flowop)
}
flowop_beginop(threadflow, flowop);
if (pwrite64(filedesc, iobuf,
- *flowop->fo_iosize, (off64_t)fileoffset) == -1) {
+ iosize, (off64_t)fileoffset) == -1) {
filebench_log(LOG_ERROR, "write failed, "
"offset %lld io buffer %zd: %s",
fileoffset, iobuf, strerror(errno));
flowop_endop(threadflow, flowop, 0);
return (FILEBENCH_ERROR);
}
- flowop_endop(threadflow, flowop, *flowop->fo_iosize);
+ flowop_endop(threadflow, flowop, iosize);
} else {
flowop_beginop(threadflow, flowop);
if (write(filedesc, iobuf,
- *flowop->fo_iosize) == -1) {
+ iosize) == -1) {
filebench_log(LOG_ERROR,
"write failed, io buffer %zd: %s",
iobuf, strerror(errno));
flowop_endop(threadflow, flowop, 0);
return (FILEBENCH_ERROR);
}
- flowop_endop(threadflow, flowop, *flowop->fo_iosize);
+ flowop_endop(threadflow, flowop, iosize);
}
return (FILEBENCH_OK);
@@ -2117,22 +2173,35 @@ flowoplib_writewholefile(threadflow_t *threadflow, flowop_t *flowop)
off64_t seek;
off64_t bytes = 0;
uint64_t wss;
+ fbint_t iosize;
int filedesc;
int srcfd = flowop->fo_srcfdnumber;
int ret;
- vinteger_t iosize = *flowop->fo_iosize;
+ char zerowrtbuf;
/* get the file to use */
if ((ret = flowoplib_filesetup(threadflow, flowop, &wss,
&filedesc)) != FILEBENCH_OK)
return (ret);
- /* an I/O size of zero means read entire working set with one I/O */
- if (iosize == 0)
+ /* an I/O size of zero means write entire working set with one I/O */
+ if ((iosize = avd_get_int(flowop->fo_iosize)) == 0)
iosize = wss;
- if (flowoplib_iobufsetup(threadflow, flowop, &iobuf, iosize) != 0)
- return (FILEBENCH_ERROR);
+ /*
+ * The file may actually be 0 bytes long, in which case skip
+ * the buffer set up call (which would fail) and substitute
+ * a small buffer, which won't really be used.
+ */
+ if (iosize == 0) {
+ iobuf = (caddr_t)&zerowrtbuf;
+ filebench_log(LOG_DEBUG_SCRIPT,
+ "flowop %s wrote zero length file", flowop->fo_name);
+ } else {
+ if (flowoplib_iobufsetup(threadflow, flowop, &iobuf,
+ iosize) != 0)
+ return (FILEBENCH_ERROR);
+ }
file = threadflow->tf_fse[srcfd];
if ((srcfd != 0) && (file == NULL)) {
@@ -2187,10 +2256,11 @@ flowoplib_appendfile(threadflow_t *threadflow, flowop_t *flowop)
{
caddr_t iobuf;
int filedesc;
- vinteger_t wss;
- vinteger_t iosize = *flowop->fo_iosize;
+ fbint_t wss;
+ fbint_t iosize;
int ret;
+ iosize = avd_get_int(flowop->fo_iosize);
if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf,
&filedesc, iosize)) != FILEBENCH_OK)
return (ret);
@@ -2205,10 +2275,10 @@ flowoplib_appendfile(threadflow_t *threadflow, flowop_t *flowop)
filebench_log(LOG_ERROR,
"Failed to write %d bytes on fd %d: %s",
iosize, filedesc, strerror(errno));
- flowop_endop(threadflow, flowop, 0);
+ flowop_endop(threadflow, flowop, ret);
return (FILEBENCH_ERROR);
}
- flowop_endop(threadflow, flowop, iosize);
+ flowop_endop(threadflow, flowop, ret);
return (FILEBENCH_OK);
}
@@ -2235,10 +2305,17 @@ flowoplib_appendfilerand(threadflow_t *threadflow, flowop_t *flowop)
caddr_t iobuf;
uint64_t appendsize;
int filedesc;
- vinteger_t wss;
- int ret;
+ fbint_t wss;
+ fbint_t iosize;
+ int ret = 0;
+
+ if ((iosize = avd_get_int(flowop->fo_iosize)) == 0) {
+ filebench_log(LOG_ERROR, "zero iosize for flowop %s",
+ flowop->fo_name);
+ return (FILEBENCH_ERROR);
+ }
- if (filebench_randomno64(&appendsize, *flowop->fo_iosize, 1LL) != 0)
+ if (filebench_randomno64(&appendsize, iosize, 1LL, NULL) != 0)
return (FILEBENCH_ERROR);
/* skip if attempting zero length append */
@@ -2272,6 +2349,92 @@ flowoplib_appendfilerand(threadflow_t *threadflow, flowop_t *flowop)
return (FILEBENCH_OK);
}
+typedef struct testrandvar_priv {
+ uint64_t sample_count;
+ double val_sum;
+ double sqr_sum;
+} testrandvar_priv_t;
+
+/*
+ * flowop to calculate various statistics from the number stream
+ * produced by a random variable. This allows verification that the
+ * random distribution used to define the random variable is producing
+ * the expected distribution of random numbers.
+ */
+/* ARGSUSED */
+static int
+flowoplib_testrandvar(threadflow_t *threadflow, flowop_t *flowop)
+{
+ testrandvar_priv_t *mystats;
+ double value;
+
+ if ((mystats = (testrandvar_priv_t *)flowop->fo_private) == NULL) {
+ filebench_log(LOG_ERROR, "testrandvar not initialized\n");
+ filebench_shutdown(1);
+ return (-1);
+ }
+
+ value = avd_get_dbl(flowop->fo_value);
+
+ mystats->sample_count++;
+ mystats->val_sum += value;
+ mystats->sqr_sum += (value * value);
+
+ return (0);
+}
+
+/*
+ * Initialize the private data area used to accumulate the statistics
+ */
+static int
+flowoplib_testrandvar_init(flowop_t *flowop)
+{
+ testrandvar_priv_t *mystats;
+
+ if ((mystats = (testrandvar_priv_t *)
+ malloc(sizeof (testrandvar_priv_t))) == NULL) {
+ filebench_log(LOG_ERROR, "could not initialize testrandvar");
+ filebench_shutdown(1);
+ return (-1);
+ }
+
+ mystats->sample_count = 0;
+ mystats->val_sum = 0;
+ mystats->sqr_sum = 0;
+ flowop->fo_private = (void *)mystats;
+
+ (void) ipc_mutex_unlock(&flowop->fo_lock);
+ return (0);
+}
+
+/*
+ * Print out the accumulated statistics, and free the private storage
+ */
+static void
+flowoplib_testrandvar_destruct(flowop_t *flowop)
+{
+ testrandvar_priv_t *mystats;
+ double mean, std_dev, dbl_count;
+
+ (void) ipc_mutex_lock(&flowop->fo_lock);
+ if ((mystats = (testrandvar_priv_t *)
+ flowop->fo_private) == NULL) {
+ (void) ipc_mutex_unlock(&flowop->fo_lock);
+ return;
+ }
+
+ flowop->fo_private = NULL;
+ (void) ipc_mutex_unlock(&flowop->fo_lock);
+
+ dbl_count = (double)mystats->sample_count;
+ mean = mystats->val_sum / dbl_count;
+ std_dev = sqrt((mystats->sqr_sum / dbl_count) - (mean * mean)) / mean;
+
+ filebench_log(LOG_VERBOSE,
+ "testrandvar: ops = %lld, mean = %8.2lf, stddev = %8.2lf",
+ mystats->sample_count, mean, std_dev);
+ free(mystats);
+}
/*
* Prints usage information for flowop operations.
diff --git a/usr/src/cmd/filebench/common/gamma_dist.c b/usr/src/cmd/filebench/common/gamma_dist.c
index 06552cbb1e..3ba0a74e8d 100644
--- a/usr/src/cmd/filebench/common/gamma_dist.c
+++ b/usr/src/cmd/filebench/common/gamma_dist.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.
*/
@@ -34,15 +34,20 @@
* From Knuth Volume 2, 3rd edition, pages 586 - 587.
*/
static double
-gamma_dist_knuth_algG(double a)
+gamma_dist_knuth_algG(double a, double (*src)(unsigned short *),
+ unsigned short *xi)
{
double p, U, V, X, q;
p = M_E/(a + M_E);
G2:
- U = drand48();
+ /* get a random number U */
+ U = (*src)(xi);
+
do {
- V = drand48();
+ /* get a random number V */
+ V = (*src)(xi);
+
} while (V == 0);
if (U < p) {
@@ -57,7 +62,10 @@ G2:
/*
* X now has density g, and q = f(X)/cg(X)
*/
- U = drand48();
+
+ /* get a random number U */
+ U = (*src)(xi);
+
if (U >= q)
goto G2;
return (X);
@@ -69,31 +77,66 @@ G2:
* From Knuth Volume 2, 3rd edition, page 134.
*/
static double
-gamma_dist_knuth_algA(double a)
+gamma_dist_knuth_algA(double a, double (*src)(unsigned short *),
+ unsigned short *xi)
{
double U, Y, X, V;
A1:
- U = drand48();
+ /* get a random number U */
+ U = (*src)(xi);
+
Y = tan(M_PI*U);
X = (sqrt((2*a) - 1) * Y) + a - 1;
if (X <= 0)
goto A1;
- V = drand48();
- /* V > (1 + Y^2) * exp((a - 1) * log(X / (a - 1)) - sqrt(2a - 1) * Y) */
+ /* get a random number V */
+ V = (*src)(xi);
+
if (V > ((1 + (Y*Y)) * exp((a-1) * log(X/(a-1)) - sqrt(2*a -1) * Y)))
goto A1;
return (X);
}
+/*
+ * fetch a uniformly distributed random number using the drand48 generator
+ */
+/* ARGSUSED */
+static double
+default_src(unsigned short *xi)
+{
+ return (drand48());
+}
+
+/*
+ * Sample the gamma distributed random variable with gamma 'a' and
+ * result mulitplier 'b', which is usually mean/gamma. Uses the default
+ * drand48 random number generator as input
+ */
double
gamma_dist_knuth(double a, double b)
{
if (a <= 1.0)
- return (b * gamma_dist_knuth_algG(a));
+ return (b * gamma_dist_knuth_algG(a, default_src, NULL));
+ else
+ return (b * gamma_dist_knuth_algA(a, default_src, NULL));
+}
+
+/*
+ * Sample the gamma distributed random variable with gamma 'a' and
+ * multiplier 'b', which is mean / gamma adjusted for the specified
+ * minimum value. The suppled random number source function is
+ * used to optain the uniformly distributed random numbers.
+ */
+double
+gamma_dist_knuth_src(double a, double b,
+ double (*src)(unsigned short *), unsigned short *xi)
+{
+ if (a <= 1.0)
+ return (b * gamma_dist_knuth_algG(a, src, xi));
else
- return (b * gamma_dist_knuth_algA(a));
+ return (b * gamma_dist_knuth_algA(a, src, xi));
}
diff --git a/usr/src/cmd/filebench/common/gamma_dist.h b/usr/src/cmd/filebench/common/gamma_dist.h
index 2773b626af..ff9375fe75 100644
--- a/usr/src/cmd/filebench/common/gamma_dist.h
+++ b/usr/src/cmd/filebench/common/gamma_dist.h
@@ -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.
*/
@@ -33,6 +33,8 @@ extern "C" {
#endif
double gamma_dist_knuth(double a, double b);
+double gamma_dist_knuth_src(double a, double b,
+ double (*src)(unsigned short *), unsigned short *xi);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/filebench/common/ipc.c b/usr/src/cmd/filebench/common/ipc.c
index 1311b4ab51..596a47ea87 100644
--- a/usr/src/cmd/filebench/common/ipc.c
+++ b/usr/src/cmd/filebench/common/ipc.c
@@ -410,14 +410,14 @@ ipc_attach(caddr_t shmaddr)
}
static int filebench_sizes[] = {
- FILEBENCH_NPROCFLOWS,
- FILEBENCH_NTHREADFLOWS,
- FILEBENCH_NFLOWOPS,
- FILEBENCH_NVARS,
- FILEBENCH_NVARS,
- FILEBENCH_NVARS,
- FILEBENCH_NFILESETS,
- FILEBENCH_NFILESETENTRIES};
+ FILEBENCH_NPROCFLOWS, /* number of procflows */
+ FILEBENCH_NTHREADFLOWS, /* number of threadflows */
+ FILEBENCH_NFLOWOPS, /* number of flowops */
+ (FILEBENCH_NVARS * 2), /* number of attribute value dscrs */
+ FILEBENCH_NVARS, /* number of variables */
+ FILEBENCH_NFILESETS, /* number of filesets */
+ FILEBENCH_NFILESETENTRIES, /* number of fileset entries */
+ FILEBENCH_NRANDDISTS}; /* number of random distributions */
/*
* Allocates filebench objects from pre allocated region of
@@ -480,21 +480,23 @@ ipc_malloc(int type)
(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
return ((char *)&filebench_shm->flowop[i]);
- case FILEBENCH_INTEGER:
- filebench_shm->integer_ptrs[i] = NULL;
+ case FILEBENCH_AVD:
+ filebench_shm->shm_avd_ptrs[i].avd_type = AVD_INVALID;
+ filebench_shm->shm_avd_ptrs[i].avd_val.varptr = NULL;
(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
- return ((char *)&filebench_shm->integer_ptrs[i]);
-
- case FILEBENCH_STRING:
- filebench_shm->string_ptrs[i] = NULL;
- (void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
- return ((char *)&filebench_shm->string_ptrs[i]);
+ return ((char *)&filebench_shm->shm_avd_ptrs[i]);
case FILEBENCH_VARIABLE:
(void) memset((char *)&filebench_shm->var[i], 0,
sizeof (var_t));
(void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
return ((char *)&filebench_shm->var[i]);
+
+ case FILEBENCH_RANDDIST:
+ (void) memset((char *)&filebench_shm->shm_randdist[i], 0,
+ sizeof (randdist_t));
+ (void) ipc_mutex_unlock(&filebench_shm->malloc_lock);
+ return ((char *)&filebench_shm->shm_randdist[i]);
}
filebench_log(LOG_ERROR, "Attempt to ipc_malloc unknown type (%d)!",
@@ -548,20 +550,20 @@ ipc_free(int type, char *addr)
size = sizeof (flowop_t);
break;
- case FILEBENCH_INTEGER:
- base = (caddr_t)&filebench_shm->integer_ptrs[0];
- size = sizeof (caddr_t);
- break;
-
- case FILEBENCH_STRING:
- base = (caddr_t)&filebench_shm->string_ptrs[0];
- size = sizeof (caddr_t);
+ case FILEBENCH_AVD:
+ base = (caddr_t)&filebench_shm->shm_avd_ptrs[0];
+ size = sizeof (avd_t);
break;
case FILEBENCH_VARIABLE:
base = (caddr_t)&filebench_shm->var[0];
size = sizeof (var_t);
break;
+
+ case FILEBENCH_RANDDIST:
+ base = (caddr_t)&filebench_shm->shm_randdist[0];
+ size = sizeof (randdist_t);
+ break;
}
offset = ((size_t)addr - (size_t)base);
diff --git a/usr/src/cmd/filebench/common/ipc.h b/usr/src/cmd/filebench/common/ipc.h
index 8eed540c66..0596d177df 100644
--- a/usr/src/cmd/filebench/common/ipc.h
+++ b/usr/src/cmd/filebench/common/ipc.h
@@ -35,6 +35,7 @@
#include "threadflow.h"
#include "fileset.h"
#include "flowop.h"
+#include "fb_random.h"
#include "filebench.h"
#ifdef __cplusplus
@@ -50,21 +51,22 @@ extern "C" {
#define FILEBENCH_NFILESETS FILEBENCH_MEMSIZE
#define FILEBENCH_NFILESETENTRIES (1024 * 1024)
#define FILEBENCH_NPROCFLOWS FILEBENCH_MEMSIZE
-#define FILEBENCH_NTHREADFLOWS 64 * FILEBENCH_MEMSIZE
-#define FILEBENCH_NFLOWOPS 64 * FILEBENCH_MEMSIZE
+#define FILEBENCH_NTHREADFLOWS (64 * FILEBENCH_MEMSIZE)
+#define FILEBENCH_NFLOWOPS (64 * FILEBENCH_MEMSIZE)
#define FILEBENCH_NVARS FILEBENCH_MEMSIZE
-#define FILEBENCH_FILESETPATHMEMORY FILEBENCH_NFILESETENTRIES*FSE_MAXPATHLEN
-#define FILEBENCH_STRINGMEMORY FILEBENCH_NVARS * 128
+#define FILEBENCH_NRANDDISTS (FILEBENCH_MEMSIZE/4)
+#define FILEBENCH_FILESETPATHMEMORY (FILEBENCH_NFILESETENTRIES*FSE_MAXPATHLEN)
+#define FILEBENCH_STRINGMEMORY (FILEBENCH_NVARS * 128)
#define FILEBENCH_MAXBITMAP FILEBENCH_NFILESETENTRIES
#define FILEBENCH_PROCFLOW 0
#define FILEBENCH_THREADFLOW 1
#define FILEBENCH_FLOWOP 2
-#define FILEBENCH_INTEGER 3
-#define FILEBENCH_STRING 4
-#define FILEBENCH_VARIABLE 5
-#define FILEBENCH_FILESET 6
-#define FILEBENCH_FILESETENTRY 7
+#define FILEBENCH_AVD 3
+#define FILEBENCH_VARIABLE 4
+#define FILEBENCH_FILESET 5
+#define FILEBENCH_FILESETENTRY 6
+#define FILEBENCH_RANDDIST 7
#define FILEBENCH_TYPES 8
#define FILEBENCH_NSEMS 128
@@ -95,6 +97,7 @@ typedef struct filebench_shm {
procflow_t *proclist;
var_t *var_list;
var_t *var_dyn_list;
+ randdist_t *shm_rand_list;
int debug_level;
hrtime_t epoch;
hrtime_t starttime;
@@ -130,8 +133,8 @@ typedef struct filebench_shm {
threadflow_t threadflow[FILEBENCH_NTHREADFLOWS];
flowop_t flowop[FILEBENCH_NFLOWOPS];
var_t var[FILEBENCH_NVARS];
- vinteger_t integer_ptrs[FILEBENCH_NVARS];
- char *string_ptrs[FILEBENCH_NVARS];
+ randdist_t shm_randdist[FILEBENCH_NRANDDISTS];
+ struct avd shm_avd_ptrs[FILEBENCH_NVARS * 2];
char strings[FILEBENCH_STRINGMEMORY];
char semids[FILEBENCH_NSEMS];
int bitmap[FILEBENCH_TYPES][FILEBENCH_MAXBITMAP];
diff --git a/usr/src/cmd/filebench/common/misc.c b/usr/src/cmd/filebench/common/misc.c
index e611e1e468..820f41c2e9 100644
--- a/usr/src/cmd/filebench/common/misc.c
+++ b/usr/src/cmd/filebench/common/misc.c
@@ -39,9 +39,8 @@
/*
* Routines to access high resolution system time, initialize and
- * shutdown filebench, obtain system generated random numbers from
- * "urandom", log filebench run progress and errors, and access system
- * information strings.
+ * shutdown filebench, log filebench run progress and errors, and
+ * access system information strings.
*/
@@ -115,7 +114,6 @@ parse_cpu_hz(void)
break;
}
}
- printf("CPU Mhz %9.6f, sysconf:%ld\n", hertz, sysconf(_SC_CLK_TCK));
hz = hertz * 1000000;
return (hz);
@@ -142,8 +140,6 @@ gethrtime(void)
}
#endif
-static int urandomfd;
-
/*
* Main filebench initialization. Opens the random number
* "device" file or shuts down the run if one is not found.
@@ -153,12 +149,8 @@ static int urandomfd;
void
filebench_init(void)
{
- /* open the "urandom" random number device file */
- if ((urandomfd = open("/dev/urandom", O_RDONLY)) < 0) {
- filebench_log(LOG_ERROR, "open /dev/urandom failed: %s",
- strerror(errno));
- filebench_shutdown(1);
- }
+ fb_random_init();
+
#if defined(USE_RDTSC) && (LINUX_PORT)
cpu_hz = parse_cpu_hz();
if (cpu_hz <= 0) {
@@ -170,93 +162,6 @@ filebench_init(void)
}
-/*
- * Reads a 64 bit random number from the urandom "file".
- * Shuts down the run if the read fails. Otherwise returns
- * the random number after rounding it off by "round".
- * Returns 0 on success, -1 on failure.
- */
-int
-filebench_randomno64(uint64_t *randp, uint64_t max, uint64_t round)
-{
- uint64_t random;
-
- /* check for round value too large */
- if (max <= round) {
- *randp = 0;
-
- /* if it just fits, its ok, otherwise error */
- if (max == round)
- return (0);
- else
- return (-1);
- }
-
- if (read(urandomfd, &random,
- sizeof (uint64_t)) != sizeof (uint64_t)) {
- filebench_log(LOG_ERROR, "read /dev/urandom failed: %s",
- strerror(errno));
- filebench_shutdown(1);
- }
-
- /* clip with max and optionally round */
- max -= round;
- random = random / (FILEBENCH_RANDMAX64 / max);
- if (round) {
- random = random / round;
- random *= round;
- }
- if (random > max)
- random = max;
-
- *randp = random;
- return (0);
-}
-
-
-/*
- * Reads a 32 bit random number from the urandom "file".
- * Shuts down the run if the read fails. Otherwise returns
- * the random number after rounding it off by "round".
- * Returns 0 on success, -1 on failure.
- */
-int
-filebench_randomno32(uint32_t *randp, uint32_t max, uint32_t round)
-{
- uint32_t random;
-
- /* check for round value too large */
- if (max <= round) {
- *randp = 0;
-
- /* if it just fits, its ok, otherwise error */
- if (max == round)
- return (0);
- else
- return (-1);
- }
-
- if (read(urandomfd, &random,
- sizeof (uint32_t)) != sizeof (uint32_t)) {
- filebench_log(LOG_ERROR, "read /dev/urandom failed: %s",
- strerror(errno));
- filebench_shutdown(1);
- }
-
- /* clip with max and optionally round */
- max -= round;
- random = random / (FILEBENCH_RANDMAX32 / max);
- if (round) {
- random = random / round;
- random *= round;
- }
- if (random > max)
- random = max;
-
- *randp = random;
- return (0);
-}
-
extern int lex_lineno;
/*
@@ -430,7 +335,7 @@ filebench_shutdown(int error) {
* Put the hostname in ${hostname}. The system supplied
* host name string is copied into an allocated string and
* the pointer to the string is placed in the supplied
- * variable "var". If var->var_string already points to
+ * variable "var". If var->var_val.string already points to
* a string, the string is freed. The routine always
* returns zero (0).
*/
@@ -438,26 +343,36 @@ var_t *
host_var(var_t *var)
{
char hoststr[128];
+ char *strptr;
(void) gethostname(hoststr, 128);
- if (var->var_string)
- free(var->var_string);
- var->var_string = fb_stralloc(hoststr);
+ if (VAR_HAS_STRING(var) && var->var_val.string)
+ free(var->var_val.string);
+
+ if ((strptr = fb_stralloc(hoststr)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "unable to allocate string for host name");
+ return (NULL);
+ }
+
+ VAR_SET_STR(var, strptr);
return (0);
}
/*
* Put the date string in ${date}. The system supplied date is
* copied into an allocated string and the pointer to the string
- * is placed in the supplied var_t's var_string. If
- * var->var_string already points to a string, the string
- * is freed. The routine always returns a pointer to the
- * supplied var_t.
+ * is placed in the supplied var_t's var_val.string. If
+ * var->var_val.string already points to a string, the string
+ * is freed. The routine returns a pointer to the supplied var_t,
+ * unless it is unable to allocate string for the date, in which
+ * case it returns NULL.
*/
var_t *
date_var(var_t *var)
{
char datestr[128];
+ char *strptr;
#ifdef HAVE_CFTIME
time_t t = time(NULL);
#else
@@ -470,9 +385,16 @@ date_var(var_t *var)
(void) strftime(datestr, sizeof (datestr), "%y%m%d%H %M", &t);
#endif
- if (var->var_string)
- free(var->var_string);
- var->var_string = fb_stralloc(datestr);
+ if (VAR_HAS_STRING(var) && var->var_val.string)
+ free(var->var_val.string);
+
+ if ((strptr = fb_stralloc(datestr)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "unable to allocate string for date");
+ return (NULL);
+ }
+
+ VAR_SET_STR(var, strptr);
return (var);
}
@@ -483,15 +405,17 @@ extern char *fscriptname;
* Put the script name in ${script}. The path name of the script
* used with this filebench run trimmed of the trailing ".f" and
* all leading subdirectories. The remaining script name is
- * copied into the var_string field of the supplied variable
- * "var". The routine always returns a pointer to the supplied
- * var_t.
+ * copied into the var_val.string field of the supplied variable
+ * "var". The routine returns a pointer to the supplied var_t,
+ * unless it is unable to allocate string space, in which case it
+ * returns NULL.
*/
var_t *
script_var(var_t *var)
{
char *scriptstr;
char *f = fb_stralloc(fscriptname);
+ char *strptr;
/* Trim the .f suffix */
for (scriptstr = f + strlen(f) - 1; scriptstr != f; scriptstr--) {
@@ -501,7 +425,14 @@ script_var(var_t *var)
}
}
- var->var_string = fb_stralloc(basename(f));
+ if ((strptr = fb_stralloc(basename(f))) == NULL) {
+ filebench_log(LOG_ERROR,
+ "unable to allocate string for script name");
+ free(f);
+ return (NULL);
+ }
+
+ VAR_SET_STR(var, strptr);
free(f);
return (var);
diff --git a/usr/src/cmd/filebench/common/parser_gram.y b/usr/src/cmd/filebench/common/parser_gram.y
index 4a8a80de57..4f159f436a 100644
--- a/usr/src/cmd/filebench/common/parser_gram.y
+++ b/usr/src/cmd/filebench/common/parser_gram.y
@@ -1,4 +1,3 @@
-
/*
* CDDL HEADER START
*
@@ -92,16 +91,20 @@ static attr_t *get_attr_bool(cmd_t *cmd, int64_t name);
static var_t *alloc_var(void);
static var_t *get_var(cmd_t *cmd, int64_t name);
static list_t *alloc_list();
+static probtabent_t *alloc_probtabent(void);
/* Info Commands */
static void parser_list(cmd_t *);
+static void parser_flowop_list(cmd_t *);
/* Define Commands */
static void parser_proc_define(cmd_t *);
static void parser_thread_define(cmd_t *, procflow_t *, int instances);
-static void parser_flowop_define(cmd_t *, threadflow_t *);
+static void parser_flowop_define(cmd_t *, threadflow_t *, flowop_t **, int);
static void parser_file_define(cmd_t *);
static void parser_fileset_define(cmd_t *);
+static void parser_randvar_define(cmd_t *);
+static void parser_randvar_set(cmd_t *);
/* Create Commands */
static void parser_proc_create(cmd_t *);
@@ -109,6 +112,10 @@ static void parser_thread_create(cmd_t *);
static void parser_flowop_create(cmd_t *);
static void parser_fileset_create(cmd_t *);
+/* set commands */
+static void parser_set_integer(char *, fbint_t);
+static void parser_set_var(char *, char *);
+
/* Shutdown Commands */
static void parser_proc_shutdown(cmd_t *);
static void parser_filebench_shutdown(cmd_t *cmd);
@@ -139,13 +146,15 @@ static void parser_abort(int arg);
%}
%union {
- int64_t ival;
- uchar_t bval;
- char * sval;
- fs_u val;
- cmd_t *cmd;
- attr_t *attr;
- list_t *list;
+ int64_t ival;
+ uchar_t bval;
+ char * sval;
+ fs_u val;
+ avd_t avd;
+ cmd_t *cmd;
+ attr_t *attr;
+ list_t *list;
+ probtabent_t *rndtb;
}
%start commands
@@ -155,9 +164,10 @@ static void parser_abort(int arg);
%token FSC_SYSTEM FSC_FLOWOP FSC_EVENTGEN FSC_ECHO FSC_LOAD FSC_RUN
%token FSC_USAGE FSC_HELP FSC_VARS
%token FSV_STRING FSV_VAL_INT FSV_VAL_BOOLEAN FSV_VARIABLE FSV_WHITESTRING
+%token FSV_RANDUNI FSV_RANDTAB FSV_RANDVAR FSV_URAND FSV_RAND48
%token FST_INT FST_BOOLEAN
%token FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSE_ALL FSE_SNAP FSE_DUMP
-%token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP FSE_MODE
+%token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP FSE_RAND FSE_MODE
%token FSK_SEPLST FSK_OPENLST FSK_CLOSELST FSK_ASSIGN FSK_IN FSK_QUOTE
%token FSK_DIRSEPLST
%token FSA_SIZE FSA_PREALLOC FSA_PARALLOC FSA_PATH FSA_REUSE
@@ -165,14 +175,18 @@ static void parser_abort(int arg);
%token FSA_IOSIZE FSA_FILE FSA_WSS FSA_NAME FSA_RANDOM FSA_INSTANCES
%token FSA_DSYNC FSA_TARGET FSA_ITERS FSA_NICE FSA_VALUE FSA_BLOCKING
%token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD
-%token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA
-%token FSA_DIRGAMMA FSA_USEISM FSA_ALLDONE FSA_FIRSTDONE FSA_TIMEOUT
+%token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA FSA_DIRDEPTHRV
+%token FSA_DIRGAMMA FSA_USEISM FSA_TYPE FSA_RANDTABLE FSA_RANDSRC FSA_RANDROUND
+%token FSA_RANDSEED FSA_RANDGAMMA FSA_RANDMEAN FSA_RANDMIN
+%token FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC FSS_ROUND
+%token FSA_ALLDONE FSA_FIRSTDONE FSA_TIMEOUT
%type <ival> FSV_VAL_INT
%type <bval> FSV_VAL_BOOLEAN
%type <sval> FSV_STRING
%type <sval> FSV_WHITESTRING
%type <sval> FSV_VARIABLE
+%type <sval> FSV_RANDVAR
%type <sval> FSK_ASSIGN
%type <ival> FSC_LIST FSC_DEFINE FSC_SET FSC_LOAD FSC_RUN
@@ -182,21 +196,29 @@ static void parser_abort(int arg);
%type <ival> entity
%type <val> value
-%type <cmd> command inner_commands load_command run_command
-%type <cmd> list_command define_command debug_command create_command
+%type <cmd> command inner_commands load_command run_command list_command
+%type <cmd> proc_define_command files_define_command randvar_define_command
+%type <cmd> debug_command create_command
%type <cmd> sleep_command stats_command set_command shutdown_command
%type <cmd> foreach_command log_command system_command flowop_command
%type <cmd> eventgen_command quit_command flowop_list thread_list
%type <cmd> thread echo_command usage_command help_command vars_command
-%type <attr> attr_op attr_ops
-%type <attr> attr_value
-%type <list> integer_seplist string_seplist string_list var_string_list var_string
-%type <list> whitevar_string whitevar_string_list
-%type <ival> attrs_define_file attrs_define_thread attrs_flowop attrs_define_fileset
-%type <ival> attrs_define_proc attrs_eventgen
-%type <ival> attr_name
-
+%type <attr> files_attr_op files_attr_ops pt_attr_op pt_attr_ops
+%type <attr> fo_attr_op fo_attr_ops ev_attr_op ev_attr_ops
+%type <attr> randvar_attr_op randvar_attr_ops randvar_attr_typop
+%type <attr> randvar_attr_srcop attr_value attr_list_value
+%type <list> integer_seplist string_seplist string_list var_string_list
+%type <list> var_string whitevar_string whitevar_string_list
+%type <ival> attrs_define_file attrs_define_thread attrs_flowop
+%type <ival> attrs_define_fileset attrs_define_proc attrs_eventgen
+%type <ival> files_attr_name pt_attr_name fo_attr_name ev_attr_name
+%type <ival> randvar_attr_name FSA_TYPE randtype_name randvar_attr_param
+%type <ival> randsrc_name FSA_RANDSRC randvar_attr_tsp
+%type <ival> FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC
+
+%type <rndtb> probtabentry_list probtabentry
+%type <avd> var_int_val
%%
commands: commands command
@@ -240,7 +262,9 @@ inner_commands: command
};
command:
- define_command
+ proc_define_command
+| files_define_command
+| randvar_define_command
| debug_command
| eventgen_command
| create_command
@@ -284,9 +308,8 @@ foreach_command: FSC_FOREACH
inner_cmd = inner_cmd->cmd_next) {
filebench_log(LOG_DEBUG_IMPL,
"packing foreach: %zx %s=%lld, cmd %zx",
- $$,
- $$->cmd_tgt1,
- *list->list_integer, inner_cmd);
+ $$, $$->cmd_tgt1,
+ avd_get_int(list->list_integer), inner_cmd);
}
}
}| foreach_command FSV_VARIABLE FSK_IN string_seplist FSK_OPENLST inner_commands FSK_CLOSELST
@@ -319,7 +342,7 @@ integer_seplist: FSV_VAL_INT
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_integer = integer_alloc($1);
+ $$->list_integer = avd_int_alloc($1);
}
| integer_seplist FSK_SEPLST FSV_VAL_INT
{
@@ -329,7 +352,7 @@ integer_seplist: FSV_VAL_INT
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_integer = integer_alloc($3);
+ $$->list_integer = avd_int_alloc($3);
/* Find end of list */
for (list = $1; list != NULL;
@@ -344,7 +367,7 @@ string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
}
| string_seplist FSK_SEPLST FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
{
@@ -354,7 +377,7 @@ string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($4);
+ $$->list_string = avd_str_alloc($4);
/* Find end of list */
for (list = $1; list != NULL;
@@ -370,7 +393,7 @@ eventgen_command: FSC_EVENTGEN
YYERROR;
$$->cmd = &parser_eventgen;
}
-| eventgen_command attr_ops
+| eventgen_command ev_attr_ops
{
$1->cmd_attr_list = $2;
};
@@ -414,8 +437,7 @@ string_list: FSV_VARIABLE
{
if (($$ = alloc_list()) == NULL)
YYERROR;
-
- $$->list_string = string_alloc($1);
+ $$->list_string = avd_str_alloc($1);
}
| string_list FSK_SEPLST FSV_VARIABLE
{
@@ -425,7 +447,7 @@ string_list: FSV_VARIABLE
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($3);
+ $$->list_string = avd_str_alloc($3);
/* Find end of list */
for (list = $1; list != NULL;
@@ -440,14 +462,14 @@ var_string: FSV_VARIABLE
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($1);
+ $$->list_string = avd_str_alloc($1);
}
| FSV_STRING
{
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($1);
+ $$->list_string = avd_str_alloc($1);
};
var_string_list: var_string
@@ -462,7 +484,7 @@ var_string_list: var_string
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -480,7 +502,7 @@ var_string_list: var_string
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -497,7 +519,7 @@ var_string_list: var_string
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -515,7 +537,7 @@ var_string_list: var_string
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -530,14 +552,14 @@ whitevar_string: FSK_QUOTE FSV_VARIABLE
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
}
| FSK_QUOTE FSV_WHITESTRING
{
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
};
whitevar_string_list: whitevar_string FSV_WHITESTRING
@@ -549,7 +571,7 @@ whitevar_string_list: whitevar_string FSV_WHITESTRING
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -567,7 +589,7 @@ whitevar_string_list: whitevar_string FSV_WHITESTRING
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -575,7 +597,25 @@ whitevar_string_list: whitevar_string FSV_WHITESTRING
list_end = list;
list_end->list_next = $$;
$$ = $1;
-} |whitevar_string_list FSV_WHITESTRING
+}| whitevar_string FSV_RANDVAR randvar_attr_tsp
+{
+ list_t *list = NULL;
+ list_t *list_end = NULL;
+
+ /* Add variable */
+ if (($$ = alloc_list()) == NULL)
+ YYERROR;
+
+ $$->list_string = avd_str_alloc($2);
+ $$->list_integer = avd_int_alloc($3);
+
+ /* Find end of list */
+ for (list = $1; list != NULL;
+ list = list->list_next)
+ list_end = list;
+ list_end->list_next = $$;
+ $$ = $1;
+}| whitevar_string_list FSV_WHITESTRING
{
list_t *list = NULL;
list_t *list_end = NULL;
@@ -584,7 +624,7 @@ whitevar_string_list: whitevar_string FSV_WHITESTRING
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
/* Find end of list */
for (list = $1; list != NULL;
@@ -602,7 +642,25 @@ whitevar_string_list: whitevar_string FSV_WHITESTRING
if (($$ = alloc_list()) == NULL)
YYERROR;
- $$->list_string = string_alloc($2);
+ $$->list_string = avd_str_alloc($2);
+
+ /* Find end of list */
+ for (list = $1; list != NULL;
+ list = list->list_next)
+ list_end = list;
+ list_end->list_next = $$;
+ $$ = $1;
+}| whitevar_string_list FSV_RANDVAR randvar_attr_tsp
+{
+ list_t *list = NULL;
+ list_t *list_end = NULL;
+
+ /* Add variable */
+ if (($$ = alloc_list()) == NULL)
+ YYERROR;
+
+ $$->list_string = avd_str_alloc($2);
+ $$->list_integer = avd_int_alloc($3);
/* Find end of list */
for (list = $1; list != NULL;
@@ -623,6 +681,10 @@ list_command: FSC_LIST
if (($$ = alloc_cmd()) == NULL)
YYERROR;
$$->cmd = &parser_list;
+}
+| list_command FSC_FLOWOP
+{
+ $1->cmd = &parser_flowop_list;
};
log_command: FSC_LOG whitevar_string_list
@@ -654,6 +716,17 @@ set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
}
$$->cmd = NULL;
}
+| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_BOOLEAN
+{
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ var_assign_boolean($2, $4);
+ if (parentscript) {
+ $$->cmd_tgt1 = $2;
+ parser_vars($$);
+ }
+ $$->cmd = NULL;
+}
| FSC_SET FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE
{
if (($$ = alloc_cmd()) == NULL)
@@ -702,6 +775,33 @@ set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT
if (($$ = alloc_cmd()) == NULL)
YYERROR;
$$->cmd = NULL;
+}| FSC_SET FSV_RANDVAR FSS_TYPE FSK_ASSIGN randvar_attr_typop
+{
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ $$->cmd = &parser_randvar_set;
+ $$->cmd_tgt1 = $2;
+ $$->cmd_qty = FSS_TYPE;
+ $$->cmd_attr_list = $5;
+
+}| FSC_SET FSV_RANDVAR FSS_SRC FSK_ASSIGN randvar_attr_srcop
+{
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ $$->cmd = &parser_randvar_set;
+ $$->cmd_tgt1 = $2;
+ $$->cmd_qty = FSS_SRC;
+ $$->cmd_attr_list = $5;
+
+}| FSC_SET FSV_RANDVAR randvar_attr_param FSK_ASSIGN attr_value
+{
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ $$->cmd = &parser_randvar_set;
+ $$->cmd_tgt1 = $2;
+ $$->cmd_qty = $3;
+ $$->cmd_attr_list = $5;
+
};
stats_command: FSC_STATS FSE_SNAP
@@ -779,7 +879,7 @@ flowop_list: flowop_command
$$ = $1;
};
-thread: FSE_THREAD attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
+thread: FSE_THREAD pt_attr_ops FSK_OPENLST flowop_list FSK_CLOSELST
{
/*
* Allocate a cmd node per thread, with a
@@ -812,7 +912,7 @@ thread_list: thread
$$ = $1;
};
-define_command: FSC_DEFINE FSE_PROC attr_ops FSK_OPENLST thread_list FSK_CLOSELST
+proc_define_command: FSC_DEFINE FSE_PROC pt_attr_ops FSK_OPENLST thread_list FSK_CLOSELST
{
if (($$ = alloc_cmd()) == NULL)
YYERROR;
@@ -820,7 +920,13 @@ define_command: FSC_DEFINE FSE_PROC attr_ops FSK_OPENLST thread_list FSK_CLOSELS
$$->cmd_list = $5;
$$->cmd_attr_list = $3;
-}| FSC_DEFINE FSE_FILE
+}
+| proc_define_command pt_attr_ops
+{
+ $1->cmd_attr_list = $2;
+};
+
+files_define_command: FSC_DEFINE FSE_FILE
{
if (($$ = alloc_cmd()) == NULL)
YYERROR;
@@ -831,11 +937,19 @@ define_command: FSC_DEFINE FSE_PROC attr_ops FSK_OPENLST thread_list FSK_CLOSELS
YYERROR;
$$->cmd = &parser_fileset_define;
}
-| define_command attr_ops
+| files_define_command files_attr_ops
{
$1->cmd_attr_list = $2;
};
+randvar_define_command: FSC_DEFINE FSE_RAND randvar_attr_ops
+{
+ if (($$ = alloc_cmd()) == NULL)
+ YYERROR;
+ $$->cmd = &parser_randvar_define;
+ $$->cmd_attr_list = $3;
+};
+
create_command: FSC_CREATE entity
{
if (($$ = alloc_cmd()) == NULL)
@@ -879,7 +993,7 @@ sleep_command: FSC_SLEEP FSV_VAL_INT
}
| FSC_SLEEP FSV_VARIABLE
{
- vinteger_t *integer;
+ fbint_t *integer;
if (($$ = alloc_cmd()) == NULL)
YYERROR;
@@ -896,7 +1010,7 @@ run_command: FSC_RUN FSV_VAL_INT
}
| FSC_RUN FSV_VARIABLE
{
- vinteger_t *integer;
+ fbint_t *integer;
if (($$ = alloc_cmd()) == NULL)
YYERROR;
@@ -905,7 +1019,7 @@ run_command: FSC_RUN FSV_VAL_INT
}
| FSC_RUN
{
- vinteger_t *integer;
+ fbint_t *integer;
if (($$ = alloc_cmd()) == NULL)
YYERROR;
@@ -926,7 +1040,7 @@ flowop_command: FSC_FLOWOP name
YYERROR;
$$->cmd_name = fb_stralloc($2);
}
-| flowop_command attr_ops
+| flowop_command fo_attr_ops
{
$1->cmd_attr_list = $2;
};
@@ -958,6 +1072,7 @@ load_command: FSC_LOAD FSV_STRING
yy_switchfileparent(yyin);
};
+
entity: FSE_PROC {$$ = FSE_PROC;}
| FSE_THREAD {$$ = FSE_THREAD;}
| FSE_FILESET {$$ = FSE_FILESET;}
@@ -969,11 +1084,130 @@ value: FSV_VAL_INT { $$.i = $1;}
name: FSV_STRING;
-attr_ops: attr_op
+/* attribute parsing for define file and define fileset */
+files_attr_ops: files_attr_op
+{
+ $$ = $1;
+}
+| files_attr_ops FSK_SEPLST files_attr_op
+{
+ attr_t *attr = NULL;
+ attr_t *list_end = NULL;
+
+ for (attr = $1; attr != NULL;
+ attr = attr->attr_next)
+ list_end = attr; /* Find end of list */
+
+ list_end->attr_next = $3;
+
+ $$ = $1;
+};
+
+files_attr_op: files_attr_name FSK_ASSIGN attr_list_value
+{
+ $$ = $3;
+ $$->attr_name = $1;
+}
+| files_attr_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_name = $1;
+};
+
+/* attribute parsing for random variables */
+randvar_attr_ops: randvar_attr_op
+{
+ $$ = $1;
+}
+| randvar_attr_ops FSK_SEPLST randvar_attr_op
+{
+ attr_t *attr = NULL;
+ attr_t *list_end = NULL;
+
+ for (attr = $1; attr != NULL;
+ attr = attr->attr_next)
+ list_end = attr; /* Find end of list */
+
+ list_end->attr_next = $3;
+
+ $$ = $1;
+}
+| randvar_attr_ops FSK_SEPLST FSA_RANDTABLE FSK_ASSIGN FSK_OPENLST probtabentry_list FSK_CLOSELST
+{
+ attr_t *attr = NULL;
+ attr_t *list_end = NULL;
+
+ for (attr = $1; attr != NULL;
+ attr = attr->attr_next)
+ list_end = attr; /* Find end of list */
+
+
+ if ((attr = alloc_attr()) == NULL)
+ YYERROR;
+
+ attr->attr_name = FSA_RANDTABLE;
+ attr->attr_obj = (void *)$6;
+ list_end->attr_next = attr;
+ $$ = $1;
+};
+
+randvar_attr_op: randvar_attr_name FSK_ASSIGN attr_list_value
+{
+ $$ = $3;
+ $$->attr_name = $1;
+}
+| randvar_attr_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_name = $1;
+}
+| FSA_TYPE FSK_ASSIGN randvar_attr_typop
+{
+ $$ = $3;
+ $$->attr_name = FSA_TYPE;
+}
+| FSA_RANDSRC FSK_ASSIGN randvar_attr_srcop
+{
+ $$ = $3;
+ $$->attr_name = FSA_RANDSRC;
+};
+
+probtabentry: FSK_OPENLST var_int_val FSK_SEPLST var_int_val FSK_SEPLST var_int_val FSK_CLOSELST
+{
+ if (($$ = alloc_probtabent()) == NULL)
+ YYERROR;
+ $$->pte_percent = $2;
+ $$->pte_segmin = $4;
+ $$->pte_segmax = $6;
+};
+
+/* attribute parsing for prob density function table */
+probtabentry_list: probtabentry
{
$$ = $1;
}
-| attr_ops FSK_SEPLST attr_op
+| probtabentry_list FSK_SEPLST probtabentry
+{
+ probtabent_t *pte = NULL;
+ probtabent_t *ptelist_end = NULL;
+
+ for (pte = $1; pte != NULL;
+ pte = pte->pte_next)
+ ptelist_end = pte; /* Find end of prob table entry list */
+
+ ptelist_end->pte_next = $3;
+
+ $$ = $1;
+};
+
+/* attribute parsing for define thread and process */
+pt_attr_ops: pt_attr_op
+{
+ $$ = $1;
+}
+| pt_attr_ops FSK_SEPLST pt_attr_op
{
attr_t *attr = NULL;
attr_t *list_end = NULL;
@@ -987,73 +1221,211 @@ attr_ops: attr_op
$$ = $1;
};
-attr_op: attr_name FSK_ASSIGN attr_value
+pt_attr_op: pt_attr_name FSK_ASSIGN attr_value
{
$$ = $3;
$$->attr_name = $1;
}
-| attr_name
+| pt_attr_name
{
if (($$ = alloc_attr()) == NULL)
YYERROR;
$$->attr_name = $1;
+};
+
+/* attribute parsing for flowops */
+fo_attr_ops: fo_attr_op
+{
+ $$ = $1;
}
+| fo_attr_ops FSK_SEPLST fo_attr_op
+{
+ attr_t *attr = NULL;
+ attr_t *list_end = NULL;
+
+ for (attr = $1; attr != NULL;
+ attr = attr->attr_next)
+ list_end = attr; /* Find end of list */
+
+ list_end->attr_next = $3;
+
+ $$ = $1;
+};
+
+fo_attr_op: fo_attr_name FSK_ASSIGN attr_value
+{
+ $$ = $3;
+ $$->attr_name = $1;
+}
+| fo_attr_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_name = $1;
+};
+
+/* attribute parsing for Event Generator */
+ev_attr_ops: ev_attr_op
+{
+ $$ = $1;
+}
+| ev_attr_ops FSK_SEPLST ev_attr_op
+{
+ attr_t *attr = NULL;
+ attr_t *list_end = NULL;
+
+ for (attr = $1; attr != NULL;
+ attr = attr->attr_next)
+ list_end = attr; /* Find end of list */
+
+ list_end->attr_next = $3;
+
+ $$ = $1;
+};
+
+ev_attr_op: ev_attr_name FSK_ASSIGN attr_value
+{
+ $$ = $3;
+ $$->attr_name = $1;
+}
+| ev_attr_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_name = $1;
+};
+
+
+files_attr_name: attrs_define_file
+|attrs_define_fileset;
+
+pt_attr_name: attrs_define_thread
+|attrs_define_proc;
-attr_name: attrs_define_file
-|attrs_define_fileset
-|attrs_define_thread
-|attrs_define_proc
-|attrs_flowop
-|attrs_eventgen;
+fo_attr_name: attrs_flowop;
+
+ev_attr_name: attrs_eventgen;
attrs_define_proc:
-FSA_NICE { $$ = FSA_NICE;}
-|FSA_INSTANCES { $$ = FSA_INSTANCES;};
+ FSA_NICE { $$ = FSA_NICE;}
+| FSA_NAME { $$ = FSA_NAME;}
+| FSA_INSTANCES { $$ = FSA_INSTANCES;};
attrs_define_file:
-FSA_SIZE { $$ = FSA_SIZE;}
+ FSA_SIZE { $$ = FSA_SIZE;}
+| FSA_NAME { $$ = FSA_NAME;}
| FSA_PATH { $$ = FSA_PATH;}
| FSA_REUSE { $$ = FSA_REUSE;}
| FSA_PREALLOC { $$ = FSA_PREALLOC;}
| FSA_PARALLOC { $$ = FSA_PARALLOC;};
attrs_define_fileset:
-FSA_SIZE { $$ = FSA_SIZE;}
+ FSA_SIZE { $$ = FSA_SIZE;}
+| FSA_NAME { $$ = FSA_NAME;}
| FSA_PATH { $$ = FSA_PATH;}
| FSA_DIRWIDTH { $$ = FSA_DIRWIDTH;}
+| FSA_DIRDEPTHRV { $$ = FSA_DIRDEPTHRV;}
| FSA_PREALLOC { $$ = FSA_PREALLOC;}
| FSA_FILESIZEGAMMA { $$ = FSA_FILESIZEGAMMA;}
| FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;}
| FSA_CACHED { $$ = FSA_CACHED;}
| FSA_ENTRIES { $$ = FSA_ENTRIES;};
+randvar_attr_name:
+ FSA_NAME { $$ = FSA_NAME;}
+| FSA_RANDSEED { $$ = FSA_RANDSEED;}
+| FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;}
+| FSA_RANDMEAN { $$ = FSA_RANDMEAN;}
+| FSA_RANDMIN { $$ = FSA_RANDMIN;}
+| FSA_RANDROUND { $$ = FSA_RANDROUND;};
+
+randvar_attr_tsp:
+ FSS_TYPE { $$ = FSS_TYPE;}
+| FSS_SRC { $$ = FSS_SRC;}
+| FSS_SEED { $$ = FSS_SEED;}
+| FSS_GAMMA { $$ = FSS_GAMMA;}
+| FSS_MEAN { $$ = FSS_MEAN;}
+| FSS_MIN { $$ = FSS_MIN;}
+| FSS_ROUND { $$ = FSS_ROUND;};
+
+
+randvar_attr_param:
+ FSS_SEED { $$ = FSS_SEED;}
+| FSS_GAMMA { $$ = FSS_GAMMA;}
+| FSS_MEAN { $$ = FSS_MEAN;}
+| FSS_MIN { $$ = FSS_MIN;}
+| FSS_ROUND { $$ = FSS_ROUND;};
+
+randvar_attr_typop: randtype_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_int_alloc($1);
+};
+
+randtype_name:
+ FSV_RANDUNI { $$ = FSV_RANDUNI;}
+| FSV_RANDTAB { $$ = FSV_RANDTAB;}
+| FSA_RANDGAMMA { $$ = FSA_RANDGAMMA;};
+
+randvar_attr_srcop: randsrc_name
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_int_alloc($1);
+};
+
+randsrc_name:
+ FSV_URAND { $$ = FSV_URAND;}
+| FSV_RAND48 { $$ = FSV_RAND48;};
+
attrs_define_thread:
-FSA_PROCESS { $$ = FSA_PROCESS;}
-|FSA_MEMSIZE { $$ = FSA_MEMSIZE;}
-|FSA_USEISM { $$ = FSA_USEISM;}
-|FSA_INSTANCES { $$ = FSA_INSTANCES;};
+ FSA_PROCESS { $$ = FSA_PROCESS;}
+| FSA_NAME { $$ = FSA_NAME;}
+| FSA_MEMSIZE { $$ = FSA_MEMSIZE;}
+| FSA_USEISM { $$ = FSA_USEISM;}
+| FSA_INSTANCES { $$ = FSA_INSTANCES;};
attrs_flowop:
-FSA_WSS { $$ = FSA_WSS;}
-|FSA_FILE { $$ = FSA_FILE;}
-|FSA_NAME { $$ = FSA_NAME;}
-|FSA_RANDOM { $$ = FSA_RANDOM;}
-|FSA_FD { $$ = FSA_FD;}
-|FSA_SRCFD { $$ = FSA_SRCFD;}
-|FSA_ROTATEFD { $$ = FSA_ROTATEFD;}
-|FSA_DSYNC { $$ = FSA_DSYNC;}
-|FSA_DIRECTIO { $$ = FSA_DIRECTIO;}
-|FSA_TARGET { $$ = FSA_TARGET;}
-|FSA_ITERS { $$ = FSA_ITERS;}
-|FSA_VALUE { $$ = FSA_VALUE;}
-|FSA_BLOCKING { $$ = FSA_BLOCKING;}
-|FSA_HIGHWATER { $$ = FSA_HIGHWATER;}
-|FSA_IOSIZE { $$ = FSA_IOSIZE;};
+ FSA_WSS { $$ = FSA_WSS;}
+| FSA_FILE { $$ = FSA_FILE;}
+| FSA_NAME { $$ = FSA_NAME;}
+| FSA_RANDOM { $$ = FSA_RANDOM;}
+| FSA_FD { $$ = FSA_FD;}
+| FSA_SRCFD { $$ = FSA_SRCFD;}
+| FSA_ROTATEFD { $$ = FSA_ROTATEFD;}
+| FSA_DSYNC { $$ = FSA_DSYNC;}
+| FSA_DIRECTIO { $$ = FSA_DIRECTIO;}
+| FSA_TARGET { $$ = FSA_TARGET;}
+| FSA_ITERS { $$ = FSA_ITERS;}
+| FSA_VALUE { $$ = FSA_VALUE;}
+| FSA_BLOCKING { $$ = FSA_BLOCKING;}
+| FSA_HIGHWATER { $$ = FSA_HIGHWATER;}
+| FSA_IOSIZE { $$ = FSA_IOSIZE;};
attrs_eventgen:
-FSA_RATE { $$ = FSA_RATE;};
+ FSA_RATE { $$ = FSA_RATE;};
-attr_value: var_string_list {
+attr_value: FSV_STRING
+{
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_str_alloc($1);
+} | FSV_VAL_INT {
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_int_alloc($1);
+} | FSV_VAL_BOOLEAN {
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_bool_alloc($1);
+} | FSV_VARIABLE {
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = var_ref_attr($1);
+};
+
+attr_list_value: var_string_list {
if (($$ = alloc_attr()) == NULL)
YYERROR;
$$->attr_param_list = $1;
@@ -1061,16 +1433,27 @@ attr_value: var_string_list {
{
if (($$ = alloc_attr()) == NULL)
YYERROR;
- $$->attr_string = string_alloc($1);
+ $$->attr_avd = avd_str_alloc($1);
} | FSV_VAL_INT {
if (($$ = alloc_attr()) == NULL)
YYERROR;
- $$->attr_integer = integer_alloc($1);
+ $$->attr_avd = avd_int_alloc($1);
+} | FSV_VAL_BOOLEAN {
+ if (($$ = alloc_attr()) == NULL)
+ YYERROR;
+ $$->attr_avd = avd_bool_alloc($1);
} | FSV_VARIABLE {
if (($$ = alloc_attr()) == NULL)
YYERROR;
- $$->attr_integer = var_ref_integer($1);
- $$->attr_string = var_ref_string($1);
+ $$->attr_avd = var_ref_attr($1);
+};
+
+var_int_val: FSV_VAL_INT
+{
+ $$ = avd_int_alloc($1);
+} | FSV_VARIABLE
+{
+ $$ = var_ref_attr($1);
};
%%
@@ -1210,8 +1593,11 @@ main(int argc, char *argv[])
exit(1);
}
- if (procflow_exec(procname, instance) < 0)
+ if (procflow_exec(procname, instance) < 0) {
+ filebench_log(LOG_ERROR, "Cannot startup process %s",
+ procname);
exit(1);
+ }
exit(0);
}
@@ -1307,8 +1693,7 @@ parser_list2string(list_t *list)
list_t *l;
char *string;
char *tmp;
- vinteger_t *integer;
-
+ fbint_t *integer;
if ((string = malloc(MAXPATHLEN)) == NULL) {
filebench_log(LOG_ERROR, "Failed to allocate memory");
return (NULL);
@@ -1318,16 +1703,69 @@ parser_list2string(list_t *list)
/* Format args */
- for (l = list; l != NULL;
- l = l->list_next) {
+ for (l = list; l != NULL; l = l->list_next) {
+ char *lstr = avd_get_str(l->list_string);
+
filebench_log(LOG_DEBUG_SCRIPT,
- "converting string '%s'", *l->list_string);
+ "converting string '%s'", lstr);
+
+ /* see if it is a random variable */
+ if (l->list_integer) {
+ fbint_t param_name;
+
+ tmp = NULL;
+ param_name = avd_get_int(l->list_integer);
+ switch (param_name) {
+ case FSS_TYPE:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_TYPE);
+ break;
+
+ case FSS_SRC:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_SRC);
+ break;
+
+ case FSS_SEED:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_SEED);
+ break;
+
+ case FSS_MIN:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_MIN);
+ break;
+
+ case FSS_MEAN:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_MEAN);
+ break;
+
+ case FSS_GAMMA:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_GAMMA);
+ break;
- if ((tmp = var_to_string(*l->list_string)) != NULL) {
- (void) strcat(string, tmp);
- free(tmp);
+ case FSS_ROUND:
+ tmp = var_randvar_to_string(lstr,
+ RAND_PARAM_ROUND);
+ break;
+ }
+
+ if (tmp) {
+ (void) strcat(string, tmp);
+ free(tmp);
+ } else {
+ (void) strcat(string, lstr);
+ }
} else {
- (void) strcat(string, *l->list_string);
+ /* perhaps a normal variable? */
+ if ((tmp = var_to_string(lstr)) != NULL) {
+ (void) strcat(string, tmp);
+ free(tmp);
+ } else {
+ (void) strcat(string, lstr);
+ }
}
}
return (string);
@@ -1340,30 +1778,34 @@ parser_list2string(list_t *list)
* containing a copy of that string. On failure either returns NULL
* or shuts down the run.
*/
-var_string_t
+avd_t
parser_list2varstring(list_t *list)
{
+ char *lstr = avd_get_str(list->list_string);
+
/* Special case - variable name */
- if ((list->list_next == NULL) && (*(*list->list_string) == '$'))
- return (var_ref_string(*list->list_string));
+ if ((list->list_next == NULL) && (*lstr == '$'))
+ return (var_ref_attr(lstr));
- return (string_alloc(parser_list2string(list)));
+ return (avd_str_alloc(parser_list2string(list)));
}
/*
* Looks for the var named in list_string of the first element of the
- * supplied list. If found, returns the var_integer portion of the var.
- * If the var is not found, cannot be allocated, the supplied list is
- * NULL, or the list_string filed is empty, returns NULL.
+ * supplied list. If found, returns the var_val portion of the var in
+ * an attribute value descriptor. If the var is not found, cannot be
+ * allocated, the supplied list is NULL, or the list_string filed is
+ * empty, returns NULL.
*/
-var_integer_t
-parser_list2integer(list_t *list)
+avd_t
+parser_list2avd(list_t *list)
{
- var_integer_t v;
+ avd_t avd;
+ char *lstr;
- if (list && (*(list->list_string) != NULL)) {
- v = var_ref_integer(*(list->list_string));
- return (v);
+ if (list && ((lstr = avd_get_str(list->list_string)) != NULL)) {
+ avd = var_ref_attr(lstr);
+ return (avd);
}
return (NULL);
@@ -1377,18 +1819,17 @@ static void
parser_eventgen(cmd_t *cmd)
{
attr_t *attr;
- vinteger_t rate;
+ fbint_t rate;
/* Get the rate from attribute */
if (attr = get_attr_integer(cmd, FSA_RATE)) {
- if (attr->attr_integer) {
+ if (attr->attr_avd) {
+ rate = avd_get_int(attr->attr_avd);
filebench_log(LOG_VERBOSE,
- "Eventgen: %lld per second",
- *attr->attr_integer);
- eventgen_setrate(*attr->attr_integer);
+ "Eventgen: %lld per second", rate);
+ eventgen_setrate(rate);
}
}
-
}
/*
@@ -1406,10 +1847,11 @@ parser_foreach_integer(cmd_t *cmd)
cmd_t *inner_cmd;
for (; list != NULL; list = list->list_next) {
- var_assign_integer(cmd->cmd_tgt1, *list->list_integer);
+ fbint_t list_int = avd_get_int(list->list_integer);
+
+ var_assign_integer(cmd->cmd_tgt1, list_int);
filebench_log(LOG_VERBOSE, "Iterating %s=%lld",
- cmd->cmd_tgt1,
- *list->list_integer);
+ cmd->cmd_tgt1, list_int);
for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
inner_cmd = inner_cmd->cmd_next) {
inner_cmd->cmd(inner_cmd);
@@ -1428,13 +1870,13 @@ static void
parser_foreach_string(cmd_t *cmd)
{
list_t *list = cmd->cmd_param_list;
- cmd_t *inner_cmd;
for (; list != NULL; list = list->list_next) {
- var_assign_string(cmd->cmd_tgt1, *list->list_string);
+ cmd_t *inner_cmd;
+ char *lstr = avd_get_str(list->list_string);
+ var_assign_string(cmd->cmd_tgt1, lstr);
filebench_log(LOG_VERBOSE, "Iterating %s=%s",
- cmd->cmd_tgt1,
- *list->list_string);
+ cmd->cmd_tgt1, lstr);
for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
inner_cmd = inner_cmd->cmd_next) {
inner_cmd->cmd(inner_cmd);
@@ -1453,6 +1895,15 @@ parser_list(cmd_t *cmd)
}
/*
+ * Lists the flowop name and instance number for all flowops.
+ */
+static void
+parser_flowop_list(cmd_t *cmd)
+{
+ flowop_printall();
+}
+
+/*
* Calls procflow_define() to allocate "instances" number of procflow(s)
* (processes) with the supplied name. The default number of instances is
* one. An optional priority level attribute can be supplied and is stored in
@@ -1466,12 +1917,13 @@ parser_proc_define(cmd_t *cmd)
procflow_t *procflow, template;
char *name;
attr_t *attr;
- var_integer_t instances = integer_alloc(1);
+ avd_t var_instances;
+ fbint_t instances;
cmd_t *inner_cmd;
/* Get the name of the process */
if (attr = get_attr(cmd, FSA_NAME)) {
- name = *attr->attr_string;
+ name = avd_get_str(attr->attr_avd);
} else {
filebench_log(LOG_ERROR,
"define proc: proc specifies no name");
@@ -1480,13 +1932,23 @@ parser_proc_define(cmd_t *cmd)
/* Get the memory size from attribute */
if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "proc_define: Instances attr cannot be random");
+ filebench_shutdown(1);
+ }
+ var_instances = attr->attr_avd;
+ instances = avd_get_int(var_instances);
+ filebench_log(LOG_DEBUG_IMPL,
+ "Setting instances = %lld", instances);
+ } else {
filebench_log(LOG_DEBUG_IMPL,
- "Setting instances = %lld",
- *attr->attr_integer);
- instances = attr->attr_integer;
+ "Defaulting to instances = 1");
+ var_instances = avd_int_alloc(1);
+ instances = 1;
}
- if ((procflow = procflow_define(name, NULL, instances)) == NULL) {
+ if ((procflow = procflow_define(name, NULL, var_instances)) == NULL) {
filebench_log(LOG_ERROR,
"Failed to instantiate %d %s process(es)\n",
instances, name);
@@ -1495,17 +1957,22 @@ parser_proc_define(cmd_t *cmd)
/* Get the pri from attribute */
if (attr = get_attr_integer(cmd, FSA_NICE)) {
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "proc_define: priority cannot be random");
+ filebench_shutdown(1);
+ }
filebench_log(LOG_DEBUG_IMPL, "Setting pri = %lld",
- *attr->attr_integer);
- procflow->pf_nice = attr->attr_integer;
+ avd_get_int(attr->attr_avd));
+ procflow->pf_nice = attr->attr_avd;
} else
- procflow->pf_nice = integer_alloc(0);
+ procflow->pf_nice = avd_int_alloc(0);
/* Create the list of threads for this process */
for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
inner_cmd = inner_cmd->cmd_next) {
- parser_thread_define(inner_cmd, procflow, *instances);
+ parser_thread_define(inner_cmd, procflow, instances);
}
}
@@ -1524,7 +1991,7 @@ parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
{
threadflow_t *threadflow, template;
attr_t *attr;
- var_integer_t instances = integer_alloc(1);
+ avd_t instances;
cmd_t *inner_cmd;
char *name;
@@ -1532,7 +1999,7 @@ parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
/* Get the name of the thread */
if (attr = get_attr(cmd, FSA_NAME)) {
- name = *attr->attr_string;
+ name = avd_get_str(attr->attr_avd);
} else {
filebench_log(LOG_ERROR,
"define thread: thread in process %s specifies no name",
@@ -1542,20 +2009,31 @@ parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
/* Get the number of instances from attribute */
if (attr = get_attr_integer(cmd, FSA_INSTANCES)) {
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "define thread: Instances attr cannot be random");
+ filebench_shutdown(1);
+ }
filebench_log(LOG_DEBUG_IMPL,
"define thread: Setting instances = %lld",
- *attr->attr_integer);
- instances = attr->attr_integer;
- }
+ avd_get_int(attr->attr_avd));
+ instances = attr->attr_avd;
+ } else
+ instances = avd_int_alloc(1);
/* Get the memory size from attribute */
if (attr = get_attr_integer(cmd, FSA_MEMSIZE)) {
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "define thread: Memory size cannot be random");
+ filebench_shutdown(1);
+ }
filebench_log(LOG_DEBUG_IMPL,
"define thread: Setting memsize = %lld",
- *attr->attr_integer);
- template.tf_memsize = attr->attr_integer;
+ avd_get_int(attr->attr_avd));
+ template.tf_memsize = attr->attr_avd;
} else
- template.tf_memsize = integer_alloc(0);
+ template.tf_memsize = avd_int_alloc(0);
if ((threadflow = threadflow_define(procflow, name,
&template, instances)) == NULL) {
@@ -1572,10 +2050,119 @@ parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
/* Create the list of flowops */
for (inner_cmd = cmd->cmd_list; inner_cmd != NULL;
inner_cmd = inner_cmd->cmd_next) {
- parser_flowop_define(inner_cmd, threadflow);
+ parser_flowop_define(inner_cmd, threadflow,
+ &threadflow->tf_ops, FLOW_MASTER);
+ }
+}
+
+/*
+ * Files in the attributes for a newly allocated flowop
+ */
+static void
+parser_flowop_get_attrs(cmd_t *cmd, flowop_t *flowop)
+{
+ attr_t *attr;
+
+ /* Get the filename from attribute */
+ if (attr = get_attr(cmd, FSA_FILE)) {
+ flowop->fo_filename = attr->attr_avd;
+ if (flowop->fo_filename == NULL) {
+ filebench_log(LOG_ERROR,
+ "define flowop: no filename specfied");
+ filebench_shutdown(1);
+ }
+
+ if ((flowop->fo_filename->avd_type == AVD_VAL_STR) ||
+ (flowop->fo_filename->avd_type == AVD_VARVAL_STR)) {
+ char *name;
+
+ name = avd_get_str(flowop->fo_filename);
+ flowop->fo_fileset = fileset_find(name);
+
+ if (flowop->fo_fileset == NULL) {
+ filebench_log(LOG_ERROR,
+ "flowop %s: file %s not found",
+ flowop->fo_name, name);
+ filebench_shutdown(1);
+ }
+ }
+ }
+
+ /* Get the iosize of the op */
+ if (attr = get_attr_integer(cmd, FSA_IOSIZE))
+ flowop->fo_iosize = attr->attr_avd;
+ else
+ flowop->fo_iosize = avd_int_alloc(0);
+
+ /* Get the working set size of the op */
+ if (attr = get_attr_integer(cmd, FSA_WSS))
+ flowop->fo_wss = attr->attr_avd;
+ else
+ flowop->fo_wss = avd_int_alloc(0);
+
+ /* Random I/O? */
+ if (attr = get_attr_bool(cmd, FSA_RANDOM))
+ flowop->fo_random = attr->attr_avd;
+ else
+ flowop->fo_random = avd_bool_alloc(FALSE);
+
+ /* Sync I/O? */
+ if (attr = get_attr_bool(cmd, FSA_DSYNC))
+ flowop->fo_dsync = attr->attr_avd;
+ else
+ flowop->fo_dsync = avd_bool_alloc(FALSE);
+
+ /* Target, for wakeup etc */
+ if (attr = get_attr(cmd, FSA_TARGET))
+ (void) strcpy(flowop->fo_targetname,
+ avd_get_str(attr->attr_avd));
+
+ /* Value */
+ if (attr = get_attr_integer(cmd, FSA_VALUE))
+ flowop->fo_value = attr->attr_avd;
+ else
+ flowop->fo_value = avd_int_alloc(0);
+
+ /* FD */
+ if (attr = get_attr_integer(cmd, FSA_FD))
+ flowop->fo_fdnumber = avd_get_int(attr->attr_avd);
+
+ /* Rotatefd? */
+ if (attr = get_attr_bool(cmd, FSA_ROTATEFD))
+ flowop->fo_rotatefd = attr->attr_avd;
+ else
+ flowop->fo_rotatefd = avd_bool_alloc(FALSE);
+
+ /* SRC FD, for copies etc... */
+ if (attr = get_attr_integer(cmd, FSA_SRCFD))
+ flowop->fo_srcfdnumber = avd_get_int(attr->attr_avd);
+
+ /* Blocking operation? */
+ if (attr = get_attr_bool(cmd, FSA_BLOCKING))
+ flowop->fo_blocking = attr->attr_avd;
+ else
+ flowop->fo_blocking = avd_bool_alloc(FALSE);
+
+ /* Direct I/O Operation */
+ if (attr = get_attr_bool(cmd, FSA_DIRECTIO))
+ flowop->fo_directio = attr->attr_avd;
+ else
+ flowop->fo_directio = avd_bool_alloc(FALSE);
+
+ /* Highwater mark */
+ if (attr = get_attr_integer(cmd, FSA_HIGHWATER)) {
+ flowop->fo_highwater = attr->attr_avd;
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "define flowop: Highwater attr cannot be random");
+ filebench_shutdown(1);
+ }
+ } else {
+ flowop->fo_highwater = avd_int_alloc(1);
}
}
+
/*
* Calls flowop_define() to allocate a flowop with the supplied name.
* The allocated flowop inherits attributes from a base flowop of the
@@ -1604,7 +2191,8 @@ parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances)
* fileobj or fileset cannot be located.
*/
static void
-parser_flowop_define(cmd_t *cmd, threadflow_t *thread)
+parser_flowop_define(cmd_t *cmd, threadflow_t *thread,
+ flowop_t **flowoplist_hdp, int category)
{
flowop_t *flowop, *flowop_type;
char *type = (char *)cmd->cmd_name;
@@ -1622,7 +2210,7 @@ parser_flowop_define(cmd_t *cmd, threadflow_t *thread)
/* Get the name of the flowop */
if (attr = get_attr(cmd, FSA_NAME)) {
- name = *attr->attr_string;
+ name = avd_get_str(attr->attr_avd);
} else {
filebench_log(LOG_ERROR,
"define flowop: flowop %s specifies no name",
@@ -1631,116 +2219,39 @@ parser_flowop_define(cmd_t *cmd, threadflow_t *thread)
}
if ((flowop = flowop_define(thread, name,
- flowop_type, FLOW_MASTER, 0)) == NULL) {
+ flowop_type, category, 0)) == NULL) {
filebench_log(LOG_ERROR,
"define flowop: Failed to instantiate flowop %s\n",
cmd->cmd_name);
filebench_shutdown(1);
}
- /* Get the filename from attribute */
- if (attr = get_attr(cmd, FSA_FILE)) {
- flowop->fo_fileset = fileset_find(*attr->attr_string);
-
- if ((flowop->fo_fileset == NULL)) {
- filebench_log(LOG_ERROR,
- "define flowop: file %s not found",
- *attr->attr_string);
- filebench_shutdown(1);
- }
- }
-
- /* Get the iosize of the op */
- if (attr = get_attr_integer(cmd, FSA_IOSIZE))
- flowop->fo_iosize = attr->attr_integer;
- else
- flowop->fo_iosize = integer_alloc(0);
-
- /* Get the working set size of the op */
- if (attr = get_attr_integer(cmd, FSA_WSS))
- flowop->fo_wss = attr->attr_integer;
- else
- flowop->fo_wss = integer_alloc(0);
-
- /* Random I/O? */
- if (attr = get_attr_bool(cmd, FSA_RANDOM))
- flowop->fo_random = attr->attr_integer;
- else
- flowop->fo_random = integer_alloc(0);
-
- /* Sync I/O? */
- if (attr = get_attr_bool(cmd, FSA_DSYNC))
- flowop->fo_dsync = attr->attr_integer;
- else
- flowop->fo_dsync = integer_alloc(0);
-
/* Iterations */
if (attr = get_attr_integer(cmd, FSA_ITERS))
- flowop->fo_iters = attr->attr_integer;
- else
- flowop->fo_iters = integer_alloc(1);
-
-
- /* Target, for wakeup etc */
- if (attr = get_attr(cmd, FSA_TARGET))
- (void) strcpy(flowop->fo_targetname, *attr->attr_string);
-
- /* Value */
- if (attr = get_attr_integer(cmd, FSA_VALUE))
- flowop->fo_value = attr->attr_integer;
- else
- flowop->fo_value = integer_alloc(0);
-
- /* FD */
- if (attr = get_attr_integer(cmd, FSA_FD))
- flowop->fo_fdnumber = *attr->attr_integer;
-
- /* Rotatefd? */
- if (attr = get_attr_bool(cmd, FSA_ROTATEFD))
- flowop->fo_rotatefd = attr->attr_integer;
- else
- flowop->fo_rotatefd = integer_alloc(0);
-
- /* SRC FD, for copies etc... */
- if (attr = get_attr_integer(cmd, FSA_SRCFD))
- flowop->fo_srcfdnumber = *attr->attr_integer;
-
- /* Blocking operation? */
- if (attr = get_attr_bool(cmd, FSA_BLOCKING))
- flowop->fo_blocking = attr->attr_integer;
+ flowop->fo_iters = attr->attr_avd;
else
- flowop->fo_blocking = integer_alloc(0);
+ flowop->fo_iters = avd_int_alloc(1);
- /* Blocking operation? */
- if (attr = get_attr_bool(cmd, FSA_DIRECTIO))
- flowop->fo_directio = attr->attr_integer;
- else
- flowop->fo_directio = integer_alloc(0);
-
- /* Highwater mark */
- if (attr = get_attr_integer(cmd, FSA_HIGHWATER))
- flowop->fo_highwater = attr->attr_integer;
- else
- flowop->fo_highwater = integer_alloc(1);
+ parser_flowop_get_attrs(cmd, flowop);
}
/*
* Calls fileset_define() to allocate a fileset with the supplied name and
- * initializes the fileset's pathname attribute, and optionally the fs_cached,
- * fs_reuse, fs_prealloc and fs_size attributes.
+ * initializes the fileset's pathname attribute, and optionally the
+ * fileset_cached, fileset_reuse, fileset_prealloc and fileset_size attributes.
*
*/
static fileset_t *
parser_fileset_define_common(cmd_t *cmd)
{
fileset_t *fileset;
- char *name;
+ avd_t name;
attr_t *attr;
- var_string_t pathname;
+ avd_t pathname;
/* Get the name of the file */
if (attr = get_attr(cmd, FSA_NAME)) {
- name = *attr->attr_string;
+ name = attr->attr_avd;
} else {
filebench_log(LOG_ERROR,
"define fileset: file or fileset specifies no name");
@@ -1750,7 +2261,7 @@ parser_fileset_define_common(cmd_t *cmd)
if ((fileset = fileset_define(name)) == NULL) {
filebench_log(LOG_ERROR,
"define file: failed to instantiate file %s\n",
- name);
+ avd_get_str(name));
return (NULL);
}
@@ -1770,36 +2281,37 @@ parser_fileset_define_common(cmd_t *cmd)
fileset->fs_path = pathname;
/* Should we prealloc in parallel? */
- if (attr = get_attr_bool(cmd, FSA_PARALLOC)) {
- fileset->fs_paralloc = attr->attr_integer;
- } else
- fileset->fs_paralloc = integer_alloc(0);
+ if (attr = get_attr_bool(cmd, FSA_PARALLOC))
+ fileset->fs_paralloc = attr->attr_avd;
+ else
+ fileset->fs_paralloc = avd_bool_alloc(FALSE);
/* Should we reuse the existing file? */
if (attr = get_attr_bool(cmd, FSA_REUSE)) {
- fileset->fs_reuse = attr->attr_integer;
+ fileset->fs_reuse = attr->attr_avd;
} else
- fileset->fs_reuse = integer_alloc(0);
+ fileset->fs_reuse = avd_bool_alloc(FALSE);
/* Should we leave in cache? */
if (attr = get_attr_bool(cmd, FSA_CACHED)) {
- fileset->fs_cached = attr->attr_integer;
+ fileset->fs_cached = attr->attr_avd;
} else
- fileset->fs_cached = integer_alloc(0);
+ fileset->fs_cached = avd_bool_alloc(FALSE);
/* Get the mean or absolute size of the file */
if (attr = get_attr_integer(cmd, FSA_SIZE)) {
- fileset->fs_size = attr->attr_integer;
+ fileset->fs_size = attr->attr_avd;
} else
- fileset->fs_size = integer_alloc(0);
+ fileset->fs_size = avd_int_alloc(0);
return (fileset);
}
/*
* Calls parser_fileset_define_common() to allocate a fileset with
- * one entry and optionally the fs_prealloc. Sets the fs_preallocpercent,
- * fs_entries, fs_dirwidth, fs_dirgamma, and fs_sizegamma attributes
+ * one entry and optionally the fileset_prealloc. Sets the
+ * fileset_preallocpercent, fileset_entries, fileset_dirwidth,
+ * fileset_dirgamma, and fileset_sizegamma attributes
* to appropriate values for emulating the old "fileobj" entity
*/
static void
@@ -1819,39 +2331,40 @@ parser_file_define(cmd_t *cmd)
fileset->fs_attrs = FILESET_IS_FILE;
/* Set the size of the fileset to 1 */
- fileset->fs_entries = integer_alloc(1);
+ fileset->fs_entries = avd_int_alloc(1);
/* Set the mean dir width to more than 1 */
- fileset->fs_dirwidth = integer_alloc(10);
+ fileset->fs_dirwidth = avd_int_alloc(10);
/* Set the dir and size gammas to 0 */
- fileset->fs_dirgamma = integer_alloc(0);
- fileset->fs_sizegamma = integer_alloc(0);
+ fileset->fs_dirgamma = avd_int_alloc(0);
+ fileset->fs_sizegamma = avd_int_alloc(0);
/* if a raw device, all done */
if (fileset_checkraw(fileset)) {
filebench_log(LOG_VERBOSE, "File %s/%s is RAW device",
- *fileset->fs_path, fileset->fs_name);
+ avd_get_str(fileset->fs_path),
+ avd_get_str(fileset->fs_name));
return;
}
/* Does file need to be preallocated? */
if (attr = get_attr_bool(cmd, FSA_PREALLOC)) {
/* yes */
- fileset->fs_prealloc = attr->attr_integer;
- fileset->fs_preallocpercent = integer_alloc(100);
+ fileset->fs_prealloc = attr->attr_avd;
+ fileset->fs_preallocpercent = avd_int_alloc(100);
} else {
/* no */
- fileset->fs_prealloc = integer_alloc(0);
- fileset->fs_preallocpercent = integer_alloc(0);
+ fileset->fs_prealloc = avd_bool_alloc(FALSE);
+ fileset->fs_preallocpercent = avd_int_alloc(0);
}
}
/*
* Calls parser_fileset_define_common() to allocate a fileset with the
- * supplied name and initializes the fileset's fs_preallocpercent,
- * fs_prealloc, fs_entries, fs_dirwidth, fs_dirgamma, and fs_sizegamma
- * attributes.
+ * supplied name and initializes the fileset's fileset_preallocpercent,
+ * fileset_prealloc, fileset_entries, fileset_dirwidth, fileset_dirgamma,
+ * and fileset_sizegamma attributes.
*/
static void
parser_fileset_define(cmd_t *cmd)
@@ -1870,54 +2383,82 @@ parser_fileset_define(cmd_t *cmd)
if (fileset_checkraw(fileset)) {
filebench_log(LOG_ERROR,
"Fileset %s/%s: Cannot create a fileset on a RAW device",
- *fileset->fs_path, fileset->fs_name);
+ avd_get_str(fileset->fs_path),
+ avd_get_str(fileset->fs_name));
filebench_shutdown(0);
return;
}
/* How much should we preallocate? */
if ((attr = get_attr_integer(cmd, FSA_PREALLOC)) &&
- attr->attr_integer) {
- fileset->fs_preallocpercent = attr->attr_integer;
- } else if (attr && !attr->attr_integer) {
- fileset->fs_preallocpercent = integer_alloc(100);
+ attr->attr_avd) {
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "define fileset: Prealloc attr cannot be random");
+ filebench_shutdown(1);
+ }
+ fileset->fs_preallocpercent = attr->attr_avd;
+ } else if (attr && !attr->attr_avd) {
+ fileset->fs_preallocpercent = avd_int_alloc(100);
} else {
- fileset->fs_preallocpercent = integer_alloc(0);
+ fileset->fs_preallocpercent = avd_int_alloc(0);
}
/* Should we preallocate? */
if (attr = get_attr_bool(cmd, FSA_PREALLOC)) {
- fileset->fs_prealloc = attr->attr_integer;
+ fileset->fs_prealloc = attr->attr_avd;
} else
- fileset->fs_prealloc = integer_alloc(0);
+ fileset->fs_prealloc = avd_bool_alloc(FALSE);
/* Get the number of files in the fileset */
if (attr = get_attr_integer(cmd, FSA_ENTRIES)) {
- fileset->fs_entries = attr->attr_integer;
+ fileset->fs_entries = attr->attr_avd;
} else {
filebench_log(LOG_ERROR, "Fileset has zero entries");
- fileset->fs_entries = integer_alloc(0);
+ fileset->fs_entries = avd_int_alloc(0);
}
/* Get the mean dir width of the fileset */
if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) {
- fileset->fs_dirwidth = attr->attr_integer;
+ fileset->fs_dirwidth = attr->attr_avd;
} else {
filebench_log(LOG_ERROR, "Fileset has zero directory width");
- fileset->fs_dirwidth = integer_alloc(0);
+ fileset->fs_dirwidth = avd_int_alloc(0);
}
- /* Get the gamma value for dir width distributions */
+ /* Get the random variable for dir depth, if supplied */
+ if (attr = get_attr_integer(cmd, FSA_DIRDEPTHRV)) {
+ if (!AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "Define fileset: dirdepthrv must be random var");
+ filebench_shutdown(1);
+ }
+ fileset->fs_dirdepthrv = attr->attr_avd;
+ } else {
+ fileset->fs_dirdepthrv = NULL;
+ }
+
+ /* Get the gamma value for dir depth distributions */
if (attr = get_attr_integer(cmd, FSA_DIRGAMMA)) {
- fileset->fs_dirgamma = attr->attr_integer;
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "Define fileset: dirgamma attr cannot be random");
+ filebench_shutdown(1);
+ }
+ fileset->fs_dirgamma = attr->attr_avd;
} else
- fileset->fs_dirgamma = integer_alloc(1500);
+ fileset->fs_dirgamma = avd_int_alloc(1500);
/* Get the gamma value for dir width distributions */
if (attr = get_attr_integer(cmd, FSA_FILESIZEGAMMA)) {
- fileset->fs_sizegamma = attr->attr_integer;
+ if (AVD_IS_RANDOM(attr->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "Define fileset: filesizegamma cannot be random");
+ filebench_shutdown(1);
+ }
+ fileset->fs_sizegamma = attr->attr_avd;
} else
- fileset->fs_sizegamma = integer_alloc(1500);
+ fileset->fs_sizegamma = avd_int_alloc(1500);
}
/*
@@ -1972,6 +2513,11 @@ parser_fileset_create(cmd_t *cmd)
{
if (!filecreate_done) {
filecreate_done = 1;
+
+ /* initialize the random number system first */
+ randdist_init();
+
+ /* create all the filesets */
if (fileset_createset(NULL) != 0) {
filebench_log(LOG_ERROR, "Failed to create filesets");
filebench_shutdown(1);
@@ -2081,7 +2627,7 @@ parser_run(cmd_t *cmd)
static void
parser_run_variable(cmd_t *cmd)
{
- vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1);
+ avd_t integer = var_ref_attr(cmd->cmd_tgt1);
int runtime;
if (integer == NULL) {
@@ -2090,7 +2636,7 @@ parser_run_variable(cmd_t *cmd)
return;
}
- runtime = *integer;
+ runtime = avd_get_int(integer);
/* check for startup errors */
if (filebench_shm->f_abort)
@@ -2199,13 +2745,35 @@ parser_sleep(cmd_t *cmd)
}
/*
+ * used by the set command to set the integer part of a regular
+ * variable, or the appropriate field of a random variable
+ */
+static void
+parser_set_integer(char *name, fbint_t integer)
+{
+ var_assign_integer(name, integer);
+}
+
+/*
+ * used by the set command to set the integer part of a regular
+ * variable from another variable, or the appropriate field of a
+ * random variable from another variable
+ */
+static void
+parser_set_var(char *dst_name, char *src_name)
+{
+ var_assign_var(dst_name, src_name);
+}
+
+
+/*
* Same as parser_sleep, except the sleep time is obtained from a variable
* whose name is passed to it as an argument on the command line.
*/
static void
parser_sleep_variable(cmd_t *cmd)
{
- vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1);
+ avd_t integer = var_ref_attr(cmd->cmd_tgt1);
int sleeptime;
if (integer == NULL) {
@@ -2214,7 +2782,7 @@ parser_sleep_variable(cmd_t *cmd)
return;
}
- sleeptime = *integer;
+ sleeptime = avd_get_int(integer);
/* check for startup errors */
if (filebench_shm->f_abort)
@@ -2575,6 +3143,205 @@ parser_abort(int arg)
}
/*
+ * define a random variable and initialize the distribution parameters
+ */
+static void
+parser_randvar_define(cmd_t *cmd)
+{
+ var_t *var;
+ randdist_t *rndp;
+ attr_t *attr;
+ char *name;
+
+ /* Get the name for the random variable */
+ if (attr = get_attr(cmd, FSA_NAME)) {
+ name = avd_get_str(attr->attr_avd);
+ } else {
+ filebench_log(LOG_ERROR,
+ "define randvar: no name specified");
+ return;
+ }
+
+ if ((var = var_define_randvar(name)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "define randvar: failed for random variable %s",
+ name);
+ return;
+ }
+
+ rndp = var->var_val.randptr;
+ rndp->rnd_type = 0;
+
+ /* Get the source of the random numbers */
+ if (attr = get_attr_integer(cmd, FSA_RANDSRC)) {
+ int randsrc = (int)avd_get_int(attr->attr_avd);
+
+ switch (randsrc) {
+ case FSV_URAND:
+ rndp->rnd_type |= RAND_SRC_URANDOM;
+ break;
+ case FSV_RAND48:
+ rndp->rnd_type |= RAND_SRC_GENERATOR;
+ break;
+ }
+ } else {
+ /* default to rand48 random number generator */
+ rndp->rnd_type |= RAND_SRC_GENERATOR;
+ }
+
+ /* Get the min value of the random distribution */
+ if (attr = get_attr_integer(cmd, FSA_RANDMIN))
+ rndp->rnd_min = attr->attr_avd;
+ else
+ rndp->rnd_min = avd_int_alloc(0);
+
+ /* Get the mean value of the random distribution */
+ if (attr = get_attr_integer(cmd, FSA_RANDMEAN))
+ rndp->rnd_mean = attr->attr_avd;
+ else
+ rndp->rnd_mean = avd_int_alloc(0);
+
+ /* Get the roundoff value for the random distribution */
+ if (attr = get_attr_integer(cmd, FSA_RANDROUND))
+ rndp->rnd_round = attr->attr_avd;
+ else
+ rndp->rnd_round = avd_int_alloc(0);
+
+ /* Get a tablular probablility distribution if there is one */
+ if (attr = get_attr(cmd, FSA_RANDTABLE)) {
+ rndp->rnd_probtabs = (probtabent_t *)(attr->attr_obj);
+ rndp->rnd_type |= RAND_TYPE_TABLE;
+
+ /* no need for the rest of the attributes */
+ return;
+ } else {
+ rndp->rnd_probtabs = NULL;
+ }
+
+ /* Get the type for the random variable */
+ if (attr = get_attr(cmd, FSA_TYPE)) {
+ int disttype = (int)avd_get_int(attr->attr_avd);
+
+ switch (disttype) {
+ case FSV_RANDUNI:
+ rndp->rnd_type |= RAND_TYPE_UNIFORM;
+ break;
+ case FSA_RANDGAMMA:
+ rndp->rnd_type |= RAND_TYPE_GAMMA;
+ break;
+ case FSV_RANDTAB:
+ filebench_log(LOG_ERROR,
+ "Table distribution type without prob table");
+ break;
+ }
+ } else {
+ /* default to gamma distribution type */
+ rndp->rnd_type |= RAND_TYPE_GAMMA;
+ }
+
+ /* Get the seed for the random variable */
+ if (attr = get_attr_integer(cmd, FSA_RANDSEED))
+ rndp->rnd_seed = attr->attr_avd;
+ else
+ rndp->rnd_seed = avd_int_alloc(0);
+
+ /* Get the gamma value of the random distribution */
+ if (attr = get_attr_integer(cmd, FSA_RANDGAMMA))
+ rndp->rnd_gamma = attr->attr_avd;
+ else
+ rndp->rnd_gamma = avd_int_alloc(1500);
+}
+
+/*
+ * Set a specified random distribution parameter in a random variable.
+ */
+static void
+parser_randvar_set(cmd_t *cmd)
+{
+ var_t *src_var, *randvar;
+ randdist_t *rndp;
+ avd_t value;
+
+ if ((randvar = var_find_randvar(cmd->cmd_tgt1)) == NULL) {
+ filebench_log(LOG_ERROR,
+ "set randvar: failed",
+ cmd->cmd_tgt1);
+ return;
+ }
+
+ rndp = randvar->var_val.randptr;
+ value = cmd->cmd_attr_list->attr_avd;
+
+ switch (cmd->cmd_qty) {
+ case FSS_TYPE:
+ {
+ int disttype = (int)avd_get_int(value);
+
+ printf("parser_randvar_set: changing type to %d\n",
+ disttype);
+ rndp->rnd_type &= (~RAND_TYPE_MASK);
+
+ switch (disttype) {
+ case FSV_RANDUNI:
+ rndp->rnd_type |= RAND_TYPE_UNIFORM;
+ break;
+ case FSA_RANDGAMMA:
+ rndp->rnd_type |= RAND_TYPE_GAMMA;
+ break;
+ case FSV_RANDTAB:
+ rndp->rnd_type |= RAND_TYPE_TABLE;
+ break;
+ }
+ break;
+ }
+
+ case FSS_SRC:
+ {
+ int randsrc = (int)avd_get_int(value);
+
+ printf("parser_randvar_set: changing source to %d\n",
+ randsrc);
+
+ rndp->rnd_type &=
+ (~(RAND_SRC_URANDOM | RAND_SRC_GENERATOR));
+
+ switch (randsrc) {
+ case FSV_URAND:
+ rndp->rnd_type |= RAND_SRC_URANDOM;
+ break;
+ case FSV_RAND48:
+ rndp->rnd_type |= RAND_SRC_GENERATOR;
+ break;
+ }
+ break;
+ }
+
+ case FSS_SEED:
+ rndp->rnd_seed = value;
+ break;
+
+ case FSS_GAMMA:
+ rndp->rnd_gamma = value;
+ break;
+
+ case FSS_MEAN:
+ rndp->rnd_mean = value;
+ break;
+
+ case FSS_MIN:
+ rndp->rnd_min = value;
+ break;
+
+ case FSS_ROUND:
+ rndp->rnd_round = value;
+ break;
+
+ default:
+ filebench_log(LOG_ERROR, "setrandvar: undefined attribute");
+ }
+}
+
+/*
* alloc_cmd() allocates the required resources for a cmd_t. On failure, a
* filebench_log is issued and NULL is returned.
*/
@@ -2622,12 +3389,29 @@ alloc_attr()
}
/*
+ * Allocates a probtabent_t structure and zeros it. Returns NULL on failure, or
+ * a pointer to the probtabent_t.
+ */
+static probtabent_t *
+alloc_probtabent(void)
+{
+ probtabent_t *rte;
+
+ if ((rte = malloc(sizeof (probtabent_t))) == NULL) {
+ return (NULL);
+ }
+
+ (void) memset(rte, 0, sizeof (probtabent_t));
+ return (rte);
+}
+
+/*
* Searches the attribute list for the command for the named attribute type.
* The attribute list is created by the parser from the list of attributes
* supplied with certain commands, such as the define and flowop commands.
* Returns a pointer to the attribute structure if the named attribute is
* found, otherwise returns NULL. If the attribute includes a parameter list,
- * the list is converted to a string and stored in the attr_string field of
+ * the list is converted to a string and stored in the attr_avd field of
* the returned attr_t struct.
*/
static attr_t *
@@ -2643,7 +3427,7 @@ get_attr(cmd_t *cmd, int64_t name)
"attr %d = %d %llx?",
attr->attr_name,
name,
- attr->attr_integer);
+ attr->attr_avd);
if (attr->attr_name == name)
rtn = attr;
@@ -2656,7 +3440,7 @@ get_attr(cmd_t *cmd, int64_t name)
filebench_log(LOG_DEBUG_SCRIPT, "attr is param list");
string = parser_list2string(rtn->attr_param_list);
if (string != NULL) {
- rtn->attr_string = string_alloc(string);
+ rtn->attr_avd = avd_str_alloc(string);
filebench_log(LOG_DEBUG_SCRIPT,
"attr string %s", string);
}
@@ -2667,7 +3451,7 @@ get_attr(cmd_t *cmd, int64_t name)
/*
* Similar to get_attr, but converts the parameter string supplied with the
- * named attribute to an integer and stores the integer in the attr_integer
+ * named attribute to an integer and stores the integer in the attr_avd
* portion of the returned attr_t struct.
*/
static attr_t *
@@ -2685,16 +3469,15 @@ get_attr_integer(cmd_t *cmd, int64_t name)
if (rtn == NULL)
return (NULL);
- if (rtn->attr_param_list) {
- rtn->attr_integer = parser_list2integer(rtn->attr_param_list);
- }
+ if (rtn->attr_param_list)
+ rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
return (rtn);
}
/*
* Similar to get_attr, but converts the parameter string supplied with the
- * named attribute to an integer and stores the integer in the attr_integer
+ * named attribute to an integer and stores the integer in the attr_avd
* portion of the returned attr_t struct. If no parameter string is supplied
* then it defaults to TRUE (1).
*/
@@ -2714,9 +3497,18 @@ get_attr_bool(cmd_t *cmd, int64_t name)
return (NULL);
if (rtn->attr_param_list) {
- rtn->attr_integer = parser_list2integer(rtn->attr_param_list);
- } else if (rtn->attr_integer == 0) {
- rtn->attr_integer = integer_alloc(1);
+ rtn->attr_avd = parser_list2avd(rtn->attr_param_list);
+
+ } else if (rtn->attr_avd == NULL) {
+ rtn->attr_avd = avd_bool_alloc(TRUE);
+ }
+
+ /* boolean attributes cannot point to random variables */
+ if (AVD_IS_RANDOM(rtn->attr_avd)) {
+ filebench_log(LOG_ERROR,
+ "define flowop: Boolean attr %s cannot be random", name);
+ filebench_shutdown(1);
+ return (NULL);
}
return (rtn);
diff --git a/usr/src/cmd/filebench/common/parser_lex.l b/usr/src/cmd/filebench/common/parser_lex.l
index 78b3a94718..064b5eb453 100644
--- a/usr/src/cmd/filebench/common/parser_lex.l
+++ b/usr/src/cmd/filebench/common/parser_lex.l
@@ -25,7 +25,7 @@
*/
%{
-#pragma ident "%Z%%M% %I% %E% SMI"
+#pragma ident "%Z%%M% %I% %E% SMI"
%}
%{
@@ -92,6 +92,7 @@ directory { return FSE_DIRECTORY; }
command { return FSE_COMMAND; }
process[es]* { return FSE_PROC; }
thread { return FSE_THREAD; }
+randvar { return FSE_RAND; }
clear { return FSE_CLEAR; }
snap { return FSE_SNAP; }
dump { return FSE_DUMP; }
@@ -101,9 +102,10 @@ mode { return FSE_MODE; }
cached { return FSA_CACHED; }
dirwidth { return FSA_DIRWIDTH; }
+dirdepthrv { return FSA_DIRDEPTHRV; }
dirgamma { return FSA_DIRGAMMA; }
namelength { return FSA_NAMELENGTH; }
-filesize { return FSA_FILESIZE; }
+filesize { return FSA_SIZE; }
filesizegamma { return FSA_FILESIZEGAMMA; }
directio { return FSA_DIRECTIO; }
dsync { return FSA_DSYNC; }
@@ -136,6 +138,26 @@ highwater { return FSA_HIGHWATER; }
alldone { return FSA_ALLDONE; }
firstdone { return FSA_FIRSTDONE; }
timeout { return FSA_TIMEOUT; }
+type { return FSA_TYPE; }
+seed { return FSA_RANDSEED; }
+gamma { return FSA_RANDGAMMA; }
+mean { return FSA_RANDMEAN; }
+min { return FSA_RANDMIN; }
+round { return FSA_RANDROUND; }
+randsrc { return FSA_RANDSRC; }
+randtable { return FSA_RANDTABLE; }
+uniform { return FSV_RANDUNI; }
+tabular { return FSV_RANDTAB; }
+"."type { return FSS_TYPE; }
+"."seed { return FSS_SEED; }
+"."gamma { return FSS_GAMMA; }
+"."mean { return FSS_MEAN; }
+"."min { return FSS_MIN; }
+"."round { return FSS_ROUND; }
+"."randsrc { return FSS_SRC; }
+urandom { return FSV_URAND; }
+rand48 { return FSV_RAND48; }
+
<INITIAL>\" {
BEGIN WHITESTRINGSTATE;
@@ -228,24 +250,42 @@ timeout { return FSA_TIMEOUT; }
return FSV_VAL_INT;
}
-<INITIAL>true|false {
- if (strcmp(yytext, "true") == 0)
- yylval.bval = 1;
- else
- yylval.bval = 0;
+<INITIAL>true {
+ yylval.bval = TRUE;
return FSV_VAL_BOOLEAN;
}
+<INITIAL>false {
+ yylval.bval = FALSE;
+ return FSV_VAL_BOOLEAN;
+ }
-
-$[({A-Za-z][A-Za-z0-9._]*[A-Za-z0-9][)}]* {
+$[({A-Za-z][A-Za-z0-9_]*[A-Za-z0-9][)}]* {
if ((yylval.sval = strdup(yytext)) == NULL) {
yyerror("Out of memory");
filebench_shutdown(E_ERROR);
}
+
return FSV_VARIABLE;
}
+
+$[({A-Za-z][A-Za-z0-9_]*"."[A-Za-z0-9][)}]* {
+ int backtrack;
+
+ if ((backtrack =
+ var_is_set4_randvar(yytext)) != 0)
+ yyless(yyleng - backtrack);
+
+ if ((yylval.sval = strdup(yytext)) == NULL) {
+ yyerror("Out of memory");
+ filebench_shutdown(E_ERROR);
+ }
+
+ return FSV_RANDVAR;
+ }
+
+
<INITIAL>[/A-Za-z-][/A-Za-z0-9._-]* {
if ((yylval.sval = strdup(yytext)) == NULL) {
yyerror("Out of memory");
@@ -254,6 +294,7 @@ $[({A-Za-z][A-Za-z0-9._]*[A-Za-z0-9][)}]* {
return FSV_STRING;
}
+
. {
yyerror("Illegal character");
}
diff --git a/usr/src/cmd/filebench/common/parsertypes.h b/usr/src/cmd/filebench/common/parsertypes.h
index a7ceaca379..d0d8db0842 100644
--- a/usr/src/cmd/filebench/common/parsertypes.h
+++ b/usr/src/cmd/filebench/common/parsertypes.h
@@ -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.
*/
@@ -47,17 +47,17 @@ typedef unsigned char uchar_t;
#define FSE_SYSTEM 1
typedef struct list {
- struct list *list_next;
- var_string_t list_string;
- var_integer_t list_integer;
+ struct list *list_next;
+ avd_t list_string;
+ avd_t list_integer;
} list_t;
typedef struct attr {
- int attr_name;
+ int attr_name;
struct attr *attr_next;
- var_string_t attr_string;
- var_integer_t attr_integer;
+ avd_t attr_avd;
list_t *attr_param_list;
+ void *attr_obj;
} attr_t;
typedef struct cmd {
diff --git a/usr/src/cmd/filebench/common/procflow.c b/usr/src/cmd/filebench/common/procflow.c
index 2a7e412c58..9bf3bba057 100644
--- a/usr/src/cmd/filebench/common/procflow.c
+++ b/usr/src/cmd/filebench/common/procflow.c
@@ -233,13 +233,14 @@ procflow_create_all_procs(void)
int ret = 0;
while (procflow) {
- int i;
+ int i, instances;
- filebench_log(LOG_INFO, "Starting %lld %s instances",
- *(procflow->pf_instances), procflow->pf_name);
+ instances = (int)avd_get_int(procflow->pf_instances);
+ filebench_log(LOG_INFO, "Starting %d %s instances",
+ instances, procflow->pf_name);
/* Create instances of procflow */
- for (i = 0; (i < *procflow->pf_instances) && (ret == 0); i++) {
+ for (i = 0; (i < instances) && (ret == 0); i++) {
procflow_t *newproc;
/* Create processes */
@@ -305,7 +306,7 @@ procflow_exec(char *name, int instance)
filebench_log(LOG_DEBUG_IMPL,
"nice = %llx", procflow->pf_nice);
- proc_nice = *procflow->pf_nice;
+ proc_nice = avd_get_int(procflow->pf_nice);
filebench_log(LOG_DEBUG_IMPL, "Setting pri of %s-%d to %d",
name, instance, nice(proc_nice + 10));
@@ -414,7 +415,7 @@ procflow_init(void)
filebench_log(LOG_DEBUG_IMPL,
"procflow_init %s, %lld",
- procflow->pf_name, *(procflow->pf_instances));
+ procflow->pf_name, avd_get_int(procflow->pf_instances));
#ifdef USE_PROCESS_MODEL
if ((ret = pthread_cond_init(&procflow_procs_created, NULL)) != 0)
@@ -707,7 +708,7 @@ procflow_define_common(procflow_t **list, char *name,
* parser_proc_define().
*/
procflow_t *
-procflow_define(char *name, procflow_t *inherit, var_integer_t instances)
+procflow_define(char *name, procflow_t *inherit, avd_t instances)
{
procflow_t *procflow;
diff --git a/usr/src/cmd/filebench/common/procflow.h b/usr/src/cmd/filebench/common/procflow.h
index 7b8134be65..f60450a626 100644
--- a/usr/src/cmd/filebench/common/procflow.h
+++ b/usr/src/cmd/filebench/common/procflow.h
@@ -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.
*/
@@ -40,19 +40,18 @@ extern "C" {
typedef struct procflow {
char pf_name[128];
int pf_instance;
- var_integer_t pf_instances;
+ avd_t pf_instances;
int pf_running;
struct procflow *pf_next;
pid_t pf_pid;
pthread_t pf_tid;
struct threadflow *pf_threads;
int pf_attrs;
- var_integer_t pf_nice;
+ avd_t pf_nice;
flowstat_t pf_stats;
} procflow_t;
-procflow_t *procflow_define(char *name, procflow_t *inherit,
- var_integer_t instances);
+procflow_t *procflow_define(char *name, procflow_t *inherit, avd_t instances);
int procflow_init(void);
void procflow_shutdown(void);
int procflow_exec(char *name, int instance);
diff --git a/usr/src/cmd/filebench/common/stats.c b/usr/src/cmd/filebench/common/stats.c
index 1b23bc21c4..95af3f2165 100644
--- a/usr/src/cmd/filebench/common/stats.c
+++ b/usr/src/cmd/filebench/common/stats.c
@@ -67,7 +67,7 @@ static kstat_t *sysinfo_ksp = NULL;
* a local pointer to the sysinfo kstat, and returns the sum of user and
* kernel time for all the cpus.
*/
-static vinteger_t
+static fbint_t
kstats_read_cpu(void)
{
int ncpus;
@@ -134,7 +134,7 @@ kstats_read_cpu(void)
#else /* HAVE_LIBKSTAT */
#ifdef HAVE_PROC_STAT
static FILE *statfd = 0;
-vinteger_t
+fbint_t
kstats_read_cpu(void)
{
/*
@@ -166,7 +166,7 @@ kstats_read_cpu(void)
}
#else /* HAVE_PROC_STAT */
-vinteger_t
+fbint_t
kstats_read_cpu(void)
{
return (0);
@@ -238,7 +238,7 @@ gl_stats_ohead(void)
}
/*
- * Places the value represented by "name" into the var_integer field of the
+ * Places the value represented by "name" into the var_val.integer field of the
* supplied var_t. Compares the supplied "name" with a set of predefined
* names and calculates the value from the appropriate globalstats field(s).
*/
@@ -255,86 +255,117 @@ stats_findvar(var_t *var, char *name)
globalstats = malloc(FLOW_TYPES * sizeof (flowstat_t));
if (strcmp(name, "iocount") == 0) {
- var->var_integer = iostat->fs_count +
- aiostat->fs_count;
+ fbint_t stat;
+
+ stat = iostat->fs_count + aiostat->fs_count;
+ VAR_SET_INT(var, stat);
filebench_log(LOG_DEBUG_IMPL, "reading stats %s = %lld",
- name, var->var_integer);
+ name, stat);
return (var);
}
if (strcmp(name, "iorate") == 0) {
+ fbint_t stat;
+
/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
- var->var_integer = (iostat->fs_count + aiostat->fs_count) /
+ stat = (iostat->fs_count + aiostat->fs_count) /
((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "ioreadrate") == 0) {
+ fbint_t stat;
+
/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
- var->var_integer = (iostat->fs_rcount + aiostat->fs_rcount) /
+ stat = (iostat->fs_rcount + aiostat->fs_rcount) /
((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iowriterate") == 0) {
+ fbint_t stat;
+
/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
- var->var_integer = (iostat->fs_wcount + aiostat->fs_wcount) /
+ stat = (iostat->fs_wcount + aiostat->fs_wcount) /
((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iobandwidth") == 0) {
+ fbint_t stat;
+
/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
- var->var_integer =
+ stat =
((iostat->fs_bytes + aiostat->fs_bytes) / (1024 * 1024)) /
((globalstats->fs_etime - globalstats->fs_stime) / FSECS);
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iolatency") == 0) {
- var->var_integer = iostat->fs_count ?
- iostat->fs_mstate[FLOW_MSTATE_LAT] /
+ fbint_t stat;
+
+ stat = iostat->fs_count ? iostat->fs_mstate[FLOW_MSTATE_LAT] /
(iostat->fs_count * 1000UL) : 0;
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iocpu") == 0) {
- var->var_integer = (iostat->fs_count + aiostat->fs_count) ?
+ fbint_t stat;
+
+ stat = (iostat->fs_count + aiostat->fs_count) ?
(iostat->fs_mstate[FLOW_MSTATE_CPU] +
aiostat->fs_mstate[FLOW_MSTATE_CPU]) / ((iostat->fs_count +
aiostat->fs_count) * 1000UL) : 0;
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "oheadcpu") == 0) {
- var->var_integer = (iostat->fs_count + aiostat->fs_count) ?
+ fbint_t stat;
+
+ stat = (iostat->fs_count + aiostat->fs_count) ?
io_stats_ohead() / ((iostat->fs_count +
aiostat->fs_count) * 1000UL) : 0;
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iowait") == 0) {
- var->var_integer = iostat->fs_count ?
+ fbint_t stat;
+
+ stat = iostat->fs_count ?
iostat->fs_mstate[FLOW_MSTATE_WAIT] /
(iostat->fs_count * 1000UL) : 0;
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "syscpu") == 0) {
+ fbint_t stat;
+
/* LINTED E_ASSIGMENT_CAUSE_LOSS_PREC */
- var->var_integer = glstat->fs_syscpu / 1000.0;
+ stat = glstat->fs_syscpu / 1000.0;
+ VAR_SET_INT(var, stat);
return (var);
}
if (strcmp(name, "iocpusys") == 0) {
- var->var_integer = (iostat->fs_count + aiostat->fs_count) ?
+ fbint_t stat;
+
+ stat = (iostat->fs_count + aiostat->fs_count) ?
iostat->fs_syscpu / ((iostat->fs_count +
aiostat->fs_count) * 1000UL) : 0;
+ VAR_SET_INT(var, stat);
return (var);
}
@@ -421,13 +452,12 @@ stats_snap(void)
while (flowop) {
flowop_t *flowop_master;
- if (flowop->fo_instance == FLOW_MASTER) {
+ if (flowop->fo_instance <= FLOW_DEFINITION) {
flowop = flowop->fo_next;
continue;
}
- flowop_master = flowop_find_one(flowop->fo_name,
- FLOW_MASTER);
+ flowop_master = flowop_find_one(flowop->fo_name, FLOW_MASTER);
/* Roll up per-flowop into global stats */
stats_add(&globalstats[flowop->fo_type],
diff --git a/usr/src/cmd/filebench/common/threadflow.c b/usr/src/cmd/filebench/common/threadflow.c
index 11351fdf17..4feaa3147b 100644
--- a/usr/src/cmd/filebench/common/threadflow.c
+++ b/usr/src/cmd/filebench/common/threadflow.c
@@ -82,12 +82,15 @@ threadflow_usage(void)
static int
threadflow_createthread(threadflow_t *threadflow)
{
+ fbint_t memsize;
+ memsize = avd_get_int(threadflow->tf_memsize);
+ threadflow->tf_constmemsize = memsize;
+
filebench_log(LOG_DEBUG_SCRIPT, "Creating thread %s, memory = %ld",
- threadflow->tf_name,
- *threadflow->tf_memsize);
+ threadflow->tf_name, memsize);
if (threadflow->tf_attrs & THREADFLOW_USEISM)
- filebench_shm->shm_required += (*threadflow->tf_memsize);
+ filebench_shm->shm_required += memsize;
if (pthread_create(&threadflow->tf_tid, NULL,
(void *(*)(void*))flowop_start, threadflow) != 0) {
@@ -161,14 +164,15 @@ threadflow_init(procflow_t *procflow)
while (threadflow) {
threadflow_t *newthread;
+ int instances;
int i;
+ instances = avd_get_int(threadflow->tf_instances);
filebench_log(LOG_VERBOSE,
"Starting %lld %s threads",
- *(threadflow->tf_instances),
- threadflow->tf_name);
+ instances, threadflow->tf_name);
- for (i = 1; i < *threadflow->tf_instances; i++) {
+ for (i = 1; i < instances; i++) {
/* Create threads */
newthread =
threadflow_define_common(procflow,
@@ -257,9 +261,8 @@ threadflow_delete(threadflow_t **threadlist, threadflow_t *threadflow,
threadflow->tf_name,
threadflow->tf_instance);
- if (threadflow->tf_attrs & THREADFLOW_USEISM) {
- filebench_shm->shm_required -= (*threadflow->tf_memsize);
- }
+ if (threadflow->tf_attrs & THREADFLOW_USEISM)
+ filebench_shm->shm_required -= threadflow->tf_constmemsize;
if (threadflow == *threadlist) {
/* First on list */
@@ -442,7 +445,7 @@ threadflow_define_common(procflow_t *procflow, char *name,
*/
threadflow_t *
threadflow_define(procflow_t *procflow, char *name,
- threadflow_t *inherit, var_integer_t instances)
+ threadflow_t *inherit, avd_t instances)
{
threadflow_t *threadflow;
diff --git a/usr/src/cmd/filebench/common/threadflow.h b/usr/src/cmd/filebench/common/threadflow.h
index 3e5feefe09..119c368a1b 100644
--- a/usr/src/cmd/filebench/common/threadflow.h
+++ b/usr/src/cmd/filebench/common/threadflow.h
@@ -80,11 +80,12 @@ typedef struct threadflow {
struct procflow *tf_process; /* Back pointer to process */
pthread_t tf_tid; /* Thread id */
pthread_mutex_t tf_lock; /* Mutex around threadflow */
- var_integer_t tf_instances; /* Number of instances for this flow */
+ avd_t tf_instances; /* Number of instances for this flow */
struct threadflow *tf_next; /* Next on proc list */
struct flowop *tf_ops; /* Flowop list */
caddr_t tf_mem; /* Private Memory */
- var_integer_t tf_memsize; /* Private Memory size */
+ avd_t tf_memsize; /* Private Memory size attribute */
+ fbint_t tf_constmemsize; /* constant copy of memory size */
int tf_fd[THREADFLOW_MAXFD + 1]; /* Thread local fd's */
filesetentry_t *tf_fse[THREADFLOW_MAXFD + 1]; /* Thread local files */
int tf_fdrotor; /* Rotating fd within set */
@@ -104,8 +105,8 @@ typedef struct threadflow {
/* Thread attrs */
#define THREADFLOW_DEFAULTMEM 1024*1024LL;
-threadflow_t *threadflow_define(procflow_t *, char *name, threadflow_t *inherit,
- var_integer_t instances);
+threadflow_t *threadflow_define(procflow_t *, char *name,
+ threadflow_t *inherit, avd_t instances);
threadflow_t *threadflow_find(threadflow_t *, char *);
int threadflow_init(procflow_t *);
void flowop_start(threadflow_t *threadflow);
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);
diff --git a/usr/src/cmd/filebench/common/vars.h b/usr/src/cmd/filebench/common/vars.h
index 7b394a0ec8..af12a801fc 100644
--- a/usr/src/cmd/filebench/common/vars.h
+++ b/usr/src/cmd/filebench/common/vars.h
@@ -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.
*/
@@ -40,30 +40,136 @@
extern "C" {
#endif
-typedef uint64_t vinteger_t;
-typedef vinteger_t *var_integer_t;
-typedef char **var_string_t;
+/* Attribute Value Descriptor types */
+typedef enum avd_type {
+ AVD_INVALID = 0, /* avd is empty */
+ AVD_VAL_BOOL, /* avd contains a boolean_t */
+ AVD_VARVAL_BOOL, /* avd points to the boolean_t in a var_t */
+ AVD_VAL_INT, /* avd contains an fbint_t */
+ AVD_VARVAL_INT, /* avd points to the fbint_t in a var_t */
+ AVD_VAL_STR, /* avd contains a sting (*char) */
+ AVD_VARVAL_STR, /* avd points to a string in a var_t */
+ AVD_VAL_DBL, /* avd contains a double float */
+ AVD_VARVAL_DBL, /* avd points to the double in a var_t */
+ AVD_IND_VAR, /* avd points a var_t */
+ AVD_IND_RANDVAR /* avd points to the randdist_t associated */
+ /* with a random type var_t */
+} avd_type_t;
+
+typedef uint64_t fbint_t;
+
+/* Attribute Value Descriptor */
+typedef struct avd {
+ avd_type_t avd_type;
+ union {
+ boolean_t boolval;
+ boolean_t *boolptr;
+ fbint_t intval;
+ fbint_t *intptr;
+ double dblval;
+ double *dblptr;
+ char *strval;
+ char **strptr;
+ struct randdist *randptr;
+ struct var *varptr;
+ } avd_val;
+} *avd_t;
+
+#define AVD_IS_RANDOM(vp) ((vp)->avd_type == AVD_IND_RANDVAR)
typedef struct var {
char *var_name;
int var_type;
struct var *var_next;
- char *var_string;
- vinteger_t var_integer;
+ union {
+ boolean_t boolean;
+ fbint_t integer;
+ double dbl_flt;
+ char *string;
+ struct randdist *randptr;
+ } var_val;
} var_t;
-#define VAR_TYPE_DYNAMIC 1
+#define VAR_TYPE_GLOBAL 0x00 /* global variable */
+#define VAR_TYPE_DYNAMIC 0x01 /* Dynamic variable */
+#define VAR_TYPE_RANDOM 0x02 /* random variable */
+#define VAR_TYPE_MASK 0x0f
+#define VAR_TYPE_BOOL_SET 0x10 /* var contains a boolean */
+#define VAR_TYPE_INT_SET 0x20 /* var contains an integer */
+#define VAR_TYPE_STR_SET 0x30 /* var contains a string */
+#define VAR_TYPE_DBL_SET 0x40 /* var contains a double */
+#define VAR_TYPE_RAND_SET 0x50 /* var contains a randdist pointer */
+#define VAR_TYPE_SET_MASK 0xf0
+
+#define VAR_HAS_BOOLEAN(vp) \
+ (((vp)->var_type & VAR_TYPE_SET_MASK) == VAR_TYPE_BOOL_SET)
+
+#define VAR_HAS_INTEGER(vp) \
+ (((vp)->var_type & VAR_TYPE_SET_MASK) == VAR_TYPE_INT_SET)
+
+#define VAR_HAS_DOUBLE(vp) \
+ (((vp)->var_type & VAR_TYPE_SET_MASK) == VAR_TYPE_DBL_SET)
+
+#define VAR_HAS_STRING(vp) \
+ (((vp)->var_type & VAR_TYPE_SET_MASK) == VAR_TYPE_STR_SET)
+
+#define VAR_HAS_RANDDIST(vp) \
+ (((vp)->var_type & VAR_TYPE_SET_MASK) == VAR_TYPE_RAND_SET)
+
+#define VAR_SET_BOOL(vp, val) \
+ { \
+ (vp)->var_val.boolean = (val); \
+ (vp)->var_type = \
+ (((vp)->var_type & (~VAR_TYPE_SET_MASK)) | VAR_TYPE_BOOL_SET);\
+ }
+
+#define VAR_SET_INT(vp, val) \
+ { \
+ (vp)->var_val.integer = (val); \
+ (vp)->var_type = \
+ (((vp)->var_type & (~VAR_TYPE_SET_MASK)) | VAR_TYPE_INT_SET); \
+ }
+
+#define VAR_SET_DBL(vp, val) \
+ { \
+ (vp)->var_val.dbl_flt = (val); \
+ (vp)->var_type = \
+ (((vp)->var_type & (~VAR_TYPE_SET_MASK)) | VAR_TYPE_DBL_SET); \
+ }
+
+#define VAR_SET_STR(vp, val) \
+ { \
+ (vp)->var_val.string = (val); \
+ (vp)->var_type = \
+ (((vp)->var_type & (~VAR_TYPE_SET_MASK)) | VAR_TYPE_STR_SET); \
+ }
+
+#define VAR_SET_RAND(vp, val) \
+ { \
+ (vp)->var_val.randptr = (val); \
+ (vp)->var_type = \
+ (((vp)->var_type & (~VAR_TYPE_SET_MASK)) | VAR_TYPE_RAND_SET);\
+ }
-vinteger_t *integer_alloc(vinteger_t integer);
-char **string_alloc(char *string);
-int var_assign_integer(char *name, vinteger_t integer);
-vinteger_t *var_ref_integer(char *name);
+avd_t avd_bool_alloc(boolean_t bool);
+avd_t avd_int_alloc(fbint_t integer);
+avd_t avd_str_alloc(char *string);
+avd_t var_ref_attr(char *name);
+int var_assign_boolean(char *name, boolean_t bool);
+int var_assign_integer(char *name, fbint_t integer);
int var_assign_string(char *name, char *string);
int var_assign_var(char *name, char *string);
-char **var_ref_string(char *name);
+var_t *var_define_randvar(char *name);
+var_t *var_find_randvar(char *name);
+boolean_t var_to_boolean(char *name);
+fbint_t var_to_integer(char *name);
char *var_to_string(char *name);
-vinteger_t var_to_integer(char *name);
-int integer_isset(var_integer_t);
+char *var_randvar_to_string(char *name, int param);
+boolean_t avd_get_bool(avd_t);
+fbint_t avd_get_int(avd_t);
+double avd_get_dbl(avd_t);
+char *avd_get_str(avd_t);
+int var_is_set4_randvar(char *name);
#ifdef __cplusplus
}
diff --git a/usr/src/cmd/filebench/workloads/filemicro_rread.f b/usr/src/cmd/filebench/workloads/filemicro_rread.f
index 9a3b44599a..6d9b04c80f 100644
--- a/usr/src/cmd/filebench/workloads/filemicro_rread.f
+++ b/usr/src/cmd/filebench/workloads/filemicro_rread.f
@@ -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.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -30,6 +30,7 @@ set $iosize=2k
set $bytes=128m
set $iters=1
set $filesize=1g
+set $cached=false
define file name=bigfile1,path=$dir,size=$filesize,prealloc,reuse,cached=$cached
@@ -42,11 +43,12 @@ define process name=filereader,instances=1
}
}
-echo "FileMicro-ReadRand Version 2.0 personality successfully loaded"
+echo "FileMicro-ReadRand Version 2.1 personality successfully loaded"
usage "Usage: set \$dir=<dir>"
-usage " set \$filesize=<size> defaults to $filesize"
-usage " set \$iosize=<size> defaults to $iosize"
-usage " set \$bytes=<value> defaults to $bytes"
-usage " set \$nthreads=<value> defaults to $nthreads"
+usage " set \$bytes=<value> defaults to $bytes"
+usage " set \$cached=<bool> defaults to $cached"
+usage " set \$filesize=<size> defaults to $filesize"
+usage " set \$iosize=<size> defaults to $iosize"
+usage " set \$nthreads=<value> defaults to $nthreads"
usage " "
usage " run runtime (e.g. run 60)"
diff --git a/usr/src/cmd/filebench/workloads/filemicro_seqwrite.f b/usr/src/cmd/filebench/workloads/filemicro_seqwrite.f
index 588dcb78be..21accc9e33 100644
--- a/usr/src/cmd/filebench/workloads/filemicro_seqwrite.f
+++ b/usr/src/cmd/filebench/workloads/filemicro_seqwrite.f
@@ -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.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,9 +28,11 @@
# 5- Sequential write(32K) of a 1G file, uncached
set $dir=/tmp
-set $nthreads=1
-set $iosize=1m
set $cached=0
+set $count=1000
+set $iosize=1m
+set $nthreads=1
+set $sync=false
define fileset name=bigfileset,path=$dir,size=0,entries=$nthreads,dirwidth=1024,prealloc=100,cached=$cached
@@ -44,10 +46,12 @@ define process name=filewriter,instances=1
}
}
-echo "FileMicro-SeqWrite Version 2.0 personality successfully loaded"
+echo "FileMicro-SeqWrite Version 2.1 personality successfully loaded"
usage "Usage: set \$dir=<dir>"
+usage " set \$cached=<bool> defaults to $cached"
+usage " set \$count=<value> defaults to $count"
usage " set \$iosize=<size> defaults to $iosize"
usage " set \$nthreads=<value> defaults to $nthreads"
-usage " set \$cached=<bool> defaults to $cached"
+usage " set \$sync=<bool> defaults to $sync"
usage " "
usage " run runtime (e.g. run 60)"
diff --git a/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvargam.f b/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvargam.f
new file mode 100644
index 0000000000..f863021068
--- /dev/null
+++ b/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvargam.f
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+# Sequential write() of a 1G file, size picked from a gamma distribution
+# min of 1k and a mean of 5.5K, followed by close(), cached.
+
+
+
+set $dir=/tmp
+set $nthreads=1
+set $cached=false
+set $sync=false
+set $count=128k
+
+define randvar name=$iosize, type=gamma, min=1k, mean=5632, gamma=1500
+
+define fileset name=bigfileset,path=$dir,size=0,entries=$nthreads,dirwidth=1024,prealloc=100,cached=$cached
+
+define process name=filewriter,instances=1
+{
+ thread name=filewriterthread,memsize=10m,instances=$nthreads
+ {
+ flowop appendfile name=write-file,dsync=$sync,filesetname=bigfileset,iosize=$iosize,fd=1,iters=$count
+ flowop closefile name=close,fd=1
+ flowop finishoncount name=finish,value=1
+ }
+}
+
+echo "FileMicro-SeqWriteRandVarGam Version 1.0 personality successfully loaded"
+usage "Usage: set \$dir=<dir>"
+usage " set \$cached=<bool> defaults to $cached"
+usage " set \$count=<value> defaults to $count"
+usage " set \$iosize.type=<type> defaults to $iosize.type"
+usage " set \$iosize.randsrc=<src> defaults to $iosize.randsrc"
+usage " set \$iosize.mean=<mean> defaults to $iosize.mean"
+usage " set \$iosize.gamma=<gamma> defaults to $iosize.gamma"
+usage " set \$nthreads=<value> defaults to $nthreads"
+usage " set \$sync=<bool> defaults to $sync"
+usage " "
+usage " run runtime (e.g. run 60)"
diff --git a/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvartab.f b/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvartab.f
new file mode 100644
index 0000000000..e01618e0ab
--- /dev/null
+++ b/usr/src/cmd/filebench/workloads/filemicro_seqwriterandvartab.f
@@ -0,0 +1,66 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+# Sequential write() of a 1G file, size picked from a table in
+# the [1K,64K] range with a mean of 5.5K, followed by close(), cached.
+
+
+
+set $dir=/tmp
+set $nthreads=1
+set $cached=false
+set $sync=false
+set $count=128k
+
+define randvar name=$iosize, type=tabular, min=1k, randtable =
+{{ 80, 1k, 4k},
+ { 15, 4k, 16k},
+ { 05, 16k, 64k}}
+
+define fileset name=bigfileset,path=$dir,size=0,entries=$nthreads,dirwidth=1024,prealloc=100,cached=$cached
+
+define process name=filewriter,instances=1
+{
+ thread name=filewriterthread,memsize=10m,instances=$nthreads
+ {
+ flowop appendfile name=write-file,dsync=$sync,filesetname=bigfileset,iosize=$iosize,fd=1,iters=$count
+ flowop closefile name=close,fd=1
+ flowop finishoncount name=finish,value=1
+ }
+}
+
+echo "FileMicro-SeqWriteRandVarTab Version 1.0 personality successfully loaded"
+usage "Usage: set \$dir=<dir>"
+usage " set \$cached=<bool> defaults to $cached"
+usage " set \$count=<value> defaults to $count"
+usage " set \$iosize.type=<type> defaults to $iosize.type"
+usage " set \$iosize.randsrc=<src> defaults to $iosize.randsrc"
+usage " set \$iosize.mean=<mean> defaults to $iosize.mean"
+usage " set \$iosize.gamma=<gamma> defaults to $iosize.gamma"
+usage " set \$nthreads=<value> defaults to $nthreads"
+usage " set \$sync=<bool> defaults to $sync"
+usage " "
+usage " run runtime (e.g. run 60)"