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 + #include + #include + #include #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 options< *** 174,179 **** --- 174,186 ---- + -T duration + + Duration of benchmark in seconds. -t and + -T are mutually exclusive. + + + -M querymode Choose the query mode from the follows. default is simple.