Home | History | Annotate | Download | only in fbscript
      1  5184  ek110237 #!/usr/bin/perl
      2  5184  ek110237 #
      3  5184  ek110237 # CDDL HEADER START
      4  5184  ek110237 #
      5  5184  ek110237 # The contents of this file are subject to the terms of the
      6  5184  ek110237 # Common Development and Distribution License (the "License").
      7  5184  ek110237 # You may not use this file except in compliance with the License.
      8  5184  ek110237 #
      9  5184  ek110237 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  5184  ek110237 # or http://www.opensolaris.org/os/licensing.
     11  5184  ek110237 # See the License for the specific language governing permissions
     12  5184  ek110237 # and limitations under the License.
     13  5184  ek110237 #
     14  5184  ek110237 # When distributing Covered Code, include this CDDL HEADER in each
     15  5184  ek110237 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  5184  ek110237 # If applicable, add the following below this CDDL HEADER, with the
     17  5184  ek110237 # fields enclosed by brackets "[]" replaced with your own identifying
     18  5184  ek110237 # information: Portions Copyright [yyyy] [name of copyright owner]
     19  5184  ek110237 #
     20  5184  ek110237 # CDDL HEADER END
     21  5184  ek110237 #
     22  5184  ek110237 #
     23  9326    Andrew # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  5184  ek110237 # Use is subject to license terms.
     25  5184  ek110237 #
     26  5184  ek110237 
     27  5184  ek110237 use POSIX;
     28  7736    Andrew use Socket;
     29  5184  ek110237 
     30  7736    Andrew my $MULTI_CLIENT = 0;
     31  5184  ek110237 my $USE_XANADU = 0;
     32  5184  ek110237 my $TIMEOUT = 60;
     33  7736    Andrew my $EOL = "\n";
     34  5184  ek110237 my $FILEBENCH = "/usr/benchmarks/filebench";
     35  9513    Andrew my $PROG = "bin/go_filebench";
     36  7736    Andrew my $SHAREDFILEALLOCATOR;
     37  7736    Andrew my $TARGETPATH;
     38  7736    Andrew my $TARGETDIR;
     39  7736    Andrew my $FB_MASTERPATH;
     40  7736    Andrew my $STATSBASE;
     41  7736    Andrew my $CONFNAME;
     42  5184  ek110237 my $FSCRIPT;
     43  5184  ek110237 my $SCRIPT_NO;
     44  7736    Andrew my @CLIENTLIST = ();
     45  7736    Andrew my %CLIENTHASH = ();
     46  5184  ek110237 my @CONFLIST;
     47  7736    Andrew my %MULTIDATA = ();
     48  9513    Andrew my %CMDLINEDATA = ();
     49  5184  ek110237 my %DEFDATA = ();
     50  5184  ek110237 my %CONFDATA = ();
     51  5184  ek110237 my %STATSHASH = ();
     52  9513    Andrew my $OPTIONFLAGS = "cleanupstorage dofscheck";
     53  5184  ek110237 @ext_stats=();
     54  5184  ek110237 @file_stats=();
     55  5184  ek110237 @arg_stats=();
     56  5184  ek110237 @pid_arr=();
     57  5184  ek110237 
     58  5184  ek110237 # The following if test caters for running benchpoint from an alternative path
     59  5184  ek110237 #if (-r $ENV{"FILEBENCH") {
     60  5184  ek110237 #	$FILEBENCH = $ENV{"FILEBENCH"};
     61  5184  ek110237 #}
     62  5184  ek110237 
     63  5184  ek110237 ##############################################################################
     64  5184  ek110237 ## Configuration hash data operations
     65  5184  ek110237 ##############################################################################
     66  5184  ek110237 
     67  5184  ek110237 # This sub allows a function program to extract the base directory for filebench
     68  5184  ek110237 sub get_FILEBENCH {
     69  5184  ek110237     return ($FILEBENCH);
     70  5184  ek110237 }
     71  5184  ek110237 
     72  5184  ek110237 sub get_STATSBASE {
     73  5184  ek110237     return ($STATSBASE);
     74  5184  ek110237 }
     75  5184  ek110237 
     76  5184  ek110237 sub get_CONFNAME {
     77  5184  ek110237     return ($CONFNAME);
     78  5184  ek110237 }
     79  5184  ek110237 
     80  7736    Andrew sub multi_putval {
     81  7736    Andrew     my ($key) = shift;
     82  7736    Andrew     my ($val) = shift;
     83  7736    Andrew     @{MULTIDATA{$key}} = ();
     84  7736    Andrew     push(@{ $MULTIDATA{$key} }, $val);
     85  7736    Andrew }
     86  7736    Andrew 
     87  7736    Andrew sub multi_getval {
     88  7736    Andrew     my ($key) = shift;
     89  7736    Andrew     return ("@{$MULTIDATA{$key}}");
     90  7736    Andrew }
     91  7736    Andrew 
     92  7736    Andrew sub multi_exists {
     93  7736    Andrew     my ($key) = shift;
     94  7736    Andrew     if (exists($MULTIDATA{$key})) {
     95  7736    Andrew 	return (1);
     96  7736    Andrew     }
     97  7736    Andrew     return (0);
     98  5184  ek110237 }
     99  5184  ek110237 
    100  5184  ek110237 sub conf_getval {
    101  5184  ek110237     my ($key) = shift;
    102  5184  ek110237     return ("@{$CONFDATA{$key}}");
    103  5184  ek110237 }
    104  5184  ek110237 
    105  5184  ek110237 sub conf_reqval {
    106  5184  ek110237     my ($key) = shift;
    107  5184  ek110237     
    108  5184  ek110237     if (exists($CONFDATA{$key})) {
    109  5184  ek110237 	return ("@{$CONFDATA{$key}}");
    110  5184  ek110237     }
    111  5184  ek110237     print "ERROR: required key \"$key\" missing from configuration\n";
    112  5184  ek110237     exit(1);
    113  5184  ek110237 }
    114  5184  ek110237 
    115  5184  ek110237 sub conf_exists {
    116  5184  ek110237     my ($key) = shift;
    117  5184  ek110237     if (exists($CONFDATA{$key})) {
    118  5184  ek110237 	return (1);
    119  5184  ek110237     }
    120  5184  ek110237     return (0);
    121  5184  ek110237 }
    122  5184  ek110237 
    123  5184  ek110237 sub conf_hash {
    124  5184  ek110237     return(%CONFDATA);
    125  5184  ek110237 }
    126  5184  ek110237 
    127  5184  ek110237 ##############################################################################
    128  5184  ek110237 ## Filebench Operations
    129  5184  ek110237 ##############################################################################
    130  5184  ek110237 
    131  5184  ek110237 sub op_init {
    132  5184  ek110237 }
    133  5184  ek110237 
    134  5184  ek110237 sub op_load {
    135  5184  ek110237     my ($workload) = shift;
    136  7736    Andrew     $scriptname = conf_reqval("statsdir") . "/thisrun.f";
    137  7736    Andrew 
    138  5184  ek110237     if($workload ne '') {
    139  7736    Andrew 	print ("Creating Client Script " . $scriptname . "\n");
    140  7736    Andrew 	open (FSCRIPT, ">$scriptname");
    141  7736    Andrew 	chmod (0755, $scriptname);
    142  9513    Andrew 	print FSCRIPT "#!$FILEBENCH/$PROG -f\n\n";
    143  7736    Andrew 	# Load the df
    144  7736    Andrew 	print FSCRIPT "load $workload\n";
    145  7736    Andrew 	# Load the user defined defaults
    146  7736    Andrew 	op_load_defaults();
    147  5184  ek110237 
    148  7736    Andrew 	# enable multiclient, if needed
    149  7736    Andrew 	if ($MULTI_CLIENT == 1) {
    150  7736    Andrew 	    print FSCRIPT "enable multi master=".multi_getval("masterhost").", client=".conf_getval("myname")."\n";
    151  7736    Andrew 	}
    152  9513    Andrew 
    153  9513    Andrew 	# Check to see if the path is legal and pointing to the correct FS
    154  9513    Andrew 	if (conf_exists("dofscheck") == 1) {
    155  9513    Andrew 	    print FSCRIPT "fscheck path=" . conf_reqval("dir") . " fstype=" . conf_reqval("filesystem") . "\n";
    156  9513    Andrew 	}
    157  9513    Andrew 
    158  7736    Andrew 	# Create the associated files and filesets
    159  9513    Andrew 	print FSCRIPT "create filesets\n";
    160  5184  ek110237     }
    161  5184  ek110237     $SCRIPT_NO = 1;
    162  5184  ek110237     return(0);
    163  9513    Andrew }
    164  9513    Andrew 
    165  9513    Andrew sub op_fsflush {
    166  9513    Andrew         print FSCRIPT "fsflush fstype=" . conf_reqval("filesystem") . "\n";
    167  5184  ek110237 }
    168  5184  ek110237 
    169  5184  ek110237 sub op_set {
    170  5184  ek110237     my ($var, $val) = @_;
    171  5184  ek110237     if($var eq 'debug') {
    172  5184  ek110237 	    print FSCRIPT "debug $val\n";
    173  5184  ek110237     } elsif($var ne '') {
    174  5184  ek110237 	    print FSCRIPT "set \$$var=$val\n";
    175  5184  ek110237     }
    176  5184  ek110237     return(0);
    177  5184  ek110237 }
    178  5184  ek110237 
    179  5184  ek110237 sub op_eventrate {
    180  5184  ek110237     my ($eventrate) = shift;
    181  5184  ek110237 	if ($eventrate ne '') {
    182  5184  ek110237 		print FSCRIPT "eventgen rate=$eventrate\n";
    183  5184  ek110237 		return(0);
    184  5184  ek110237 	}
    185  5184  ek110237 }
    186  5184  ek110237 
    187  5184  ek110237 sub op_run {
    188  5184  ek110237     my ($time) = shift;
    189  5184  ek110237     print FSCRIPT "run $time\n";
    190  5184  ek110237     return(0);
    191  5184  ek110237 }
    192  5184  ek110237 
    193  5184  ek110237 sub op_sleep {
    194  5184  ek110237     my ($time) = shift;
    195  5184  ek110237     print FSCRIPT "sleep $time\n";
    196  5184  ek110237     return(0);
    197  5184  ek110237 }
    198  5184  ek110237 
    199  5184  ek110237 sub op_msg {
    200  5184  ek110237     my ($msg) = shift;
    201  5184  ek110237     print FSCRIPT "echo \"$msg\"\n";
    202  5184  ek110237     return(0);
    203  5184  ek110237 }
    204  5184  ek110237 
    205  5184  ek110237 sub op_quit {
    206  7736    Andrew     # Shutdown the appropriate processes
    207  7736    Andrew     print FSCRIPT "shutdown processes\n";
    208  9356    Andrew 
    209  9356    Andrew     # remove filesets, if requested
    210  9356    Andrew     if (conf_exists("cleanupstorage") == 1) {
    211  9356    Andrew 	printf FSCRIPT "shutdown filesets\n";
    212  9356    Andrew     }
    213  5184  ek110237 
    214  7736    Andrew     # Quit filebench
    215  7736    Andrew     print FSCRIPT "quit\n";
    216  7736    Andrew     close(FSCRIPT);
    217  5184  ek110237 }
    218  5184  ek110237 
    219  5184  ek110237 sub op_statsdir {
    220  5184  ek110237     print FSCRIPT "stats directory ".conf_reqval("statsdir")."\n";
    221  5184  ek110237     return(0);
    222  5184  ek110237 }
    223  5184  ek110237 
    224  5184  ek110237 sub op_indiv_vars {
    225  5184  ek110237     my ($ivar) = shift;
    226  5184  ek110237     print FSCRIPT "echo \"\$$ivar\"\n";
    227  5184  ek110237     my ($imatch, $ierr, $ibefore, $iafter) = &expect(FSCRIPT,
    228  5184  ek110237 						 $TIMEOUT, "filebench>");
    229  5184  ek110237    
    230  5184  ek110237     $ibefore =~ /(.*): (.*): (-*\d+)/;
    231  5184  ek110237     $imatch = $3;
    232  5184  ek110237     $imatch =~ s/^\s+//;
    233  5184  ek110237     chomp($imatch);
    234  5184  ek110237     return($imatch);
    235  5184  ek110237 }
    236  5184  ek110237 
    237  5184  ek110237 sub op_indiv_stats {
    238  5184  ek110237     my ($var) = shift;
    239  5184  ek110237     print FSCRIPT "echo \"\${stats.$var}\"\n";
    240  5184  ek110237     my ($match, $err, $before, $after) = &expect(FSCRIPT,
    241  5184  ek110237 						 $TIMEOUT, "filebench>");
    242  5184  ek110237    
    243  5184  ek110237     $before =~ /(.*): (.*): (-*\d+)/;
    244  5184  ek110237     $match = $3;
    245  5184  ek110237     $match =~ s/^\s+//;
    246  5184  ek110237     chomp($match);
    247  5184  ek110237     return($match);
    248  5184  ek110237 }
    249  5184  ek110237 
    250  5184  ek110237 sub op_stats {
    251  5184  ek110237     my ($time) = shift;
    252  9326    Andrew     my ($warmup) = shift;
    253  5184  ek110237     my ($statsfile) = shift;
    254  7736    Andrew     my $mstrstatsdir = $STATSBASE."/".$CONFNAME;
    255  5184  ek110237 
    256  7736    Andrew     if ($MULTI_CLIENT == 1) {
    257  7736    Andrew 	print FSCRIPT "domultisync value=1\n";
    258  7736    Andrew     }
    259  5184  ek110237 
    260  7736    Andrew     # Create the associated processes and start them running
    261  7736    Andrew     print FSCRIPT "create processes\n";
    262  9326    Andrew 
    263  9326    Andrew     if ($warmup ne '') {
    264  9326    Andrew 	print FSCRIPT "warmup $warmup\n";
    265  9326    Andrew     }
    266  5184  ek110237 
    267  7736    Andrew     if (($time ne '') && ($statsfile ne '')) {
    268  7736    Andrew 	# Clear the current statistics buffers
    269  7736    Andrew 	print FSCRIPT "stats clear\n";
    270  7736    Andrew 
    271  7736    Andrew 	# Start external statistics collection (if any)
    272  7736    Andrew 	# Note all statistics arrays MUST be the same length !
    273  7736    Andrew 	if (@ext_stats != ()) {
    274  7736    Andrew 	    if (($#ext_stats == $#file_stats) && ($#ext_stats == $#arg_stats)) {
    275  7736    Andrew 		$script = $mstrstatsdir . "/stats$SCRIPT_NO.sh";
    276  7736    Andrew 		open (RUNSCRIPT, ">$script");
    277  7736    Andrew 		chmod (0755, $script);
    278  7736    Andrew 		print FSCRIPT "system \"$script\"\n";
    279  7736    Andrew 		$SCRIPT_NO++;
    280  7736    Andrew 		$index=0;
    281  7736    Andrew 		foreach my $ext (@ext_stats) {
    282  7736    Andrew 		    print RUNSCRIPT "$FILEBENCH/scripts/collect_$ext $ext $file_stats[$index] ";
    283  7736    Andrew 		    print RUNSCRIPT  $mstrstatsdir;
    284  7736    Andrew 		    print RUNSCRIPT " $time $FILEBENCH $arg_stats[$index] &\n";
    285  7736    Andrew 		    $index++;
    286  5184  ek110237 		}
    287  5184  ek110237 	    }
    288  7736    Andrew 	}
    289  7736    Andrew 	close(RUNSCRIPT);
    290  5184  ek110237 
    291  7736    Andrew 	# Sleep for the run time
    292  7736    Andrew 	print FSCRIPT "sleep $time\n";
    293  5184  ek110237 
    294  7736    Andrew 	# Snap the statistics
    295  7736    Andrew 	print FSCRIPT "stats snap\n";
    296  5184  ek110237 
    297  7736    Andrew 	# Dump the statistics to a raw file - out required due to filename constraint
    298  7736    Andrew 	if ($MULTI_CLIENT == 1) {
    299  7736    Andrew 	    print FSCRIPT "domultisync value=2\n";
    300  7736    Andrew 	    print FSCRIPT "stats multidump \"$statsfile.out\"\n";
    301  7736    Andrew 	} else {
    302  7736    Andrew 	    print FSCRIPT "stats dump \"$statsfile.out\"\n";
    303  7736    Andrew 	}
    304  5184  ek110237 
    305  7736    Andrew 	# Statistics reaping occurs here
    306  7736    Andrew 	if (@ext_stats != ()) {
    307  7736    Andrew 	    if (($#ext_stats == $#file_stats) && ($#ext_stats == $#arg_stats)) {
    308  7736    Andrew 		$script = $mstrstatsdir . "/stats$SCRIPT_NO.sh";
    309  7736    Andrew 		open (RUNSCRIPT, ">$script");
    310  7736    Andrew 		chmod (0755, $script);
    311  7736    Andrew 		print FSCRIPT "system \"$script\"\n";
    312  7736    Andrew 		$SCRIPT_NO++;
    313  7736    Andrew 		foreach my $ext (@ext_stats) {
    314  7736    Andrew 		    print RUNSCRIPT "$FILEBENCH/scripts/kill_stats $ext &\n";
    315  5184  ek110237 		}
    316  7736    Andrew 		close(RUNSCRIPT);
    317  5184  ek110237 	    }
    318  5184  ek110237 	}
    319  7736    Andrew 
    320  7736    Andrew 	# Dump the statistics to a Xanadu compatible XML file
    321  7736    Andrew 	if ($USE_XANADU) {
    322  7736    Andrew 	    op_xmlstats($statsfile);
    323  7736    Andrew 
    324  7736    Andrew 	    $script = $mstrstatsdir . "/stats$SCRIPT_NO.pl";
    325  7736    Andrew 	    open (RUNSCRIPT, ">$script");
    326  7736    Andrew 	    chmod (0755, $script);
    327  7736    Andrew 	    print FSCRIPT "system \"$script\"\n";
    328  7736    Andrew 	    $SCRIPT_NO++;
    329  7736    Andrew 
    330  7736    Andrew 	    # The following loop adds the benchpoint run parameters and statistics into the filebench XML file
    331  7736    Andrew 	    # We capture the meta data from the start of the filebench xml file
    332  7736    Andrew 	    print RUNSCRIPT "#!/usr/bin/perl\n";
    333  7736    Andrew 	    print RUNSCRIPT "\$phase=1;\n";
    334  7736    Andrew 	    print RUNSCRIPT "open(STATSFILE,\"<".$mstrstatsdir."/$statsfile.xml\");\n";
    335  7736    Andrew 	    print RUNSCRIPT "open(OSTATSFILE,\">".$mstrstatsdir."/$statsfile.new.xml\");\n";
    336  7736    Andrew 	    print RUNSCRIPT "while (<STATSFILE>) {\n";
    337  7736    Andrew 	    print RUNSCRIPT "\t\$temp=\$_;\n";
    338  7736    Andrew 	    print RUNSCRIPT "\tif ((!((/.*meta.*/) || (/.*stat_doc.*/))) && (\$phase == 1)) {\n";
    339  7736    Andrew 	    print RUNSCRIPT "\t\topen(XMLFILE,\"<".$mstrstatsdir."/$statsfile.config.xml\");\n";
    340  7736    Andrew 	    print RUNSCRIPT "\t\twhile (<XMLFILE>) {\n";
    341  7736    Andrew 	    print RUNSCRIPT "\t\t\tprint OSTATSFILE \$_;\n";
    342  7736    Andrew 	    print RUNSCRIPT "\t\t}\n";
    343  7736    Andrew 	    print RUNSCRIPT "\t\tclose(XMLFILE);\n";
    344  7736    Andrew 	    print RUNSCRIPT "\t\t\$phase++;\n";
    345  7736    Andrew 	    print RUNSCRIPT "\t}\n";
    346  7736    Andrew 	    print RUNSCRIPT "\tprint OSTATSFILE \$temp;\n";
    347  7736    Andrew 	    print RUNSCRIPT "}\n";
    348  7736    Andrew 	    print RUNSCRIPT "close(STATSFILE);\n";
    349  7736    Andrew 	    print RUNSCRIPT "close(OSTATSFILE);\n";
    350  7736    Andrew 	    print RUNSCRIPT "unlink(\"".$mstrstatsdir."/$statsfile.xml\");\n";
    351  7736    Andrew 	    print RUNSCRIPT "unlink(\"".$mstrstatsdir."/$statsfile.config.xml\");\n";
    352  7736    Andrew 	    print RUNSCRIPT "system(\"mv ".$mstrstatsdir."/$statsfile.new.xml ".$mstrstatsdir."/$statsfile.xml\");\n";
    353  7736    Andrew 
    354  7736    Andrew 	    $script = $mstrstatsdir . "/stats$SCRIPT_NO.sh";
    355  7736    Andrew 	    open (RUNSCRIPT, ">$script");
    356  7736    Andrew 	    chmod (0755, $script);
    357  7736    Andrew 	    print FSCRIPT "system \"$script\"\n";
    358  7736    Andrew 	    $SCRIPT_NO++;
    359  7736    Andrew 
    360  7736    Andrew 	    print RUNSCRIPT "mkdir ".$mstrstatsdir."/xml\n";
    361  7736    Andrew 	    print RUNSCRIPT "mkdir ".$mstrstatsdir."/html\n";
    362  7736    Andrew 
    363  7736    Andrew 	    print RUNSCRIPT "mv ".$mstrstatsdir."/$statsfile.xml ".$mstrstatsdir."/xml/$statsfile.xml\n";
    364  7736    Andrew 
    365  7736    Andrew 	    # Process XML file using Xanadu 2
    366  7736    Andrew 	    print RUNSCRIPT "$FILEBENCH/xanadu/scripts/xanadu import ".$mstrstatsdir." ".$mstrstatsdir."/xml ".conf_reqval("function")."-".$mstrstatsdir."\n";
    367  7736    Andrew 	    print RUNSCRIPT "$FILEBENCH/xanadu/scripts/xanadu export ".$mstrstatsdir."/xml ".$mstrstatsdir."/html\n";
    368  7736    Andrew 	    close(RUNSCRIPT);
    369  7736    Andrew 	}
    370  7736    Andrew     }
    371  7736    Andrew     return(0);	
    372  5184  ek110237 }
    373  5184  ek110237 
    374  5184  ek110237 sub op_xmlstats {
    375  5184  ek110237     my ($statsfile) = shift;
    376  7736    Andrew     my $mstrstatsdir = $STATSBASE."/".$CONFNAME;
    377  7736    Andrew     if($statsfile ne '') {
    378  7736    Andrew 	print FSCRIPT "stats xmldump \"$statsfile.xml\"\n";	
    379  5184  ek110237 
    380  7736    Andrew 	# The following loop adds the benchpoint run parameters and statistics into a temporary XML file
    381  7736    Andrew 	open(OSTATSFILE,">".$mstrstatsdir."/$statsfile.config.xml");
    382  7736    Andrew 	%CONFHASH = conf_hash();
    383  7736    Andrew 	# There is no test for whether CONFHASH contains no keys 
    384  7736    Andrew 	# The following two lines is to obtain the stats run directory name for xanadu meta data
    385  7736    Andrew 	print OSTATSFILE "<meta name=\"RunId\" value=\"".conf_reqval("function")."-".$mstrstatsdir."\"/>\n";
    386  7736    Andrew 	print OSTATSFILE "<stat_group name=\"Benchpoint Configuration\">\n";
    387  7736    Andrew 	print OSTATSFILE "<cell_list>\n";
    388  7736    Andrew 	foreach $k (keys(%CONFHASH)) {
    389  7736    Andrew 	    print OSTATSFILE "<cell>@{ $CONFHASH{$k} }</cell>\n";
    390  7736    Andrew 	}
    391  7736    Andrew 	print OSTATSFILE "</cell_list>\n";
    392  7736    Andrew 	print OSTATSFILE "<dim_list>\n";
    393  7736    Andrew 	print OSTATSFILE "<dim>\n";
    394  7736    Andrew 	print OSTATSFILE "<dimval>Value</dimval>\n";
    395  7736    Andrew 	print OSTATSFILE "</dim>\n";
    396  7736    Andrew 	print OSTATSFILE "<dim>\n";
    397  7736    Andrew 	foreach $k (keys(%CONFHASH)) {
    398  7736    Andrew 	    print OSTATSFILE "<dimval>$k</dimval>\n";
    399  7736    Andrew 	}
    400  7736    Andrew 	print OSTATSFILE "</dim>\n";
    401  7736    Andrew 	print OSTATSFILE "</dim_list>\n";
    402  7736    Andrew 	print OSTATSFILE "</stat_group>\n";
    403  7736    Andrew 	close(OSTATSFILE);
    404  5184  ek110237 
    405  7736    Andrew 	return(0);	
    406  7736    Andrew     }
    407  7736    Andrew     return(1);	
    408  5184  ek110237 }
    409  5184  ek110237 
    410  5184  ek110237 sub op_command {
    411  5184  ek110237     my ($command) = shift;
    412  5184  ek110237 	if($command ne '') {
    413  5184  ek110237 	    print FSCRIPT "$command\n";	
    414  5184  ek110237 	}
    415  5184  ek110237 	return(0);	
    416  5184  ek110237 }
    417  5184  ek110237 
    418  5184  ek110237 sub op_statshash {
    419  5184  ek110237     op_indiv_stats("iocount");	
    420  5184  ek110237     $STATSHASH{"iocount"} = op_indiv_stats("iocount");	
    421  5184  ek110237     $STATSHASH{"iorate"} = op_indiv_stats("iorate");	
    422  5184  ek110237     $STATSHASH{"ioreadrate"} = op_indiv_stats("ioreadrate");	
    423  5184  ek110237     $STATSHASH{"iowriterate"} = op_indiv_stats("iowriterate");	
    424  5184  ek110237     $STATSHASH{"iobandwidth"} = op_indiv_stats("iobandwidth");	
    425  5184  ek110237     $STATSHASH{"iolatency"} = op_indiv_stats("iolatency");	
    426  5184  ek110237     $STATSHASH{"iocpu"} = op_indiv_stats("iocpu");	
    427  5184  ek110237     $STATSHASH{"oheadcpu"} = op_indiv_stats("oheadcpu");	
    428  5184  ek110237     $STATSHASH{"iowait"} = op_indiv_stats("iowait");	
    429  5184  ek110237     $STATSHASH{"syscpu"} = op_indiv_stats("syscpu");	
    430  5184  ek110237     $STATSHASH{"iocpusys"} = op_indiv_stats("iocpusys");	
    431  5184  ek110237     return(%STATSHASH);
    432  5184  ek110237 }
    433  5184  ek110237 
    434  5184  ek110237 sub op_load_defaults {
    435  5184  ek110237 # The following code causes an intermittent bug - may be fixed at a later date
    436  5184  ek110237 # Prevents the capture of filebench default parameters
    437  5184  ek110237 #    print FSCRIPT "vars\n";
    438  5184  ek110237 #    my ($match, $err, $before, $after) = &expect(FSCRIPT,
    439  5184  ek110237 #						 $TIMEOUT, "filebench>");
    440  5184  ek110237 #    chomp($before);
    441  5184  ek110237 #    $before =~ /(.*): (.*): (.*)/;
    442  5184  ek110237 #    $match = $3;
    443  5184  ek110237 #    my @vars = split(/ /, $match);
    444  5184  ek110237 #    my $value = "";
    445  5184  ek110237 #    # Cater for the default filebench commands
    446  5184  ek110237 #    foreach my $var (@vars) {
    447  5184  ek110237 #        if (!conf_exists($var)) {
    448  5184  ek110237 #            $var =~ s/ //g;
    449  5184  ek110237 #	    if ($var ne '') {
    450  5184  ek110237 #		$value = op_indiv_vars($var);
    451  5184  ek110237 #       	        push(@{ $CONFDATA{$var} }, $value);		   
    452  5184  ek110237 #	    }
    453  5184  ek110237 #	}
    454  5184  ek110237 #    }
    455  5184  ek110237 
    456  5184  ek110237     # Cater for the user defined defaults
    457  5184  ek110237     foreach $var (keys(%CONFDATA)) {
    458  5184  ek110237         if (conf_exists($var)) {
    459  5184  ek110237             $var =~ s/ //g;
    460  5184  ek110237             my $val = conf_getval($var);
    461  7736    Andrew 
    462  7736    Andrew 	    if (($SHAREDFILEALLOCATOR) and ($var eq "sharedprealloc")) {
    463  7736    Andrew 		if (conf_reqval("myname") ne $SHAREDFILEALLOCATOR) {
    464  7736    Andrew 		    $val = "0";
    465  7736    Andrew 		}
    466  7736    Andrew 	    }
    467  7736    Andrew 
    468  9356    Andrew 	    if ($val ne "") {
    469  9356    Andrew 		op_set($var, $val);
    470  9356    Andrew 	    }
    471  5184  ek110237 	}
    472  5184  ek110237     }
    473  5184  ek110237 }
    474  5184  ek110237 
    475  5184  ek110237 ##############################################################################
    476  5184  ek110237 ## Local functions
    477  5184  ek110237 ##############################################################################
    478  5184  ek110237 
    479  5184  ek110237 sub parse_profile {
    480  5184  ek110237     my ($profile) = shift;
    481  7736    Andrew     my ($config_section, $default_section, $multi_section);
    482  5184  ek110237     
    483  5184  ek110237     open(CFILE, "$profile") or 
    484  9513    Andrew 	die "ERROR: couldn't open profile $profile";
    485  5184  ek110237     
    486  5184  ek110237     while(<CFILE>) {
    487  5184  ek110237 	my ($line) = $_;
    488  5184  ek110237 	chomp($line);
    489  5184  ek110237 	$line =~ s/^\s+//; # Get rid of spaces
    490  5184  ek110237 	
    491  5184  ek110237 	if($line =~ /^#/ or $line eq "") {
    492  5184  ek110237 	} else {
    493  5184  ek110237 	    if($line =~ /}/) {
    494  7736    Andrew 		if($multi_section == 1) {
    495  7736    Andrew 		    $multi_section = 0;
    496  7736    Andrew 		}
    497  5184  ek110237 		if($default_section == 1) {
    498  5184  ek110237 		    $default_section = 0;
    499  5184  ek110237 		}
    500  5184  ek110237 		if($config_section == 1) {
    501  5184  ek110237 		    $config_section = 0;
    502  5184  ek110237 		}
    503  7736    Andrew 	    } elsif($multi_section) {
    504  9513    Andrew 		$line =~ /([^\s]+)\s*=\s*(.+);/;
    505  7736    Andrew 		my $opt = $1;
    506  7736    Andrew 		my $val = $2;
    507  7736    Andrew 		chomp($opt);
    508  7736    Andrew 		chomp($val);
    509  7736    Andrew 		my @vals = ();
    510  7736    Andrew 		# Check to see if this needs to be a list
    511  7736    Andrew 		if($val =~ /,/) {
    512  7736    Andrew 		    push(@vals, $+) while $val =~
    513  7736    Andrew 			m{"([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx;
    514  7736    Andrew 		    push(@vals, undef) if substr($val, -1,1) eq ',';
    515  7736    Andrew 		    @{ $MULTIDATA{$opt} } = @vals;
    516  7736    Andrew 		} else {
    517  7736    Andrew 		    @{MULTIDATA{$opt}} = ();
    518  7736    Andrew 		    push(@{ $MULTIDATA{$opt} }, $val);		   
    519  7736    Andrew 		}	       
    520  5184  ek110237 	    } elsif($default_section) {
    521  9513    Andrew 		if ($line =~ /([^\s]+)\s*=\s*(.+);/) {
    522  9356    Andrew 		    my $opt = $1;
    523  9356    Andrew 		    my $val = $2;
    524  9356    Andrew 		    chomp($opt);
    525  9356    Andrew 		    chomp($val);
    526  9356    Andrew 		    my @vals = ();
    527  9356    Andrew 		    # Check to see if this needs to be a list
    528  9356    Andrew 		    if(($val =~ /,/) && ($val !~ /"/)) {
    529  9356    Andrew 			push(@vals, $+) while $val =~
    530  9356    Andrew 			    m{"([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx;
    531  9356    Andrew 			push(@vals, undef) if substr($val, -1,1) eq ',';
    532  9356    Andrew 			@{ $DEFDATA{$opt} } = @vals;
    533  9513    Andrew 		    } elsif(exists($CMDLINEDATA{$opt})) {
    534  9513    Andrew 			@{DEFDATA{$opt}} = ();
    535  9513    Andrew 			push(@{ $DEFDATA{$opt} }, @{$CMDLINEDATA{$opt}});
    536  9356    Andrew 		    } else {
    537  9356    Andrew 			@{DEFDATA{$opt}} = ();
    538  9356    Andrew 			push(@{ $DEFDATA{$opt} }, $val);		   
    539  9356    Andrew 		    }
    540  5184  ek110237 		} else {
    541  9513    Andrew 		    if ($line =~ /([^;]+);/) {
    542  9513    Andrew 			my $opt = $1;
    543  9513    Andrew 			if ($OPTIONFLAGS =~ /$opt/) {
    544  9513    Andrew 			    @{DEFDATA{$opt}} = ();
    545  9513    Andrew 			    push(@{ $DEFDATA{$opt} }, "");
    546  9513    Andrew 			}
    547  9513    Andrew 		    }
    548  9356    Andrew 		}
    549  5184  ek110237 	    } else {
    550  5184  ek110237 		if($line =~ /^CONFIG /) {
    551  5184  ek110237                     my $config = $line;
    552  9513    Andrew 	 	    $config =~ s/CONFIG\s+(.+) {/$1/;
    553  5184  ek110237 		    push(@CONFLIST, $config);
    554  5184  ek110237 		    $config_section = 1;
    555  9513    Andrew 		} elsif($line =~ /MULTICLIENT\s{/) {
    556  7736    Andrew 		    $multi_section = 1;
    557  7736    Andrew 		    $MULTI_CLIENT = 1;
    558  9513    Andrew 		} elsif($line =~ /DEFAULTS\s{/) {
    559  5184  ek110237 		    $default_section = 1;
    560  5184  ek110237 		}
    561  5184  ek110237 	    }
    562  5184  ek110237 	}
    563  5184  ek110237     }
    564  5184  ek110237 }
    565  5184  ek110237 
    566  5184  ek110237 
    567  5184  ek110237 #
    568  5184  ek110237 # Parse the configuration file
    569  5184  ek110237 #
    570  5184  ek110237 sub parse_config {
    571  5184  ek110237     my ($config) = shift;
    572  5184  ek110237 
    573  5184  ek110237     my $config_section = 0;
    574  5184  ek110237 
    575  5184  ek110237     print "parsing profile for config: $config\n";
    576  5184  ek110237     
    577  5184  ek110237     # Howdy
    578  5184  ek110237     seek(CFILE, 0, 0);
    579  5184  ek110237     
    580  5184  ek110237     while(<CFILE>) {
    581  5184  ek110237 	# Read in the line and chomp...munch...chomp
    582  5184  ek110237 	my ($line) = $_;
    583  5184  ek110237 	chomp($line);
    584  5184  ek110237 	$line =~ s/^\s+//; # Get rid of spaces
    585  5184  ek110237 
    586  5184  ek110237 	# look for our stuff
    587  5184  ek110237 	if ($line =~ /CONFIG $config /) {
    588  5184  ek110237 	    $config_section = 1;
    589  5184  ek110237         }
    590  5184  ek110237 
    591  5184  ek110237         if($line =~ /}/) {
    592  5184  ek110237 	    $config_section = 0;
    593  5184  ek110237         }
    594  5184  ek110237 
    595  5184  ek110237 	# Skip until our config is found
    596  5184  ek110237 	next if (!$config_section);
    597  5184  ek110237 
    598  5184  ek110237 	next if ($line =~ /^#/ or $line eq "");
    599  5184  ek110237 
    600  9513    Andrew 	if ($line =~ /([^\s]+)\s*=\s*(.+);/) {
    601  9356    Andrew 	    my $opt = $1;
    602  9356    Andrew 	    my $val = $2;
    603  9356    Andrew 	    chomp($opt);
    604  9356    Andrew 	    chomp($val);
    605  9356    Andrew 	    my @vals = ();
    606  9356    Andrew 	    # Check to see if this needs to be a list
    607  9356    Andrew 	    if(($val =~ /,/) && ($val !~ /"/)) {
    608  9356    Andrew 		push(@vals, $+) while $val =~
    609  9356    Andrew 	            m{"([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx;
    610  9356    Andrew 		push(@vals, undef) if substr($val, -1,1) eq ',';
    611  5184  ek110237 		@{ $CONFDATA{$opt} }  = @vals;
    612  9356    Andrew 	    } else {
    613  9356    Andrew 		@{CONFDATA{$opt}} = ();
    614  9356    Andrew 		push(@{ $CONFDATA{$opt} }, $val);
    615  9356    Andrew 	    }
    616  5184  ek110237 	} else {
    617  9356    Andrew 	    $line =~ /($OPTIONFLAGS);/;
    618  9356    Andrew 	    my $opt = $1;
    619  9356    Andrew 	    chomp($opt);
    620  5184  ek110237 	    @{CONFDATA{$opt}} = ();
    621  9356    Andrew 	    push(@{ $CONFDATA{$opt} }, "");
    622  5184  ek110237 	}
    623  5184  ek110237     }
    624  5184  ek110237     
    625  5184  ek110237     # Bye, bye
    626  5184  ek110237     #close(CFILE) or die "ERROR: config file closing difficulties";
    627  7736    Andrew     return \%confdata;
    628  7736    Andrew }
    629  7736    Andrew 
    630  7736    Andrew sub build_run
    631  7736    Andrew {
    632  7736    Andrew     # The following function is taken from the user's function file
    633  7736    Andrew     pre_run();
    634  7736    Andrew 
    635  7736    Andrew     # Set the global statistics directory for this run
    636  7736    Andrew     op_statsdir();
    637  7736    Andrew 
    638  7736    Andrew     # The following function is taken from the user's function file
    639  7736    Andrew     bm_run();
    640  7736    Andrew 
    641  7736    Andrew     # Finish and close the .f script
    642  7736    Andrew     op_quit();
    643  7736    Andrew }
    644  7736    Andrew 
    645  7736    Andrew # statistics aggregation section
    646  7736    Andrew my %FLOWOPVALS;
    647  7736    Andrew my @SUMMARYVALS;
    648  7736    Andrew 
    649  7736    Andrew sub init_combined_stats
    650  7736    Andrew {
    651  7736    Andrew     %FLOWOPVALS = ();
    652  7736    Andrew     @SUMMARYVALS = (0,0,0,0,0,0);
    653  7736    Andrew }
    654  7736    Andrew 
    655  7736    Andrew sub add_2combstats
    656  7736    Andrew {
    657  7736    Andrew     my ($confname) = shift;
    658  7736    Andrew     my ($thisclient) = shift;
    659  7736    Andrew     my $clstatdir;
    660  7736    Andrew     my $flowopmode = 0;
    661  7736    Andrew     my $summarymode = 0;
    662  7736    Andrew 
    663  7736    Andrew     print "adding in stats for client: $thisclient, configuration: $confname\n";
    664  7736    Andrew 
    665  7736    Andrew     $clstatdir = multi_getval("masterpath")."/".$thisclient;
    666  7736    Andrew 
    667  7736    Andrew     print "from: ".$clstatdir."/stats.".$confname.".out\n";
    668  7736    Andrew     open (CLSTATS, $clstatdir."/stats.".$confname.".out");
    669  7736    Andrew     while(<CLSTATS>) {
    670  7736    Andrew 	my ($line) = $_;
    671  7736    Andrew 	chomp($line);
    672  7736    Andrew 	if (($flowopmode == 0) and ($summarymode == 0)) {
    673  7736    Andrew 	    if ($line =~ /^Flowop totals:/) {
    674  7736    Andrew 		$flowopmode = 1;
    675  7736    Andrew 		next;
    676  7736    Andrew 	    }
    677  7736    Andrew 	    if ($line =~ /^IO Summary:/) {
    678  7736    Andrew 		$summarymode = 1;
    679  7736    Andrew 		next;
    680  7736    Andrew 	    }
    681  7736    Andrew 	}
    682  7736    Andrew 	if ($line eq "") {
    683  7736    Andrew 	    $flowopmode = 0;
    684  7736    Andrew 	    $summarymode = 0;
    685  7736    Andrew 	    next;
    686  7736    Andrew 	}
    687  7736    Andrew 
    688  7736    Andrew 	# get the good stuff
    689  7736    Andrew 	if ($flowopmode == 1) {
    690  7736    Andrew 	    my @elementlist;
    691  7736    Andrew 	    my @valuelist;
    692  7736    Andrew 	    my $flkey;
    693  7736    Andrew 	    my $vallistref = [];
    694  7736    Andrew 
    695  7736    Andrew 	    @elementlist = split('	', $line);
    696  7736    Andrew 	    $flkey = $elementlist[0];
    697  7736    Andrew 	    @valuelist = @elementlist[1..$#elementlist];
    698  7736    Andrew 
    699  7736    Andrew 	    if (exists($FLOWOPVALS{$flkey})) {
    700  7736    Andrew 		my $numvals;
    701  7736    Andrew 
    702  7736    Andrew 		$vallistref = $FLOWOPVALS{$flkey};
    703  7736    Andrew 		$numvals = @{$vallistref};
    704  7736    Andrew 		for (my $idx = 0; $idx < $numvals; $idx++) {
    705  7736    Andrew 		    $vallistref->[$idx] += $valuelist[$idx];
    706  7736    Andrew 		}
    707  7736    Andrew 	    } else {
    708  7736    Andrew 		# newly found flowop name
    709  7736    Andrew 		$vallistref = [@valuelist];
    710  7736    Andrew 		$FLOWOPVALS{$flkey} = $vallistref;
    711  7736    Andrew 	    }
    712  7736    Andrew 	    next;
    713  7736    Andrew 	}
    714  7736    Andrew 
    715  7736    Andrew 	# get final totals
    716  7736    Andrew 	if ($summarymode == 1) {
    717  7736    Andrew 	    my @valuelist;
    718  7736    Andrew 
    719  7736    Andrew 	    @valuelist = split('	', $line);
    720  7736    Andrew 
    721  7736    Andrew 	    for (my $idx = 0; $idx <= $#valuelist; $idx++) {
    722  7736    Andrew 		$SUMMARYVALS[$idx] += $valuelist[$idx];
    723  7736    Andrew 	    }
    724  7736    Andrew 	    next;
    725  7736    Andrew 	}
    726  7736    Andrew     }
    727  7736    Andrew     close (CLSTATS);
    728  5184  ek110237 }
    729  5184  ek110237 
    730  5184  ek110237 sub print_usage
    731  5184  ek110237 {
    732  9513    Andrew     print "Usage:\n\tfilebench -c <stat_dir>\n";
    733  9513    Andrew     print "\tfilebench [-b <base_path>] ";
    734  9513    Andrew     print "[-D[ ]<variable name>[ |=| = ]<value>]... <profile name>\n";
    735  7736    Andrew }
    736  7736    Andrew 
    737  7736    Andrew sub dump_combined_stats
    738  7736    Andrew {
    739  7736    Andrew     my ($confname) = shift;
    740  7736    Andrew     my $totvalsref = [];
    741  7736    Andrew     my $flkey;
    742  7736    Andrew     use FileHandle;
    743  7736    Andrew 
    744  7736    Andrew ## set up output formating info
    745  7736    Andrew format flowoplinefrm =
    746  7736    Andrew @<<<<<<<<<<<<<<<<<<< @#######ops/s @###.#mb/s @#####.#ms/op @#######us/op-cpu
    747  7736    Andrew $flkey, $totvalsref->[0], $totvalsref->[1], $totvalsref->[2]/$#CLIENTLIST, $totvalsref->[3]/$#CLIENTLIST
    748  7736    Andrew .
    749  7736    Andrew 
    750  7736    Andrew format summarylinefrm =
    751  7736    Andrew 
    752  7736    Andrew IO Summary: @#######ops, @#####.#ops/s, (@####/@#### r/w) @#####.#mb/s, @######us cpu/op, @####.#ms latency
    753  7736    Andrew $SUMMARYVALS[0], $SUMMARYVALS[1], $SUMMARYVALS[2], $SUMMARYVALS[3], $SUMMARYVALS[4], $SUMMARYVALS[5], $SUMMARYVALS[6]
    754  7736    Andrew .
    755  7736    Andrew 
    756  7736    Andrew     open (SUMSTATS, ">$STATSBASE/$confname/stats.$confname.out");
    757  7736    Andrew     print "Per-Operation Breakdown:\n";
    758  7736    Andrew     print SUMSTATS "Per-Operation Breakdown:\n";
    759  7736    Andrew 
    760  7736    Andrew     format_name  STDOUT "flowoplinefrm";
    761  7736    Andrew     format_name  SUMSTATS "flowoplinefrm";
    762  7736    Andrew 
    763  7736    Andrew     foreach $flkey (keys %FLOWOPVALS) {
    764  7736    Andrew 
    765  7736    Andrew 	$totvalsref = $FLOWOPVALS{$flkey};
    766  7736    Andrew 
    767  7736    Andrew 	write STDOUT;
    768  7736    Andrew 	write SUMSTATS;
    769  7736    Andrew     }
    770  7736    Andrew 
    771  7736    Andrew     format_name  STDOUT "summarylinefrm";
    772  7736    Andrew     format_name  SUMSTATS "summarylinefrm";
    773  7736    Andrew 
    774  7736    Andrew     write STDOUT;
    775  7736    Andrew     write SUMSTATS;
    776  7736    Andrew     close (SUMSTATS);
    777  7736    Andrew }
    778  7736    Andrew 
    779  7736    Andrew #
    780  7736    Andrew # polls the synchronization socket for each client in turn every 5 seconds,
    781  7736    Andrew # then sends synch responses once all clients have "checked in". The
    782  7736    Andrew # sample number in the received sync requests must match the sequence
    783  7736    Andrew # number supplied with the call.
    784  7736    Andrew #
    785  7736    Andrew sub sync_receive
    786  7736    Andrew {
    787  7736    Andrew     my $seqnum = shift;
    788  7736    Andrew #    my @cl_list;
    789  7736    Andrew     my %cl_hash = ();
    790  7736    Andrew     %cl_hash = %CLIENTHASH;
    791  7736    Andrew 
    792  7736    Andrew     my $count = @CLIENTLIST;
    793  7736    Andrew     print "waiting for sync message: $seqnum from $count clients\n";
    794  7736    Andrew     while ($count > 0) {
    795  7736    Andrew 	my $rcv_str = "";
    796  7736    Andrew 
    797  7736    Andrew 	sleep 5;
    798  7736    Andrew 
    799  7736    Andrew 	foreach my $client_name (keys %cl_hash)
    800  7736    Andrew 	{
    801  7736    Andrew 	    my $clientdata = $CLIENTHASH{$client_name};
    802  7736    Andrew 	    my $client_hndl = $$clientdata[0];
    803  7736    Andrew 	    print "recv sync: $client_name undefined handle\n" unless defined($client_hndl);
    804  7736    Andrew 	    my $client_iaddr = $$clientdata[1];
    805  7736    Andrew 	    my $sn = $$clientdata[2];
    806  7736    Andrew 	    my $rtn = 0;
    807  7736    Andrew 
    808  7736    Andrew 	    do {
    809  7736    Andrew 		my $tmp_str;
    810  7736    Andrew 		$rtn = recv($client_hndl, $tmp_str, 80, MSG_DONTWAIT);
    811  7736    Andrew 		if (defined($rtn)) {
    812  7736    Andrew 		    $rcv_str = $rcv_str.$tmp_str;
    813  7736    Andrew 		}   
    814  7736    Andrew 	    } until (!defined($rtn) || ($rcv_str =~ /$EOL/s ));
    815  7736    Andrew 
    816  7736    Andrew 	    if (defined($rtn)) {
    817  7736    Andrew 		my %ophash = ();
    818  7736    Andrew 		my $ok;
    819  7736    Andrew 
    820  7736    Andrew 		my @oplist = split /,/,$rcv_str;
    821  7736    Andrew 		foreach my $opent (@oplist)
    822  7736    Andrew 		{
    823  7736    Andrew 		    my ($op, $val) = split /=/,$opent;
    824  7736    Andrew 		    $ophash{$op} = $val;
    825  7736    Andrew 		}
    826  7736    Andrew 		$ok = ($sn == $seqnum);
    827  7736    Andrew 		$ok &&= defined((my $cmd_val = $ophash{"cmd"}));
    828  7736    Andrew 		$ok &&= defined((my $samp_val = $ophash{"sample"}));
    829  7736    Andrew 		if ($ok && ($cmd_val eq "SYNC") && ($samp_val == $seqnum))
    830  7736    Andrew 		{
    831  7736    Andrew 		    delete $cl_hash{$client_name};
    832  7736    Andrew 		    $count--;
    833  7736    Andrew 		    print "received a sync request from $client_name\n";
    834  7736    Andrew 		    ${$CLIENTHASH{$client_name}}[2] = ($sn + 1);
    835  7736    Andrew 		} else {
    836  7736    Andrew 		    print "received invalid sync request string [".rcv_str."] from client $client_name\n";
    837  7736    Andrew 		}
    838  7736    Andrew 	    }
    839  7736    Andrew 	}
    840  7736    Andrew     }
    841  7736    Andrew     print "received all sync requests for seq $seqnum, sending responses\n";
    842  7736    Andrew     foreach my $client_name (@CLIENTLIST)
    843  7736    Andrew     {
    844  7736    Andrew 	my $clientdata = $CLIENTHASH{$client_name};
    845  7736    Andrew 	my $client_hndl = $$clientdata[0];
    846  7736    Andrew 	print "send resp: $client_name undefined handle\n" unless defined($client_hndl);
    847  7736    Andrew 
    848  7736    Andrew 	send ($client_hndl, "rsp=PASS,sample=$seqnum\n", 0);
    849  7736    Andrew     }
    850  7736    Andrew }
    851  7736    Andrew 
    852  7736    Andrew #
    853  7736    Andrew # waits for all known clients to connect, then calls sync_recieve(1) to
    854  7736    Andrew # sync_receive(N) to wait for N sync requests for designated sync points
    855  7736    Andrew # 1..N.
    856  7736    Andrew #
    857  7736    Andrew sub sync_server
    858  7736    Andrew {
    859  7736    Andrew     my $port = shift || 8001;
    860  7736    Andrew     my $proto = getprotobyname('tcp');
    861  7736    Andrew     my $paddr;
    862  7736    Andrew     my $count;
    863  7736    Andrew 
    864  7736    Andrew     socket(Server, PF_INET, SOCK_STREAM, $proto)     || die "socket: $!";
    865  7736    Andrew     setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
    866  7736    Andrew 	       pack("l", 1))			     || die "setsockopt: $1";
    867  7736    Andrew     bind(Server, sockaddr_in($port, INADDR_ANY))     || die "bind: $1";
    868  7736    Andrew     listen(Server, SOMAXCONN)			     || die "listen: $1";
    869  7736    Andrew 
    870  7736    Andrew # wait for connection requests from clients
    871  7736    Andrew     print "sync: Waiting for ".@CLIENTLIST." Clients\n";
    872  7736    Andrew     for ($count = @CLIENTLIST; $count > 0; $count--) {
    873  7736    Andrew 	$paddr = accept(my $client_hndl, Server);
    874  7736    Andrew 	die "bad socket address" unless $paddr;
    875  7736    Andrew 
    876  7736    Andrew 	my ($port, $iaddr) = sockaddr_in($paddr);
    877  7736    Andrew 	my $cl_name = gethostbyaddr($iaddr, AF_INET);
    878  7736    Andrew 
    879  7736    Andrew 	if (!exists($CLIENTHASH{$cl_name})) {
    880  7736    Andrew 	    die "sync from unknown client $cl_name";
    881  7736    Andrew 	}
    882  7736    Andrew 
    883  7736    Andrew 	print "received sync connection from client: $cl_name\n";
    884  7736    Andrew 	${$CLIENTHASH{$cl_name}}[0] = $client_hndl;
    885  7736    Andrew 	${$CLIENTHASH{$cl_name}}[1] = $iaddr;
    886  7736    Andrew     }
    887  7736    Andrew 
    888  7736    Andrew # indicate that all clients have checked in
    889  7736    Andrew     sync_receive(1);
    890  7736    Andrew     if (conf_exists("runtime") == 1) {
    891  7736    Andrew 	my $runtime =  conf_getval("runtime");
    892  7736    Andrew 	sleep $runtime;
    893  7736    Andrew     }
    894  7736    Andrew     sync_receive(2);
    895  5184  ek110237 }
    896  5184  ek110237 
    897  5184  ek110237 ##############################################################################
    898  5184  ek110237 ## Main program
    899  5184  ek110237 ##############################################################################
    900  5184  ek110237 
    901  5184  ek110237 ## Make sure arguments are okay
    902  5184  ek110237 $numargs = $#ARGV + 1;
    903  5184  ek110237 
    904  5184  ek110237 if($numargs < 1) {
    905  5184  ek110237     print_usage();
    906  5184  ek110237     exit(2);
    907  5184  ek110237 }
    908  5184  ek110237 
    909  9513    Andrew for (my $idx = 0; $idx < $numargs;) {
    910  9513    Andrew     my $cur_argv = $ARGV[$idx++];
    911  9513    Andrew     my $cmdvar = "";
    912  9513    Andrew     my $cmddata = "";
    913  9513    Andrew 
    914  9513    Andrew     # See if filebench_compare should be run
    915  9513    Andrew     if($cur_argv eq "-c") {
    916  9513    Andrew 	if($numargs < ($idx + 1)) {
    917  9513    Andrew 	    print_usage();
    918  9513    Andrew 	    exit(2);
    919  9513    Andrew 	}
    920  9513    Andrew 	# next argument variable is path to results files
    921  9513    Andrew 	exec("$FILEBENCH/scripts/filebench_compare", $ARGV[$idx++]);
    922  9513    Andrew     }
    923  9513    Andrew 
    924  9513    Andrew     # Capture specification of an alternate FileBench path
    925  9513    Andrew     if($cur_argv eq "-b") {
    926  9513    Andrew 	if($numargs < ($idx + 1)) {
    927  9513    Andrew 	    print_usage();
    928  9513    Andrew 	    exit(2);
    929  9513    Andrew 	}
    930  9513    Andrew 	# next argument is the base path name
    931  9513    Andrew 	$FILEBENCH = $ARGV[$idx++];
    932  9513    Andrew 
    933  9513    Andrew     # See if Default variable will be supplied.
    934  9513    Andrew     } elsif($cur_argv =~ /^-D(.*)/) {
    935  9513    Andrew 	my $def_arg = $1;
    936  9513    Andrew 
    937  9513    Andrew 	# rest of info in separate argvs
    938  9513    Andrew 	if ($def_arg eq "") {
    939  9513    Andrew 	    if($numargs < ($idx + 2)) {
    940  9513    Andrew 		print_usage();
    941  9513    Andrew 		exit(2);
    942  9513    Andrew 	    }
    943  9513    Andrew 
    944  9513    Andrew 	    # get next bit
    945  9513    Andrew 	    $def_arg = $ARGV[$idx++];
    946  9513    Andrew 	}
    947  9513    Andrew 
    948  9513    Andrew 	# with variable name but without "=" or value
    949  9513    Andrew 	if($def_arg =~ /^([^=]+)$/) {
    950  9513    Andrew 	    $cmdvar = $1;
    951  9513    Andrew 	    if($numargs < ($idx + 2)) {
    952  9513    Andrew 		print_usage();
    953  9513    Andrew 		exit(2);
    954  9513    Andrew 	    }
    955  9513    Andrew 
    956  9513    Andrew 	    # get data from next argument, or next after that if '=' encountered
    957  9513    Andrew 	    $cmddata = $ARGV[$idx++];
    958  9513    Andrew 	    if ($cmddata eq "=") {
    959  9513    Andrew 		if($numargs < ($idx + 2)) {
    960  9513    Andrew 		    print_usage();
    961  9513    Andrew 		    exit(2);
    962  9513    Andrew 		}
    963  9513    Andrew 		$cmddata = $ARGV[$idx++];
    964  9513    Andrew 	    } else {
    965  9513    Andrew 		$cmddata =~ s/^=//;
    966  9513    Andrew 	    }
    967  9513    Andrew 
    968  9513    Andrew 	# see if variable name and data supplied
    969  9513    Andrew 	} elsif($def_arg =~ /^([^=]+)=(.+)/) {
    970  9513    Andrew 	    $cmdvar = $1;
    971  9513    Andrew 	    $cmddata = $2;
    972  9513    Andrew 	    if($numargs < ($idx + 1)) {
    973  9513    Andrew 		print_usage();
    974  9513    Andrew 		exit(2);
    975  9513    Andrew 	    }
    976  9513    Andrew 
    977  9513    Andrew 	# see if variable name and '=' but no data supplied
    978  9513    Andrew 	} elsif($def_arg =~ /^([^=]+)=$/) {
    979  9513    Andrew 	    $cmdvar = $1;
    980  9513    Andrew 	    if($numargs < ($idx + 2)) {
    981  9513    Andrew 		print_usage();
    982  9513    Andrew 		exit(2);
    983  9513    Andrew 	    }
    984  9513    Andrew 	    $cmddata = $ARGV[$idx++];
    985  9513    Andrew 	}
    986  9513    Andrew 
    987  9513    Andrew 	# push the variable onto the command line hash
    988  9513    Andrew 	$CMDLINEDATA{$cmdvar} = ();
    989  9513    Andrew 	push(@{ $CMDLINEDATA{$cmdvar} }, $cmddata);
    990  9513    Andrew 
    991  9513    Andrew     # otherwise argument is the profile name
    992  9513    Andrew     } else {
    993  9513    Andrew 	$PROFILENAME = $cur_argv;
    994  9513    Andrew     }
    995  9513    Andrew }
    996  9513    Andrew 
    997  5184  ek110237 $PROFILE = $PROFILENAME;
    998  5184  ek110237 $PROFILE =~ s/.*\/(.+)$/$1/;
    999  5184  ek110237 parse_profile("$PROFILENAME.prof");
   1000  5184  ek110237 
   1001  5184  ek110237 %CONFDATA = ();
   1002  5184  ek110237 %CONFDATA = %DEFDATA;
   1003  5184  ek110237 
   1004  7736    Andrew # get the name of the host this script is running on
   1005  5184  ek110237 my $hostname = `hostname`;
   1006  5184  ek110237 chomp($hostname);
   1007  7736    Andrew 
   1008  7736    Andrew # Check for Multi-Client operation
   1009  7736    Andrew if ($MULTI_CLIENT == 1) {
   1010  7736    Andrew 
   1011  7736    Andrew     if (multi_exists("targetpath")) {
   1012  7736    Andrew 	$TARGETPATH = multi_getval("targetpath");
   1013  7736    Andrew     } else {
   1014  7736    Andrew 	print "ERROR: Target pathname required for multi-client operation\n";
   1015  7736    Andrew 	exit(1);
   1016  7736    Andrew     }
   1017  7736    Andrew 
   1018  7736    Andrew     if (multi_exists("clients")) {
   1019  7736    Andrew 	@CLIENTLIST = split(' ',multi_getval("clients"));
   1020  7736    Andrew     } else {
   1021  7736    Andrew 	print "ERROR: client list required for multi-client operation\n";
   1022  7736    Andrew 	exit(1);
   1023  7736    Andrew     }
   1024  7736    Andrew 
   1025  7736    Andrew     if (multi_exists("sharefiles")) {
   1026  7736    Andrew 	$SHAREDFILEALLOCATOR = multi_getval("sharefiles");
   1027  7736    Andrew     } else {
   1028  7736    Andrew 	$SHAREDFILEALLOCATOR = "";
   1029  7736    Andrew     }
   1030  7736    Andrew 
   1031  7736    Andrew     $TARGETDIR = $TARGETPATH.conf_getval("dir");
   1032  7736    Andrew 
   1033  7736    Andrew     # Setup the multi client statistics base directory
   1034  7736    Andrew     $STATSBASE = $TARGETPATH.conf_reqval("stats");
   1035  7736    Andrew 
   1036  7736    Andrew     multi_putval("masterhost", $hostname) unless multi_exists("masterhost");
   1037  7736    Andrew     multi_putval("masterpath", $STATSBASE) unless multi_exists("masterpath");
   1038  7736    Andrew 
   1039  7736    Andrew     # create a path for filebench.pl to use to access the master directory
   1040  7736    Andrew     $FB_MASTERPATH = multi_getval("masterpath");
   1041  7736    Andrew 
   1042  7736    Andrew     print "Target PathName = $TARGETPATH, path = ".multi_getval("masterpath")."\n";
   1043  7736    Andrew 
   1044  7736    Andrew } else {
   1045  7736    Andrew     # Setup the single client statistics base directory
   1046  7736    Andrew     $STATSBASE = conf_reqval("stats");
   1047  7736    Andrew }
   1048  7736    Andrew 
   1049  7736    Andrew my $filesystem = conf_reqval("filesystem");
   1050  5184  ek110237 $STATSBASE = $STATSBASE . "/$hostname-$filesystem-$PROFILENAME-";
   1051  5184  ek110237 my $timestamp = strftime "%b_%e_%Y-%Hh_%Mm_%Ss", localtime;
   1052  5184  ek110237 $timestamp =~ s/ //;
   1053  5184  ek110237 $STATSBASE = $STATSBASE . $timestamp;
   1054  5184  ek110237 
   1055  7736    Andrew foreach $config_name (@CONFLIST)
   1056  7736    Andrew {
   1057  5184  ek110237     %CONFDATA = ();
   1058  5184  ek110237     %CONFDATA = %DEFDATA;
   1059  7736    Andrew     $CONFNAME = $config_name;
   1060  7736    Andrew     parse_config("$config_name");
   1061  5184  ek110237     my $function = conf_reqval("function");
   1062  7736    Andrew     my $statsdir;
   1063  7736    Andrew 
   1064  5184  ek110237     if (-f "$function.func") {
   1065  5184  ek110237 	require "$function.func";
   1066  5184  ek110237     } else {
   1067  5184  ek110237 	require "$FILEBENCH/config/$function.func";
   1068  5184  ek110237     }
   1069  5184  ek110237 
   1070  7736    Andrew     # Setup the final statistics directory
   1071  7736    Andrew     system("mkdir -p $STATSBASE");
   1072  5184  ek110237 
   1073  5184  ek110237     # Leave a log of the run info	
   1074  5184  ek110237     open (RUNLOG, ">$STATSBASE/thisrun.prof");
   1075  5184  ek110237     print RUNLOG "# " . conf_reqval("description") . "\n";
   1076  5184  ek110237     close (RUNLOG);
   1077  5184  ek110237 
   1078  7736    Andrew     system ("cat $PROFILENAME.prof >>".$STATSBASE."/thisrun.prof");
   1079  5184  ek110237 
   1080  7736    Andrew     $statsdir = $STATSBASE . "/" . $config_name;
   1081  7736    Andrew     system("mkdir -p $statsdir");
   1082  7736    Andrew     system("chmod a+w $statsdir");
   1083  5184  ek110237 
   1084  7736    Andrew     if ($MULTI_CLIENT == 1) {
   1085  7736    Andrew 	my @pidlist;
   1086  7736    Andrew 	my %multi_confdata;
   1087  7736    Andrew 	my $procpid;
   1088  7736    Andrew 	my $syncclients = "";
   1089  7736    Andrew 
   1090  7736    Andrew 	%multi_confdata = %CONFDATA;
   1091  7736    Andrew 
   1092  7736    Andrew 	foreach my $thisclient (@CLIENTLIST) {
   1093  7736    Andrew 	    my $tmpdir;
   1094  7736    Andrew 	    my $tmpstatdir;
   1095  7736    Andrew 	    my @clientdata;
   1096  7736    Andrew 
   1097  7736    Andrew 	    %CONFDATA = ();
   1098  7736    Andrew 	    %CONFDATA = %multi_confdata;
   1099  7736    Andrew 	    printf "building client: " . $thisclient . "\n";
   1100  7736    Andrew 
   1101  7736    Andrew 	    # Setup the statistics directory for each client
   1102  7736    Andrew 	    $tmpstatdir = multi_getval("masterpath")."/".$thisclient;
   1103  7736    Andrew 
   1104  7736    Andrew 	    if ($SHAREDFILEALLOCATOR) {
   1105  7736    Andrew 		$tmpdir = $TARGETDIR;
   1106  7736    Andrew 	    } else {
   1107  7736    Andrew 		$tmpdir = $TARGETDIR."/".$thisclient;
   1108  7736    Andrew 	    }
   1109  7736    Andrew 
   1110  7736    Andrew # add info to client hash
   1111  7736    Andrew 	    @clientdata = ();
   1112  7736    Andrew 	    $clientdata[2] = 1;
   1113  7736    Andrew 	    $CLIENTHASH{$thisclient} = \@clientdata;
   1114  7736    Andrew 	    $syncclients = $syncclients." --client ".$thisclient;
   1115  7736    Andrew 
   1116  7736    Andrew 	    push(@{ $CONFDATA{"myname"} }, $thisclient);
   1117  7736    Andrew 	    push(@{ $CONFDATA{"statsdir"} }, $tmpstatdir);
   1118  7736    Andrew 	    system("mkdir -p ".$FB_MASTERPATH."/".$thisclient);
   1119  7736    Andrew 	    system("chmod 0777 ".$FB_MASTERPATH."/".$thisclient);
   1120  7736    Andrew 
   1121  7736    Andrew 	    # modify dir config variable for multiclient
   1122  7736    Andrew 	    if (conf_exists("dir")) {
   1123  7736    Andrew 		@{$CONFDATA{"dir"}} = ($tmpdir);
   1124  7736    Andrew 	    }
   1125  7736    Andrew 	    build_run();
   1126  7736    Andrew 	}
   1127  7736    Andrew 
   1128  7736    Andrew 	# Begin the RUN!!!
   1129  7736    Andrew 	print "Running " . $STATSBASE . "\n";
   1130  7736    Andrew 
   1131  7736    Andrew 	#spawn the synchronization server
   1132  7736    Andrew 	print "Starting sync server on host ".$hostname."\n";
   1133  7736    Andrew 	if ($procpid = fork) {
   1134  7736    Andrew 	    push(@pidlist, $procpid);
   1135  7736    Andrew 	} else {
   1136  7736    Andrew 	    sync_server();
   1137  7736    Andrew 	    exit(0);
   1138  7736    Andrew 	}
   1139  7736    Andrew 
   1140  7736    Andrew 	sleep(3);
   1141  7736    Andrew 
   1142  7736    Andrew 	# remotely execute the run on each client
   1143  7736    Andrew 	foreach $thisclient (@CLIENTLIST) {
   1144  7736    Andrew 	    if($procpid = fork) {
   1145  7736    Andrew 		push(@pidlist, $procpid);
   1146  7736    Andrew 	    } else {
   1147  7736    Andrew 		if ($thisclient eq $hostname) {
   1148  7736    Andrew 		    print "Starting local client: $thisclient\n";
   1149  7736    Andrew 		    system(multi_getval("masterpath")."/".$thisclient."/thisrun.f");
   1150  7736    Andrew 		} else {
   1151  7736    Andrew 		    print "Starting remote client: $thisclient\n";
   1152  7736    Andrew 		    system("ssh ".$thisclient." ".multi_getval("masterpath")."/".$thisclient."/thisrun.f >> ".multi_getval("masterpath")."/".$thisclient."/runs.out");
   1153  7736    Andrew 		}
   1154  7736    Andrew 		exit(0);
   1155  7736    Andrew 	    }
   1156  7736    Andrew 	}
   1157  7736    Andrew 
   1158  7736    Andrew 	# wait for all of them to finish
   1159  7736    Andrew 	foreach $procpid (@pidlist) {
   1160  7736    Andrew 	    waitpid($procpid, 0);
   1161  7736    Andrew 	}
   1162  7736    Andrew 
   1163  7736    Andrew 	init_combined_stats();
   1164  7736    Andrew 
   1165  7736    Andrew 	foreach $thisclient (@CLIENTLIST) {
   1166  7736    Andrew 	    add_2combstats($config_name, $thisclient);
   1167  7736    Andrew 	}
   1168  7736    Andrew 
   1169  7736    Andrew 	# dump the combined client stats
   1170  7736    Andrew 	dump_combined_stats($config_name);
   1171  7736    Andrew 
   1172  7736    Andrew     } else {
   1173  7736    Andrew 	push(@{ $CONFDATA{"statsdir"} }, $statsdir);
   1174  7736    Andrew 
   1175  7736    Andrew 	build_run();
   1176  7736    Andrew 
   1177  7736    Andrew 	# Execute the run
   1178  7736    Andrew 	print "Running " . conf_reqval("statsdir") . "/thisrun.f\n";
   1179  7736    Andrew 	system ($statsdir."/thisrun.f");
   1180  7736    Andrew 
   1181  7736    Andrew 
   1182  7736    Andrew     }
   1183  7736    Andrew 
   1184  5184  ek110237 }
   1185  7736    Andrew 
   1186  7736    Andrew # The following function is taken from the user's function file
   1187  7736    Andrew post_run();
   1188  7736    Andrew 
   1189  7736    Andrew print "\n";
   1190