Commit 0c57c832 authored by Tatsuo Ishii's avatar Tatsuo Ishii

New features contributed by Tomoaki Sato.

- predefined variable "tps"
  The value of variable tps is taken from the scaling factor
  specified by -s option.

- -D option
  Variable values can be defined by -D option.

- \set command now allows arithmetic calculations.
parent 88b39634
pgbench README 2005/10/04 Tatsuo Ishii pgbench README 2006/07/26 Tatsuo Ishii
o What is pgbench? o What is pgbench?
pgbench is a simple program to run a benchmark test sort of pgbench is a simple program to run a benchmark test. pgbench is a
"TPC-B". pgbench is a client application of PostgreSQL and runs client application of PostgreSQL and runs with PostgreSQL only. It
with PostgreSQL only. It performs lots of small and simple performs lots of small and simple transactions including
transactions including select/update/insert operations then SELECT/UPDATE/INSERT operations then calculates number of
calculates number of transactions successfully completed within a transactions successfully completed within a second (transactions
second (transactions per second, tps). Targeting data includes a per second, tps). Targeting data includes a table with at least 100k
table with at least 100k tuples. tuples.
Example outputs from pgbench look like: Example outputs from pgbench look like:
...@@ -39,7 +39,7 @@ o How to install pgbench ...@@ -39,7 +39,7 @@ o How to install pgbench
o How to use pgbench? o How to use pgbench?
(1) Initialize database by: (1) (optional)Initialize database by:
pgbench -i <dbname> pgbench -i <dbname>
...@@ -95,6 +95,10 @@ o options ...@@ -95,6 +95,10 @@ o options
as large as the largest number of clients you intend as large as the largest number of clients you intend
to test; else you'll mostly be measuring update contention. to test; else you'll mostly be measuring update contention.
-D varname=value
Define a variable. It can be refereed to by a script
provided by using -f option. Multile -D options are allowed.
-U login -U login
Specify db user's login name if it is different from Specify db user's login name if it is different from
the Unix login name. the Unix login name.
...@@ -173,6 +177,15 @@ o -f option ...@@ -173,6 +177,15 @@ o -f option
slash). A meta command takes some arguments separted by white slash). A meta command takes some arguments separted by white
spaces. Currently following meta command is supported: spaces. Currently following meta command is supported:
\set name operand1 [ operator operand2 ]
set the calculated value using "operand1" "operator"
"operand2" to variable "name". If "operator" and "operand2"
are omitted, the value of operand1 is set to variable "name".
example:
\set ntellers 10 * :tps
\setrandom name min max \setrandom name min max
assign random integer to name between min and max assign random integer to name between min and max
...@@ -188,12 +201,17 @@ o -f option ...@@ -188,12 +201,17 @@ o -f option
SELECT abalance FROM accounts WHERE aid = :aid SELECT abalance FROM accounts WHERE aid = :aid
For example, TPC-B like benchmark can be defined as follows(scaling Variables can also be defined by using -D option.
Example, TPC-B like benchmark can be defined as follows(scaling
factor = 1): factor = 1):
\setrandom aid 1 100000 \set nbranches :tps
\setrandom bid 1 1 \set ntellers 10 * :tps
\setrandom tid 1 10 \set naccounts 100000 * :tps
\setrandom aid 1 :naccounts
\setrandom bid 1 :nbranches
\setrandom tid 1 :ntellers
\setrandom delta 1 10000 \setrandom delta 1 10000
BEGIN BEGIN
UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
...@@ -203,12 +221,30 @@ UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid ...@@ -203,12 +221,30 @@ UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid
INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, 'now') INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, 'now')
END END
If you want to automatically set the scaling factor from the number of
tuples in branches table, use -s option and shell command like this:
pgbench -s $(psql -At -c "SELECT count(*) FROM branches") -f tpc_b.sql
Notice that -f option does not execute vacuum and clearing history
table before starting benchmark.
o License? o License?
Basically it is same as BSD license. See pgbench.c for more details. Basically it is same as BSD license. See pgbench.c for more details.
o History o History
2006/07/26
* New features contributed by Tomoaki Sato.
* predefined variable "tps"
The value of variable tps is taken from the scaling factor
specified by -s option.
* -D option
Variable values can be defined by -D option.
* \set command now allows arithmetic calculations.
2005/09/29 2005/09/29
* add -f option. contributed by Tomoaki Sato. * add -f option. contributed by Tomoaki Sato.
......
pgbench README 2005/09/29 Tatsuo Ishii pgbench README 2006/07/26 Tatsuo Ishii
$B"#(Bpgbench $B$H$O!)(B $B"#(Bpgbench $B$H$O!)(B
pgbench $B$O%Y%s%A%^!<%/%F%9%H$r9T$J$&%W%m%0%i%`$G$9!%:#$N$H$3$m(B pgbench $B$O(BPostgreSQL$B$N%Y%s%A%^!<%/%F%9%H$r9T$J$&%W%m%0%i%`$G$9!%(B
PostgreSQL $B@lMQ$G$9!%(B
pgbench $B$O(B select/update/insert $B$r4^$`%H%i%s%6%/%7%g%s$r<B9T$7!$A4BN$N(B pgbench $B$O(B SELECT/UPDATE/INSERT $B$r4^$`%H%i%s%6%/%7%g%s$r<B9T$7!$A4BN$N(B
$B<B9T;~4V$H<B:]$K40N;$7$?%H%i%s%6%/%7%g%s$N?t$+$i(B 1 $BIC4V$K<B9T$G$-$?%H(B $B<B9T;~4V$H<B:]$K40N;$7$?%H%i%s%6%/%7%g%s$N?t$+$i(B 1 $BIC4V$K<B9T$G$-$?%H(B
$B%i%s%6%/%7%g%s?t(B (tps) $B$rI=<($7$^$9!%=hM}$NBP>]$H$J$k%F!<%V%k$O%G%U%)(B $B%i%s%6%/%7%g%s?t(B (tps) $B$rI=<($7$^$9!%=hM}$NBP>]$H$J$k%F!<%V%k$O%G%U%)(B
$B%k%H$G$O(B 10$BK|%?%W%k$N%G!<%?$r4^$_$^$9!%(B $B%k%H$G$O(B 10$BK|%?%W%k$N%G!<%?$r4^$_$^$9!%(B
...@@ -44,7 +43,8 @@ $ pgbench [$B%G!<%?%Y!<%9L>(B] ...@@ -44,7 +43,8 @@ $ pgbench [$B%G!<%?%Y!<%9L>(B]
$B$G$9!%%G!<%?%Y!<%9L>$r>JN,$9$k$H!$%f!<%6L>$HF1$8%G!<%?%Y!<%9$r;XDj$7$?(B $B$G$9!%%G!<%?%Y!<%9L>$r>JN,$9$k$H!$%f!<%6L>$HF1$8%G!<%?%Y!<%9$r;XDj$7$?(B
$B$b$N$H$_$J$7$^$9!%%G!<%?%Y!<%9$O8e=R$N(B -i $B%*%W%7%g%s$r;H$C$F$"$i$+$8$a(B $B$b$N$H$_$J$7$^$9!%%G!<%?%Y!<%9$O8e=R$N(B -i $B%*%W%7%g%s$r;H$C$F$"$i$+$8$a(B
$B=i4|2=$7$F$*$/I,MW$,$"$j$^$9!%(B $B=i4|2=$7$F$*$/$3$H$,$G$-$^$9!%(B-f$B%*%W%7%g%s$r;H$C$FFH<+$N%H%i%s%6%/%7%g(B
$B%s$rDj5A$9$k>l9g$O!$<+J,$G%G!<%?%Y!<%9$N=i4|2=$r$7$F$*$/I,MW$,$"$j$^$9!%(B
pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B
...@@ -72,6 +72,14 @@ pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B ...@@ -72,6 +72,14 @@ pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B
$B%/%?!<$rJQ$($k$3$H$K$h$j!$%F%9%H$NBP>]$H$J$k%F!<%V%k$N(B $B%/%?!<$rJQ$($k$3$H$K$h$j!$%F%9%H$NBP>]$H$J$k%F!<%V%k$N(B
$BBg$-$5$,(B 10$BK|(B x [$B%9%1!<%j%s%0%U%!%/%?!<(B]$B$K$J$j$^$9!%(B $BBg$-$5$,(B 10$BK|(B x [$B%9%1!<%j%s%0%U%!%/%?!<(B]$B$K$J$j$^$9!%(B
$B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!%(B $B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!%(B
-f $B%*%W%7%g%s$G;XDj$7$?%U%!%$%k$+$i%9%1!<%j%s%0%U%!%/(B
$B%?!<$r;2>H$9$k$K$O(B tps $B$H$$$&JQ?tL>$r;HMQ$7$^$9!%(B
-D varname=value
$BJQ?t$rDj5A$7$^$9!%Dj5A$7$?JQ?t$O(B -f $B%*%W%7%g%s$G;XDj$7$?%U%!%$(B
$B%k$+$i;2>H$G$-$^$9!%(B-D $B%*%W%7%g%s$G$OJQ?tL>$HCM$r(B = ($B%$%3!<%k(B)
$B$G6h@Z$C$F;XDj$7$^$9!%(B-D $B%*%W%7%g%s$OJ#?t;XDj$G$-$^$9!%(B
-U login DB$B%f!<%6$N%m%0%$%sL>$r;XDj$7$^$9!%(B -U login DB$B%f!<%6$N%m%0%$%sL>$r;XDj$7$^$9!%(B
...@@ -129,7 +137,9 @@ pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B ...@@ -129,7 +137,9 @@ pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!%(B
$B"#%G!<%?%Y!<%9$N=i4|2=(B $B"#%G!<%?%Y!<%9$N=i4|2=(B
pgbench $B$G%Y%s%A%^!<%/%F%9%H$r<B;\$9$k$?$a$K$O!$$"$i$+$8$a%G!<%?%Y!<%9(B pgbench $B$G%Y%s%A%^!<%/%F%9%H$r<B;\$9$k$?$a$K$O!$$"$i$+$8$a%G!<%?%Y!<%9(B
$B$r=i4|2=$7!$%F%9%H%G!<%?$r:n$kI,MW$,$"$j$^$9!%(B $B$r=i4|2=$7!$%F%9%H%G!<%?$r:n$kI,MW$,$"$j$^$9!%(B-f$B%*%W%7%g%s$r;H$C$FFH<+(B
$B$N%H%i%s%6%/%7%g%s$rDj5A$9$k>l9g$O!$<+J,$G%G!<%?%Y!<%9$N=i4|2=$r$7$F$*(B
$B$/I,MW$,$"$j$^$9!%(B
$ pgbench -i [$B%G!<%?%Y!<%9L>(B] $ pgbench -i [$B%G!<%?%Y!<%9L>(B]
...@@ -146,8 +156,11 @@ accounts 100000 ...@@ -146,8 +156,11 @@ accounts 100000
history 0 history 0
$B%9%1!<%j%s%0%U%!%/%?!<$r(B 10,100,1000 $B$J$I$KJQ99$9$k$H!$>e5-%?%W%k?t$O(B $B%9%1!<%j%s%0%U%!%/%?!<$r(B 10,100,1000 $B$J$I$KJQ99$9$k$H!$>e5-%?%W%k?t$O(B
$B$=$l$K1~$8$F(B10$BG\!$(B100$BG\!$(B1000$BG\$K$J$j$^$9!%$?$H$($P!$%9%1!<%j%s%0%U%!(B $B$=$l$K1~$8$F(B10$BG\!$(B100$BG\!$(B1000$BG\$K$J$j$^$9!%%F!<%V%k$H%$%s%G%C%/%9$N%5(B
$B%/%?!<$r(B 10 $B$H$9$k$H!$(B $B%$%:$O%G!<%?%Y!<%9%5%$%:$O35$M$=$l$>$l!$(B130MB$B!$(B1.3GB$B!$(B13GB$B$[$I$K$J$j$^(B
$B$9!%(B
$B$?$H$($P!$%9%1!<%j%s%0%U%!%/%?!<$r(B 10 $B$H$9$k$H!$(B
$B%F!<%V%kL>(B $B%?%W%k?t(B $B%F!<%V%kL>(B $B%?%W%k?t(B
------------------------- -------------------------
...@@ -201,37 +214,69 @@ pgbench $B$G$O!$0J2<$N%7!<%1%s%9$rA4It40N;$7$F(B1$B%H%i%s%6%/%7%g%s$H?t$($F( ...@@ -201,37 +214,69 @@ pgbench $B$G$O!$0J2<$N%7!<%1%s%9$rA4It40N;$7$F(B1$B%H%i%s%6%/%7%g%s$H?t$($F(
$B8=:_$N$H$3$m!$0J2<$N%a%?%3%^%s%I$,Dj5A$5$l$F$$$^$9!%(B $B8=:_$N$H$3$m!$0J2<$N%a%?%3%^%s%I$,Dj5A$5$l$F$$$^$9!%(B
\set name operand1 [ operator operand2 ]
$BHo1i;;?t(B operand1 $B$H(B operand2 $B$r1i;;;R(B operator $B$K$h$C$F1i;;$7(B
$B$?7k2L$rJQ?t(B name $B$K@_Dj$7$^$9!%8=>u$G$O@0?t$N;MB'1i;;$N$_$KBP(B
$B1~$7$F$$$^$9!%$J$*!$1i;;;R$H(B 2 $B$DL\$NHo1i;;?t$r>JN,$9$k$HC1=c(B
$B$K(B 1 $B$DL\$NHo1i;;?t$rJQ?t$K@_Dj$7$^$9!%(B
$BJQ?t$K1i;;$N7k2L$r@_Dj$9$k$K$O!$(B\set $B%a%?%3%^%s%I$r;HMQ$7$F0J(B
$B2<$N$h$&$K5-=R$7$^$9!%(B
\set ntellers 10 * :tps
$B$3$l$O!$JQ?t(B ntellers $B$K%9%1!<%j%s%0%U%!%/%?!<(B (-s $B%*%W%7%g%s(B
$B$G;XDj$7$?(B) $B$r(B 10 $BG\$7$?7k2L$r@_Dj$7$^$9!%(B
\setrandom name min max \setrandom name min max
$B:G>.CM(B min $B$H:GBgCM(B max $B$N4V$NCM$r<h$kMp?t$r!$(Bname $BJQ?t$K@_Dj(B $B:G>.CM(B min $B$H:GBgCM(B max $B$N4V$NCM$r<h$kMp?t$r!$(Bname $BJQ?t$K@_Dj(B
$B$7$^$9!%(B $B$7$^$9!%(B
$BJQ?t$KMp?t$r@_Dj$9$k$K$O!$(B\setrandom $B%a%?%3%^%s%I$r;HMQ$7$F0J2<$N$h$&(B $BJQ?t$KMp?t$r@_Dj$9$k$K$O!$(B\setrandom $B%a%?%3%^%s%I$r;HMQ$7$F0J2<$N$h$&(B
$B$K5-=R$7$^$9!%(B $B$K5-=R$7$^$9!%(B
\setrandom aid 1 100000
\setrandom aid 1 100000 $B$3$l$O!$JQ?t(B aid $B$K(B 1 $B$+$i(B 100000 $B$N4V$NMp?t$r@_Dj$7$^$9!%(B
$B$3$l$O!$JQ?t(B aid $B$K(B 1 $B$+$i(B 100000 $B$N4V$NMp?t$r@_Dj$7$^$9!%$^$?!$JQ?t$N(B $BJQ?t$O(B SQL $B%3%^%s%I$*$h$S%a%?%3%^%s%I$+$i;2>H$G$-$^$9!%$=$l$K$O0J2<$N(B
$BCM$r(B SQL $B%3%^%s%I$KKd$a9~$`$K$O!$0J2<$N$h$&$K$=$NL>A0$NA0$K%3%m%s$rIU(B $B$h$&$KJQ?tL>$NA0$K%3%m%s$rIU$1$^$9!%(B
$B$1$^$9!%(B
SELECT abalance FROM accounts WHERE aid = :aid SELECT abalance FROM accounts WHERE aid = :aid
$BJQ?t$rDj5A$9$k$K$O%a%?%3%^%s%I0J30$K(B -D $B%*%W%7%g%s$r;HMQ$9$k$3$H$b$G$-(B
$B$^$9!%(B -D $B%*%W%7%g%s$GDj5A$7$?JQ?t$bJQ?tL>$NA0$K%3%m%s$rIU$1$F;2>H$7$^(B
$B$9!%(B
$BNc$($P!$(BTCP-B $B$KN`;w$7$?%Y%s%A%^!<%/$r7WB,$9$k$K$O!$0J2<$N$h$&$K%H%i%s(B $BNc$($P!$(BTCP-B $B$KN`;w$7$?%Y%s%A%^!<%/$r7WB,$9$k$K$O!$0J2<$N$h$&$K%H%i%s(B
$B%6%/%7%g%s$NFbMF$r%U%!%$%k$K5-=R$7!$(B-f $B%*%W%7%g%s$K$h$C$F$=$N%U%!%$%k(B $B%6%/%7%g%s$NFbMF$r%U%!%$%k$K5-=R$7!$(B-f $B%*%W%7%g%s$K$h$C$F$=$N%U%!%$%k(B
$B$r;XDj$7$F(B pgbench $B$r<B9T$7$^$9!%(B $B$r;XDj$7$F(B pgbench $B$r<B9T$7$^$9!%(B
\setrandom aid 1 100000 \set nbranches :tps
\setrandom bid 1 1 \set ntellers 10 * :tps
\setrandom tid 1 10 \set naccounts 100000 * :tps
\setrandom aid 1 :naccounts
\setrandom bid 1 :nbranches
\setrandom tid 1 :ntellers
\setrandom delta 1 10000 \setrandom delta 1 10000
BEGIN BEGIN
UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid
SELECT abalance FROM accounts WHERE aid = :aid SELECT abalance FROM accounts WHERE aid = :aid
UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid
UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid
INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, 'now') INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, current_timestamp)
END END
$B%9%1!<%j%s%0%U%!%/%?!<$r(B branches $B%F!<%V%k$N%?%W%k?t$+$i<+F0E*$K@_Dj$7(B
$B$?$$>l9g!$0J2<$N$h$&$K(B -s $B%*%W%7%g%s$H%7%'%k$N%3%^%s%ICV49$J$I$rAH$_9g(B
$B$o$;$^$9!%(B
pgbench -s $(psql -At -c "SELECT count(*) FROM branches") -f tpc_b.sql
$B$J$*!$(B-f $B%*%W%7%g%s$r;XDj$7$?>l9g!$%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B
history $B$N%/%j%"$O<+F0E*$K9T$o$l$^$;$s!%(B
$B"#:n<T$H%i%$%;%s%9>r7o(B $B"#:n<T$H%i%$%;%s%9>r7o(B
pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!%%i%$%;%s%9>r7o$O(B pgbench.c $B$N(B pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!%%i%$%;%s%9>r7o$O(B pgbench.c $B$N(B
...@@ -240,6 +285,18 @@ pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!%%i%$%;%s%9>r7o$O(B pgbench.c ...@@ -240,6 +285,18 @@ pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!%%i%$%;%s%9>r7o$O(B pgbench.c
$B"#2~DjMzNr(B $B"#2~DjMzNr(B
2006/07/26
* $B:4F#$5$s$N%Q%C%A$rE,MQ!%0J2<$N5!G=DI2C!%(BPostgreSQL 8.2$B$K<h$j(B
$B9~$^$l$^$9!%(B
$BJQ?t(B tps
-s $B%*%W%7%g%s$G;XDj$7$?%9%1!<%j%s%0%U%!%/%?!<$r%U%!%$%kFb$GJQ?t$H$7(B
$B$F;2>H$9$k5!G=(B
-D $B%*%W%7%g%s(B
$B%3%^%s%I$N%*%W%7%g%s$H$7$FDj5A$7$?JQ?t$r%U%!%$%kFb$+$i;2>H$9$k5!G=(B
\set $B%3%^%s%I(B
$B%U%!%$%kFb$G;MB'1i;;$r9T$$!"$=$N7k2L$rJQ?t$KBeF~$9$k5!G=(B
2005/09/29 2005/09/29
* $B:4F#$5$s$N%Q%C%A$rE,MQ!%(B-f $B%*%W%7%g%s$NDI2C!%(B * $B:4F#$5$s$N%Q%C%A$rE,MQ!%(B-f $B%*%W%7%g%s$NDI2C!%(B
......
/* /*
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.49 2005/12/10 01:09:07 tgl Exp $ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.50 2006/07/26 07:24:50 ishii Exp $
* *
* pgbench: a simple benchmark program for PostgreSQL * pgbench: a simple benchmark program for PostgreSQL
* written by Tatsuo Ishii * written by Tatsuo Ishii
...@@ -169,7 +169,7 @@ static char *select_only = { ...@@ -169,7 +169,7 @@ static char *select_only = {
static void static void
usage(void) usage(void)
{ {
fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-n][-C][-v][-S][-N][-f filename][-l][-U login][-P password][-d][dbname]\n"); fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-f filename][-l][-U login][-P password][-d][dbname]\n");
fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P password][-d][dbname]\n"); fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P password][-d][dbname]\n");
} }
...@@ -552,26 +552,130 @@ top: ...@@ -552,26 +552,130 @@ top:
if (strcasecmp(argv[0], "setrandom") == 0) if (strcasecmp(argv[0], "setrandom") == 0)
{ {
char *val; char *var;
int min,
max;
char res[64];
if ((val = malloc(strlen(argv[3]) + 1)) == NULL) if (*argv[2] == ':')
{
if ((var = getVariable(st, argv[2] + 1)) == NULL)
{
fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[2]);
st->ecnt++;
return;
}
min = atoi(var);
}
else
min = atoi(argv[2]);
if (min < 0)
{
fprintf(stderr, "%s: invalid minimum number %d\n", argv[0], min);
st->ecnt++;
return;
}
if (*argv[3] == ':')
{
if ((var = getVariable(st, argv[3] + 1)) == NULL)
{
fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[3]);
st->ecnt++;
return;
}
max = atoi(var);
}
else
max = atoi(argv[3]);
if (max < min || max > MAX_RANDOM_VALUE)
{
fprintf(stderr, "%s: invalid maximum number %d\n", argv[0], max);
st->ecnt++;
return;
}
snprintf(res, sizeof(res), "%d", getrand(min, max));
if (putVariable(st, argv[1], res) == false)
{ {
fprintf(stderr, "%s: out of memory\n", argv[0]); fprintf(stderr, "%s: out of memory\n", argv[0]);
st->ecnt++; st->ecnt++;
return; return;
} }
sprintf(val, "%d", getrand(atoi(argv[2]), atoi(argv[3]))); st->listen = 1;
}
else if (strcasecmp(argv[0], "set") == 0)
{
char *var;
int ope1,
ope2;
char res[64];
if (putVariable(st, argv[1], val) == false) if (*argv[2] == ':')
{
if ((var = getVariable(st, argv[2] + 1)) == NULL)
{
fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[2]);
st->ecnt++;
return;
}
ope1 = atoi(var);
}
else
ope1 = atoi(argv[2]);
if (argc < 5)
snprintf(res, sizeof(res), "%d", ope1);
else
{
if (*argv[4] == ':')
{
if ((var = getVariable(st, argv[4] + 1)) == NULL)
{
fprintf(stderr, "%s: undefined variable %s\n", argv[0], argv[4]);
st->ecnt++;
return;
}
ope2 = atoi(var);
}
else
ope2 = atoi(argv[4]);
if (strcmp(argv[3], "+") == 0)
snprintf(res, sizeof(res), "%d", ope1 + ope2);
else if (strcmp(argv[3], "-") == 0)
snprintf(res, sizeof(res), "%d", ope1 - ope2);
else if (strcmp(argv[3], "*") == 0)
snprintf(res, sizeof(res), "%d", ope1 * ope2);
else if (strcmp(argv[3], "/") == 0)
{
if (ope2 == 0)
{
fprintf(stderr, "%s: division by zero\n", argv[0]);
st->ecnt++;
return;
}
snprintf(res, sizeof(res), "%d", ope1 / ope2);
}
else
{
fprintf(stderr, "%s: unsupported operator %s\n", argv[0], argv[3]);
st->ecnt++;
return;
}
}
if (putVariable(st, argv[1], res) == false)
{ {
fprintf(stderr, "%s: out of memory\n", argv[0]); fprintf(stderr, "%s: out of memory\n", argv[0]);
free(val);
st->ecnt++; st->ecnt++;
return; return;
} }
free(val);
st->listen = 1; st->listen = 1;
} }
...@@ -808,9 +912,6 @@ process_commands(char *buf) ...@@ -808,9 +912,6 @@ process_commands(char *buf)
if (strcasecmp(my_commands->argv[0], "setrandom") == 0) if (strcasecmp(my_commands->argv[0], "setrandom") == 0)
{ {
int min,
max;
if (my_commands->argc < 4) if (my_commands->argc < 4)
{ {
fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]); fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
...@@ -820,20 +921,18 @@ process_commands(char *buf) ...@@ -820,20 +921,18 @@ process_commands(char *buf)
for (j = 4; j < my_commands->argc; j++) for (j = 4; j < my_commands->argc; j++)
fprintf(stderr, "%s: extra argument \"%s\" ignored\n", fprintf(stderr, "%s: extra argument \"%s\" ignored\n",
my_commands->argv[0], my_commands->argv[j]); my_commands->argv[0], my_commands->argv[j]);
if ((min = atoi(my_commands->argv[2])) < 0)
{
fprintf(stderr, "%s: invalid minimum number %s\n",
my_commands->argv[0], my_commands->argv[2]);
return NULL;
} }
else if (strcasecmp(my_commands->argv[0], "set") == 0)
if ((max = atoi(my_commands->argv[3])) < min || max > MAX_RANDOM_VALUE) {
if (my_commands->argc < 3)
{ {
fprintf(stderr, "%s: invalid maximum number %s\n", fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
my_commands->argv[0], my_commands->argv[3]);
return NULL; return NULL;
} }
for (j = my_commands->argc < 5 ? 3 : 5; j < my_commands->argc; j++)
fprintf(stderr, "%s: extra argument \"%s\" ignored\n",
my_commands->argv[0], my_commands->argv[j]);
} }
else else
{ {
...@@ -889,10 +988,14 @@ process_file(char *filename) ...@@ -889,10 +988,14 @@ process_file(char *filename)
while (fgets(buf, sizeof(buf), fd) != NULL) while (fgets(buf, sizeof(buf), fd) != NULL)
{ {
Command *commands; Command *commands;
int i;
i = 0;
while (isspace((unsigned char) buf[i]))
i++;
if (strncmp(buf, "\n", 1) != 0) { if (strncmp(&buf[i], "\n", 1) != 0 && strncmp(&buf[i], "--", 2) != 0) {
commands = process_commands(buf); commands = process_commands(&buf[i]);
if (commands == NULL) if (commands == NULL)
{ {
fclose(fd); fclose(fd);
...@@ -1067,7 +1170,16 @@ main(int argc, char **argv) ...@@ -1067,7 +1170,16 @@ main(int argc, char **argv)
else if ((env = getenv("PGUSER")) != NULL && *env != '\0') else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
login = env; login = env;
while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSlf:")) != -1) state = (CState *) malloc(sizeof(CState));
if (state == NULL)
{
fprintf(stderr, "Couldn't allocate memory for state\n");
exit(1);
}
memset(state, 0, sizeof(*state));
while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSlf:D:")) != -1)
{ {
switch (c) switch (c)
{ {
...@@ -1151,8 +1263,26 @@ main(int argc, char **argv) ...@@ -1151,8 +1263,26 @@ main(int argc, char **argv)
case 'f': case 'f':
ttype = 3; ttype = 3;
filename = optarg; filename = optarg;
if (process_file(filename) == false) if (process_file(filename) == false || *sql_files[num_files - 1] == NULL)
exit(1);
break;
case 'D':
{
char *p;
if ((p = strchr(optarg, '=')) == NULL || p == optarg || *(p + 1) == '\0')
{
fprintf(stderr, "invalid variable definition: %s\n", optarg);
exit(1);
}
*p++ = '\0';
if (putVariable(&state[0], optarg, p) == false)
{
fprintf(stderr, "Couldn't allocate memory for variable\n");
exit(1); exit(1);
}
}
break; break;
default: default:
usage(); usage();
...@@ -1181,14 +1311,43 @@ main(int argc, char **argv) ...@@ -1181,14 +1311,43 @@ main(int argc, char **argv)
remains = nclients; remains = nclients;
state = (CState *) malloc(sizeof(CState) * nclients); if (getVariable(&state[0], "tps") == NULL)
{
char val[64];
snprintf(val, sizeof(val), "%d", tps);
if (putVariable(&state[0], "tps", val) == false)
{
fprintf(stderr, "Couldn't allocate memory for variable\n");
exit(1);
}
}
if (nclients > 1)
{
state = (CState *) realloc(state, sizeof(CState) * nclients);
if (state == NULL) if (state == NULL)
{ {
fprintf(stderr, "Couldn't allocate memory for state\n"); fprintf(stderr, "Couldn't allocate memory for state\n");
exit(1); exit(1);
} }
memset(state, 0, sizeof(*state) * nclients); memset(state + sizeof(*state), 0, sizeof(*state) * (nclients - 1));
for (i = 1; i < nclients; i++)
{
int j;
for (j = 0; j < state[0].nvariables; j++)
{
if (putVariable(&state[i], state[0].variables[j].name, state[0].variables[j].value) == false)
{
fprintf(stderr, "Couldn't allocate memory for variable\n");
exit(1);
}
}
}
}
if (use_log) if (use_log)
{ {
...@@ -1357,8 +1516,19 @@ main(int argc, char **argv) ...@@ -1357,8 +1516,19 @@ main(int argc, char **argv)
/* send start up queries in async manner */ /* send start up queries in async manner */
for (i = 0; i < nclients; i++) for (i = 0; i < nclients; i++)
{ {
Command **commands = sql_files[state[i].use_file];
int prev_ecnt = state[i].ecnt;
state[i].use_file = getrand(0, num_files - 1); state[i].use_file = getrand(0, num_files - 1);
doCustom(state, i, debug); doCustom(state, i, debug);
if (state[i].ecnt > prev_ecnt && commands[state[i].state]->type == META_COMMAND)
{
fprintf(stderr, "Client %d aborted in state %d. Execution meta-command failed.\n", i, state[i].state);
remains--; /* I've aborted */
PQfinish(state[i].con);
state[i].con = NULL;
}
} }
for (;;) for (;;)
...@@ -1424,12 +1594,21 @@ main(int argc, char **argv) ...@@ -1424,12 +1594,21 @@ main(int argc, char **argv)
for (i = 0; i < nclients; i++) for (i = 0; i < nclients; i++)
{ {
Command **commands = sql_files[state[i].use_file]; Command **commands = sql_files[state[i].use_file];
int prev_ecnt = state[i].ecnt;
if (state[i].con && (FD_ISSET(PQsocket(state[i].con), &input_mask) if (state[i].con && (FD_ISSET(PQsocket(state[i].con), &input_mask)
|| commands[state[i].state]->type == META_COMMAND)) || commands[state[i].state]->type == META_COMMAND))
{ {
doCustom(state, i, debug); doCustom(state, i, debug);
} }
if (state[i].ecnt > prev_ecnt && commands[state[i].state]->type == META_COMMAND)
{
fprintf(stderr, "Client %d aborted in state %d. Execution meta-command failed.\n", i, state[i].state);
remains--; /* I've aborted */
PQfinish(state[i].con);
state[i].con = NULL;
}
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment