#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # SDKtest # # # Usage: SDKtest [ConfigFile] [parameter=value parameter=value ...] # where parameter=value clauses override those in the ConfigFile # # Example: SDKtest SDKtest_client.config hitrate=50 users=400 \ # 'origin_servers=foo:8080 bar:80' client_pids=""; server_pids=""; Bye () { # in case user hits ^C multiple times trap Bye 1 2 3 15 echo "" echo "SDKtest interrupted!" echo "" echo "making sure child processes are dead..." # ps -aux | grep $user all_pids=$client_pids" "$server_pids for pid in $all_pids ; do echo "Killing child process " $pid # ps -aux | grep $pid | grep -v grep kill -9 $pid done echo "" echo "Note: in some environments, SDKtest_client and SDKtest_server processes" echo " might not be automatically killed." echo " Double check on client/server machines with 'ps' to be sure." exit 1 } trap Bye 1 2 3 15 # get variable from config_file # strip comments, look for the parameter lines, and strip left hand side # use default value if parameter isn't found # return result in $value GetParam () { file=$1 param=$2 default=$3 value=`sed 's/#.*$//' < $file | grep "[ ]*$param[ ]*=" | tail -1 | sed 's/^[^=]*=[ ]*//g'` if [ "$value" = "" ]; then value=$default fi export value } # echo to stdout and to output file EchoBoth () { outfile=$1 string=$2 echo $string echo $string >> $outfile } CheckFile () { file=$1 if [ ! -f $file ]; then echo "Can't find file: " $file exit 1 fi } CheckBinary() { file=$1 if [ ! -x $file ]; then echo "Can't find executable file: " $file exit 1 fi } base_config_file=client/SDKtest_client.config # allow config file override with command-line arguments # treat anything with '=' as variable assignment, not config filename if [ $# -gt 0 ]; then if [ "`echo $1 | grep =`" = "" ]; then base_config_file=$1 shift fi fi CheckFile $base_config_file host=`hostname` user=$USER tempdir=/tmp/$user config_file=SDKtest_client.config.new temp_config_file=/tmp/$user.$$.SDKtest_client.config sed "s/localhost/$host/g" $base_config_file | tr '\011' ' ' > $temp_config_file echo "# Beginning changes from command line arguments" >> $temp_config_file for arg in "$@" ; do if [ -n "$arg" ]; then if [ "`echo $arg | grep '='`" = "" ]; then echo "Command line argument $arg does not contain '='." echo "Usage: "SDKtest [ConfigFile] [parameter=value parameter=value ...] echo " (use quotes for parameter values containing whitespace)" exit 1 fi fi echo $arg | sed "s/localhost/$host/g" | grep '=' >> $temp_config_file done GetParam $temp_config_file output output base_output=$value test ! -d $base_output && mkdir $base_output lastdir=`ls -1 $base_output | grep '^[0-9]*$' | sort -n | tail -1` if [ "$lastdir" = "" ]; then lastdir=0 fi lastdir=`expr $lastdir + 1` output=$base_output/$lastdir mkdir $output mv $temp_config_file $output/$config_file GetParam $output/$config_file injection_type none injection_type=$value GetParam $output/$config_file injection_interval 0 injection_interval=$value GetParam $output/$config_file request_rate 0 request_rate=$value GetParam $output/$config_file execution_interval 10 execution_interval=$value GetParam $output/$config_file client_program SDKtest_client binary=client/$value CheckBinary $binary GetParam $output/$config_file clients $host client_machine_list=$value GetParam $output/$config_file docsize_dist_file docsize.specweb docsize_dist_file=$value CheckFile client/$docsize_dist_file GetParam $output/$config_file thinktime_dist_file thinktime.0 thinktime_dist_file=$value CheckFile client/$thinktime_dist_file GetParam $output/$config_file byterate_dist_file byterate.fast byterate_dist_file=$value CheckFile client/$byterate_dist_file GetParam $output/$config_file warmup 1 warmup=$value GetParam $output/$config_file hitrate 100 hitrate=$value GetParam $output/$config_file hotset 1 hotset=$value GetParam $output/$config_file remote_shell rsh remote_sh=$value if [ "$remote_sh" = "rsh" ]; then remote_cp="rcp" else remote_cp="scp" fi if [ $request_rate -gt 0 ]; then thinktime_dist_file="thinktime.0" CheckFile client/$thinktime_dist_file fi mode="fixed_user" if [ "$injection_type" = "uniform" ] ; then if [ $injection_interval -le 0 ]; then echo "Invalid injection_interval" exit 0; fi # get the number of clients to be injected over the execution_interval tmp_i=`expr $execution_interval - $injection_interval` number_of_clients_to_be_injected=`expr $tmp_i / $injection_interval` original_list=$client_machine_list client_machine_list="" # num_clients is the number of clients in the config_file, or specified in command line num_clients=0 for client in $original_list; do num_clients=`expr $num_clients + 1` done if [ $number_of_clients_to_be_injected -le 1 ]; then echo "SDKtest error: injection_interval too big" echo "Exiting SDKtest :" echo "increase execution_time, reduce interval, or run fixed_user mode" exit 0 fi if [ $number_of_clients_to_be_injected -lt $num_clients ]; then echo "Warning: number of clients started will be less than the number of clients given as input" fi number_of_duplicates=`expr $number_of_clients_to_be_injected / $num_clients - 1` tmp_i=0 while [ $number_of_duplicates -gt 0 ]; do client_machine_list=$client_machine_list" "$original_list number_of_duplicates=`expr $number_of_duplicates - 1` tmp_i=`expr $tmp_i + $num_clients` done if [ $tmp_i -lt $number_of_clients_to_be_injected ] ; then tmp_i=`expr $number_of_clients_to_be_injected - $tmp_i` while [ $tmp_i -gt 0 ] ; do for client in $original_list; do if [ $tmp_i -gt 0 ] ; then client_machine_list=$client_machine_list" "$client else break fi tmp_i=`expr $tmp_i - 1` done done fi mode="fixed_injection" echo "Mode: $mode" echo "Total number of clients: $number_of_clients_to_be_injected" echo "clients will be invoked @ 1 client per $injection_interval sec(s)" fi echo > $output/summary.txt EchoBoth $output/summary.txt "Starting SDKtest at `date`" EchoBoth $output/summary.txt "Using clients: $client_machine_list" EchoBoth $output/summary.txt "Using output directory $output" #echo "Client OS: " `uname -a` num_machines=`echo $client_machine_list | awk '{print NF}'` client_id=0; for client in $client_machine_list; do if [ "$client" = "$host" ]; then rsh="" rhost="" rcp="cp" else rsh="$remote_sh $client" rhost="$client:" rcp="$remote_cp" fi $rsh mkdir $tempdir.$client_id 2>&1 | grep -v -i exists echo "Copying the client executable/config onto $client in $tempdir.$client_id using $rcp" $rcp $binary "$rhost""$tempdir"".$client_id"/SDKtest_client & $rcp $output/$config_file "$rhost""$tempdir"".$client_id" & $rcp client/$docsize_dist_file "$rhost""$tempdir"".$client_id" & $rcp client/$thinktime_dist_file "$rhost""$tempdir"".$client_id" & $rcp client/$byterate_dist_file "$rhost""$tempdir"".$client_id" & GetParam $output/$config_file plugin "" client_plugin=$value if [ "$client_plugin" = "" ]; then echo "" else CheckFile client/$client_plugin $rcp client/$client_plugin "$rhost""$tempdir"".$client_id" & echo "Copying $client_plugin onto $client int $tempdir.$cliend_id using $rcp" fi client_id=`expr $client_id + 1` done wait GetParam $output/$config_file origin_autostart none origin_autostart=$value origin_binary=`echo $origin_autostart | awk '{print $1;}'` origin_basename=`basename $origin_binary` origin_args=`echo $origin_autostart | sed 's/^[ ]*[^ ]*[ ]*//g'` origin_config=synth_server/SDKtest_server.config GetParam $output/$config_file origin_servers $host origin_servers=$value for origin_server in $origin_servers ; do origin_port=`echo $origin_server | grep : | sed 's/^.*:\([0-9][0-9]*\)/\1/'` origin_server=`echo $origin_server | sed 's/:.*$//'` if [ "$origin_autostart" = "none" ]; then echo "No origin_autostart specifed:" echo " Assuming that SDKtest_server is already running on $origin_server port $origin_port." else if [ "$origin_port" = "" ]; then origin_port=8081 echo "No port for origin server specified. Setting to $origin_port" fi CheckBinary $origin_binary echo "" echo "Attempting to connect to $origin_server on port $origin_port to" echo " request shutdown of SDKtest_server (in case one is running)" awk 'BEGIN{printf "GET LOST\n\n\n";}' < /dev/null | telnet $origin_server $origin_port echo "" if [ "$origin_server" = "$host" ]; then rcp="cp" rsh="" rhost="" else rcp="$remote_cp" rsh="$remote_sh $origin_server" rhost="$origin_server:" fi echo "" echo "Copying the SDKtest_server executable onto $origin_server in $tempdir.$origin_port using $rcp" $rsh mkdir $tempdir.$origin_port 2>&1 | grep -v -i exists $rcp $origin_binary "$rhost""$tempdir.$origin_port" $rcp $origin_config "$rhost""$tempdir.$origin_port" echo "Copying $origin_config into $rhost$tempdir.$origin_port" GetParam $origin_config plugin "" server_plugin=$value if [ "$server_plugin" = "" ]; then echo "" else CheckFile "synth_server/$server_plugin" $rcp "synth_server/$server_plugin" "$rhost""$tempdir.$origin_port" echo "Copying synth_server/$server_plugin into $rhost$tempdir.$origin_port" fi echo "Starting SDKtest_server on host $origin_server port $origin_port" cmd="$tempdir.$origin_port/$origin_basename -d$tempdir.$origin_port -p$origin_port -a$server_plugin -t$host:$output $origin_args"; echo "$rsh $cmd &" ($rsh $cmd &) server_pids=$server_pids" "$! echo "" fi done GetParam $output/$config_file server_sleep 10 server_sleep=$value if [ "$origin_autostart" != "none" ]; then # hack to allow server to start echo "Sleeping for" $server_sleep "seconds to allow SDKtest_server to start..." echo " (override with SDKtest server_sleep=xx)" sleep $server_sleep echo "" fi if [ $warmup -eq 0 ]; then echo "Skipping warmup" else if [ $hitrate -eq 0 ]; then echo "Skipping warmup for 0% hitrate" else client_id=0; client=`echo $client_machine_list | awk '{print $1;}'` if [ "$client" = "$host" ]; then rsh="eval" else rsh="rsh $client" fi while [ $warmup -gt 0 ] ; do warmup=`expr $warmup - 1` echo "Starting warmup from client $client for hotset of size $hotset" cmd="$tempdir.$client_id/SDKtest_client -d$tempdir.$client_id -c$config_file -i$client_id -p$client_plugin -w > /dev/null"; $rsh "$cmd" done echo "Done with warmup" echo "" fi fi files=`ls -1 $base_output` for f in $files ; do if [ -h $base_output/$f ]; then # echo "Removing old symbolic link:" $base_output/$f rm $base_output/$f # else # echo "Not a symbolic link:" $base_output/$f fi done echo "starting $num_machines clients" grep '^[^#]*execution_interval' $output/$config_file | tail -1 new_execution_interval=$execution_interval client_id=0; for client in $client_machine_list; do if [ "$client" = "$host" ]; then rsh="" else rsh="rsh $client" fi if [ "$mode" = "fixed_injection" ] ; then if [ $client_id -ne 0 ]; then new_execution_interval=`expr $new_execution_interval - $injection_interval` fi fi echo "client_id: $client_id, new_execution_interval = $new_execution_interval" cmd="$tempdir.$client_id/SDKtest_client -d$tempdir.$client_id -c$config_file -i$client_id -p$client_plugin -x$new_execution_interval -r$request_rate"; # used to be "...2>&1 &", but now want user to see stderr echo "$rsh $cmd > $output/$client.$client_id.SDKtest_client.out &" $rsh $cmd > $output/$client.$client_id.SDKtest_client.out & client_pids=$client_pids" "$! client_id=`expr $client_id + 1` if [ "$mode" = "fixed_injection" ] ; then sleep $injection_interval fi done #wait for i in $client_pids; do #echo "waiting for completion of PID $i" wait $i done echo "" if [ "$origin_autostart" = "none" ]; then echo "Leaving SDKtest_server running" else echo "Attempting to connect to $origin_server on port $origin_port to" echo " request shutdown of SDKtest_server" awk 'BEGIN{printf "GET LOST\n\n\n";}' < /dev/null | telnet $origin_server $origin_port echo "" fi rm -f $output/all_clients.out client_id=0; for client in $client_machine_list; do if [ "$client" = "$host" ]; then rsh="eval" else rsh="rsh $client" fi egrep '(Client|.\]|time distribution:|percentile|Max connections open)' $output/$client.$client_id.SDKtest_client.out >> $output/all_clients.out $rsh "\rm $tempdir.$client_id/SDKtest_client $tempdir.$client_id/$config_file $tempdir.$client_id/$docsize_dist_file $tempdir.$client_id/$thinktime_dist_file $tempdir.$client_id/$byterate_dist_file" & client_id=`expr $client_id + 1` done wait lines=`wc -l $output/all_clients.out | awk '{print $1;}'` if [ $lines -ne 0 ]; then client_names="" for client in $client_machine_list; do if [ "$client_names" = "" ] ; then client_names=$client else client_names=$client_names","$client fi done echo "Connect times (seconds):" > $output/connect.csv sed 's/^= c/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=1 number_of_machines=$num_machines >> $output/connect.csv echo "First byte latency (seconds):" > $output/first_byte.csv sed 's/^= f/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=1 number_of_machines=$num_machines >> $output/first_byte.csv echo "Round trip latency (seconds):" > $output/round_trip.csv sed 's/^= r/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=1 number_of_machines=$num_machines >> $output/round_trip.csv echo "Summary statistics:" > $output/summary.csv awk -f client/summarize.awk client_names="$client_names" excel=1 number_of_machines=$num_machines < $output/all_clients.out >> $output/summary.csv EchoBoth $output/summary.txt "Done with SDKtest at `date`" EchoBoth $output/summary.txt "" echo "Connect times (seconds):" >> $output/summary.txt sed 's/^= c/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=0 number_of_machines=$num_machines >> $output/summary.txt echo "First byte latency (seconds):" >> $output/summary.txt sed 's/^= f/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=0 number_of_machines=$num_machines >> $output/summary.txt echo "Round trip latency (seconds):" >> $output/summary.txt sed 's/^= r/= X/' $output/all_clients.out \ | awk -f client/histogram.awk client_names="$client_names" excel=0 number_of_machines=$num_machines >> $output/summary.txt echo "Summary statistics:" >> $output/summary.txt awk -f client/summarize.awk client_names="$client_names" excel=0 number_of_machines=$num_machines < $output/all_clients.out >> $output/summary.txt grep -v SDKtest $output/summary.txt files=`ls -1 $output` for f in $files ; do ln -s $lastdir/$f $base_output # echo "Making symbolic link from $lastdir/$f to $base_output" done echo "" echo "Raw output, excel CSV files, and summaries are in the directory" $output echo "(Symbolic links to these files are in $base_output.)" else echo "Not enough output data to process" echo "Raw output files are in the directory" $output fi exit 0