diff -cprN head/contrib/pgbench/pgbench.c work/contrib/pgbench/pgbench.c
*** head/contrib/pgbench/pgbench.c	2010-02-26 11:29:55.507518000 +0900
--- work/contrib/pgbench/pgbench.c	2010-03-16 11:48:29.572863239 +0900
*************** int			fillfactor = 100;
*** 131,141 ****
  #define ntellers	10
  #define naccounts	100000
  
- FILE	   *LOGFILE = NULL;
- 
  bool		use_log;			/* log transaction latencies to a file */
! 
! int			is_connect;			/* establish connection for each transaction */
  
  char	   *pghost = "";
  char	   *pgport = "";
--- 131,139 ----
  #define ntellers	10
  #define naccounts	100000
  
  bool		use_log;			/* log transaction latencies to a file */
! bool		is_connect;			/* establish connection for each transaction */
! int			main_pid;			/* main process id used in log filename */
  
  char	   *pghost = "";
  char	   *pgport = "";
*************** typedef struct
*** 183,188 ****
--- 181,187 ----
   */
  typedef struct
  {
+ 	int			tid;			/* thread id */
  	pthread_t	thread;			/* thread handle */
  	CState	   *state;			/* array of CState */
  	int			nstate;			/* length of state[] */
*************** clientDone(CState *st, bool ok)
*** 741,747 ****
  
  /* return false iff client should be disconnected */
  static bool
! doCustom(CState *st, instr_time *conn_time)
  {
  	PGresult   *res;
  	Command   **commands;
--- 740,746 ----
  
  /* return false iff client should be disconnected */
  static bool
! doCustom(CState *st, instr_time *conn_time, FILE *log_file)
  {
  	PGresult   *res;
  	Command   **commands;
*************** top:
*** 778,784 ****
  		/*
  		 * transaction finished: record the time it took in the log
  		 */
! 		if (use_log && commands[st->state + 1] == NULL)
  		{
  			instr_time	now;
  			instr_time	diff;
--- 777,783 ----
  		/*
  		 * transaction finished: record the time it took in the log
  		 */
! 		if (log_file && commands[st->state + 1] == NULL)
  		{
  			instr_time	now;
  			instr_time	diff;
*************** top:
*** 791,802 ****
  
  #ifndef WIN32
  			/* This is more than we really ought to know about instr_time */
! 			fprintf(LOGFILE, "%d %d %.0f %d %ld %ld\n",
  					st->id, st->cnt, usec, st->use_file,
  					(long) now.tv_sec, (long) now.tv_usec);
  #else
  			/* On Windows, instr_time doesn't provide a timestamp anyway */
! 			fprintf(LOGFILE, "%d %d %.0f %d 0 0\n",
  					st->id, st->cnt, usec, st->use_file);
  #endif
  		}
--- 790,801 ----
  
  #ifndef WIN32
  			/* This is more than we really ought to know about instr_time */
! 			fprintf(log_file, "%d %d %.0f %d %ld %ld\n",
  					st->id, st->cnt, usec, st->use_file,
  					(long) now.tv_sec, (long) now.tv_usec);
  #else
  			/* On Windows, instr_time doesn't provide a timestamp anyway */
! 			fprintf(log_file, "%d %d %.0f %d 0 0\n",
  					st->id, st->cnt, usec, st->use_file);
  #endif
  		}
*************** top:
*** 857,863 ****
  		INSTR_TIME_ACCUM_DIFF(*conn_time, end, start);
  	}
  
! 	if (use_log && st->state == 0)
  		INSTR_TIME_SET_CURRENT(st->txn_begin);
  
  	if (commands[st->state]->type == SQL_COMMAND)
--- 856,862 ----
  		INSTR_TIME_ACCUM_DIFF(*conn_time, end, start);
  	}
  
! 	if (log_file && st->state == 0)
  		INSTR_TIME_SET_CURRENT(st->txn_begin);
  
  	if (commands[st->state]->type == SQL_COMMAND)
*************** main(int argc, char **argv)
*** 1833,1839 ****
  				}
  				break;
  			case 'C':
! 				is_connect = 1;
  				break;
  			case 's':
  				scale_given = true;
--- 1832,1838 ----
  				}
  				break;
  			case 'C':
! 				is_connect = true;
  				break;
  			case 's':
  				scale_given = true;
*************** main(int argc, char **argv)
*** 1955,1960 ****
--- 1954,1965 ----
  		exit(1);
  	}
  
+ 	/*
+ 	 * save main process id in the global variable because process id will be
+ 	 * changed after fork.
+ 	 */
+ 	main_pid = (int) getpid();
+ 
  	if (nclients > 1)
  	{
  		state = (CState *) realloc(state, sizeof(CState) * nclients);
*************** main(int argc, char **argv)
*** 1980,1999 ****
  		}
  	}
  
