diff -cpr HEAD/contrib/pgbench/pgbench.c pgbench-duration_v2/contrib/pgbench/pgbench.c
*** HEAD/contrib/pgbench/pgbench.c	Sat May 10 00:53:07 2008
--- pgbench-duration_v2/contrib/pgbench/pgbench.c	Tue Aug 19 10:59:29 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;
*** 70,75 ****
--- 74,82 ----
  int			nclients = 1;		/* default number of simulated clients */
  int			nxacts = 10;		/* default 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
   * accounts table.
*************** static char *select_only = {
*** 208,213 ****
--- 215,222 ----
  /* 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");
  }
  
--- 250,256 ----
  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)
--- 639,660 ----
  				st->con = NULL;
  			}
  
! 			++st->cnt;
! 
! 			if (duration > 0)
! 			{
! 				if (timer_exceeded)
! 				{
! 					remains--;		/* I've done */
! 					if (st->con != NULL)
! 					{
! 						PQfinish(st->con);
! 						st->con = NULL;
! 					}
! 					return;
! 				}
! 			}
! 			else if (st->cnt >= nxacts)
  			{
  				remains--;		/* I've done */
  				if (st->con != NULL)
*************** printResults(
*** 1431,1438 ****
  	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);
  }
--- 1455,1469 ----
  	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)
*** 1496,1502 ****
  
  	memset(state, 0, sizeof(*state));
  
! 	while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:M:")) != -1)
  	{
  		switch (c)
  		{
--- 1527,1533 ----
  
  	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)
*** 1569,1574 ****
--- 1600,1613 ----
  					exit(1);
  				}
  				break;
+ 			case 'T':
+ 				duration = atoi(optarg);
+ 				if (duration <= 0)
+ 				{
+ 					fprintf(stderr, "invalid number of duration(-T): %d\n", duration);
+ 					exit(1);
+ 				}
+ 				break;
  			case 'U':
  				login = optarg;
  				break;
*************** main(int argc, char **argv)
*** 1692,1699 ****
  
  	if (debug)
  	{
! 		printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
  			   pghost, pgport, nclients, nxacts, dbName);
  	}
  
  	/* opening connection... */
--- 1731,1742 ----
  
  	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)
*** 1777,1782 ****
--- 1820,1832 ----
  	/* 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)
*** 1949,1951 ****
--- 1999,2044 ----
  		}
  	}
  }
+ 
+ static void
+ handle_sig_alarm(SIGNAL_ARGS)
+ {
+ 	timer_exceeded = true;
+ }
+ 
+ #ifdef WIN32
+ 
+ static VOID CALLBACK
+ win32_timer_callback(PVOID lpParameter, BOOL 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_v2/doc/src/sgml/pgbench.sgml
*** HEAD/doc/src/sgml/pgbench.sgml	Wed Mar 19 12:33:21 2008
--- pgbench-duration_v2/doc/src/sgml/pgbench.sgml	Tue Aug 19 10:52:45 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.
