diff -rcpN original/contrib/pgbench/pgbench.c new/contrib/pgbench/pgbench.c
*** original/contrib/pgbench/pgbench.c	2013-04-01 11:20:36.000000000 -0700
--- new/contrib/pgbench/pgbench.c	2013-11-12 21:03:45.349693960 -0800
*************** int			fillfactor = 100;
*** 125,130 ****
--- 125,168 ----
  int			unlogged_tables = 0;
  
  /*
+  * do not close client if query error is encountered
+  */
+ int			proceed_on_error = 0;
+ 
+ /*
+  * start second for per-second rate reporting
+  */
+ uint64			persecondstart;
+ 
+ /*
+  * number of seconds to keep tally
+  *
+  */
+ #define PERSECOND_NUMSECONDS	604800
+ 
+ /*
+  * per-second report table
+  * persecond[threadnum][second]
+  */
+ int			**persecond;
+ 
+ /*
+  * size of transaction batches to report on per second
+  *
+  */
+ int			persecondbatchsize;
+ 
+ /*
+  * per thread per second completed transactions tally
+  */
+ int			*persecondtally;
+ 
+ /*
+  * use /dev/urandom for random seed state
+  */
+ int			use_urandom = 0;
+ 
+ /*
   * tablespace selection
   */
  char	   *tablespace = NULL;
*************** char	   *pgoptions = NULL;
*** 150,155 ****
--- 188,194 ----
  char	   *pgtty = NULL;
  char	   *login = NULL;
  char	   *dbName;
+ char	   *password;
  
  volatile bool timer_exceeded = false;	/* flag from signal handler */
  
*************** usage(const char *progname)
*** 361,366 ****
--- 400,406 ----
  		   "  -D VARNAME=VALUE\n"
  		   "               define variable for use by custom script\n"
  		   "  -f FILENAME  read transaction script from FILENAME\n"
+ 		   "  -I           do not abort connection if query error is encountered\n"
  		   "  -j NUM       number of threads (default: 1)\n"
  		   "  -l           write transaction times to log file\n"
  		   "  -M simple|extended|prepared\n"
*************** usage(const char *progname)
*** 373,383 ****
--- 413,433 ----
  	 "  -t NUM       number of transactions each client runs (default: 10)\n"
  		   "  -T NUM       duration of benchmark test in seconds\n"
  		   "  -v           vacuum all four standard tables before tests\n"
+ 		   "  --per-second=NUM\n"
+ 		   "               report per second throughput rate per thread. NUM is the # of\n"
+ 		   "               statements in each batch to be added to the per second tally.\n"
+ 		   "               As NUM increases, the sampling rate to get the current\n"
+ 		   "               time decreases.\n"
+ 
+ 		   "               Note that one tally is made per statement in a multi-statement\n"
+ 		   "               transaction, including BEGIN and COMMIT.\n"
+ 		   "  --urandom    use /dev/urandom for seeding random number generator\n"
  		   "\nCommon options:\n"
  		   "  -d             print debugging output\n"
  		   "  -h HOSTNAME    database server host or socket directory\n"
  		   "  -p PORT        database server port number\n"
  		   "  -U USERNAME    connect as specified database user\n"
+ 		   "  -P PASSWORD    send specified password\n"
  		   "  -V, --version  output version information, then exit\n"
  		   "  -?, --help     show this help, then exit\n"
  		   "\n"
*************** static PGconn *
*** 421,427 ****
  doConnect(void)
  {
  	PGconn	   *conn;
- 	static char *password = NULL;
  	bool		new_pass;
  
  	/*
--- 471,476 ----
*************** top:
*** 884,895 ****
  			{
  				case PGRES_COMMAND_OK:
  				case PGRES_TUPLES_OK:
  					break;		/* OK */
  				default:
! 					fprintf(stderr, "Client %d aborted in state %d: %s",
! 							st->id, st->state, PQerrorMessage(st->con));
! 					PQclear(res);
! 					return clientDone(st, false);
  			}
  			PQclear(res);
  			discard_response(st);