- 	if (use_log)
- 	{
- 		char		logpath[64];
- 
- 		snprintf(logpath, 64, "pgbench_log.%d", (int) getpid());
- 		LOGFILE = fopen(logpath, "w");
- 
- 		if (LOGFILE == NULL)
- 		{
- 			fprintf(stderr, "Couldn't open logfile \"%s\": %s", logpath, strerror(errno));
- 			exit(1);
- 		}
- 	}
- 
  	if (debug)
  	{
  		if (duration <= 0)
--- 1985,1990 ----
*************** main(int argc, char **argv)
*** 2111,2116 ****
--- 2102,2108 ----
  	threads = (TState *) malloc(sizeof(TState) * nthreads);
  	for (i = 0; i < nthreads; i++)
  	{
+ 		threads[i].tid = i;
  		threads[i].state = &state[nclients / nthreads * i];
  		threads[i].nstate = nclients / nthreads;
  		INSTR_TIME_SET_CURRENT(threads[i].start_time);
*************** main(int argc, char **argv)
*** 2159,2166 ****
  	INSTR_TIME_SET_CURRENT(total_time);
  	INSTR_TIME_SUBTRACT(total_time, start_time);
  	printResults(ttype, total_xacts, nclients, nthreads, total_time, conn_total_time);
- 	if (LOGFILE)
- 		fclose(LOGFILE);
  
  	return 0;
  }
--- 2151,2156 ----
*************** threadRun(void *arg)
*** 2171,2176 ****
--- 2161,2167 ----
  	TState	   *thread = (TState *) arg;
  	CState	   *state = thread->state;
  	TResult    *result;
+ 	FILE	   *log_file = NULL;		/* per-thread log file */
  	instr_time	start,
  				end;
  	int			nstate = thread->nstate;
*************** threadRun(void *arg)
*** 2180,2186 ****
  	result = malloc(sizeof(TResult));
  	INSTR_TIME_SET_ZERO(result->conn_time);
  
! 	if (is_connect == 0)
  	{
  		/* make connections to the database */
  		for (i = 0; i < nstate; i++)
--- 2171,2195 ----
  	result = malloc(sizeof(TResult));
  	INSTR_TIME_SET_ZERO(result->conn_time);
  
! 	/* open log file if requested */
! 	if (use_log)
! 	{
! 		char		logpath[64];
! 
! 		if (thread->tid == 0)
! 			snprintf(logpath, 64, "pgbench_log.%d", main_pid);
! 		else
! 			snprintf(logpath, 64, "pgbench_log.%d.%d", main_pid, thread->tid);
! 		log_file = fopen(logpath, "w");
! 
! 		if (log_file == NULL)
! 		{
! 			fprintf(stderr, "Couldn't open logfile \"%s\": %s", logpath, strerror(errno));
! 			goto done;
! 		}
! 	}
! 
! 	if (!is_connect)
  	{
  		/* make connections to the database */
  		for (i = 0; i < nstate; i++)
*************** threadRun(void *arg)
*** 2202,2208 ****
  		int			prev_ecnt = st->ecnt;
  
  		st->use_file = getrand(0, num_files - 1);
! 		if (!doCustom(st, &result->conn_time))
  			remains--;			/* I've aborted */
  
  		if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
--- 2211,2217 ----
  		int			prev_ecnt = st->ecnt;
  
  		st->use_file = getrand(0, num_files - 1);
! 		if (!doCustom(st, &result->conn_time, log_file))
  			remains--;			/* I've aborted */
  
  		if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
*************** threadRun(void *arg)
*** 2304,2310 ****
  			if (st->con && (FD_ISSET(PQsocket(st->con), &input_mask)
  							|| commands[st->state]->type == META_COMMAND))
  			{
! 				if (!doCustom(st, &result->conn_time))
  					remains--;	/* I've aborted */
  			}
  
--- 2313,2319 ----
  			if (st->con && (FD_ISSET(PQsocket(st->con), &input_mask)
  							|| commands[st->state]->type == META_COMMAND))
  			{
! 				if (!doCustom(st, &result->conn_time, log_file))
  					remains--;	/* I've aborted */
  			}
  
*************** done:
*** 2326,2331 ****
--- 2335,2342 ----
  		result->xacts += state[i].cnt;
  	INSTR_TIME_SET_CURRENT(end);
  	INSTR_TIME_ACCUM_DIFF(result->conn_time, end, start);
+ 	if (log_file)
+ 		fclose(log_file);
  	return result;
  }
  
diff -cprN head/doc/src/sgml/pgbench.sgml work/doc/src/sgml/pgbench.sgml
*** head/doc/src/sgml/pgbench.sgml	2009-12-16 09:17:22.613136000 +0900
--- work/doc/src/sgml/pgbench.sgml	2010-03-16 11:59:11.389926000 +0900
*************** END;
*** 551,556 ****
--- 551,564 ----
     taken by each transaction to a logfile.  The logfile will be named
     <filename>pgbench_log.<replaceable>nnn</></filename>, where
     <replaceable>nnn</> is the PID of the pgbench process.
+    If <literal>-j</> option is 2 or higher, each worker threads use a
+    dedicated log file. Those log files except the first thread will be named
+    <filename>pgbench_log.<replaceable>nnn</>.<replaceable>mmm</></filename>,
+    where <replaceable>mmm</> is a sequential number of the threads starting
+    with 1.
+   </para>
+ 
+   <para>
     The format of the log is:
  
     <programlisting>
