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 pgbench_log.nnn, where nnn is the PID of the pgbench process. + If -j option is 2 or higher, each worker threads use a + dedicated log file. Those log files except the first thread will be named + pgbench_log.nnn.mmm, + where mmm is a sequential number of the threads starting + with 1. + + + The format of the log is: