diff -cpr HEAD/contrib/pgbench/pgbench.c pgbench-duration_v3/contrib/pgbench/pgbench.c
*** HEAD/contrib/pgbench/pgbench.c	Sat Aug 23 02:57:34 2008
--- pgbench-duration_v3/contrib/pgbench/pgbench.c	Mon Sep  8 17:39:49 2008
***************
*** 29,36 ****
--- 29,40 ----
  #include "postgres_fe.h"
  
  #include "libpq-fe.h"
+ #include "pqsignal.h"
  
  #include <ctype.h>
+ #include <signal.h>
+ #include <sys/time.h>
+ #include <unistd.h>
  
  #ifdef WIN32
  #undef FD_SETSIZE
*************** extern int	optind;
*** 67,74 ****
  #define MAXCLIENTS	1024
  #endif
  
  int			nclients = 1;		/* default number of simulated clients */
! int			nxacts = 10;		/* default number of transactions per clients */
  
  /*
   * scaling factor. for example, scale = 10 will make 1000000 tuples of
--- 71,82 ----
  #define MAXCLIENTS	1024
  #endif
  
+ #define DEFAULT_NXACTS	10		/* default nxacts */
+ 
  int			nclients = 1;		/* default number of simulated clients */
! int			nxacts = 0;			/* number of transactions per clients */
! int			duration = 0;		/* duration is not used by default */
! volatile bool	timer_exceeded = false;
  
  /*
   * scaling factor. for example, scale = 10 will make 1000000 tuples of
*************** static char *select_only = {
*** 208,213 ****
--- 216,223 ----
  /* Connection overhead time */
  static struct timeval conn_total_time = {0, 0};
  
+ static void setalarm(int seconds);
+ 
  /* Calculate total time */
  static void
  addTime(struct timeval *t1, struct timeval *t2, struct timeval *result)
*************** diffTime(struct timeval *t1, struct time
*** 241,247 ****
  static void
  usage(void)
  {
! 	fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-M querymode][-f filename][-l][-U login][-d][dbname]\n");
  	fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-d][dbname]\n");
  }
  
--- 251,257 ----
  static void
  usage(void)
  {
! 	fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions | -T duration][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-M querymode][-f filename][-l][-U login][-d][dbname]\n");
  	fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-d][dbname]\n");
  }
  
*************** top:
*** 630,636 ****
  				st->con = NULL;
  			}
  
! 			if (++st->cnt >= nxacts)
  			{
  				remains--;		/* I've done */
  				if (st->con != NULL)
--- 640,647 ----
  				st->con = NULL;
  			}
  
! 			++st->cnt;
! 			if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
  			{
  				remains--;		/* I've done */
  				if (st->con != NULL)
*************** printResults(
*** 1434,1441 ****
  	printf("scaling factor: %d\n", scale);
  	printf("query mode: %s\n", QUERYMODE[querymode]);
  	printf("number of clients: %d\n", nclients);
! 	printf("number of transactions per client: %d\n", nxacts);
! 	printf("number of transactions actually processed: %d/%d\n", normal_xacts, nxacts * nclients);
  	printf("tps = %f (including connections establishing)\n", t1);
  	printf("tps = %f (excluding connections establishing)\n", t2);
  }
--- 1445,1459 ----
  	printf("scaling factor: %d\n", scale);
  	printf("query mode: %s\n", QUERYMODE[querymode]);
  	printf("number of clients: %d\n", nclients);
! 	if (duration <= 0)
! 	{
! 		printf("number of transactions per client: %d\n", nxacts);
! 		printf("number of transactions actually processed: %d/%d\n", normal_xacts, nxacts * nclients);
! 	}
! 	else
! 	{
! 		printf("number of transactions actually processed: %d in %d s\n", normal_xacts, duration);
! 	}
  	printf("tps = %f (including connections establishing)\n", t1);
  	printf("tps = %f (excluding connections establishing)\n", t2);
  }
*************** main(int argc, char **argv)
*** 1499,1505 ****
  
  	memset(state, 0, sizeof(*state));
  
! 	while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:")) != -1)
  	{
  		switch (c)
  		{
--- 1517,1523 ----
  
  	memset(state, 0, sizeof(*state));
  
! 	while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:T:")) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 1565,1570 ****
--- 1583,1593 ----
  				}
  				break;
  			case 't':
+ 				if (duration > 0)
+ 				{
+ 					fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both.\n");
+ 					exit(1);
+ 				}
  				nxacts = atoi(optarg);
  				if (nxacts <= 0)
  				{
*************** main(int argc, char **argv)
*** 1572,1577 ****
--- 1595,1613 ----
  					exit(1);
  				}
  				break;
+ 			case 'T':
+ 				if (nxacts > 0)
+ 				{
+ 					fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both.\n");
+ 					exit(1);
+ 				}
+ 				duration = atoi(optarg);
+ 				if (duration <= 0)
+ 				{
+ 					fprintf(stderr, "invalid duration(-T): %d\n", duration);
+ 					exit(1);
+ 				}
+ 				break;
  			case 'U':
  				login = optarg;
  				break;
*************** main(int argc, char **argv)
*** 1650,1655 ****
--- 1686,1695 ----
  		exit(0);
  	}
  
+ 	/* Use DEFAULT_NXACTS if neither nxacts nor duration is specified. */
+ 	if (nxacts <= 0 && duration <= 0)
+ 		nxacts = DEFAULT_NXACTS;
+ 
  	remains = nclients;
  
  	if (nclients > 1)
*************** main(int argc, char **argv)
*** 1695,1702 ****
  
  	if (debug)
  	{
! 		printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
  			   pghost, pgport, nclients, nxacts, dbName);
  	}
  
  	/* opening connection... */
--- 1735,1746 ----
  
  	if (debug)
  	{
! 		if (duration <= 0)
! 			printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
  			   pghost, pgport, nclients, nxacts, dbName);
+ 		else
+ 			printf("pghost: %s pgport: %s nclients: %d duration: %d dbName: %s\n",
+ 			   pghost, pgport, nclients, duration, dbName);
  	}
  
  	/* opening connection... */
*************** main(int argc, char **argv)
*** 1779,1784 ****
--- 1823,1835 ----
  	/* get start up time */
  	gettimeofday(&start_time, NULL);
  
+ 	/* set alarm if duration is specified. */
+ 	if (duration > 0)
+ 	{
+ 		timer_exceeded = false;
+ 		setalarm(duration);
+ 	}
+ 
  	if (is_connect == 0)
  	{
  		struct timeval t, now;
*************** main(int argc, char **argv)
*** 1951,1953 ****
--- 2002,2047 ----
  		}
  	}
  }
+ 
+ static void
+ handle_sig_alarm(SIGNAL_ARGS)
+ {
+ 	timer_exceeded = true;
+ }
+ 
+ #ifdef WIN32
+ 
+ static VOID CALLBACK
+ win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+ {
+ 	handle_sig_alarm(SIGALRM);
+ }
+ 
+ /* This function will be called only once. */
+ static void
+ setalarm(int seconds)
+ {
+ 	HANDLE	queue;
+ 	HANDLE	timer;
+ 
+ 	queue = CreateTimerQueue();
+ 	if (seconds > ((DWORD)-1) / 1000 ||
+ 		!CreateTimerQueueTimer(&timer, queue,
+ 			win32_timer_callback, NULL, seconds * 1000, 0,
+ 			WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
+ 	{
+ 		fprintf(stderr, "Failed to set timer\n");
+ 		exit(1);
+ 	}
+ }
+ 
+ #else
+ 
+ static void
+ setalarm(int seconds)
+ {
+ 	pqsignal(SIGALRM, handle_sig_alarm);
+ 	alarm(seconds);
+ }
+ 
+ #endif
diff -cpr HEAD/doc/src/sgml/pgbench.sgml pgbench-duration_v3/doc/src/sgml/pgbench.sgml
*** HEAD/doc/src/sgml/pgbench.sgml	Wed Mar 19 12:33:21 2008
--- pgbench-duration_v3/doc/src/sgml/pgbench.sgml	Mon Sep  8 17:36:28 2008
*************** pgbench <optional> <replaceable>options<
*** 174,179 ****
--- 174,186 ----
        </entry>
       </row>
       <row>
+       <entry><literal>-T</literal> <replaceable>duration</></entry>
+       <entry>
+        Duration of benchmark in seconds. <literal>-t</literal> and
+        <literal>-T</literal> are mutually exclusive.
+       </entry>
+      </row>
+      <row>
        <entry><literal>-M</literal> <replaceable>querymode</></entry>
        <entry>
         Choose the query mode from the follows. default is simple.
*************** END;
*** 515,521 ****
  
    <para>
     In the first place, <emphasis>never</> believe any test that runs
!    for only a few seconds.  Increase the <literal>-t</> setting enough
     to make the run last at least a few minutes, so as to average out noise.
     In some cases you could need hours to get numbers that are reproducible.
     It's a good idea to try the test run a few times, to find out if your
--- 522,528 ----
  
    <para>
     In the first place, <emphasis>never</> believe any test that runs
!    for only a few seconds.  Use the <literal>-t</> or <literal>-T</> setting enough
     to make the run last at least a few minutes, so as to average out noise.
     In some cases you could need hours to get numbers that are reproducible.
     It's a good idea to try the test run a few times, to find out if your