--- 933,965 ----
  			{
  				case PGRES_COMMAND_OK:
  				case PGRES_TUPLES_OK:
+ 					if (persecondbatchsize)
+ 					{
+ 						if (!(++persecondtally[thread->tid] % persecondbatchsize))
+ 						{
+ 							instr_time now;
+ 							uint64 nowsec;
+ 							INSTR_TIME_SET_CURRENT(now);
+ 							nowsec = INSTR_TIME_GET_MICROSEC(now) / 1000000;
+ 							if (nowsec-persecondstart <= PERSECOND_NUMSECONDS-1)
+ 							{
+ 								persecond[thread->tid][nowsec-persecondstart] += persecondtally[thread->tid];
+ 								persecondtally[thread->tid] = 0;
+ 							}
+ 						}
+ 					}
  					break;		/* OK */
  				default:
! 					if (!proceed_on_error)
! 					{
! 						fprintf(stderr, "Client %d aborted in state %d: %s", st->id, st->state, PQerrorMessage(st->con));
! 						PQclear(res);
! 						return clientDone(st, false);
! 					}
! 					else
! 					{
! 						fprintf(stderr, "Client %d proceeding after error in state %d: %s", st->id, st->state, PQerrorMessage(st->con));
! 					}
  			}
  			PQclear(res);
  			discard_response(st);
*************** printResults(int ttype, int normal_xacts
*** 1841,1846 ****
--- 1911,1948 ----
  			}
  		}
  	}
+ 
+ 	if (persecondbatchsize)
+ 	{
+ 		int lastsecond=-1;
+ 		int n;
+ 		int tnum;
+ 		printf("\nsecond");
+ 		for (tnum=0; tnum < nthreads; tnum++)
+ 		{
+ 			printf(",thread%i", tnum);
+ 		}
+ 		printf("\n");
+ 		for (tnum=0; tnum < nthreads; tnum++)
+ 		{
+ 			for (n=0; n < PERSECOND_NUMSECONDS; n++)
+ 			{
+ 				if (lastsecond < n && persecond[tnum][n])
+ 				{
+ 					lastsecond = n;
+ 				}
+ 			}
+ 		}
+ 		for (n=0; n < lastsecond; n++)
+ 		{
+ 			printf("%lu", persecondstart+n);
+ 			for (tnum=0; tnum < nthreads; tnum++)
+ 			{
+ 				printf(",%i", persecond[tnum][n]);
+ 			}
+ 			printf("\n");
+ 		}
+ 	}
  }
  
  
*************** main(int argc, char **argv)
*** 1868,1875 ****
--- 1970,1980 ----
  	int			total_xacts;
  
  	int			i;
