--- postgresql-8.4.0.orig/contrib/pgbench/pgbench.c 2009-06-11 23:48:51.000000000 +0900 +++ postgresql-8.4.0/contrib/pgbench/pgbench.c 2009-08-06 10:03:42.000000000 +0900 @@ -31,6 +31,7 @@ #include "libpq-fe.h" #include "pqsignal.h" +#include #include #ifdef WIN32 @@ -120,6 +121,7 @@ typedef struct } Variable; #define MAX_FILES 128 /* max number of SQL script files allowed */ +#define SHELL_COMMAND_SIZE 256 /* maximum size allowed for shell command */ /* * structures used in custom query mode @@ -189,6 +191,29 @@ static char *tpc_b = { "END;\n" }; +/* -P case */ +static char *tpc_pcase = { + "\\set nbranches :scale\n" + "\\set ntellers 10 * :scale\n" + "\\set naccounts 100000 * :scale\n" + "\\setrandom aid 1 :naccounts\n" + "\\setrandom bid 1 :nbranches\n" + "\\setrandom tid 1 :ntellers\n" + "\\setrandom delta -5000 5000\n" + "\\setrandom txidrand 0 10000\n" + "START TRANSACTION;\n" + "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n" + "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n" + "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n" + "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n" + "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n" + "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n" + "PREPARE TRANSACTION ':txidrand';\n" + "\\shell ls -ll >> /tmp/log_data`date '+%Y%m%d'`_`date '+%k%M'`\n" + "COMMIT PREPARED ':txidrand';\n" +}; + + /* -N case */ static char *simple_update = { "\\set nbranches :scale\n" @@ -272,6 +297,7 @@ usage(const char *progname) " protocol for submitting queries to server (default: simple)\n" " -n do not run VACUUM before tests\n" " -N do not update tables \"pgbench_tellers\" and \"pgbench_branches\"\n" + " -P run 2PC transactions with random prepared TXID" " -s NUM report this scale factor in output\n" " -S perform SELECT-only transactions\n" " -t NUM number of transactions each client runs (default: 10)\n" @@ -984,6 +1010,40 @@ top: st->listen = 1; } + else if (pg_strcasecmp(argv[0], "shell") == 0) + { + int j, + retval, + retvalglob; + char commandLoc[SHELL_COMMAND_SIZE]; + + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s",argv[1]); + if (retval < 0 + || retval > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error launching shell command: too many characters\n"); + return; + } + retvalglob = retval; + + for (j = 2; j < argc; j++) + { + char *commandLoc2 = strdup(commandLoc); + + retval = snprintf(commandLoc,SHELL_COMMAND_SIZE-1,"%s %s", commandLoc2, argv[j]); + retvalglob += retval; + if (retval < 0 + || retvalglob > SHELL_COMMAND_SIZE-1) + { + fprintf(stderr, "Error launching shell command: too many characters\n"); + free(commandLoc2); + return; + } + free(commandLoc2); + } + system(commandLoc); + st->listen = 1; + } goto top; } @@ -1280,6 +1340,14 @@ process_commands(char *buf) fprintf(stderr, "%s: extra argument \"%s\" ignored\n", my_commands->argv[0], my_commands->argv[j]); } + else if (pg_strcasecmp(my_commands->argv[0], "shell") == 0) + { + if (my_commands->argc < 1) + { + fprintf(stderr, "%s: missing command\n", my_commands->argv[0]); + return NULL; + } + } else { fprintf(stderr, "Invalid command %s\n", my_commands->argv[0]); @@ -1472,6 +1540,8 @@ printResults( if (ttype == 0) s = "TPC-B (sort of)"; + else if (ttype == 4) + s = "2PC requests"; else if (ttype == 2) s = "Update only pgbench_accounts"; else if (ttype == 1) @@ -1576,7 +1646,7 @@ main(int argc, char **argv) memset(state, 0, sizeof(*state)); - while ((c = getopt(argc, argv, "ih:nvp:dSNc:Cs:t:T:U:lf:D:F:M:")) != -1) + while ((c = getopt(argc, argv, "ih:nvp:dSNPc:Cs:t:T:U:lf:D:F:M:")) != -1) { switch (c) { @@ -1604,6 +1674,9 @@ main(int argc, char **argv) case 'N': ttype = 2; break; + case 'P': + ttype = 4; + break; case 'c': nclients = atoi(optarg); if (nclients <= 0 || nclients > MAXCLIENTS) @@ -1922,6 +1995,11 @@ main(int argc, char **argv) num_files = 1; break; + case 4: + num_files = 1; + sql_files[0] = process_builtin(tpc_pcase); + break; + default: break; }