+ 	FILE		*urandomfd;
  
  	static struct option long_options[] = {
+ 		{"urandom", no_argument, &use_urandom, 1},
+ 		{"per-second", required_argument, NULL, 4},
  		{"index-tablespace", required_argument, NULL, 3},
  		{"tablespace", required_argument, NULL, 2},
  		{"unlogged-tables", no_argument, &unlogged_tables, 1},
*************** main(int argc, char **argv)
*** 1919,1925 ****
  	state = (CState *) xmalloc(sizeof(CState));
  	memset(state, 0, sizeof(CState));
  
! 	while ((c = getopt_long(argc, argv, "ih:nvp:dSNc:j:Crs:t:T:U:lf:D:F:M:", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 2024,2030 ----
  	state = (CState *) xmalloc(sizeof(CState));
  	memset(state, 0, sizeof(CState));
  
! 	while ((c = getopt_long(argc, argv, "ih:nvp:dSNc:j:Crs:t:T:U:lf:D:F:M:P:Ix:f", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 2071,2076 ****
--- 2176,2187 ----
  					exit(1);
  				}
  				break;
+ 			case 'P':
+ 				password = optarg;
+ 				break;
+ 			case 'I':
+ 				proceed_on_error = 1;
+ 				break;
  			case 0:
  				/* This covers long options which take no argument. */
  				break;
*************** main(int argc, char **argv)
*** 2080,2085 ****
--- 2191,2199 ----
  			case 3:				/* index-tablespace */
  				index_tablespace = optarg;
  				break;
+ 			case 4:				/* per-second */
+ 				persecondbatchsize = atoi(optarg);
+ 				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  				exit(1);
*************** main(int argc, char **argv)
*** 2116,2132 ****
  	}
  
  	/*
! 	 * is_latencies only works with multiple threads in thread-based
! 	 * implementations, not fork-based ones, because it supposes that the
  	 * parent can see changes made to the per-thread execution stats by child
  	 * threads.  It seems useful enough to accept despite this limitation, but
  	 * perhaps we should FIXME someday (by passing the stats data back up
  	 * through the parent-to-child pipes).
  	 */
  #ifndef ENABLE_THREAD_SAFETY
! 	if (is_latencies && nthreads > 1)
  	{
! 		fprintf(stderr, "-r does not work with -j larger than 1 on this platform.\n");
  		exit(1);
  	}
  #endif
--- 2230,2247 ----
  	}
  
  	/*
! 	 * is_latencies and per second reporting only work
! 	 * with multiple threads in thread-based
! 	 * implementations, not fork-based ones, because they suppose that the
  	 * parent can see changes made to the per-thread execution stats by child
  	 * threads.  It seems useful enough to accept despite this limitation, but
  	 * perhaps we should FIXME someday (by passing the stats data back up
  	 * through the parent-to-child pipes).
  	 */
  #ifndef ENABLE_THREAD_SAFETY
! 	if ((is_latencies && nthreads > 1) || (persecondbatchsize && nthreads >1))
  	{
! 		fprintf(stderr, "-r and --per-second do not work with -j larger than 1 on this platform.\n");
  		exit(1);
  	}
  #endif
*************** main(int argc, char **argv)
*** 2271,2279 ****
  		thread->tid = i;
  		thread->state = &state[nclients / nthreads * i];
  		thread->nstate = nclients / nthreads;
! 		thread->random_state[0] = random();
! 		thread->random_state[1] = random();
! 		thread->random_state[2] = random();
  
  		if (is_latencies)
  		{
--- 2386,2411 ----
  		thread->tid = i;
  		thread->state = &state[nclients / nthreads * i];
  		thread->nstate = nclients / nthreads;
! 		if (use_urandom==0)
! 		{
! 			thread->random_state[0] = random();
! 			thread->random_state[1] = random();
! 			thread->random_state[2] = random();
! 		}
! 		else
! 		{
! 			urandomfd = fopen("/dev/urandom", "r");
! 			if (urandomfd == NULL)
! 			{
! 				fprintf(stderr, "could not open /dev/urandom: %s\n", strerror(errno));
! 				exit(1);
! 			}
! 			if (fread(thread->random_state, sizeof(unsigned short), 3, urandomfd)==-1)
! 			{
! 				fprintf(stderr, "couldn't read from /dev/urandom: %s\n", strerror(errno));
! 				exit(1);
! 			}
! 		}
  
  		if (is_latencies)
  		{
*************** main(int argc, char **argv)
*** 2305,2310 ****
--- 2437,2469 ----
  	if (duration > 0)
  		setalarm(duration);
  
+ 	if (persecondbatchsize)
+ 	{
+ 		int n;
+ 		persecond = malloc(nthreads * sizeof(int *));
+ 		if (!persecond)
+ 		{
+ 			fprintf(stderr, "out of memory for persecond report\n");
+ 			exit(1);
+ 		}
+ 		for (n=0; n < nthreads; n++)
+ 		{
+ 			persecond[n] = (int *)calloc(PERSECOND_NUMSECONDS, sizeof(int));
+ 			if (!persecond[n])
+ 			{
+ 				fprintf(stderr, "out of memory for persecond report\n");
+ 				exit(1);
+ 			}
+ 		}
+ 		persecondtally = calloc(nthreads, sizeof(int));
+ 		if (!persecondtally)
+ 		{
+ 			fprintf(stderr, "out of memory for persecondtally\n");
+ 			exit(1);
+ 		}
+                 persecondstart = INSTR_TIME_GET_MICROSEC(start_time) / 1000000;
+ 	}
+ 
  	/* start threads */
  	for (i = 0; i < nthreads; i++)
  	{
