PageRenderTime 73ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/src/bin/pgbench/pgbench.c

https://bitbucket.org/adunstan/pgdevel
C | 6094 lines | 4299 code | 787 blank | 1008 comment | 1030 complexity | 582d1a68b5374ea7045beecb09405bd8 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * pgbench.c
  3. *
  4. * A simple benchmark program for PostgreSQL
  5. * Originally written by Tatsuo Ishii and enhanced by many contributors.
  6. *
  7. * src/bin/pgbench/pgbench.c
  8. * Copyright (c) 2000-2018, PostgreSQL Global Development Group
  9. * ALL RIGHTS RESERVED;
  10. *
  11. * Permission to use, copy, modify, and distribute this software and its
  12. * documentation for any purpose, without fee, and without a written agreement
  13. * is hereby granted, provided that the above copyright notice and this
  14. * paragraph and the following two paragraphs appear in all copies.
  15. *
  16. * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
  17. * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
  18. * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
  19. * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
  20. * POSSIBILITY OF SUCH DAMAGE.
  21. *
  22. * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  23. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24. * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  25. * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
  26. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  27. *
  28. */
  29. #ifdef WIN32
  30. #define FD_SETSIZE 1024 /* set before winsock2.h is included */
  31. #endif /* ! WIN32 */
  32. #include "postgres_fe.h"
  33. #include "fe_utils/conditional.h"
  34. #include "getopt_long.h"
  35. #include "libpq-fe.h"
  36. #include "portability/instr_time.h"
  37. #include <ctype.h>
  38. #include <float.h>
  39. #include <limits.h>
  40. #include <math.h>
  41. #include <signal.h>
  42. #include <time.h>
  43. #include <sys/time.h>
  44. #ifdef HAVE_SYS_SELECT_H
  45. #include <sys/select.h>
  46. #endif
  47. #ifdef HAVE_SYS_RESOURCE_H
  48. #include <sys/resource.h> /* for getrlimit */
  49. #endif
  50. #ifndef M_PI
  51. #define M_PI 3.14159265358979323846
  52. #endif
  53. #include "pgbench.h"
  54. #define ERRCODE_UNDEFINED_TABLE "42P01"
  55. /*
  56. * Hashing constants
  57. */
  58. #define FNV_PRIME UINT64CONST(0x100000001b3)
  59. #define FNV_OFFSET_BASIS UINT64CONST(0xcbf29ce484222325)
  60. #define MM2_MUL UINT64CONST(0xc6a4a7935bd1e995)
  61. #define MM2_MUL_TIMES_8 UINT64CONST(0x35253c9ade8f4ca8)
  62. #define MM2_ROT 47
  63. /*
  64. * Multi-platform pthread implementations
  65. */
  66. #ifdef WIN32
  67. /* Use native win32 threads on Windows */
  68. typedef struct win32_pthread *pthread_t;
  69. typedef int pthread_attr_t;
  70. static int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
  71. static int pthread_join(pthread_t th, void **thread_return);
  72. #elif defined(ENABLE_THREAD_SAFETY)
  73. /* Use platform-dependent pthread capability */
  74. #include <pthread.h>
  75. #else
  76. /* No threads implementation, use none (-j 1) */
  77. #define pthread_t void *
  78. #endif
  79. /********************************************************************
  80. * some configurable parameters */
  81. /* max number of clients allowed */
  82. #ifdef FD_SETSIZE
  83. #define MAXCLIENTS (FD_SETSIZE - 10)
  84. #else
  85. #define MAXCLIENTS 1024
  86. #endif
  87. #define DEFAULT_INIT_STEPS "dtgvp" /* default -I setting */
  88. #define LOG_STEP_SECONDS 5 /* seconds between log messages */
  89. #define DEFAULT_NXACTS 10 /* default nxacts */
  90. #define ZIPF_CACHE_SIZE 15 /* cache cells number */
  91. #define MIN_GAUSSIAN_PARAM 2.0 /* minimum parameter for gauss */
  92. #define MAX_ZIPFIAN_PARAM 1000 /* maximum parameter for zipfian */
  93. int nxacts = 0; /* number of transactions per client */
  94. int duration = 0; /* duration in seconds */
  95. int64 end_time = 0; /* when to stop in micro seconds, under -T */
  96. /*
  97. * scaling factor. for example, scale = 10 will make 1000000 tuples in
  98. * pgbench_accounts table.
  99. */
  100. int scale = 1;
  101. /*
  102. * fillfactor. for example, fillfactor = 90 will use only 90 percent
  103. * space during inserts and leave 10 percent free.
  104. */
  105. int fillfactor = 100;
  106. /*
  107. * use unlogged tables?
  108. */
  109. bool unlogged_tables = false;
  110. /*
  111. * log sampling rate (1.0 = log everything, 0.0 = option not given)
  112. */
  113. double sample_rate = 0.0;
  114. /*
  115. * When threads are throttled to a given rate limit, this is the target delay
  116. * to reach that rate in usec. 0 is the default and means no throttling.
  117. */
  118. int64 throttle_delay = 0;
  119. /*
  120. * Transactions which take longer than this limit (in usec) are counted as
  121. * late, and reported as such, although they are completed anyway. When
  122. * throttling is enabled, execution time slots that are more than this late
  123. * are skipped altogether, and counted separately.
  124. */
  125. int64 latency_limit = 0;
  126. /*
  127. * tablespace selection
  128. */
  129. char *tablespace = NULL;
  130. char *index_tablespace = NULL;
  131. /* random seed used when calling srandom() */
  132. int64 random_seed = -1;
  133. /*
  134. * end of configurable parameters
  135. *********************************************************************/
  136. #define nbranches 1 /* Makes little sense to change this. Change
  137. * -s instead */
  138. #define ntellers 10
  139. #define naccounts 100000
  140. /*
  141. * The scale factor at/beyond which 32bit integers are incapable of storing
  142. * 64bit values.
  143. *
  144. * Although the actual threshold is 21474, we use 20000 because it is easier to
  145. * document and remember, and isn't that far away from the real threshold.
  146. */
  147. #define SCALE_32BIT_THRESHOLD 20000
  148. bool use_log; /* log transaction latencies to a file */
  149. bool use_quiet; /* quiet logging onto stderr */
  150. int agg_interval; /* log aggregates instead of individual
  151. * transactions */
  152. bool per_script_stats = false; /* whether to collect stats per script */
  153. int progress = 0; /* thread progress report every this seconds */
  154. bool progress_timestamp = false; /* progress report with Unix time */
  155. int nclients = 1; /* number of clients */
  156. int nthreads = 1; /* number of threads */
  157. bool is_connect; /* establish connection for each transaction */
  158. bool is_latencies; /* report per-command latencies */
  159. int main_pid; /* main process id used in log filename */
  160. char *pghost = "";
  161. char *pgport = "";
  162. char *login = NULL;
  163. char *dbName;
  164. char *logfile_prefix = NULL;
  165. const char *progname;
  166. #define WSEP '@' /* weight separator */
  167. volatile bool timer_exceeded = false; /* flag from signal handler */
  168. /*
  169. * Variable definitions.
  170. *
  171. * If a variable only has a string value, "svalue" is that value, and value is
  172. * "not set". If the value is known, "value" contains the value (in any
  173. * variant).
  174. *
  175. * In this case "svalue" contains the string equivalent of the value, if we've
  176. * had occasion to compute that, or NULL if we haven't.
  177. */
  178. typedef struct
  179. {
  180. char *name; /* variable's name */
  181. char *svalue; /* its value in string form, if known */
  182. PgBenchValue value; /* actual variable's value */
  183. } Variable;
  184. #define MAX_SCRIPTS 128 /* max number of SQL scripts allowed */
  185. #define SHELL_COMMAND_SIZE 256 /* maximum size allowed for shell command */
  186. /*
  187. * Simple data structure to keep stats about something.
  188. *
  189. * XXX probably the first value should be kept and used as an offset for
  190. * better numerical stability...
  191. */
  192. typedef struct SimpleStats
  193. {
  194. int64 count; /* how many values were encountered */
  195. double min; /* the minimum seen */
  196. double max; /* the maximum seen */
  197. double sum; /* sum of values */
  198. double sum2; /* sum of squared values */
  199. } SimpleStats;
  200. /*
  201. * Data structure to hold various statistics: per-thread and per-script stats
  202. * are maintained and merged together.
  203. */
  204. typedef struct StatsData
  205. {
  206. time_t start_time; /* interval start time, for aggregates */
  207. int64 cnt; /* number of transactions, including skipped */
  208. int64 skipped; /* number of transactions skipped under --rate
  209. * and --latency-limit */
  210. SimpleStats latency;
  211. SimpleStats lag;
  212. } StatsData;
  213. /*
  214. * Connection state machine states.
  215. */
  216. typedef enum
  217. {
  218. /*
  219. * The client must first choose a script to execute. Once chosen, it can
  220. * either be throttled (state CSTATE_START_THROTTLE under --rate) or start
  221. * right away (state CSTATE_START_TX).
  222. */
  223. CSTATE_CHOOSE_SCRIPT,
  224. /*
  225. * In CSTATE_START_THROTTLE state, we calculate when to begin the next
  226. * transaction, and advance to CSTATE_THROTTLE. CSTATE_THROTTLE state
  227. * sleeps until that moment. (If throttling is not enabled, doCustom()
  228. * falls directly through from CSTATE_START_THROTTLE to CSTATE_START_TX.)
  229. */
  230. CSTATE_START_THROTTLE,
  231. CSTATE_THROTTLE,
  232. /*
  233. * CSTATE_START_TX performs start-of-transaction processing. Establishes
  234. * a new connection for the transaction, in --connect mode, and records
  235. * the transaction start time.
  236. */
  237. CSTATE_START_TX,
  238. /*
  239. * We loop through these states, to process each command in the script:
  240. *
  241. * CSTATE_START_COMMAND starts the execution of a command. On a SQL
  242. * command, the command is sent to the server, and we move to
  243. * CSTATE_WAIT_RESULT state. On a \sleep meta-command, the timer is set,
  244. * and we enter the CSTATE_SLEEP state to wait for it to expire. Other
  245. * meta-commands are executed immediately.
  246. *
  247. * CSTATE_SKIP_COMMAND for conditional branches which are not executed,
  248. * quickly skip commands that do not need any evaluation.
  249. *
  250. * CSTATE_WAIT_RESULT waits until we get a result set back from the server
  251. * for the current command.
  252. *
  253. * CSTATE_SLEEP waits until the end of \sleep.
  254. *
  255. * CSTATE_END_COMMAND records the end-of-command timestamp, increments the
  256. * command counter, and loops back to CSTATE_START_COMMAND state.
  257. */
  258. CSTATE_START_COMMAND,
  259. CSTATE_SKIP_COMMAND,
  260. CSTATE_WAIT_RESULT,
  261. CSTATE_SLEEP,
  262. CSTATE_END_COMMAND,
  263. /*
  264. * CSTATE_END_TX performs end-of-transaction processing. Calculates
  265. * latency, and logs the transaction. In --connect mode, closes the
  266. * current connection. Chooses the next script to execute and starts over
  267. * in CSTATE_START_THROTTLE state, or enters CSTATE_FINISHED if we have no
  268. * more work to do.
  269. */
  270. CSTATE_END_TX,
  271. /*
  272. * Final states. CSTATE_ABORTED means that the script execution was
  273. * aborted because a command failed, CSTATE_FINISHED means success.
  274. */
  275. CSTATE_ABORTED,
  276. CSTATE_FINISHED
  277. } ConnectionStateEnum;
  278. /*
  279. * Connection state.
  280. */
  281. typedef struct
  282. {
  283. PGconn *con; /* connection handle to DB */
  284. int id; /* client No. */
  285. ConnectionStateEnum state; /* state machine's current state. */
  286. ConditionalStack cstack; /* enclosing conditionals state */
  287. int use_file; /* index in sql_script for this client */
  288. int command; /* command number in script */
  289. /* client variables */
  290. Variable *variables; /* array of variable definitions */
  291. int nvariables; /* number of variables */
  292. bool vars_sorted; /* are variables sorted by name? */
  293. /* various times about current transaction */
  294. int64 txn_scheduled; /* scheduled start time of transaction (usec) */
  295. int64 sleep_until; /* scheduled start time of next cmd (usec) */
  296. instr_time txn_begin; /* used for measuring schedule lag times */
  297. instr_time stmt_begin; /* used for measuring statement latencies */
  298. bool prepared[MAX_SCRIPTS]; /* whether client prepared the script */
  299. /* per client collected stats */
  300. int64 cnt; /* client transaction count, for -t */
  301. int ecnt; /* error count */
  302. } CState;
  303. /*
  304. * Cache cell for zipfian_random call
  305. */
  306. typedef struct
  307. {
  308. /* cell keys */
  309. double s; /* s - parameter of zipfan_random function */
  310. int64 n; /* number of elements in range (max - min + 1) */
  311. double harmonicn; /* generalizedHarmonicNumber(n, s) */
  312. double alpha;
  313. double beta;
  314. double eta;
  315. uint64 last_used; /* last used logical time */
  316. } ZipfCell;
  317. /*
  318. * Zipf cache for zeta values
  319. */
  320. typedef struct
  321. {
  322. uint64 current; /* counter for LRU cache replacement algorithm */
  323. int nb_cells; /* number of filled cells */
  324. int overflowCount; /* number of cache overflows */
  325. ZipfCell cells[ZIPF_CACHE_SIZE];
  326. } ZipfCache;
  327. /*
  328. * Thread state
  329. */
  330. typedef struct
  331. {
  332. int tid; /* thread id */
  333. pthread_t thread; /* thread handle */
  334. CState *state; /* array of CState */
  335. int nstate; /* length of state[] */
  336. unsigned short random_state[3]; /* separate randomness for each thread */
  337. int64 throttle_trigger; /* previous/next throttling (us) */
  338. FILE *logfile; /* where to log, or NULL */
  339. ZipfCache zipf_cache; /* for thread-safe zipfian random number
  340. * generation */
  341. /* per thread collected stats */
  342. instr_time start_time; /* thread start time */
  343. instr_time conn_time;
  344. StatsData stats;
  345. int64 latency_late; /* executed but late transactions */
  346. } TState;
  347. #define INVALID_THREAD ((pthread_t) 0)
  348. /*
  349. * queries read from files
  350. */
  351. #define SQL_COMMAND 1
  352. #define META_COMMAND 2
  353. #define MAX_ARGS 10
  354. typedef enum MetaCommand
  355. {
  356. META_NONE, /* not a known meta-command */
  357. META_SET, /* \set */
  358. META_SETSHELL, /* \setshell */
  359. META_SHELL, /* \shell */
  360. META_SLEEP, /* \sleep */
  361. META_IF, /* \if */
  362. META_ELIF, /* \elif */
  363. META_ELSE, /* \else */
  364. META_ENDIF /* \endif */
  365. } MetaCommand;
  366. typedef enum QueryMode
  367. {
  368. QUERY_SIMPLE, /* simple query */
  369. QUERY_EXTENDED, /* extended query */
  370. QUERY_PREPARED, /* extended query with prepared statements */
  371. NUM_QUERYMODE
  372. } QueryMode;
  373. static QueryMode querymode = QUERY_SIMPLE;
  374. static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
  375. typedef struct
  376. {
  377. char *line; /* text of command line */
  378. int command_num; /* unique index of this Command struct */
  379. int type; /* command type (SQL_COMMAND or META_COMMAND) */
  380. MetaCommand meta; /* meta command identifier, or META_NONE */
  381. int argc; /* number of command words */
  382. char *argv[MAX_ARGS]; /* command word list */
  383. PgBenchExpr *expr; /* parsed expression, if needed */
  384. SimpleStats stats; /* time spent in this command */
  385. } Command;
  386. typedef struct ParsedScript
  387. {
  388. const char *desc; /* script descriptor (eg, file name) */
  389. int weight; /* selection weight */
  390. Command **commands; /* NULL-terminated array of Commands */
  391. StatsData stats; /* total time spent in script */
  392. } ParsedScript;
  393. static ParsedScript sql_script[MAX_SCRIPTS]; /* SQL script files */
  394. static int num_scripts; /* number of scripts in sql_script[] */
  395. static int num_commands = 0; /* total number of Command structs */
  396. static int64 total_weight = 0;
  397. static int debug = 0; /* debug flag */
  398. /* Builtin test scripts */
  399. typedef struct BuiltinScript
  400. {
  401. const char *name; /* very short name for -b ... */
  402. const char *desc; /* short description */
  403. const char *script; /* actual pgbench script */
  404. } BuiltinScript;
  405. static const BuiltinScript builtin_script[] =
  406. {
  407. {
  408. "tpcb-like",
  409. "<builtin: TPC-B (sort of)>",
  410. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  411. "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
  412. "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
  413. "\\set delta random(-5000, 5000)\n"
  414. "BEGIN;\n"
  415. "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
  416. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  417. "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
  418. "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
  419. "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
  420. "END;\n"
  421. },
  422. {
  423. "simple-update",
  424. "<builtin: simple update>",
  425. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  426. "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
  427. "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
  428. "\\set delta random(-5000, 5000)\n"
  429. "BEGIN;\n"
  430. "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
  431. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  432. "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
  433. "END;\n"
  434. },
  435. {
  436. "select-only",
  437. "<builtin: select only>",
  438. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  439. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  440. }
  441. };
  442. /* Function prototypes */
  443. static void setNullValue(PgBenchValue *pv);
  444. static void setBoolValue(PgBenchValue *pv, bool bval);
  445. static void setIntValue(PgBenchValue *pv, int64 ival);
  446. static void setDoubleValue(PgBenchValue *pv, double dval);
  447. static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *);
  448. static void doLog(TState *thread, CState *st,
  449. StatsData *agg, bool skipped, double latency, double lag);
  450. static void processXactStats(TState *thread, CState *st, instr_time *now,
  451. bool skipped, StatsData *agg);
  452. static void pgbench_error(const char *fmt,...) pg_attribute_printf(1, 2);
  453. static void addScript(ParsedScript script);
  454. static void *threadRun(void *arg);
  455. static void setalarm(int seconds);
  456. static void finishCon(CState *st);
  457. /* callback functions for our flex lexer */
  458. static const PsqlScanCallbacks pgbench_callbacks = {
  459. NULL, /* don't need get_variable functionality */
  460. pgbench_error
  461. };
  462. static void
  463. usage(void)
  464. {
  465. printf("%s is a benchmarking tool for PostgreSQL.\n\n"
  466. "Usage:\n"
  467. " %s [OPTION]... [DBNAME]\n"
  468. "\nInitialization options:\n"
  469. " -i, --initialize invokes initialization mode\n"
  470. " -I, --init-steps=[dtgvpf]+ (default \"dtgvp\")\n"
  471. " run selected initialization steps\n"
  472. " -F, --fillfactor=NUM set fill factor\n"
  473. " -n, --no-vacuum do not run VACUUM during initialization\n"
  474. " -q, --quiet quiet logging (one message each 5 seconds)\n"
  475. " -s, --scale=NUM scaling factor\n"
  476. " --foreign-keys create foreign key constraints between tables\n"
  477. " --index-tablespace=TABLESPACE\n"
  478. " create indexes in the specified tablespace\n"
  479. " --tablespace=TABLESPACE create tables in the specified tablespace\n"
  480. " --unlogged-tables create tables as unlogged tables\n"
  481. "\nOptions to select what to run:\n"
  482. " -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
  483. " (use \"-b list\" to list available scripts)\n"
  484. " -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
  485. " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
  486. " (same as \"-b simple-update\")\n"
  487. " -S, --select-only perform SELECT-only transactions\n"
  488. " (same as \"-b select-only\")\n"
  489. "\nBenchmarking options:\n"
  490. " -c, --client=NUM number of concurrent database clients (default: 1)\n"
  491. " -C, --connect establish new connection for each transaction\n"
  492. " -D, --define=VARNAME=VALUE\n"
  493. " define variable for use by custom script\n"
  494. " -j, --jobs=NUM number of threads (default: 1)\n"
  495. " -l, --log write transaction times to log file\n"
  496. " -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
  497. " -M, --protocol=simple|extended|prepared\n"
  498. " protocol for submitting queries (default: simple)\n"
  499. " -n, --no-vacuum do not run VACUUM before tests\n"
  500. " -P, --progress=NUM show thread progress report every NUM seconds\n"
  501. " -r, --report-latencies report average latency per command\n"
  502. " -R, --rate=NUM target rate in transactions per second\n"
  503. " -s, --scale=NUM report this scale factor in output\n"
  504. " -t, --transactions=NUM number of transactions each client runs (default: 10)\n"
  505. " -T, --time=NUM duration of benchmark test in seconds\n"
  506. " -v, --vacuum-all vacuum all four standard tables before tests\n"
  507. " --aggregate-interval=NUM aggregate data over NUM seconds\n"
  508. " --log-prefix=PREFIX prefix for transaction time log file\n"
  509. " (default: \"pgbench_log\")\n"
  510. " --progress-timestamp use Unix epoch timestamps for progress\n"
  511. " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
  512. " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
  513. "\nCommon options:\n"
  514. " -d, --debug print debugging output\n"
  515. " -h, --host=HOSTNAME database server host or socket directory\n"
  516. " -p, --port=PORT database server port number\n"
  517. " -U, --username=USERNAME connect as specified database user\n"
  518. " -V, --version output version information, then exit\n"
  519. " -?, --help show this help, then exit\n"
  520. "\n"
  521. "Report bugs to <pgsql-bugs@postgresql.org>.\n",
  522. progname, progname);
  523. }
  524. /* return whether str matches "^\s*[-+]?[0-9]+$" */
  525. static bool
  526. is_an_int(const char *str)
  527. {
  528. const char *ptr = str;
  529. /* skip leading spaces; cast is consistent with strtoint64 */
  530. while (*ptr && isspace((unsigned char) *ptr))
  531. ptr++;
  532. /* skip sign */
  533. if (*ptr == '+' || *ptr == '-')
  534. ptr++;
  535. /* at least one digit */
  536. if (*ptr && !isdigit((unsigned char) *ptr))
  537. return false;
  538. /* eat all digits */
  539. while (*ptr && isdigit((unsigned char) *ptr))
  540. ptr++;
  541. /* must have reached end of string */
  542. return *ptr == '\0';
  543. }
  544. /*
  545. * strtoint64 -- convert a string to 64-bit integer
  546. *
  547. * This function is a modified version of scanint8() from
  548. * src/backend/utils/adt/int8.c.
  549. */
  550. int64
  551. strtoint64(const char *str)
  552. {
  553. const char *ptr = str;
  554. int64 result = 0;
  555. int sign = 1;
  556. /*
  557. * Do our own scan, rather than relying on sscanf which might be broken
  558. * for long long.
  559. */
  560. /* skip leading spaces */
  561. while (*ptr && isspace((unsigned char) *ptr))
  562. ptr++;
  563. /* handle sign */
  564. if (*ptr == '-')
  565. {
  566. ptr++;
  567. /*
  568. * Do an explicit check for INT64_MIN. Ugly though this is, it's
  569. * cleaner than trying to get the loop below to handle it portably.
  570. */
  571. if (strncmp(ptr, "9223372036854775808", 19) == 0)
  572. {
  573. result = PG_INT64_MIN;
  574. ptr += 19;
  575. goto gotdigits;
  576. }
  577. sign = -1;
  578. }
  579. else if (*ptr == '+')
  580. ptr++;
  581. /* require at least one digit */
  582. if (!isdigit((unsigned char) *ptr))
  583. fprintf(stderr, "invalid input syntax for integer: \"%s\"\n", str);
  584. /* process digits */
  585. while (*ptr && isdigit((unsigned char) *ptr))
  586. {
  587. int64 tmp = result * 10 + (*ptr++ - '0');
  588. if ((tmp / 10) != result) /* overflow? */
  589. fprintf(stderr, "value \"%s\" is out of range for type bigint\n", str);
  590. result = tmp;
  591. }
  592. gotdigits:
  593. /* allow trailing whitespace, but not other trailing chars */
  594. while (*ptr != '\0' && isspace((unsigned char) *ptr))
  595. ptr++;
  596. if (*ptr != '\0')
  597. fprintf(stderr, "invalid input syntax for integer: \"%s\"\n", str);
  598. return ((sign < 0) ? -result : result);
  599. }
  600. /* random number generator: uniform distribution from min to max inclusive */
  601. static int64
  602. getrand(TState *thread, int64 min, int64 max)
  603. {
  604. /*
  605. * Odd coding is so that min and max have approximately the same chance of
  606. * being selected as do numbers between them.
  607. *
  608. * pg_erand48() is thread-safe and concurrent, which is why we use it
  609. * rather than random(), which in glibc is non-reentrant, and therefore
  610. * protected by a mutex, and therefore a bottleneck on machines with many
  611. * CPUs.
  612. */
  613. return min + (int64) ((max - min + 1) * pg_erand48(thread->random_state));
  614. }
  615. /*
  616. * random number generator: exponential distribution from min to max inclusive.
  617. * the parameter is so that the density of probability for the last cut-off max
  618. * value is exp(-parameter).
  619. */
  620. static int64
  621. getExponentialRand(TState *thread, int64 min, int64 max, double parameter)
  622. {
  623. double cut,
  624. uniform,
  625. rand;
  626. /* abort if wrong parameter, but must really be checked beforehand */
  627. Assert(parameter > 0.0);
  628. cut = exp(-parameter);
  629. /* erand in [0, 1), uniform in (0, 1] */
  630. uniform = 1.0 - pg_erand48(thread->random_state);
  631. /*
  632. * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
  633. */
  634. Assert((1.0 - cut) != 0.0);
  635. rand = -log(cut + (1.0 - cut) * uniform) / parameter;
  636. /* return int64 random number within between min and max */
  637. return min + (int64) ((max - min + 1) * rand);
  638. }
  639. /* random number generator: gaussian distribution from min to max inclusive */
  640. static int64
  641. getGaussianRand(TState *thread, int64 min, int64 max, double parameter)
  642. {
  643. double stdev;
  644. double rand;
  645. /* abort if parameter is too low, but must really be checked beforehand */
  646. Assert(parameter >= MIN_GAUSSIAN_PARAM);
  647. /*
  648. * Get user specified random number from this loop, with -parameter <
  649. * stdev <= parameter
  650. *
  651. * This loop is executed until the number is in the expected range.
  652. *
  653. * As the minimum parameter is 2.0, the probability of looping is low:
  654. * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
  655. * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
  656. * the worst case. For a parameter value of 5.0, the looping probability
  657. * is about e^{-5} * 2 / pi ~ 0.43%.
  658. */
  659. do
  660. {
  661. /*
  662. * pg_erand48 generates [0,1), but for the basic version of the
  663. * Box-Muller transform the two uniformly distributed random numbers
  664. * are expected in (0, 1] (see
  665. * http://en.wikipedia.org/wiki/Box_muller)
  666. */
  667. double rand1 = 1.0 - pg_erand48(thread->random_state);
  668. double rand2 = 1.0 - pg_erand48(thread->random_state);
  669. /* Box-Muller basic form transform */
  670. double var_sqrt = sqrt(-2.0 * log(rand1));
  671. stdev = var_sqrt * sin(2.0 * M_PI * rand2);
  672. /*
  673. * we may try with cos, but there may be a bias induced if the
  674. * previous value fails the test. To be on the safe side, let us try
  675. * over.
  676. */
  677. }
  678. while (stdev < -parameter || stdev >= parameter);
  679. /* stdev is in [-parameter, parameter), normalization to [0,1) */
  680. rand = (stdev + parameter) / (parameter * 2.0);
  681. /* return int64 random number within between min and max */
  682. return min + (int64) ((max - min + 1) * rand);
  683. }
  684. /*
  685. * random number generator: generate a value, such that the series of values
  686. * will approximate a Poisson distribution centered on the given value.
  687. */
  688. static int64
  689. getPoissonRand(TState *thread, int64 center)
  690. {
  691. /*
  692. * Use inverse transform sampling to generate a value > 0, such that the
  693. * expected (i.e. average) value is the given argument.
  694. */
  695. double uniform;
  696. /* erand in [0, 1), uniform in (0, 1] */
  697. uniform = 1.0 - pg_erand48(thread->random_state);
  698. return (int64) (-log(uniform) * ((double) center) + 0.5);
  699. }
  700. /* helper function for getZipfianRand */
  701. static double
  702. generalizedHarmonicNumber(int64 n, double s)
  703. {
  704. int i;
  705. double ans = 0.0;
  706. for (i = n; i > 1; i--)
  707. ans += pow(i, -s);
  708. return ans + 1.0;
  709. }
  710. /* set harmonicn and other parameters to cache cell */
  711. static void
  712. zipfSetCacheCell(ZipfCell *cell, int64 n, double s)
  713. {
  714. double harmonic2;
  715. cell->n = n;
  716. cell->s = s;
  717. harmonic2 = generalizedHarmonicNumber(2, s);
  718. cell->harmonicn = generalizedHarmonicNumber(n, s);
  719. cell->alpha = 1.0 / (1.0 - s);
  720. cell->beta = pow(0.5, s);
  721. cell->eta = (1.0 - pow(2.0 / n, 1.0 - s)) / (1.0 - harmonic2 / cell->harmonicn);
  722. }
  723. /*
  724. * search for cache cell with keys (n, s)
  725. * and create new cell if it does not exist
  726. */
  727. static ZipfCell *
  728. zipfFindOrCreateCacheCell(ZipfCache *cache, int64 n, double s)
  729. {
  730. int i,
  731. least_recently_used = 0;
  732. ZipfCell *cell;
  733. /* search cached cell for given parameters */
  734. for (i = 0; i < cache->nb_cells; i++)
  735. {
  736. cell = &cache->cells[i];
  737. if (cell->n == n && cell->s == s)
  738. return &cache->cells[i];
  739. if (cell->last_used < cache->cells[least_recently_used].last_used)
  740. least_recently_used = i;
  741. }
  742. /* create new one if it does not exist */
  743. if (cache->nb_cells < ZIPF_CACHE_SIZE)
  744. i = cache->nb_cells++;
  745. else
  746. {
  747. /* replace LRU cell if cache is full */
  748. i = least_recently_used;
  749. cache->overflowCount++;
  750. }
  751. zipfSetCacheCell(&cache->cells[i], n, s);
  752. cache->cells[i].last_used = cache->current++;
  753. return &cache->cells[i];
  754. }
  755. /*
  756. * Computing zipfian using rejection method, based on
  757. * "Non-Uniform Random Variate Generation",
  758. * Luc Devroye, p. 550-551, Springer 1986.
  759. */
  760. static int64
  761. computeIterativeZipfian(TState *thread, int64 n, double s)
  762. {
  763. double b = pow(2.0, s - 1.0);
  764. double x,
  765. t,
  766. u,
  767. v;
  768. while (true)
  769. {
  770. /* random variates */
  771. u = pg_erand48(thread->random_state);
  772. v = pg_erand48(thread->random_state);
  773. x = floor(pow(u, -1.0 / (s - 1.0)));
  774. t = pow(1.0 + 1.0 / x, s - 1.0);
  775. /* reject if too large or out of bound */
  776. if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
  777. break;
  778. }
  779. return (int64) x;
  780. }
  781. /*
  782. * Computing zipfian using harmonic numbers, based on algorithm described in
  783. * "Quickly Generating Billion-Record Synthetic Databases",
  784. * Jim Gray et al, SIGMOD 1994
  785. */
  786. static int64
  787. computeHarmonicZipfian(TState *thread, int64 n, double s)
  788. {
  789. ZipfCell *cell = zipfFindOrCreateCacheCell(&thread->zipf_cache, n, s);
  790. double uniform = pg_erand48(thread->random_state);
  791. double uz = uniform * cell->harmonicn;
  792. if (uz < 1.0)
  793. return 1;
  794. if (uz < 1.0 + cell->beta)
  795. return 2;
  796. return 1 + (int64) (cell->n * pow(cell->eta * uniform - cell->eta + 1.0, cell->alpha));
  797. }
  798. /* random number generator: zipfian distribution from min to max inclusive */
  799. static int64
  800. getZipfianRand(TState *thread, int64 min, int64 max, double s)
  801. {
  802. int64 n = max - min + 1;
  803. /* abort if parameter is invalid */
  804. Assert(s > 0.0 && s != 1.0 && s <= MAX_ZIPFIAN_PARAM);
  805. return min - 1 + ((s > 1)
  806. ? computeIterativeZipfian(thread, n, s)
  807. : computeHarmonicZipfian(thread, n, s));
  808. }
  809. /*
  810. * FNV-1a hash function
  811. */
  812. static int64
  813. getHashFnv1a(int64 val, uint64 seed)
  814. {
  815. int64 result;
  816. int i;
  817. result = FNV_OFFSET_BASIS ^ seed;
  818. for (i = 0; i < 8; ++i)
  819. {
  820. int32 octet = val & 0xff;
  821. val = val >> 8;
  822. result = result ^ octet;
  823. result = result * FNV_PRIME;
  824. }
  825. return result;
  826. }
  827. /*
  828. * Murmur2 hash function
  829. *
  830. * Based on original work of Austin Appleby
  831. * https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
  832. */
  833. static int64
  834. getHashMurmur2(int64 val, uint64 seed)
  835. {
  836. uint64 result = seed ^ MM2_MUL_TIMES_8; /* sizeof(int64) */
  837. uint64 k = (uint64) val;
  838. k *= MM2_MUL;
  839. k ^= k >> MM2_ROT;
  840. k *= MM2_MUL;
  841. result ^= k;
  842. result *= MM2_MUL;
  843. result ^= result >> MM2_ROT;
  844. result *= MM2_MUL;
  845. result ^= result >> MM2_ROT;
  846. return (int64) result;
  847. }
  848. /*
  849. * Initialize the given SimpleStats struct to all zeroes
  850. */
  851. static void
  852. initSimpleStats(SimpleStats *ss)
  853. {
  854. memset(ss, 0, sizeof(SimpleStats));
  855. }
  856. /*
  857. * Accumulate one value into a SimpleStats struct.
  858. */
  859. static void
  860. addToSimpleStats(SimpleStats *ss, double val)
  861. {
  862. if (ss->count == 0 || val < ss->min)
  863. ss->min = val;
  864. if (ss->count == 0 || val > ss->max)
  865. ss->max = val;
  866. ss->count++;
  867. ss->sum += val;
  868. ss->sum2 += val * val;
  869. }
  870. /*
  871. * Merge two SimpleStats objects
  872. */
  873. static void
  874. mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
  875. {
  876. if (acc->count == 0 || ss->min < acc->min)
  877. acc->min = ss->min;
  878. if (acc->count == 0 || ss->max > acc->max)
  879. acc->max = ss->max;
  880. acc->count += ss->count;
  881. acc->sum += ss->sum;
  882. acc->sum2 += ss->sum2;
  883. }
  884. /*
  885. * Initialize a StatsData struct to mostly zeroes, with its start time set to
  886. * the given value.
  887. */
  888. static void
  889. initStats(StatsData *sd, time_t start_time)
  890. {
  891. sd->start_time = start_time;
  892. sd->cnt = 0;
  893. sd->skipped = 0;
  894. initSimpleStats(&sd->latency);
  895. initSimpleStats(&sd->lag);
  896. }
  897. /*
  898. * Accumulate one additional item into the given stats object.
  899. */
  900. static void
  901. accumStats(StatsData *stats, bool skipped, double lat, double lag)
  902. {
  903. stats->cnt++;
  904. if (skipped)
  905. {
  906. /* no latency to record on skipped transactions */
  907. stats->skipped++;
  908. }
  909. else
  910. {
  911. addToSimpleStats(&stats->latency, lat);
  912. /* and possibly the same for schedule lag */
  913. if (throttle_delay)
  914. addToSimpleStats(&stats->lag, lag);
  915. }
  916. }
  917. /* call PQexec() and exit() on failure */
  918. static void
  919. executeStatement(PGconn *con, const char *sql)
  920. {
  921. PGresult *res;
  922. res = PQexec(con, sql);
  923. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  924. {
  925. fprintf(stderr, "%s", PQerrorMessage(con));
  926. exit(1);
  927. }
  928. PQclear(res);
  929. }
  930. /* call PQexec() and complain, but without exiting, on failure */
  931. static void
  932. tryExecuteStatement(PGconn *con, const char *sql)
  933. {
  934. PGresult *res;
  935. res = PQexec(con, sql);
  936. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  937. {
  938. fprintf(stderr, "%s", PQerrorMessage(con));
  939. fprintf(stderr, "(ignoring this error and continuing anyway)\n");
  940. }
  941. PQclear(res);
  942. }
  943. /* set up a connection to the backend */
  944. static PGconn *
  945. doConnect(void)
  946. {
  947. PGconn *conn;
  948. bool new_pass;
  949. static bool have_password = false;
  950. static char password[100];
  951. /*
  952. * Start the connection. Loop until we have a password if requested by
  953. * backend.
  954. */
  955. do
  956. {
  957. #define PARAMS_ARRAY_SIZE 7
  958. const char *keywords[PARAMS_ARRAY_SIZE];
  959. const char *values[PARAMS_ARRAY_SIZE];
  960. keywords[0] = "host";
  961. values[0] = pghost;
  962. keywords[1] = "port";
  963. values[1] = pgport;
  964. keywords[2] = "user";
  965. values[2] = login;
  966. keywords[3] = "password";
  967. values[3] = have_password ? password : NULL;
  968. keywords[4] = "dbname";
  969. values[4] = dbName;
  970. keywords[5] = "fallback_application_name";
  971. values[5] = progname;
  972. keywords[6] = NULL;
  973. values[6] = NULL;
  974. new_pass = false;
  975. conn = PQconnectdbParams(keywords, values, true);
  976. if (!conn)
  977. {
  978. fprintf(stderr, "connection to database \"%s\" failed\n",
  979. dbName);
  980. return NULL;
  981. }
  982. if (PQstatus(conn) == CONNECTION_BAD &&
  983. PQconnectionNeedsPassword(conn) &&
  984. !have_password)
  985. {
  986. PQfinish(conn);
  987. simple_prompt("Password: ", password, sizeof(password), false);
  988. have_password = true;
  989. new_pass = true;
  990. }
  991. } while (new_pass);
  992. /* check to see that the backend connection was successfully made */
  993. if (PQstatus(conn) == CONNECTION_BAD)
  994. {
  995. fprintf(stderr, "connection to database \"%s\" failed:\n%s",
  996. dbName, PQerrorMessage(conn));
  997. PQfinish(conn);
  998. return NULL;
  999. }
  1000. return conn;
  1001. }
  1002. /* throw away response from backend */
  1003. static void
  1004. discard_response(CState *state)
  1005. {
  1006. PGresult *res;
  1007. do
  1008. {
  1009. res = PQgetResult(state->con);
  1010. if (res)
  1011. PQclear(res);
  1012. } while (res);
  1013. }
  1014. /* qsort comparator for Variable array */
  1015. static int
  1016. compareVariableNames(const void *v1, const void *v2)
  1017. {
  1018. return strcmp(((const Variable *) v1)->name,
  1019. ((const Variable *) v2)->name);
  1020. }
  1021. /* Locate a variable by name; returns NULL if unknown */
  1022. static Variable *
  1023. lookupVariable(CState *st, char *name)
  1024. {
  1025. Variable key;
  1026. /* On some versions of Solaris, bsearch of zero items dumps core */
  1027. if (st->nvariables <= 0)
  1028. return NULL;
  1029. /* Sort if we have to */
  1030. if (!st->vars_sorted)
  1031. {
  1032. qsort((void *) st->variables, st->nvariables, sizeof(Variable),
  1033. compareVariableNames);
  1034. st->vars_sorted = true;
  1035. }
  1036. /* Now we can search */
  1037. key.name = name;
  1038. return (Variable *) bsearch((void *) &key,
  1039. (void *) st->variables,
  1040. st->nvariables,
  1041. sizeof(Variable),
  1042. compareVariableNames);
  1043. }
  1044. /* Get the value of a variable, in string form; returns NULL if unknown */
  1045. static char *
  1046. getVariable(CState *st, char *name)
  1047. {
  1048. Variable *var;
  1049. char stringform[64];
  1050. var = lookupVariable(st, name);
  1051. if (var == NULL)
  1052. return NULL; /* not found */
  1053. if (var->svalue)
  1054. return var->svalue; /* we have it in string form */
  1055. /* We need to produce a string equivalent of the value */
  1056. Assert(var->value.type != PGBT_NO_VALUE);
  1057. if (var->value.type == PGBT_NULL)
  1058. snprintf(stringform, sizeof(stringform), "NULL");
  1059. else if (var->value.type == PGBT_BOOLEAN)
  1060. snprintf(stringform, sizeof(stringform),
  1061. "%s", var->value.u.bval ? "true" : "false");
  1062. else if (var->value.type == PGBT_INT)
  1063. snprintf(stringform, sizeof(stringform),
  1064. INT64_FORMAT, var->value.u.ival);
  1065. else if (var->value.type == PGBT_DOUBLE)
  1066. snprintf(stringform, sizeof(stringform),
  1067. "%.*g", DBL_DIG, var->value.u.dval);
  1068. else /* internal error, unexpected type */
  1069. Assert(0);
  1070. var->svalue = pg_strdup(stringform);
  1071. return var->svalue;
  1072. }
  1073. /* Try to convert variable to a value; return false on failure */
  1074. static bool
  1075. makeVariableValue(Variable *var)
  1076. {
  1077. size_t slen;
  1078. if (var->value.type != PGBT_NO_VALUE)
  1079. return true; /* no work */
  1080. slen = strlen(var->svalue);
  1081. if (slen == 0)
  1082. /* what should it do on ""? */
  1083. return false;
  1084. if (pg_strcasecmp(var->svalue, "null") == 0)
  1085. {
  1086. setNullValue(&var->value);
  1087. }
  1088. /*
  1089. * accept prefixes such as y, ye, n, no... but not for "o". 0/1 are
  1090. * recognized later as an int, which is converted to bool if needed.
  1091. */
  1092. else if (pg_strncasecmp(var->svalue, "true", slen) == 0 ||
  1093. pg_strncasecmp(var->svalue, "yes", slen) == 0 ||
  1094. pg_strcasecmp(var->svalue, "on") == 0)
  1095. {
  1096. setBoolValue(&var->value, true);
  1097. }
  1098. else if (pg_strncasecmp(var->svalue, "false", slen) == 0 ||
  1099. pg_strncasecmp(var->svalue, "no", slen) == 0 ||
  1100. pg_strcasecmp(var->svalue, "off") == 0 ||
  1101. pg_strcasecmp(var->svalue, "of") == 0)
  1102. {
  1103. setBoolValue(&var->value, false);
  1104. }
  1105. else if (is_an_int(var->svalue))
  1106. {
  1107. setIntValue(&var->value, strtoint64(var->svalue));
  1108. }
  1109. else /* type should be double */
  1110. {
  1111. double dv;
  1112. char xs;
  1113. if (sscanf(var->svalue, "%lf%c", &dv, &xs) != 1)
  1114. {
  1115. fprintf(stderr,
  1116. "malformed variable \"%s\" value: \"%s\"\n",
  1117. var->name, var->svalue);
  1118. return false;
  1119. }
  1120. setDoubleValue(&var->value, dv);
  1121. }
  1122. return true;
  1123. }
  1124. /*
  1125. * Check whether a variable's name is allowed.
  1126. *
  1127. * We allow any non-ASCII character, as well as ASCII letters, digits, and
  1128. * underscore.
  1129. *
  1130. * Keep this in sync with the definitions of variable name characters in
  1131. * "src/fe_utils/psqlscan.l", "src/bin/psql/psqlscanslash.l" and
  1132. * "src/bin/pgbench/exprscan.l". Also see parseVariable(), below.
  1133. *
  1134. * Note: this static function is copied from "src/bin/psql/variables.c"
  1135. */
  1136. static bool
  1137. valid_variable_name(const char *name)
  1138. {
  1139. const unsigned char *ptr = (const unsigned char *) name;
  1140. /* Mustn't be zero-length */
  1141. if (*ptr == '\0')
  1142. return false;
  1143. while (*ptr)
  1144. {
  1145. if (IS_HIGHBIT_SET(*ptr) ||
  1146. strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
  1147. "_0123456789", *ptr) != NULL)
  1148. ptr++;
  1149. else
  1150. return false;
  1151. }
  1152. return true;
  1153. }
  1154. /*
  1155. * Lookup a variable by name, creating it if need be.
  1156. * Caller is expected to assign a value to the variable.
  1157. * Returns NULL on failure (bad name).
  1158. */
  1159. static Variable *
  1160. lookupCreateVariable(CState *st, const char *context, char *name)
  1161. {
  1162. Variable *var;
  1163. var = lookupVariable(st, name);
  1164. if (var == NULL)
  1165. {
  1166. Variable *newvars;
  1167. /*
  1168. * Check for the name only when declaring a new variable to avoid
  1169. * overhead.
  1170. */
  1171. if (!valid_variable_name(name))
  1172. {
  1173. fprintf(stderr, "%s: invalid variable name: \"%s\"\n",
  1174. context, name);
  1175. return NULL;
  1176. }
  1177. /* Create variable at the end of the array */
  1178. if (st->variables)
  1179. newvars = (Variable *) pg_realloc(st->variables,
  1180. (st->nvariables + 1) * sizeof(Variable));
  1181. else
  1182. newvars = (Variable *) pg_malloc(sizeof(Variable));
  1183. st->variables = newvars;
  1184. var = &newvars[st->nvariables];
  1185. var->name = pg_strdup(name);
  1186. var->svalue = NULL;
  1187. /* caller is expected to initialize remaining fields */
  1188. st->nvariables++;
  1189. /* we don't re-sort the array till we have to */
  1190. st->vars_sorted = false;
  1191. }
  1192. return var;
  1193. }
  1194. /* Assign a string value to a variable, creating it if need be */
  1195. /* Returns false on failure (bad name) */
  1196. static bool
  1197. putVariable(CState *st, const char *context, char *name, const char *value)
  1198. {
  1199. Variable *var;
  1200. char *val;
  1201. var = lookupCreateVariable(st, context, name);
  1202. if (!var)
  1203. return false;
  1204. /* dup then free, in case value is pointing at this variable */
  1205. val = pg_strdup(value);
  1206. if (var->svalue)
  1207. free(var->svalue);
  1208. var->svalue = val;
  1209. var->value.type = PGBT_NO_VALUE;
  1210. return true;
  1211. }
  1212. /* Assign a value to a variable, creating it if need be */
  1213. /* Returns false on failure (bad name) */
  1214. static bool
  1215. putVariableValue(CState *st, const char *context, char *name,
  1216. const PgBenchValue *value)
  1217. {
  1218. Variable *var;
  1219. var = lookupCreateVariable(st, context, name);
  1220. if (!var)
  1221. return false;
  1222. if (var->svalue)
  1223. free(var->svalue);
  1224. var->svalue = NULL;
  1225. var->value = *value;
  1226. return true;
  1227. }
  1228. /* Assign an integer value to a variable, creating it if need be */
  1229. /* Returns false on failure (bad name) */
  1230. static bool
  1231. putVariableInt(CState *st, const char *context, char *name, int64 value)
  1232. {
  1233. PgBenchValue val;
  1234. setIntValue(&val, value);
  1235. return putVariableValue(st, context, name, &val);
  1236. }
  1237. /*
  1238. * Parse a possible variable reference (:varname).
  1239. *
  1240. * "sql" points at a colon. If what follows it looks like a valid
  1241. * variable name, return a malloc'd string containing the variable name,
  1242. * and set *eaten to the number of characters consumed.
  1243. * Otherwise, return NULL.
  1244. */
  1245. static char *
  1246. parseVariable(const char *sql, int *eaten)
  1247. {
  1248. int i = 0;
  1249. char *name;
  1250. do
  1251. {
  1252. i++;
  1253. } while (IS_HIGHBIT_SET(sql[i]) ||
  1254. strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
  1255. "_0123456789", sql[i]) != NULL);
  1256. if (i == 1)
  1257. return NULL; /* no valid variable name chars */
  1258. name = pg_malloc(i);
  1259. memcpy(name, &sql[1], i - 1);
  1260. name[i - 1] = '\0';
  1261. *eaten = i;
  1262. return name;
  1263. }
  1264. static char *
  1265. replaceVariable(char **sql, char *param, int len, char *value)
  1266. {
  1267. int valueln = strlen(value);
  1268. if (valueln > len)
  1269. {
  1270. size_t offset = param - *sql;
  1271. *sql = pg_realloc(*sql, strlen(*sql) - len + valueln + 1);
  1272. param = *sql + offset;
  1273. }
  1274. if (valueln != len)
  1275. memmove(param + valueln, param + len, strlen(param + len) + 1);
  1276. memcpy(param, value, valueln);
  1277. return param + valueln;
  1278. }
  1279. static char *
  1280. assignVariables(CState *st, char *sql)
  1281. {
  1282. char *p,
  1283. *name,
  1284. *val;
  1285. p = sql;
  1286. while ((p = strchr(p, ':')) != NULL)
  1287. {
  1288. int eaten;
  1289. name = parseVariable(p, &eaten);
  1290. if (name == NULL)
  1291. {
  1292. while (*p == ':')
  1293. {
  1294. p++;
  1295. }
  1296. continue;
  1297. }
  1298. val = getVariable(st, name);
  1299. free(name);
  1300. if (val == NULL)
  1301. {
  1302. p++;
  1303. continue;
  1304. }
  1305. p = replaceVariable(&sql, p, eaten, val);
  1306. }
  1307. return sql;
  1308. }
  1309. static void
  1310. getQueryParams(CState *st, const Command *command, const char **params)
  1311. {
  1312. int i;
  1313. for (i = 0; i < command->argc - 1; i++)
  1314. params[i] = getVariable(st, command->argv[i + 1]);
  1315. }
  1316. static char *
  1317. valueTypeName(PgBenchValue *pval)
  1318. {
  1319. if (pval->type == PGBT_NO_VALUE)
  1320. return "none";
  1321. else if (pval->type == PGBT_NULL)
  1322. return "null";
  1323. else if (pval->type == PGBT_INT)
  1324. return "int";
  1325. else if (pval->type == PGBT_DOUBLE)
  1326. return "double";
  1327. else if (pval->type == PGBT_BOOLEAN)
  1328. return "boolean";
  1329. else
  1330. {
  1331. /* internal error, should never get there */
  1332. Assert(false);
  1333. return NULL;
  1334. }
  1335. }
  1336. /* get a value as a boolean, or tell if there is a problem */
  1337. static bool
  1338. coerceToBool(PgBenchValue *pval, bool *bval)
  1339. {
  1340. if (pval->type == PGBT_BOOLEAN)
  1341. {
  1342. *bval = pval->u.bval;
  1343. return true;
  1344. }
  1345. else /* NULL, INT or DOUBLE */
  1346. {
  1347. fprintf(stderr, "cannot coerce %s to boolean\n", valueTypeName(pval));
  1348. *bval = false; /* suppress uninitialized-variable warnings */
  1349. return false;
  1350. }
  1351. }
  1352. /*
  1353. * Return true or false from an expression for conditional purposes.
  1354. * Non zero numerical values are true, zero and NULL are false.
  1355. */
  1356. static bool
  1357. valueTruth(PgBenchValue *pval)
  1358. {
  1359. switch (pval->type)
  1360. {
  1361. case PGBT_NULL:
  1362. return false;
  1363. case PGBT_BOOLEAN:
  1364. return pval->u.bval;
  1365. case PGBT_INT:
  1366. return pval->u.ival != 0;
  1367. case PGBT_DOUBLE:
  1368. return pval->u.dval != 0.0;
  1369. default:
  1370. /* internal error, unexpected type */
  1371. Assert(0);
  1372. return false;
  1373. }
  1374. }
  1375. /* get a value as an int, tell if there is a problem */
  1376. static bool
  1377. coerceToInt(PgBenchValue *pval, int64 *ival)
  1378. {
  1379. if (pval->type == PGBT_INT)
  1380. {
  1381. *ival = pval->u.ival;
  1382. return true;
  1383. }
  1384. else if (pval->type == PGBT_DOUBLE)
  1385. {
  1386. double dval = pval->u.dval;
  1387. if (dval < PG_INT64_MIN || PG_INT64_MAX < dval)
  1388. {
  1389. fprintf(stderr, "double to int overflow for %f\n", dval);
  1390. return false;
  1391. }
  1392. *ival = (int64) dval;
  1393. return true;
  1394. }
  1395. else /* BOOLEAN or NULL */
  1396. {
  1397. fprintf(stderr, "cannot coerce %s to int\n", valueTypeName(pval));
  1398. return false;
  1399. }
  1400. }
  1401. /* get a value as a double, or tell if there is a problem */
  1402. static bool
  1403. coerceToDouble(PgBenchValue *pval, double *dval)
  1404. {
  1405. if (pval->type == PGBT_DOUBLE)
  1406. {
  1407. *dval = pval->u.dval;
  1408. return true;
  1409. }
  1410. else if (pval->type == PGBT_INT)
  1411. {
  1412. *dval = (double) pval->u.ival;
  1413. return true;
  1414. }
  1415. else /* BOOLEAN or NULL */
  1416. {
  1417. fprintf(stderr, "cannot coerce %s to double\n", valueTypeName(pval));
  1418. return false;
  1419. }
  1420. }
  1421. /* assign a null value */
  1422. static void
  1423. setNullValue(PgBenchValue *pv)
  1424. {
  1425. pv->type = PGBT_NULL;
  1426. pv->u.ival = 0;
  1427. }
  1428. /* assign a boolean value */
  1429. static void
  1430. setBoolValue(PgBenchValue *pv, bool bval)
  1431. {
  1432. pv->type = PGBT_BOOLEAN;
  1433. pv->u.bval = bval;
  1434. }
  1435. /* assign an integer value */
  1436. static void
  1437. setIntValue(PgBenchValue *pv, int64 ival)
  1438. {
  1439. pv->type = PGBT_INT;
  1440. pv->u.ival = ival;
  1441. }
  1442. /* assign a double value */
  1443. static void
  1444. setDoubleValue(PgBenchValue *pv, double dval)
  1445. {
  1446. pv->type = PGBT_DOUBLE;
  1447. pv->u.dval = dval;
  1448. }
  1449. static bool
  1450. isLazyFunc(PgBenchFunction func)
  1451. {
  1452. return func == PGBENCH_AND || func == PGBENCH_OR || func == PGBENCH_CASE;
  1453. }
  1454. /* lazy evaluation of some functions */
  1455. static bool
  1456. evalLazyFunc(TState *thread, CState *st,
  1457. PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
  1458. {
  1459. PgBenchValue a1,
  1460. a2;
  1461. bool ba1,
  1462. ba2;
  1463. Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
  1464. /* args points to first condition */
  1465. if (!evaluateExpr(thread, st, args->expr, &a1))
  1466. return false;
  1467. /* second condition for AND/OR and corresponding branch for CASE */
  1468. args = args->next;
  1469. switch (func)
  1470. {
  1471. case PGBENCH_AND:
  1472. if (a1.type == PGBT_NULL)
  1473. {
  1474. setNullValue(retval);
  1475. return true;
  1476. }
  1477. if (!coerceToBool(&a1, &ba1))
  1478. return false;
  1479. if (!ba1)
  1480. {
  1481. setBoolValue(retval, false);
  1482. return true;
  1483. }
  1484. if (!evaluateExpr(thread, st, args->expr, &a2))
  1485. return false;
  1486. if (a2.type == PGBT_NULL)
  1487. {
  1488. setNullValue(retval);
  1489. return true;
  1490. }
  1491. else if (!coerceToBool(&a2, &ba2))
  1492. return false;
  1493. else
  1494. {
  1495. setBoolValue(retval, ba2);
  1496. return true;
  1497. }
  1498. return true;
  1499. case PGBENCH_OR:
  1500. if (a1.type == PGBT_NULL)
  1501. {
  1502. setNullValue(retval);
  1503. return true;
  1504. }
  1505. if (!coerceToBool(&a1, &ba1))
  1506. return false;
  1507. if (ba1)
  1508. {
  1509. setBoolValue(retval, true);
  1510. return true;
  1511. }
  1512. if (!evaluateExpr(thread, st, args->expr, &a2))
  1513. return false;
  1514. if (a2.type == PGBT_NULL)
  1515. {
  1516. setNullValue(retval);
  1517. return true;
  1518. }
  1519. else if (!coerceToBool(&a2, &ba2))
  1520. return false;
  1521. else
  1522. {
  1523. setBoolValue(retval, ba2);
  1524. return true;
  1525. }
  1526. case PGBENCH_CASE:
  1527. /* when true, execute branch */
  1528. if (valueTruth(&a1))
  1529. return evaluateExpr(thread, st, args->expr, retval);
  1530. /* now args contains next condition or final else expression */
  1531. args = args->next;
  1532. /* final else case? */
  1533. if (args->next == NULL)
  1534. return evaluateExpr(thread, st, args->expr, retval);
  1535. /* no, another when, proceed */
  1536. return evalLazyFunc(thread, st, PGBENCH_CASE, args, retval);
  1537. default:
  1538. /* internal error, cannot get here */
  1539. Assert(0);
  1540. break;
  1541. }
  1542. return false;
  1543. }
  1544. /* maximum number of function arguments */
  1545. #define MAX_FARGS 16
  1546. /*
  1547. * Recursive evaluation of standard functions,
  1548. * which do not require lazy evaluation.
  1549. */
  1550. static bool
  1551. evalStandardFunc(TState *thread, CState *st,
  1552. PgBenchFunction func, PgBenchExprLink *args,
  1553. PgBenchValue *retval)
  1554. {
  1555. /* evaluate all function arguments */
  1556. int nargs = 0;
  1557. PgBenchValue vargs[MAX_FARGS];
  1558. PgBenchExprLink *l = args;
  1559. bool has_null = false;
  1560. for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
  1561. {
  1562. if (!evaluateExpr(thread, st, l->expr, &vargs[nargs]))
  1563. return false;
  1564. has_null |= vargs[nargs].type == PGBT_NULL;
  1565. }
  1566. if (l != NULL)
  1567. {
  1568. fprintf(stderr,
  1569. "too many function arguments, maximum is %d\n", MAX_FARGS);
  1570. return false;
  1571. }
  1572. /* NULL arguments */
  1573. if (has_null && func != PGBENCH_IS && func != PGBENCH_DEBUG)
  1574. {
  1575. setNullValue(retval);
  1576. return true;
  1577. }
  1578. /* then evaluate function */
  1579. switch (func)
  1580. {
  1581. /* overloaded operators */
  1582. case PGBENCH_ADD:
  1583. case PGBENCH_SUB:
  1584. case PGBENCH_MUL:
  1585. case PGBENCH_DIV:
  1586. case PGBENCH_MOD:
  1587. case PGBENCH_EQ:
  1588. case PGBENCH_NE:
  1589. case PGBENCH_LE:
  1590. case PGBENCH_LT:
  1591. {
  1592. PgBenchValue *lval = &vargs[0],
  1593. *rval = &vargs[1];
  1594. Assert(nargs == 2);
  1595. /* overloaded type management, double if some double */
  1596. if ((lval->type == PGBT_DOUBLE ||
  1597. rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
  1598. {
  1599. double ld,
  1600. rd;
  1601. if (!coerceToDouble(lval, &ld) ||
  1602. !coerceToDouble(rval, &rd))
  1603. return false;
  1604. switch (func)
  1605. {
  1606. case PGBENCH_ADD:
  1607. setDoubleValue(retval, ld + rd);
  1608. return true;
  1609. case PGBENCH_SUB:
  1610. setDoubleValue(retval, ld - rd);
  1611. return true;
  1612. case PGBENCH_MUL:
  1613. setDoubleValue(retval, ld * rd);
  1614. return true;
  1615. case PGBENCH_DIV:
  1616. setDoubleValue(retval, ld / rd);
  1617. return true;
  1618. case PGBENCH_EQ:
  1619. setBoolValue(retval, ld == rd);
  1620. return true;
  1621. case PGBENCH_NE:
  1622. setBoolValue(retval, ld != rd);
  1623. return true;
  1624. case PGBENCH_LE:
  1625. setBoolValue(retval, ld <= rd);
  1626. return true;
  1627. case PGBENCH_LT:
  1628. setBoolValue(retval, ld < rd);
  1629. return true;
  1630. default:
  1631. /* cannot get here */
  1632. Assert(0);
  1633. }
  1634. }
  1635. else /* we have integer operands, or % */
  1636. {
  1637. int64 li,
  1638. ri;
  1639. if (!coerceToInt(lval, &li) ||
  1640. !coerceToInt(rval, &ri))
  1641. return false;
  1642. switch (func)
  1643. {
  1644. case PGBENCH_ADD:
  1645. setIntValue(retval, li + ri);
  1646. return true;
  1647. case PGBENCH_SUB:
  1648. setIntValue(retval, li - ri);
  1649. return true;
  1650. case PGBENCH_MUL:
  1651. setIntValue(retval, li * ri);
  1652. return true;
  1653. case PGBENCH_EQ:
  1654. setBoolValue(retval, li == ri);
  1655. return true;
  1656. case PGBENCH_NE:
  1657. setBoolValue(retval, li != ri);
  1658. return true;
  1659. case PGBENCH_LE:
  1660. setBoolValue(retval, li <= ri);
  1661. return true;
  1662. case PGBENCH_LT:
  1663. setBoolValue(retval, li < ri);
  1664. return true;
  1665. case PGBENCH_DIV:
  1666. case PGBENCH_MOD:
  1667. if (ri == 0)
  1668. {
  1669. fprintf(stderr, "division by zero\n");
  1670. return false;
  1671. }
  1672. /* special handling of -1 divisor */
  1673. if (ri == -1)
  1674. {
  1675. if (func == PGBENCH_DIV)
  1676. {
  1677. /* overflow check (needed for INT64_MIN) */
  1678. if (li == PG_INT64_MIN)
  1679. {
  1680. fprintf(stderr, "bigint out of range\n");
  1681. return false;
  1682. }
  1683. else
  1684. setIntValue(retval, -li);
  1685. }
  1686. else
  1687. setIntValue(retval, 0);
  1688. return true;
  1689. }
  1690. /* else divisor is not -1 */
  1691. if (func == PGBENCH_DIV)
  1692. setIntValue(retval, li / ri);
  1693. else /* func == PGBENCH_MOD */
  1694. setIntValue(retval, li % ri);
  1695. return true;
  1696. default:
  1697. /* cannot get here */
  1698. Assert(0);
  1699. }
  1700. }
  1701. Assert(0);
  1702. return false; /* NOTREACHED */
  1703. }
  1704. /* integer bitwise operators */
  1705. case PGBENCH_BITAND:
  1706. case PGBENCH_BITOR:
  1707. case PGBENCH_BITXOR:
  1708. case PGBENCH_LSHIFT:
  1709. case PGBENCH_RSHIFT:
  1710. {
  1711. int64 li,
  1712. ri;
  1713. if (!coerceToInt(&vargs[0], &li) || !coerceToInt(&vargs[1], &ri))
  1714. return false;
  1715. if (func == PGBENCH_BITAND)
  1716. setIntValue(retval, li & ri);
  1717. else if (func == PGBENCH_BITOR)
  1718. setIntValue(retval, li | ri);
  1719. else if (func == PGBENCH_BITXOR)
  1720. setIntValue(retval, li ^ ri);
  1721. else if (func == PGBENCH_LSHIFT)
  1722. setIntValue(retval, li << ri);
  1723. else if (func == PGBENCH_RSHIFT)
  1724. setIntValue(retval, li >> ri);
  1725. else /* cannot get here */
  1726. Assert(0);
  1727. return true;
  1728. }
  1729. /* logical operators */
  1730. case PGBENCH_NOT:
  1731. {
  1732. bool b;
  1733. if (!coerceToBool(&vargs[0], &b))
  1734. return false;
  1735. setBoolValue(retval, !b);
  1736. return true;
  1737. }
  1738. /* no arguments */
  1739. case PGBENCH_PI:
  1740. setDoubleValue(retval, M_PI);
  1741. return true;
  1742. /* 1 overloaded argument */
  1743. case PGBENCH_ABS:
  1744. {
  1745. PgBenchValue *varg = &vargs[0];
  1746. Assert(nargs == 1);
  1747. if (varg->type == PGBT_INT)
  1748. {
  1749. int64 i = varg->u.ival;
  1750. setIntValue(retval, i < 0 ? -i : i);
  1751. }
  1752. else
  1753. {
  1754. double d = varg->u.dval;
  1755. Assert(varg->type == PGBT_DOUBLE);
  1756. setDoubleValue(retval, d < 0.0 ? -d : d);
  1757. }
  1758. return true;
  1759. }
  1760. case PGBENCH_DEBUG:
  1761. {
  1762. PgBenchValue *varg = &vargs[0];
  1763. Assert(nargs == 1);
  1764. fprintf(stderr, "debug(script=%d,command=%d): ",
  1765. st->use_file, st->command + 1);
  1766. if (varg->type == PGBT_NULL)
  1767. fprintf(stderr, "null\n");
  1768. else if (varg->type == PGBT_BOOLEAN)
  1769. fprintf(stderr, "boolean %s\n", varg->u.bval ? "true" : "false");
  1770. else if (varg->type == PGBT_INT)
  1771. fprintf(stderr, "int " INT64_FORMAT "\n", varg->u.ival);
  1772. else if (varg->type == PGBT_DOUBLE)
  1773. fprintf(stderr, "double %.*g\n", DBL_DIG, varg->u.dval);
  1774. else /* internal error, unexpected type */
  1775. Assert(0);
  1776. *retval = *varg;
  1777. return true;
  1778. }
  1779. /* 1 double argument */
  1780. case PGBENCH_DOUBLE:
  1781. case PGBENCH_SQRT:
  1782. case PGBENCH_LN:
  1783. case PGBENCH_EXP:
  1784. {
  1785. double dval;
  1786. Assert(nargs == 1);
  1787. if (!coerceToDouble(&vargs[0], &dval))
  1788. return false;
  1789. if (func == PGBENCH_SQRT)
  1790. dval = sqrt(dval);
  1791. else if (func == PGBENCH_LN)
  1792. dval = log(dval);
  1793. else if (func == PGBENCH_EXP)
  1794. dval = exp(dval);
  1795. /* else is cast: do nothing */
  1796. setDoubleValue(retval, dval);
  1797. return true;
  1798. }
  1799. /* 1 int argument */
  1800. case PGBENCH_INT:
  1801. {
  1802. int64 ival;
  1803. Assert(nargs == 1);
  1804. if (!coerceToInt(&vargs[0], &ival))
  1805. return false;
  1806. setIntValue(retval, ival);
  1807. return true;
  1808. }
  1809. /* variable number of arguments */
  1810. case PGBENCH_LEAST:
  1811. case PGBENCH_GREATEST:
  1812. {
  1813. bool havedouble;
  1814. int i;
  1815. Assert(nargs >= 1);
  1816. /* need double result if any input is double */
  1817. havedouble = false;
  1818. for (i = 0; i < nargs; i++)
  1819. {
  1820. if (vargs[i].type == PGBT_DOUBLE)
  1821. {
  1822. havedouble = true;
  1823. break;
  1824. }
  1825. }
  1826. if (havedouble)
  1827. {
  1828. double extremum;
  1829. if (!coerceToDouble(&vargs[0], &extremum))
  1830. return false;
  1831. for (i = 1; i < nargs; i++)
  1832. {
  1833. double dval;
  1834. if (!coerceToDouble(&vargs[i], &dval))
  1835. return false;
  1836. if (func == PGBENCH_LEAST)
  1837. extremum = Min(extremum, dval);
  1838. else
  1839. extremum = Max(extremum, dval);
  1840. }
  1841. setDoubleValue(retval, extremum);
  1842. }
  1843. else
  1844. {
  1845. int64 extremum;
  1846. if (!coerceToInt(&vargs[0], &extremum))
  1847. return false;
  1848. for (i = 1; i < nargs; i++)
  1849. {
  1850. int64 ival;
  1851. if (!coerceToInt(&vargs[i], &ival))
  1852. return false;
  1853. if (func == PGBENCH_LEAST)
  1854. extremum = Min(extremum, ival);
  1855. else
  1856. extremum = Max(extremum, ival);
  1857. }
  1858. setIntValue(retval, extremum);
  1859. }
  1860. return true;
  1861. }
  1862. /* random functions */
  1863. case PGBENCH_RANDOM:
  1864. case PGBENCH_RANDOM_EXPONENTIAL:
  1865. case PGBENCH_RANDOM_GAUSSIAN:
  1866. case PGBENCH_RANDOM_ZIPFIAN:
  1867. {
  1868. int64 imin,
  1869. imax;
  1870. Assert(nargs >= 2);
  1871. if (!coerceToInt(&vargs[0], &imin) ||
  1872. !coerceToInt(&vargs[1], &imax))
  1873. return false;
  1874. /* check random range */
  1875. if (imin > imax)
  1876. {
  1877. fprintf(stderr, "empty range given to random\n");
  1878. return false;
  1879. }
  1880. else if (imax - imin < 0 || (imax - imin) + 1 < 0)
  1881. {
  1882. /* prevent int overflows in random functions */
  1883. fprintf(stderr, "random range is too large\n");
  1884. return false;
  1885. }
  1886. if (func == PGBENCH_RANDOM)
  1887. {
  1888. Assert(nargs == 2);
  1889. setIntValue(retval, getrand(thread, imin, imax));
  1890. }
  1891. else /* gaussian & exponential */
  1892. {
  1893. double param;
  1894. Assert(nargs == 3);
  1895. if (!coerceToDouble(&vargs[2], &param))
  1896. return false;
  1897. if (func == PGBENCH_RANDOM_GAUSSIAN)
  1898. {
  1899. if (param < MIN_GAUSSIAN_PARAM)
  1900. {
  1901. fprintf(stderr,
  1902. "gaussian parameter must be at least %f "
  1903. "(not %f)\n", MIN_GAUSSIAN_PARAM, param);
  1904. return false;
  1905. }
  1906. setIntValue(retval,
  1907. getGaussianRand(thread, imin, imax, param));
  1908. }
  1909. else if (func == PGBENCH_RANDOM_ZIPFIAN)
  1910. {
  1911. if (param <= 0.0 || param == 1.0 || param > MAX_ZIPFIAN_PARAM)
  1912. {
  1913. fprintf(stderr,
  1914. "zipfian parameter must be in range (0, 1) U (1, %d]"
  1915. " (got %f)\n", MAX_ZIPFIAN_PARAM, param);
  1916. return false;
  1917. }
  1918. setIntValue(retval,
  1919. getZipfianRand(thread, imin, imax, param));
  1920. }
  1921. else /* exponential */
  1922. {
  1923. if (param <= 0.0)
  1924. {
  1925. fprintf(stderr,
  1926. "exponential parameter must be greater than zero"
  1927. " (got %f)\n", param);
  1928. return false;
  1929. }
  1930. setIntValue(retval,
  1931. getExponentialRand(thread, imin, imax, param));
  1932. }
  1933. }
  1934. return true;
  1935. }
  1936. case PGBENCH_POW:
  1937. {
  1938. PgBenchValue *lval = &vargs[0];
  1939. PgBenchValue *rval = &vargs[1];
  1940. double ld,
  1941. rd;
  1942. Assert(nargs == 2);
  1943. if (!coerceToDouble(lval, &ld) ||
  1944. !coerceToDouble(rval, &rd))
  1945. return false;
  1946. setDoubleValue(retval, pow(ld, rd));
  1947. return true;
  1948. }
  1949. case PGBENCH_IS:
  1950. {
  1951. Assert(nargs == 2);
  1952. /*
  1953. * note: this simple implementation is more permissive than
  1954. * SQL
  1955. */
  1956. setBoolValue(retval,
  1957. vargs[0].type == vargs[1].type &&
  1958. vargs[0].u.bval == vargs[1].u.bval);
  1959. return true;
  1960. }
  1961. /* hashing */
  1962. case PGBENCH_HASH_FNV1A:
  1963. case PGBENCH_HASH_MURMUR2:
  1964. {
  1965. int64 val,
  1966. seed;
  1967. Assert(nargs == 2);
  1968. if (!coerceToInt(&vargs[0], &val) ||
  1969. !coerceToInt(&vargs[1], &seed))
  1970. return false;
  1971. if (func == PGBENCH_HASH_MURMUR2)
  1972. setIntValue(retval, getHashMurmur2(val, seed));
  1973. else if (func == PGBENCH_HASH_FNV1A)
  1974. setIntValue(retval, getHashFnv1a(val, seed));
  1975. else
  1976. /* cannot get here */
  1977. Assert(0);
  1978. return true;
  1979. }
  1980. default:
  1981. /* cannot get here */
  1982. Assert(0);
  1983. /* dead code to avoid a compiler warning */
  1984. return false;
  1985. }
  1986. }
  1987. /* evaluate some function */
  1988. static bool
  1989. evalFunc(TState *thread, CState *st,
  1990. PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
  1991. {
  1992. if (isLazyFunc(func))
  1993. return evalLazyFunc(thread, st, func, args, retval);
  1994. else
  1995. return evalStandardFunc(thread, st, func, args, retval);
  1996. }
  1997. /*
  1998. * Recursive evaluation of an expression in a pgbench script
  1999. * using the current state of variables.
  2000. * Returns whether the evaluation was ok,
  2001. * the value itself is returned through the retval pointer.
  2002. */
  2003. static bool
  2004. evaluateExpr(TState *thread, CState *st, PgBenchExpr *expr, PgBenchValue *retval)
  2005. {
  2006. switch (expr->etype)
  2007. {
  2008. case ENODE_CONSTANT:
  2009. {
  2010. *retval = expr->u.constant;
  2011. return true;
  2012. }
  2013. case ENODE_VARIABLE:
  2014. {
  2015. Variable *var;
  2016. if ((var = lookupVariable(st, expr->u.variable.varname)) == NULL)
  2017. {
  2018. fprintf(stderr, "undefined variable \"%s\"\n",
  2019. expr->u.variable.varname);
  2020. return false;
  2021. }
  2022. if (!makeVariableValue(var))
  2023. return false;
  2024. *retval = var->value;
  2025. return true;
  2026. }
  2027. case ENODE_FUNCTION:
  2028. return evalFunc(thread, st,
  2029. expr->u.function.function,
  2030. expr->u.function.args,
  2031. retval);
  2032. default:
  2033. /* internal error which should never occur */
  2034. fprintf(stderr, "unexpected enode type in evaluation: %d\n",
  2035. expr->etype);
  2036. exit(1);
  2037. }
  2038. }
  2039. /*
  2040. * Convert command name to meta-command enum identifier
  2041. */
  2042. static MetaCommand
  2043. getMetaCommand(const char *cmd)
  2044. {
  2045. MetaCommand mc;
  2046. if (cmd == NULL)
  2047. mc = META_NONE;
  2048. else if (pg_strcasecmp(cmd, "set") == 0)
  2049. mc = META_SET;
  2050. else if (pg_strcasecmp(cmd, "setshell") == 0)
  2051. mc = META_SETSHELL;
  2052. else if (pg_strcasecmp(cmd, "shell") == 0)
  2053. mc = META_SHELL;
  2054. else if (pg_strcasecmp(cmd, "sleep") == 0)
  2055. mc = META_SLEEP;
  2056. else if (pg_strcasecmp(cmd, "if") == 0)
  2057. mc = META_IF;
  2058. else if (pg_strcasecmp(cmd, "elif") == 0)
  2059. mc = META_ELIF;
  2060. else if (pg_strcasecmp(cmd, "else") == 0)
  2061. mc = META_ELSE;
  2062. else if (pg_strcasecmp(cmd, "endif") == 0)
  2063. mc = META_ENDIF;
  2064. else
  2065. mc = META_NONE;
  2066. return mc;
  2067. }
  2068. /*
  2069. * Run a shell command. The result is assigned to the variable if not NULL.
  2070. * Return true if succeeded, or false on error.
  2071. */
  2072. static bool
  2073. runShellCommand(CState *st, char *variable, char **argv, int argc)
  2074. {
  2075. char command[SHELL_COMMAND_SIZE];
  2076. int i,
  2077. len = 0;
  2078. FILE *fp;
  2079. char res[64];
  2080. char *endptr;
  2081. int retval;
  2082. /*----------
  2083. * Join arguments with whitespace separators. Arguments starting with
  2084. * exactly one colon are treated as variables:
  2085. * name - append a string "name"
  2086. * :var - append a variable named 'var'
  2087. * ::name - append a string ":name"
  2088. *----------
  2089. */
  2090. for (i = 0; i < argc; i++)
  2091. {
  2092. char *arg;
  2093. int arglen;
  2094. if (argv[i][0] != ':')
  2095. {
  2096. arg = argv[i]; /* a string literal */
  2097. }
  2098. else if (argv[i][1] == ':')
  2099. {
  2100. arg = argv[i] + 1; /* a string literal starting with colons */
  2101. }
  2102. else if ((arg = getVariable(st, argv[i] + 1)) == NULL)
  2103. {
  2104. fprintf(stderr, "%s: undefined variable \"%s\"\n",
  2105. argv[0], argv[i]);
  2106. return false;
  2107. }
  2108. arglen = strlen(arg);
  2109. if (len + arglen + (i > 0 ? 1 : 0) >= SHELL_COMMAND_SIZE - 1)
  2110. {
  2111. fprintf(stderr, "%s: shell command is too long\n", argv[0]);
  2112. return false;
  2113. }
  2114. if (i > 0)
  2115. command[len++] = ' ';
  2116. memcpy(command + len, arg, arglen);
  2117. len += arglen;
  2118. }
  2119. command[len] = '\0';
  2120. /* Fast path for non-assignment case */
  2121. if (variable == NULL)
  2122. {
  2123. if (system(command))
  2124. {
  2125. if (!timer_exceeded)
  2126. fprintf(stderr, "%s: could not launch shell command\n", argv[0]);
  2127. return false;
  2128. }
  2129. return true;
  2130. }
  2131. /* Execute the command with pipe and read the standard output. */
  2132. if ((fp = popen(command, "r")) == NULL)
  2133. {
  2134. fprintf(stderr, "%s: could not launch shell command\n", argv[0]);
  2135. return false;
  2136. }
  2137. if (fgets(res, sizeof(res), fp) == NULL)
  2138. {
  2139. if (!timer_exceeded)
  2140. fprintf(stderr, "%s: could not read result of shell command\n", argv[0]);
  2141. (void) pclose(fp);
  2142. return false;
  2143. }
  2144. if (pclose(fp) < 0)
  2145. {
  2146. fprintf(stderr, "%s: could not close shell command\n", argv[0]);
  2147. return false;
  2148. }
  2149. /* Check whether the result is an integer and assign it to the variable */
  2150. retval = (int) strtol(res, &endptr, 10);
  2151. while (*endptr != '\0' && isspace((unsigned char) *endptr))
  2152. endptr++;
  2153. if (*res == '\0' || *endptr != '\0')
  2154. {
  2155. fprintf(stderr, "%s: shell command must return an integer (not \"%s\")\n",
  2156. argv[0], res);
  2157. return false;
  2158. }
  2159. if (!putVariableInt(st, "setshell", variable, retval))
  2160. return false;
  2161. #ifdef DEBUG
  2162. printf("shell parameter name: \"%s\", value: \"%s\"\n", argv[1], res);
  2163. #endif
  2164. return true;
  2165. }
  2166. #define MAX_PREPARE_NAME 32
  2167. static void
  2168. preparedStatementName(char *buffer, int file, int state)
  2169. {
  2170. sprintf(buffer, "P%d_%d", file, state);
  2171. }
  2172. static void
  2173. commandFailed(CState *st, const char *cmd, const char *message)
  2174. {
  2175. fprintf(stderr,
  2176. "client %d aborted in command %d (%s) of script %d; %s\n",
  2177. st->id, st->command, cmd, st->use_file, message);
  2178. }
  2179. /* return a script number with a weighted choice. */
  2180. static int
  2181. chooseScript(TState *thread)
  2182. {
  2183. int i = 0;
  2184. int64 w;
  2185. if (num_scripts == 1)
  2186. return 0;
  2187. w = getrand(thread, 0, total_weight - 1);
  2188. do
  2189. {
  2190. w -= sql_script[i++].weight;
  2191. } while (w >= 0);
  2192. return i - 1;
  2193. }
  2194. /* Send a SQL command, using the chosen querymode */
  2195. static bool
  2196. sendCommand(CState *st, Command *command)
  2197. {
  2198. int r;
  2199. if (querymode == QUERY_SIMPLE)
  2200. {
  2201. char *sql;
  2202. sql = pg_strdup(command->argv[0]);
  2203. sql = assignVariables(st, sql);
  2204. if (debug)
  2205. fprintf(stderr, "client %d sending %s\n", st->id, sql);
  2206. r = PQsendQuery(st->con, sql);
  2207. free(sql);
  2208. }
  2209. else if (querymode == QUERY_EXTENDED)
  2210. {
  2211. const char *sql = command->argv[0];
  2212. const char *params[MAX_ARGS];
  2213. getQueryParams(st, command, params);
  2214. if (debug)
  2215. fprintf(stderr, "client %d sending %s\n", st->id, sql);
  2216. r = PQsendQueryParams(st->con, sql, command->argc - 1,
  2217. NULL, params, NULL, NULL, 0);
  2218. }
  2219. else if (querymode == QUERY_PREPARED)
  2220. {
  2221. char name[MAX_PREPARE_NAME];
  2222. const char *params[MAX_ARGS];
  2223. if (!st->prepared[st->use_file])
  2224. {
  2225. int j;
  2226. Command **commands = sql_script[st->use_file].commands;
  2227. for (j = 0; commands[j] != NULL; j++)
  2228. {
  2229. PGresult *res;
  2230. char name[MAX_PREPARE_NAME];
  2231. if (commands[j]->type != SQL_COMMAND)
  2232. continue;
  2233. preparedStatementName(name, st->use_file, j);
  2234. res = PQprepare(st->con, name,
  2235. commands[j]->argv[0], commands[j]->argc - 1, NULL);
  2236. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  2237. fprintf(stderr, "%s", PQerrorMessage(st->con));
  2238. PQclear(res);
  2239. }
  2240. st->prepared[st->use_file] = true;
  2241. }
  2242. getQueryParams(st, command, params);
  2243. preparedStatementName(name, st->use_file, st->command);
  2244. if (debug)
  2245. fprintf(stderr, "client %d sending %s\n", st->id, name);
  2246. r = PQsendQueryPrepared(st->con, name, command->argc - 1,
  2247. params, NULL, NULL, 0);
  2248. }
  2249. else /* unknown sql mode */
  2250. r = 0;
  2251. if (r == 0)
  2252. {
  2253. if (debug)
  2254. fprintf(stderr, "client %d could not send %s\n",
  2255. st->id, command->argv[0]);
  2256. st->ecnt++;
  2257. return false;
  2258. }
  2259. else
  2260. return true;
  2261. }
  2262. /*
  2263. * Parse the argument to a \sleep command, and return the requested amount
  2264. * of delay, in microseconds. Returns true on success, false on error.
  2265. */
  2266. static bool
  2267. evaluateSleep(CState *st, int argc, char **argv, int *usecs)
  2268. {
  2269. char *var;
  2270. int usec;
  2271. if (*argv[1] == ':')
  2272. {
  2273. if ((var = getVariable(st, argv[1] + 1)) == NULL)
  2274. {
  2275. fprintf(stderr, "%s: undefined variable \"%s\"\n",
  2276. argv[0], argv[1]);
  2277. return false;
  2278. }
  2279. usec = atoi(var);
  2280. }
  2281. else
  2282. usec = atoi(argv[1]);
  2283. if (argc > 2)
  2284. {
  2285. if (pg_strcasecmp(argv[2], "ms") == 0)
  2286. usec *= 1000;
  2287. else if (pg_strcasecmp(argv[2], "s") == 0)
  2288. usec *= 1000000;
  2289. }
  2290. else
  2291. usec *= 1000000;
  2292. *usecs = usec;
  2293. return true;
  2294. }
  2295. /*
  2296. * Advance the state machine of a connection, if possible.
  2297. */
  2298. static void
  2299. doCustom(TState *thread, CState *st, StatsData *agg)
  2300. {
  2301. PGresult *res;
  2302. Command *command;
  2303. instr_time now;
  2304. bool end_tx_processed = false;
  2305. int64 wait;
  2306. /*
  2307. * gettimeofday() isn't free, so we get the current timestamp lazily the
  2308. * first time it's needed, and reuse the same value throughout this
  2309. * function after that. This also ensures that e.g. the calculated
  2310. * latency reported in the log file and in the totals are the same. Zero
  2311. * means "not set yet". Reset "now" when we execute shell commands or
  2312. * expressions, which might take a non-negligible amount of time, though.
  2313. */
  2314. INSTR_TIME_SET_ZERO(now);
  2315. /*
  2316. * Loop in the state machine, until we have to wait for a result from the
  2317. * server (or have to sleep, for throttling or for \sleep).
  2318. *
  2319. * Note: In the switch-statement below, 'break' will loop back here,
  2320. * meaning "continue in the state machine". Return is used to return to
  2321. * the caller.
  2322. */
  2323. for (;;)
  2324. {
  2325. switch (st->state)
  2326. {
  2327. /*
  2328. * Select transaction to run.
  2329. */
  2330. case CSTATE_CHOOSE_SCRIPT:
  2331. st->use_file = chooseScript(thread);
  2332. if (debug)
  2333. fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
  2334. sql_script[st->use_file].desc);
  2335. if (throttle_delay > 0)
  2336. st->state = CSTATE_START_THROTTLE;
  2337. else
  2338. st->state = CSTATE_START_TX;
  2339. /* check consistency */
  2340. Assert(conditional_stack_empty(st->cstack));
  2341. break;
  2342. /*
  2343. * Handle throttling once per transaction by sleeping.
  2344. */
  2345. case CSTATE_START_THROTTLE:
  2346. /*
  2347. * Generate a delay such that the series of delays will
  2348. * approximate a Poisson distribution centered on the
  2349. * throttle_delay time.
  2350. *
  2351. * If transactions are too slow or a given wait is shorter
  2352. * than a transaction, the next transaction will start right
  2353. * away.
  2354. */
  2355. Assert(throttle_delay > 0);
  2356. wait = getPoissonRand(thread, throttle_delay);
  2357. thread->throttle_trigger += wait;
  2358. st->txn_scheduled = thread->throttle_trigger;
  2359. /*
  2360. * stop client if next transaction is beyond pgbench end of
  2361. * execution
  2362. */
  2363. if (duration > 0 && st->txn_scheduled > end_time)
  2364. {
  2365. st->state = CSTATE_FINISHED;
  2366. break;
  2367. }
  2368. /*
  2369. * If --latency-limit is used, and this slot is already late
  2370. * so that the transaction will miss the latency limit even if
  2371. * it completed immediately, we skip this time slot and
  2372. * iterate till the next slot that isn't late yet. But don't
  2373. * iterate beyond the -t limit, if one is given.
  2374. */
  2375. if (latency_limit)
  2376. {
  2377. int64 now_us;
  2378. if (INSTR_TIME_IS_ZERO(now))
  2379. INSTR_TIME_SET_CURRENT(now);
  2380. now_us = INSTR_TIME_GET_MICROSEC(now);
  2381. while (thread->throttle_trigger < now_us - latency_limit &&
  2382. (nxacts <= 0 || st->cnt < nxacts))
  2383. {
  2384. processXactStats(thread, st, &now, true, agg);
  2385. /* next rendez-vous */
  2386. wait = getPoissonRand(thread, throttle_delay);
  2387. thread->throttle_trigger += wait;
  2388. st->txn_scheduled = thread->throttle_trigger;
  2389. }
  2390. /* stop client if -t exceeded */
  2391. if (nxacts > 0 && st->cnt >= nxacts)
  2392. {
  2393. st->state = CSTATE_FINISHED;
  2394. break;
  2395. }
  2396. }
  2397. st->state = CSTATE_THROTTLE;
  2398. if (debug)
  2399. fprintf(stderr, "client %d throttling " INT64_FORMAT " us\n",
  2400. st->id, wait);
  2401. break;
  2402. /*
  2403. * Wait until it's time to start next transaction.
  2404. */
  2405. case CSTATE_THROTTLE:
  2406. if (INSTR_TIME_IS_ZERO(now))
  2407. INSTR_TIME_SET_CURRENT(now);
  2408. if (INSTR_TIME_GET_MICROSEC(now) < st->txn_scheduled)
  2409. return; /* Still sleeping, nothing to do here */
  2410. /* Else done sleeping, start the transaction */
  2411. st->state = CSTATE_START_TX;
  2412. break;
  2413. /* Start new transaction */
  2414. case CSTATE_START_TX:
  2415. /*
  2416. * Establish connection on first call, or if is_connect is
  2417. * true.
  2418. */
  2419. if (st->con == NULL)
  2420. {
  2421. instr_time start;
  2422. if (INSTR_TIME_IS_ZERO(now))
  2423. INSTR_TIME_SET_CURRENT(now);
  2424. start = now;
  2425. if ((st->con = doConnect()) == NULL)
  2426. {
  2427. fprintf(stderr, "client %d aborted while establishing connection\n",
  2428. st->id);
  2429. st->state = CSTATE_ABORTED;
  2430. break;
  2431. }
  2432. INSTR_TIME_SET_CURRENT(now);
  2433. INSTR_TIME_ACCUM_DIFF(thread->conn_time, now, start);
  2434. /* Reset session-local state */
  2435. memset(st->prepared, 0, sizeof(st->prepared));
  2436. }
  2437. /*
  2438. * Record transaction start time under logging, progress or
  2439. * throttling.
  2440. */
  2441. if (use_log || progress || throttle_delay || latency_limit ||
  2442. per_script_stats)
  2443. {
  2444. if (INSTR_TIME_IS_ZERO(now))
  2445. INSTR_TIME_SET_CURRENT(now);
  2446. st->txn_begin = now;
  2447. /*
  2448. * When not throttling, this is also the transaction's
  2449. * scheduled start time.
  2450. */
  2451. if (!throttle_delay)
  2452. st->txn_scheduled = INSTR_TIME_GET_MICROSEC(now);
  2453. }
  2454. /* Begin with the first command */
  2455. st->command = 0;
  2456. st->state = CSTATE_START_COMMAND;
  2457. break;
  2458. /*
  2459. * Send a command to server (or execute a meta-command)
  2460. */
  2461. case CSTATE_START_COMMAND:
  2462. command = sql_script[st->use_file].commands[st->command];
  2463. /*
  2464. * If we reached the end of the script, move to end-of-xact
  2465. * processing.
  2466. */
  2467. if (command == NULL)
  2468. {
  2469. st->state = CSTATE_END_TX;
  2470. break;
  2471. }
  2472. /*
  2473. * Record statement start time if per-command latencies are
  2474. * requested
  2475. */
  2476. if (is_latencies)
  2477. {
  2478. if (INSTR_TIME_IS_ZERO(now))
  2479. INSTR_TIME_SET_CURRENT(now);
  2480. st->stmt_begin = now;
  2481. }
  2482. if (command->type == SQL_COMMAND)
  2483. {
  2484. if (!sendCommand(st, command))
  2485. {
  2486. commandFailed(st, "SQL", "SQL command send failed");
  2487. st->state = CSTATE_ABORTED;
  2488. }
  2489. else
  2490. st->state = CSTATE_WAIT_RESULT;
  2491. }
  2492. else if (command->type == META_COMMAND)
  2493. {
  2494. int argc = command->argc,
  2495. i;
  2496. char **argv = command->argv;
  2497. if (debug)
  2498. {
  2499. fprintf(stderr, "client %d executing \\%s", st->id, argv[0]);
  2500. for (i = 1; i < argc; i++)
  2501. fprintf(stderr, " %s", argv[i]);
  2502. fprintf(stderr, "\n");
  2503. }
  2504. if (command->meta == META_SLEEP)
  2505. {
  2506. /*
  2507. * A \sleep doesn't execute anything, we just get the
  2508. * delay from the argument, and enter the CSTATE_SLEEP
  2509. * state. (The per-command latency will be recorded
  2510. * in CSTATE_SLEEP state, not here, after the delay
  2511. * has elapsed.)
  2512. */
  2513. int usec;
  2514. if (!evaluateSleep(st, argc, argv, &usec))
  2515. {
  2516. commandFailed(st, "sleep", "execution of meta-command failed");
  2517. st->state = CSTATE_ABORTED;
  2518. break;
  2519. }
  2520. if (INSTR_TIME_IS_ZERO(now))
  2521. INSTR_TIME_SET_CURRENT(now);
  2522. st->sleep_until = INSTR_TIME_GET_MICROSEC(now) + usec;
  2523. st->state = CSTATE_SLEEP;
  2524. break;
  2525. }
  2526. else if (command->meta == META_SET ||
  2527. command->meta == META_IF ||
  2528. command->meta == META_ELIF)
  2529. {
  2530. /* backslash commands with an expression to evaluate */
  2531. PgBenchExpr *expr = command->expr;
  2532. PgBenchValue result;
  2533. if (command->meta == META_ELIF &&
  2534. conditional_stack_peek(st->cstack) == IFSTATE_TRUE)
  2535. {
  2536. /*
  2537. * elif after executed block, skip eval and wait
  2538. * for endif
  2539. */
  2540. conditional_stack_poke(st->cstack, IFSTATE_IGNORED);
  2541. goto move_to_end_command;
  2542. }
  2543. if (!evaluateExpr(thread, st, expr, &result))
  2544. {
  2545. commandFailed(st, argv[0], "evaluation of meta-command failed");
  2546. st->state = CSTATE_ABORTED;
  2547. break;
  2548. }
  2549. if (command->meta == META_SET)
  2550. {
  2551. if (!putVariableValue(st, argv[0], argv[1], &result))
  2552. {
  2553. commandFailed(st, "set", "assignment of meta-command failed");
  2554. st->state = CSTATE_ABORTED;
  2555. break;
  2556. }
  2557. }
  2558. else /* if and elif evaluated cases */
  2559. {
  2560. bool cond = valueTruth(&result);
  2561. /* execute or not depending on evaluated condition */
  2562. if (command->meta == META_IF)
  2563. {
  2564. conditional_stack_push(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
  2565. }
  2566. else /* elif */
  2567. {
  2568. /*
  2569. * we should get here only if the "elif"
  2570. * needed evaluation
  2571. */
  2572. Assert(conditional_stack_peek(st->cstack) == IFSTATE_FALSE);
  2573. conditional_stack_poke(st->cstack, cond ? IFSTATE_TRUE : IFSTATE_FALSE);
  2574. }
  2575. }
  2576. }
  2577. else if (command->meta == META_ELSE)
  2578. {
  2579. switch (conditional_stack_peek(st->cstack))
  2580. {
  2581. case IFSTATE_TRUE:
  2582. conditional_stack_poke(st->cstack, IFSTATE_ELSE_FALSE);
  2583. break;
  2584. case IFSTATE_FALSE: /* inconsistent if active */
  2585. case IFSTATE_IGNORED: /* inconsistent if active */
  2586. case IFSTATE_NONE: /* else without if */
  2587. case IFSTATE_ELSE_TRUE: /* else after else */
  2588. case IFSTATE_ELSE_FALSE: /* else after else */
  2589. default:
  2590. /* dead code if conditional check is ok */
  2591. Assert(false);
  2592. }
  2593. goto move_to_end_command;
  2594. }
  2595. else if (command->meta == META_ENDIF)
  2596. {
  2597. Assert(!conditional_stack_empty(st->cstack));
  2598. conditional_stack_pop(st->cstack);
  2599. goto move_to_end_command;
  2600. }
  2601. else if (command->meta == META_SETSHELL)
  2602. {
  2603. bool ret = runShellCommand(st, argv[1], argv + 2, argc - 2);
  2604. if (timer_exceeded) /* timeout */
  2605. {
  2606. st->state = CSTATE_FINISHED;
  2607. break;
  2608. }
  2609. else if (!ret) /* on error */
  2610. {
  2611. commandFailed(st, "setshell", "execution of meta-command failed");
  2612. st->state = CSTATE_ABORTED;
  2613. break;
  2614. }
  2615. else
  2616. {
  2617. /* succeeded */
  2618. }
  2619. }
  2620. else if (command->meta == META_SHELL)
  2621. {
  2622. bool ret = runShellCommand(st, NULL, argv + 1, argc - 1);
  2623. if (timer_exceeded) /* timeout */
  2624. {
  2625. st->state = CSTATE_FINISHED;
  2626. break;
  2627. }
  2628. else if (!ret) /* on error */
  2629. {
  2630. commandFailed(st, "shell", "execution of meta-command failed");
  2631. st->state = CSTATE_ABORTED;
  2632. break;
  2633. }
  2634. else
  2635. {
  2636. /* succeeded */
  2637. }
  2638. }
  2639. move_to_end_command:
  2640. /*
  2641. * executing the expression or shell command might take a
  2642. * non-negligible amount of time, so reset 'now'
  2643. */
  2644. INSTR_TIME_SET_ZERO(now);
  2645. st->state = CSTATE_END_COMMAND;
  2646. }
  2647. break;
  2648. /*
  2649. * non executed conditional branch
  2650. */
  2651. case CSTATE_SKIP_COMMAND:
  2652. Assert(!conditional_active(st->cstack));
  2653. /* quickly skip commands until something to do... */
  2654. while (true)
  2655. {
  2656. command = sql_script[st->use_file].commands[st->command];
  2657. /* cannot reach end of script in that state */
  2658. Assert(command != NULL);
  2659. /*
  2660. * if this is conditional related, update conditional
  2661. * state
  2662. */
  2663. if (command->type == META_COMMAND &&
  2664. (command->meta == META_IF ||
  2665. command->meta == META_ELIF ||
  2666. command->meta == META_ELSE ||
  2667. command->meta == META_ENDIF))
  2668. {
  2669. switch (conditional_stack_peek(st->cstack))
  2670. {
  2671. case IFSTATE_FALSE:
  2672. if (command->meta == META_IF || command->meta == META_ELIF)
  2673. {
  2674. /* we must evaluate the condition */
  2675. st->state = CSTATE_START_COMMAND;
  2676. }
  2677. else if (command->meta == META_ELSE)
  2678. {
  2679. /* we must execute next command */
  2680. conditional_stack_poke(st->cstack, IFSTATE_ELSE_TRUE);
  2681. st->state = CSTATE_START_COMMAND;
  2682. st->command++;
  2683. }
  2684. else if (command->meta == META_ENDIF)
  2685. {
  2686. Assert(!conditional_stack_empty(st->cstack));
  2687. conditional_stack_pop(st->cstack);
  2688. if (conditional_active(st->cstack))
  2689. st->state = CSTATE_START_COMMAND;
  2690. /*
  2691. * else state remains in
  2692. * CSTATE_SKIP_COMMAND
  2693. */
  2694. st->command++;
  2695. }
  2696. break;
  2697. case IFSTATE_IGNORED:
  2698. case IFSTATE_ELSE_FALSE:
  2699. if (command->meta == META_IF)
  2700. conditional_stack_push(st->cstack, IFSTATE_IGNORED);
  2701. else if (command->meta == META_ENDIF)
  2702. {
  2703. Assert(!conditional_stack_empty(st->cstack));
  2704. conditional_stack_pop(st->cstack);
  2705. if (conditional_active(st->cstack))
  2706. st->state = CSTATE_START_COMMAND;
  2707. }
  2708. /* could detect "else" & "elif" after "else" */
  2709. st->command++;
  2710. break;
  2711. case IFSTATE_NONE:
  2712. case IFSTATE_TRUE:
  2713. case IFSTATE_ELSE_TRUE:
  2714. default:
  2715. /*
  2716. * inconsistent if inactive, unreachable dead
  2717. * code
  2718. */
  2719. Assert(false);
  2720. }
  2721. }
  2722. else
  2723. {
  2724. /* skip and consider next */
  2725. st->command++;
  2726. }
  2727. if (st->state != CSTATE_SKIP_COMMAND)
  2728. break;
  2729. }
  2730. break;
  2731. /*
  2732. * Wait for the current SQL command to complete
  2733. */
  2734. case CSTATE_WAIT_RESULT:
  2735. command = sql_script[st->use_file].commands[st->command];
  2736. if (debug)
  2737. fprintf(stderr, "client %d receiving\n", st->id);
  2738. if (!PQconsumeInput(st->con))
  2739. { /* there's something wrong */
  2740. commandFailed(st, "SQL", "perhaps the backend died while processing");
  2741. st->state = CSTATE_ABORTED;
  2742. break;
  2743. }
  2744. if (PQisBusy(st->con))
  2745. return; /* don't have the whole result yet */
  2746. /*
  2747. * Read and discard the query result;
  2748. */
  2749. res = PQgetResult(st->con);
  2750. switch (PQresultStatus(res))
  2751. {
  2752. case PGRES_COMMAND_OK:
  2753. case PGRES_TUPLES_OK:
  2754. case PGRES_EMPTY_QUERY:
  2755. /* OK */
  2756. PQclear(res);
  2757. discard_response(st);
  2758. st->state = CSTATE_END_COMMAND;
  2759. break;
  2760. default:
  2761. commandFailed(st, "SQL", PQerrorMessage(st->con));
  2762. PQclear(res);
  2763. st->state = CSTATE_ABORTED;
  2764. break;
  2765. }
  2766. break;
  2767. /*
  2768. * Wait until sleep is done. This state is entered after a
  2769. * \sleep metacommand. The behavior is similar to
  2770. * CSTATE_THROTTLE, but proceeds to CSTATE_START_COMMAND
  2771. * instead of CSTATE_START_TX.
  2772. */
  2773. case CSTATE_SLEEP:
  2774. if (INSTR_TIME_IS_ZERO(now))
  2775. INSTR_TIME_SET_CURRENT(now);
  2776. if (INSTR_TIME_GET_MICROSEC(now) < st->sleep_until)
  2777. return; /* Still sleeping, nothing to do here */
  2778. /* Else done sleeping. */
  2779. st->state = CSTATE_END_COMMAND;
  2780. break;
  2781. /*
  2782. * End of command: record stats and proceed to next command.
  2783. */
  2784. case CSTATE_END_COMMAND:
  2785. /*
  2786. * command completed: accumulate per-command execution times
  2787. * in thread-local data structure, if per-command latencies
  2788. * are requested.
  2789. */
  2790. if (is_latencies)
  2791. {
  2792. if (INSTR_TIME_IS_ZERO(now))
  2793. INSTR_TIME_SET_CURRENT(now);
  2794. /* XXX could use a mutex here, but we choose not to */
  2795. command = sql_script[st->use_file].commands[st->command];
  2796. addToSimpleStats(&command->stats,
  2797. INSTR_TIME_GET_DOUBLE(now) -
  2798. INSTR_TIME_GET_DOUBLE(st->stmt_begin));
  2799. }
  2800. /* Go ahead with next command, to be executed or skipped */
  2801. st->command++;
  2802. st->state = conditional_active(st->cstack) ?
  2803. CSTATE_START_COMMAND : CSTATE_SKIP_COMMAND;
  2804. break;
  2805. /*
  2806. * End of transaction.
  2807. */
  2808. case CSTATE_END_TX:
  2809. /* transaction finished: calculate latency and do log */
  2810. processXactStats(thread, st, &now, false, agg);
  2811. /* conditional stack must be empty */
  2812. if (!conditional_stack_empty(st->cstack))
  2813. {
  2814. fprintf(stderr, "end of script reached within a conditional, missing \\endif\n");
  2815. exit(1);
  2816. }
  2817. if (is_connect)
  2818. {
  2819. finishCon(st);
  2820. INSTR_TIME_SET_ZERO(now);
  2821. }
  2822. if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
  2823. {
  2824. /* exit success */
  2825. st->state = CSTATE_FINISHED;
  2826. break;
  2827. }
  2828. /*
  2829. * No transaction is underway anymore.
  2830. */
  2831. st->state = CSTATE_CHOOSE_SCRIPT;
  2832. /*
  2833. * If we paced through all commands in the script in this
  2834. * loop, without returning to the caller even once, do it now.
  2835. * This gives the thread a chance to process other
  2836. * connections, and to do progress reporting. This can
  2837. * currently only happen if the script consists entirely of
  2838. * meta-commands.
  2839. */
  2840. if (end_tx_processed)
  2841. return;
  2842. else
  2843. {
  2844. end_tx_processed = true;
  2845. break;
  2846. }
  2847. /*
  2848. * Final states. Close the connection if it's still open.
  2849. */
  2850. case CSTATE_ABORTED:
  2851. case CSTATE_FINISHED:
  2852. finishCon(st);
  2853. return;
  2854. }
  2855. }
  2856. }
  2857. /*
  2858. * Print log entry after completing one transaction.
  2859. *
  2860. * We print Unix-epoch timestamps in the log, so that entries can be
  2861. * correlated against other logs. On some platforms this could be obtained
  2862. * from the instr_time reading the caller has, but rather than get entangled
  2863. * with that, we just eat the cost of an extra syscall in all cases.
  2864. */
  2865. static void
  2866. doLog(TState *thread, CState *st,
  2867. StatsData *agg, bool skipped, double latency, double lag)
  2868. {
  2869. FILE *logfile = thread->logfile;
  2870. Assert(use_log);
  2871. /*
  2872. * Skip the log entry if sampling is enabled and this row doesn't belong
  2873. * to the random sample.
  2874. */
  2875. if (sample_rate != 0.0 &&
  2876. pg_erand48(thread->random_state) > sample_rate)
  2877. return;
  2878. /* should we aggregate the results or not? */
  2879. if (agg_interval > 0)
  2880. {
  2881. /*
  2882. * Loop until we reach the interval of the current moment, and print
  2883. * any empty intervals in between (this may happen with very low tps,
  2884. * e.g. --rate=0.1).
  2885. */
  2886. time_t now = time(NULL);
  2887. while (agg->start_time + agg_interval <= now)
  2888. {
  2889. /* print aggregated report to logfile */
  2890. fprintf(logfile, "%ld " INT64_FORMAT " %.0f %.0f %.0f %.0f",
  2891. (long) agg->start_time,
  2892. agg->cnt,
  2893. agg->latency.sum,
  2894. agg->latency.sum2,
  2895. agg->latency.min,
  2896. agg->latency.max);
  2897. if (throttle_delay)
  2898. {
  2899. fprintf(logfile, " %.0f %.0f %.0f %.0f",
  2900. agg->lag.sum,
  2901. agg->lag.sum2,
  2902. agg->lag.min,
  2903. agg->lag.max);
  2904. if (latency_limit)
  2905. fprintf(logfile, " " INT64_FORMAT, agg->skipped);
  2906. }
  2907. fputc('\n', logfile);
  2908. /* reset data and move to next interval */
  2909. initStats(agg, agg->start_time + agg_interval);
  2910. }
  2911. /* accumulate the current transaction */
  2912. accumStats(agg, skipped, latency, lag);
  2913. }
  2914. else
  2915. {
  2916. /* no, print raw transactions */
  2917. struct timeval tv;
  2918. gettimeofday(&tv, NULL);
  2919. if (skipped)
  2920. fprintf(logfile, "%d " INT64_FORMAT " skipped %d %ld %ld",
  2921. st->id, st->cnt, st->use_file,
  2922. (long) tv.tv_sec, (long) tv.tv_usec);
  2923. else
  2924. fprintf(logfile, "%d " INT64_FORMAT " %.0f %d %ld %ld",
  2925. st->id, st->cnt, latency, st->use_file,
  2926. (long) tv.tv_sec, (long) tv.tv_usec);
  2927. if (throttle_delay)
  2928. fprintf(logfile, " %.0f", lag);
  2929. fputc('\n', logfile);
  2930. }
  2931. }
  2932. /*
  2933. * Accumulate and report statistics at end of a transaction.
  2934. *
  2935. * (This is also called when a transaction is late and thus skipped.
  2936. * Note that even skipped transactions are counted in the "cnt" fields.)
  2937. */
  2938. static void
  2939. processXactStats(TState *thread, CState *st, instr_time *now,
  2940. bool skipped, StatsData *agg)
  2941. {
  2942. double latency = 0.0,
  2943. lag = 0.0;
  2944. bool thread_details = progress || throttle_delay || latency_limit,
  2945. detailed = thread_details || use_log || per_script_stats;
  2946. if (detailed && !skipped)
  2947. {
  2948. if (INSTR_TIME_IS_ZERO(*now))
  2949. INSTR_TIME_SET_CURRENT(*now);
  2950. /* compute latency & lag */
  2951. latency = INSTR_TIME_GET_MICROSEC(*now) - st->txn_scheduled;
  2952. lag = INSTR_TIME_GET_MICROSEC(st->txn_begin) - st->txn_scheduled;
  2953. }
  2954. if (thread_details)
  2955. {
  2956. /* keep detailed thread stats */
  2957. accumStats(&thread->stats, skipped, latency, lag);
  2958. /* count transactions over the latency limit, if needed */
  2959. if (latency_limit && latency > latency_limit)
  2960. thread->latency_late++;
  2961. }
  2962. else
  2963. {
  2964. /* no detailed stats, just count */
  2965. thread->stats.cnt++;
  2966. }
  2967. /* client stat is just counting */
  2968. st->cnt++;
  2969. if (use_log)
  2970. doLog(thread, st, agg, skipped, latency, lag);
  2971. /* XXX could use a mutex here, but we choose not to */
  2972. if (per_script_stats)
  2973. accumStats(&sql_script[st->use_file].stats, skipped, latency, lag);
  2974. }
  2975. /* discard connections */
  2976. static void
  2977. disconnect_all(CState *state, int length)
  2978. {
  2979. int i;
  2980. for (i = 0; i < length; i++)
  2981. finishCon(&state[i]);
  2982. }
  2983. /*
  2984. * Remove old pgbench tables, if any exist
  2985. */
  2986. static void
  2987. initDropTables(PGconn *con)
  2988. {
  2989. fprintf(stderr, "dropping old tables...\n");
  2990. /*
  2991. * We drop all the tables in one command, so that whether there are
  2992. * foreign key dependencies or not doesn't matter.
  2993. */
  2994. executeStatement(con, "drop table if exists "
  2995. "pgbench_accounts, "
  2996. "pgbench_branches, "
  2997. "pgbench_history, "
  2998. "pgbench_tellers");
  2999. }
  3000. /*
  3001. * Create pgbench's standard tables
  3002. */
  3003. static void
  3004. initCreateTables(PGconn *con)
  3005. {
  3006. /*
  3007. * The scale factor at/beyond which 32-bit integers are insufficient for
  3008. * storing TPC-B account IDs.
  3009. *
  3010. * Although the actual threshold is 21474, we use 20000 because it is
  3011. * easier to document and remember, and isn't that far away from the real
  3012. * threshold.
  3013. */
  3014. #define SCALE_32BIT_THRESHOLD 20000
  3015. /*
  3016. * Note: TPC-B requires at least 100 bytes per row, and the "filler"
  3017. * fields in these table declarations were intended to comply with that.
  3018. * The pgbench_accounts table complies with that because the "filler"
  3019. * column is set to blank-padded empty string. But for all other tables
  3020. * the columns default to NULL and so don't actually take any space. We
  3021. * could fix that by giving them non-null default values. However, that
  3022. * would completely break comparability of pgbench results with prior
  3023. * versions. Since pgbench has never pretended to be fully TPC-B compliant
  3024. * anyway, we stick with the historical behavior.
  3025. */
  3026. struct ddlinfo
  3027. {
  3028. const char *table; /* table name */
  3029. const char *smcols; /* column decls if accountIDs are 32 bits */
  3030. const char *bigcols; /* column decls if accountIDs are 64 bits */
  3031. int declare_fillfactor;
  3032. };
  3033. static const struct ddlinfo DDLs[] = {
  3034. {
  3035. "pgbench_history",
  3036. "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
  3037. "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
  3038. 0
  3039. },
  3040. {
  3041. "pgbench_tellers",
  3042. "tid int not null,bid int,tbalance int,filler char(84)",
  3043. "tid int not null,bid int,tbalance int,filler char(84)",
  3044. 1
  3045. },
  3046. {
  3047. "pgbench_accounts",
  3048. "aid int not null,bid int,abalance int,filler char(84)",
  3049. "aid bigint not null,bid int,abalance int,filler char(84)",
  3050. 1
  3051. },
  3052. {
  3053. "pgbench_branches",
  3054. "bid int not null,bbalance int,filler char(88)",
  3055. "bid int not null,bbalance int,filler char(88)",
  3056. 1
  3057. }
  3058. };
  3059. int i;
  3060. fprintf(stderr, "creating tables...\n");
  3061. for (i = 0; i < lengthof(DDLs); i++)
  3062. {
  3063. char opts[256];
  3064. char buffer[256];
  3065. const struct ddlinfo *ddl = &DDLs[i];
  3066. const char *cols;
  3067. /* Construct new create table statement. */
  3068. opts[0] = '\0';
  3069. if (ddl->declare_fillfactor)
  3070. snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
  3071. " with (fillfactor=%d)", fillfactor);
  3072. if (tablespace != NULL)
  3073. {
  3074. char *escape_tablespace;
  3075. escape_tablespace = PQescapeIdentifier(con, tablespace,
  3076. strlen(tablespace));
  3077. snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
  3078. " tablespace %s", escape_tablespace);
  3079. PQfreemem(escape_tablespace);
  3080. }
  3081. cols = (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols;
  3082. snprintf(buffer, sizeof(buffer), "create%s table %s(%s)%s",
  3083. unlogged_tables ? " unlogged" : "",
  3084. ddl->table, cols, opts);
  3085. executeStatement(con, buffer);
  3086. }
  3087. }
  3088. /*
  3089. * Fill the standard tables with some data
  3090. */
  3091. static void
  3092. initGenerateData(PGconn *con)
  3093. {
  3094. char sql[256];
  3095. PGresult *res;
  3096. int i;
  3097. int64 k;
  3098. /* used to track elapsed time and estimate of the remaining time */
  3099. instr_time start,
  3100. diff;
  3101. double elapsed_sec,
  3102. remaining_sec;
  3103. int log_interval = 1;
  3104. fprintf(stderr, "generating data...\n");
  3105. /*
  3106. * we do all of this in one transaction to enable the backend's
  3107. * data-loading optimizations
  3108. */
  3109. executeStatement(con, "begin");
  3110. /*
  3111. * truncate away any old data, in one command in case there are foreign
  3112. * keys
  3113. */
  3114. executeStatement(con, "truncate table "
  3115. "pgbench_accounts, "
  3116. "pgbench_branches, "
  3117. "pgbench_history, "
  3118. "pgbench_tellers");
  3119. /*
  3120. * fill branches, tellers, accounts in that order in case foreign keys
  3121. * already exist
  3122. */
  3123. for (i = 0; i < nbranches * scale; i++)
  3124. {
  3125. /* "filler" column defaults to NULL */
  3126. snprintf(sql, sizeof(sql),
  3127. "insert into pgbench_branches(bid,bbalance) values(%d,0)",
  3128. i + 1);
  3129. executeStatement(con, sql);
  3130. }
  3131. for (i = 0; i < ntellers * scale; i++)
  3132. {
  3133. /* "filler" column defaults to NULL */
  3134. snprintf(sql, sizeof(sql),
  3135. "insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
  3136. i + 1, i / ntellers + 1);
  3137. executeStatement(con, sql);
  3138. }
  3139. /*
  3140. * accounts is big enough to be worth using COPY and tracking runtime
  3141. */
  3142. res = PQexec(con, "copy pgbench_accounts from stdin");
  3143. if (PQresultStatus(res) != PGRES_COPY_IN)
  3144. {
  3145. fprintf(stderr, "%s", PQerrorMessage(con));
  3146. exit(1);
  3147. }
  3148. PQclear(res);
  3149. INSTR_TIME_SET_CURRENT(start);
  3150. for (k = 0; k < (int64) naccounts * scale; k++)
  3151. {
  3152. int64 j = k + 1;
  3153. /* "filler" column defaults to blank padded empty string */
  3154. snprintf(sql, sizeof(sql),
  3155. INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
  3156. j, k / naccounts + 1, 0);
  3157. if (PQputline(con, sql))
  3158. {
  3159. fprintf(stderr, "PQputline failed\n");
  3160. exit(1);
  3161. }
  3162. /*
  3163. * If we want to stick with the original logging, print a message each
  3164. * 100k inserted rows.
  3165. */
  3166. if ((!use_quiet) && (j % 100000 == 0))
  3167. {
  3168. INSTR_TIME_SET_CURRENT(diff);
  3169. INSTR_TIME_SUBTRACT(diff, start);
  3170. elapsed_sec = INSTR_TIME_GET_DOUBLE(diff);
  3171. remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
  3172. fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)\n",
  3173. j, (int64) naccounts * scale,
  3174. (int) (((int64) j * 100) / (naccounts * (int64) scale)),
  3175. elapsed_sec, remaining_sec);
  3176. }
  3177. /* let's not call the timing for each row, but only each 100 rows */
  3178. else if (use_quiet && (j % 100 == 0))
  3179. {
  3180. INSTR_TIME_SET_CURRENT(diff);
  3181. INSTR_TIME_SUBTRACT(diff, start);
  3182. elapsed_sec = INSTR_TIME_GET_DOUBLE(diff);
  3183. remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
  3184. /* have we reached the next interval (or end)? */
  3185. if ((j == scale * naccounts) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
  3186. {
  3187. fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)\n",
  3188. j, (int64) naccounts * scale,
  3189. (int) (((int64) j * 100) / (naccounts * (int64) scale)), elapsed_sec, remaining_sec);
  3190. /* skip to the next interval */
  3191. log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
  3192. }
  3193. }
  3194. }
  3195. if (PQputline(con, "\\.\n"))
  3196. {
  3197. fprintf(stderr, "very last PQputline failed\n");
  3198. exit(1);
  3199. }
  3200. if (PQendcopy(con))
  3201. {
  3202. fprintf(stderr, "PQendcopy failed\n");
  3203. exit(1);
  3204. }
  3205. executeStatement(con, "commit");
  3206. }
  3207. /*
  3208. * Invoke vacuum on the standard tables
  3209. */
  3210. static void
  3211. initVacuum(PGconn *con)
  3212. {
  3213. fprintf(stderr, "vacuuming...\n");
  3214. executeStatement(con, "vacuum analyze pgbench_branches");
  3215. executeStatement(con, "vacuum analyze pgbench_tellers");
  3216. executeStatement(con, "vacuum analyze pgbench_accounts");
  3217. executeStatement(con, "vacuum analyze pgbench_history");
  3218. }
  3219. /*
  3220. * Create primary keys on the standard tables
  3221. */
  3222. static void
  3223. initCreatePKeys(PGconn *con)
  3224. {
  3225. static const char *const DDLINDEXes[] = {
  3226. "alter table pgbench_branches add primary key (bid)",
  3227. "alter table pgbench_tellers add primary key (tid)",
  3228. "alter table pgbench_accounts add primary key (aid)"
  3229. };
  3230. int i;
  3231. fprintf(stderr, "creating primary keys...\n");
  3232. for (i = 0; i < lengthof(DDLINDEXes); i++)
  3233. {
  3234. char buffer[256];
  3235. strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
  3236. if (index_tablespace != NULL)
  3237. {
  3238. char *escape_tablespace;
  3239. escape_tablespace = PQescapeIdentifier(con, index_tablespace,
  3240. strlen(index_tablespace));
  3241. snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
  3242. " using index tablespace %s", escape_tablespace);
  3243. PQfreemem(escape_tablespace);
  3244. }
  3245. executeStatement(con, buffer);
  3246. }
  3247. }
  3248. /*
  3249. * Create foreign key constraints between the standard tables
  3250. */
  3251. static void
  3252. initCreateFKeys(PGconn *con)
  3253. {
  3254. static const char *const DDLKEYs[] = {
  3255. "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
  3256. "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
  3257. "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
  3258. "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
  3259. "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
  3260. };
  3261. int i;
  3262. fprintf(stderr, "creating foreign keys...\n");
  3263. for (i = 0; i < lengthof(DDLKEYs); i++)
  3264. {
  3265. executeStatement(con, DDLKEYs[i]);
  3266. }
  3267. }
  3268. /*
  3269. * Validate an initialization-steps string
  3270. *
  3271. * (We could just leave it to runInitSteps() to fail if there are wrong
  3272. * characters, but since initialization can take awhile, it seems friendlier
  3273. * to check during option parsing.)
  3274. */
  3275. static void
  3276. checkInitSteps(const char *initialize_steps)
  3277. {
  3278. const char *step;
  3279. if (initialize_steps[0] == '\0')
  3280. {
  3281. fprintf(stderr, "no initialization steps specified\n");
  3282. exit(1);
  3283. }
  3284. for (step = initialize_steps; *step != '\0'; step++)
  3285. {
  3286. if (strchr("dtgvpf ", *step) == NULL)
  3287. {
  3288. fprintf(stderr, "unrecognized initialization step \"%c\"\n",
  3289. *step);
  3290. fprintf(stderr, "allowed steps are: \"d\", \"t\", \"g\", \"v\", \"p\", \"f\"\n");
  3291. exit(1);
  3292. }
  3293. }
  3294. }
  3295. /*
  3296. * Invoke each initialization step in the given string
  3297. */
  3298. static void
  3299. runInitSteps(const char *initialize_steps)
  3300. {
  3301. PGconn *con;
  3302. const char *step;
  3303. if ((con = doConnect()) == NULL)
  3304. exit(1);
  3305. for (step = initialize_steps; *step != '\0'; step++)
  3306. {
  3307. switch (*step)
  3308. {
  3309. case 'd':
  3310. initDropTables(con);
  3311. break;
  3312. case 't':
  3313. initCreateTables(con);
  3314. break;
  3315. case 'g':
  3316. initGenerateData(con);
  3317. break;
  3318. case 'v':
  3319. initVacuum(con);
  3320. break;
  3321. case 'p':
  3322. initCreatePKeys(con);
  3323. break;
  3324. case 'f':
  3325. initCreateFKeys(con);
  3326. break;
  3327. case ' ':
  3328. break; /* ignore */
  3329. default:
  3330. fprintf(stderr, "unrecognized initialization step \"%c\"\n",
  3331. *step);
  3332. PQfinish(con);
  3333. exit(1);
  3334. }
  3335. }
  3336. fprintf(stderr, "done.\n");
  3337. PQfinish(con);
  3338. }
  3339. /*
  3340. * Replace :param with $n throughout the command's SQL text, which
  3341. * is a modifiable string in cmd->argv[0].
  3342. */
  3343. static bool
  3344. parseQuery(Command *cmd)
  3345. {
  3346. char *sql,
  3347. *p;
  3348. /* We don't want to scribble on cmd->argv[0] until done */
  3349. sql = pg_strdup(cmd->argv[0]);
  3350. cmd->argc = 1;
  3351. p = sql;
  3352. while ((p = strchr(p, ':')) != NULL)
  3353. {
  3354. char var[13];
  3355. char *name;
  3356. int eaten;
  3357. name = parseVariable(p, &eaten);
  3358. if (name == NULL)
  3359. {
  3360. while (*p == ':')
  3361. {
  3362. p++;
  3363. }
  3364. continue;
  3365. }
  3366. if (cmd->argc >= MAX_ARGS)
  3367. {
  3368. fprintf(stderr, "statement has too many arguments (maximum is %d): %s\n",
  3369. MAX_ARGS - 1, cmd->argv[0]);
  3370. pg_free(name);
  3371. return false;
  3372. }
  3373. sprintf(var, "$%d", cmd->argc);
  3374. p = replaceVariable(&sql, p, eaten, var);
  3375. cmd->argv[cmd->argc] = name;
  3376. cmd->argc++;
  3377. }
  3378. pg_free(cmd->argv[0]);
  3379. cmd->argv[0] = sql;
  3380. return true;
  3381. }
  3382. /*
  3383. * Simple error-printing function, might be needed by lexer
  3384. */
  3385. static void
  3386. pgbench_error(const char *fmt,...)
  3387. {
  3388. va_list ap;
  3389. fflush(stdout);
  3390. va_start(ap, fmt);
  3391. vfprintf(stderr, _(fmt), ap);
  3392. va_end(ap);
  3393. }
  3394. /*
  3395. * syntax error while parsing a script (in practice, while parsing a
  3396. * backslash command, because we don't detect syntax errors in SQL)
  3397. *
  3398. * source: source of script (filename or builtin-script ID)
  3399. * lineno: line number within script (count from 1)
  3400. * line: whole line of backslash command, if available
  3401. * command: backslash command name, if available
  3402. * msg: the actual error message
  3403. * more: optional extra message
  3404. * column: zero-based column number, or -1 if unknown
  3405. */
  3406. void
  3407. syntax_error(const char *source, int lineno,
  3408. const char *line, const char *command,
  3409. const char *msg, const char *more, int column)
  3410. {
  3411. fprintf(stderr, "%s:%d: %s", source, lineno, msg);
  3412. if (more != NULL)
  3413. fprintf(stderr, " (%s)", more);
  3414. if (column >= 0 && line == NULL)
  3415. fprintf(stderr, " at column %d", column + 1);
  3416. if (command != NULL)
  3417. fprintf(stderr, " in command \"%s\"", command);
  3418. fprintf(stderr, "\n");
  3419. if (line != NULL)
  3420. {
  3421. fprintf(stderr, "%s\n", line);
  3422. if (column >= 0)
  3423. {
  3424. int i;
  3425. for (i = 0; i < column; i++)
  3426. fprintf(stderr, " ");
  3427. fprintf(stderr, "^ error found here\n");
  3428. }
  3429. }
  3430. exit(1);
  3431. }
  3432. /*
  3433. * Parse a SQL command; return a Command struct, or NULL if it's a comment
  3434. *
  3435. * On entry, psqlscan.l has collected the command into "buf", so we don't
  3436. * really need to do much here except check for comment and set up a
  3437. * Command struct.
  3438. */
  3439. static Command *
  3440. process_sql_command(PQExpBuffer buf, const char *source)
  3441. {
  3442. Command *my_command;
  3443. char *p;
  3444. char *nlpos;
  3445. /* Skip any leading whitespace, as well as "--" style comments */
  3446. p = buf->data;
  3447. for (;;)
  3448. {
  3449. if (isspace((unsigned char) *p))
  3450. p++;
  3451. else if (strncmp(p, "--", 2) == 0)
  3452. {
  3453. p = strchr(p, '\n');
  3454. if (p == NULL)
  3455. return NULL;
  3456. p++;
  3457. }
  3458. else
  3459. break;
  3460. }
  3461. /* If there's nothing but whitespace and comments, we're done */
  3462. if (*p == '\0')
  3463. return NULL;
  3464. /* Allocate and initialize Command structure */
  3465. my_command = (Command *) pg_malloc0(sizeof(Command));
  3466. my_command->command_num = num_commands++;
  3467. my_command->type = SQL_COMMAND;
  3468. my_command->meta = META_NONE;
  3469. initSimpleStats(&my_command->stats);
  3470. /*
  3471. * Install query text as the sole argv string. If we are using a
  3472. * non-simple query mode, we'll extract parameters from it later.
  3473. */
  3474. my_command->argv[0] = pg_strdup(p);
  3475. my_command->argc = 1;
  3476. /*
  3477. * If SQL command is multi-line, we only want to save the first line as
  3478. * the "line" label.
  3479. */
  3480. nlpos = strchr(p, '\n');
  3481. if (nlpos)
  3482. {
  3483. my_command->line = pg_malloc(nlpos - p + 1);
  3484. memcpy(my_command->line, p, nlpos - p);
  3485. my_command->line[nlpos - p] = '\0';
  3486. }
  3487. else
  3488. my_command->line = pg_strdup(p);
  3489. return my_command;
  3490. }
  3491. /*
  3492. * Parse a backslash command; return a Command struct, or NULL if comment
  3493. *
  3494. * At call, we have scanned only the initial backslash.
  3495. */
  3496. static Command *
  3497. process_backslash_command(PsqlScanState sstate, const char *source)
  3498. {
  3499. Command *my_command;
  3500. PQExpBufferData word_buf;
  3501. int word_offset;
  3502. int offsets[MAX_ARGS]; /* offsets of argument words */
  3503. int start_offset;
  3504. int lineno;
  3505. int j;
  3506. initPQExpBuffer(&word_buf);
  3507. /* Remember location of the backslash */
  3508. start_offset = expr_scanner_offset(sstate) - 1;
  3509. lineno = expr_scanner_get_lineno(sstate, start_offset);
  3510. /* Collect first word of command */
  3511. if (!expr_lex_one_word(sstate, &word_buf, &word_offset))
  3512. {
  3513. termPQExpBuffer(&word_buf);
  3514. return NULL;
  3515. }
  3516. /* Allocate and initialize Command structure */
  3517. my_command = (Command *) pg_malloc0(sizeof(Command));
  3518. my_command->command_num = num_commands++;
  3519. my_command->type = META_COMMAND;
  3520. my_command->argc = 0;
  3521. initSimpleStats(&my_command->stats);
  3522. /* Save first word (command name) */
  3523. j = 0;
  3524. offsets[j] = word_offset;
  3525. my_command->argv[j++] = pg_strdup(word_buf.data);
  3526. my_command->argc++;
  3527. /* ... and convert it to enum form */
  3528. my_command->meta = getMetaCommand(my_command->argv[0]);
  3529. if (my_command->meta == META_SET ||
  3530. my_command->meta == META_IF ||
  3531. my_command->meta == META_ELIF)
  3532. {
  3533. yyscan_t yyscanner;
  3534. /* For \set, collect var name */
  3535. if (my_command->meta == META_SET)
  3536. {
  3537. if (!expr_lex_one_word(sstate, &word_buf, &word_offset))
  3538. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3539. "missing argument", NULL, -1);
  3540. offsets[j] = word_offset;
  3541. my_command->argv[j++] = pg_strdup(word_buf.data);
  3542. my_command->argc++;
  3543. }
  3544. /* then for all parse the expression */
  3545. yyscanner = expr_scanner_init(sstate, source, lineno, start_offset,
  3546. my_command->argv[0]);
  3547. if (expr_yyparse(yyscanner) != 0)
  3548. {
  3549. /* dead code: exit done from syntax_error called by yyerror */
  3550. exit(1);
  3551. }
  3552. my_command->expr = expr_parse_result;
  3553. /* Save line, trimming any trailing newline */
  3554. my_command->line = expr_scanner_get_substring(sstate,
  3555. start_offset,
  3556. expr_scanner_offset(sstate),
  3557. true);
  3558. expr_scanner_finish(yyscanner);
  3559. termPQExpBuffer(&word_buf);
  3560. return my_command;
  3561. }
  3562. /* For all other commands, collect remaining words. */
  3563. while (expr_lex_one_word(sstate, &word_buf, &word_offset))
  3564. {
  3565. if (j >= MAX_ARGS)
  3566. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3567. "too many arguments", NULL, -1);
  3568. offsets[j] = word_offset;
  3569. my_command->argv[j++] = pg_strdup(word_buf.data);
  3570. my_command->argc++;
  3571. }
  3572. /* Save line, trimming any trailing newline */
  3573. my_command->line = expr_scanner_get_substring(sstate,
  3574. start_offset,
  3575. expr_scanner_offset(sstate),
  3576. true);
  3577. if (my_command->meta == META_SLEEP)
  3578. {
  3579. if (my_command->argc < 2)
  3580. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3581. "missing argument", NULL, -1);
  3582. if (my_command->argc > 3)
  3583. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3584. "too many arguments", NULL,
  3585. offsets[3] - start_offset);
  3586. /*
  3587. * Split argument into number and unit to allow "sleep 1ms" etc. We
  3588. * don't have to terminate the number argument with null because it
  3589. * will be parsed with atoi, which ignores trailing non-digit
  3590. * characters.
  3591. */
  3592. if (my_command->argc == 2 && my_command->argv[1][0] != ':')
  3593. {
  3594. char *c = my_command->argv[1];
  3595. while (isdigit((unsigned char) *c))
  3596. c++;
  3597. if (*c)
  3598. {
  3599. my_command->argv[2] = c;
  3600. offsets[2] = offsets[1] + (c - my_command->argv[1]);
  3601. my_command->argc = 3;
  3602. }
  3603. }
  3604. if (my_command->argc == 3)
  3605. {
  3606. if (pg_strcasecmp(my_command->argv[2], "us") != 0 &&
  3607. pg_strcasecmp(my_command->argv[2], "ms") != 0 &&
  3608. pg_strcasecmp(my_command->argv[2], "s") != 0)
  3609. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3610. "unrecognized time unit, must be us, ms or s",
  3611. my_command->argv[2], offsets[2] - start_offset);
  3612. }
  3613. }
  3614. else if (my_command->meta == META_SETSHELL)
  3615. {
  3616. if (my_command->argc < 3)
  3617. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3618. "missing argument", NULL, -1);
  3619. }
  3620. else if (my_command->meta == META_SHELL)
  3621. {
  3622. if (my_command->argc < 2)
  3623. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3624. "missing command", NULL, -1);
  3625. }
  3626. else if (my_command->meta == META_ELSE || my_command->meta == META_ENDIF)
  3627. {
  3628. if (my_command->argc != 1)
  3629. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3630. "unexpected argument", NULL, -1);
  3631. }
  3632. else
  3633. {
  3634. /* my_command->meta == META_NONE */
  3635. syntax_error(source, lineno, my_command->line, my_command->argv[0],
  3636. "invalid command", NULL, -1);
  3637. }
  3638. termPQExpBuffer(&word_buf);
  3639. return my_command;
  3640. }
  3641. static void
  3642. ConditionError(const char *desc, int cmdn, const char *msg)
  3643. {
  3644. fprintf(stderr,
  3645. "condition error in script \"%s\" command %d: %s\n",
  3646. desc, cmdn, msg);
  3647. exit(1);
  3648. }
  3649. /*
  3650. * Partial evaluation of conditionals before recording and running the script.
  3651. */
  3652. static void
  3653. CheckConditional(ParsedScript ps)
  3654. {
  3655. /* statically check conditional structure */
  3656. ConditionalStack cs = conditional_stack_create();
  3657. int i;
  3658. for (i = 0; ps.commands[i] != NULL; i++)
  3659. {
  3660. Command *cmd = ps.commands[i];
  3661. if (cmd->type == META_COMMAND)
  3662. {
  3663. switch (cmd->meta)
  3664. {
  3665. case META_IF:
  3666. conditional_stack_push(cs, IFSTATE_FALSE);
  3667. break;
  3668. case META_ELIF:
  3669. if (conditional_stack_empty(cs))
  3670. ConditionError(ps.desc, i + 1, "\\elif without matching \\if");
  3671. if (conditional_stack_peek(cs) == IFSTATE_ELSE_FALSE)
  3672. ConditionError(ps.desc, i + 1, "\\elif after \\else");
  3673. break;
  3674. case META_ELSE:
  3675. if (conditional_stack_empty(cs))
  3676. ConditionError(ps.desc, i + 1, "\\else without matching \\if");
  3677. if (conditional_stack_peek(cs) == IFSTATE_ELSE_FALSE)
  3678. ConditionError(ps.desc, i + 1, "\\else after \\else");
  3679. conditional_stack_poke(cs, IFSTATE_ELSE_FALSE);
  3680. break;
  3681. case META_ENDIF:
  3682. if (!conditional_stack_pop(cs))
  3683. ConditionError(ps.desc, i + 1, "\\endif without matching \\if");
  3684. break;
  3685. default:
  3686. /* ignore anything else... */
  3687. break;
  3688. }
  3689. }
  3690. }
  3691. if (!conditional_stack_empty(cs))
  3692. ConditionError(ps.desc, i + 1, "\\if without matching \\endif");
  3693. conditional_stack_destroy(cs);
  3694. }
  3695. /*
  3696. * Parse a script (either the contents of a file, or a built-in script)
  3697. * and add it to the list of scripts.
  3698. */
  3699. static void
  3700. ParseScript(const char *script, const char *desc, int weight)
  3701. {
  3702. ParsedScript ps;
  3703. PsqlScanState sstate;
  3704. PQExpBufferData line_buf;
  3705. int alloc_num;
  3706. int index;
  3707. #define COMMANDS_ALLOC_NUM 128
  3708. alloc_num = COMMANDS_ALLOC_NUM;
  3709. /* Initialize all fields of ps */
  3710. ps.desc = desc;
  3711. ps.weight = weight;
  3712. ps.commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
  3713. initStats(&ps.stats, 0);
  3714. /* Prepare to parse script */
  3715. sstate = psql_scan_create(&pgbench_callbacks);
  3716. /*
  3717. * Ideally, we'd scan scripts using the encoding and stdstrings settings
  3718. * we get from a DB connection. However, without major rearrangement of
  3719. * pgbench's argument parsing, we can't have a DB connection at the time
  3720. * we parse scripts. Using SQL_ASCII (encoding 0) should work well enough
  3721. * with any backend-safe encoding, though conceivably we could be fooled
  3722. * if a script file uses a client-only encoding. We also assume that
  3723. * stdstrings should be true, which is a bit riskier.
  3724. */
  3725. psql_scan_setup(sstate, script, strlen(script), 0, true);
  3726. initPQExpBuffer(&line_buf);
  3727. index = 0;
  3728. for (;;)
  3729. {
  3730. PsqlScanResult sr;
  3731. promptStatus_t prompt;
  3732. Command *command;
  3733. resetPQExpBuffer(&line_buf);
  3734. sr = psql_scan(sstate, &line_buf, &prompt);
  3735. /* If we collected a SQL command, process that */
  3736. command = process_sql_command(&line_buf, desc);
  3737. if (command)
  3738. {
  3739. ps.commands[index] = command;
  3740. index++;
  3741. if (index >= alloc_num)
  3742. {
  3743. alloc_num += COMMANDS_ALLOC_NUM;
  3744. ps.commands = (Command **)
  3745. pg_realloc(ps.commands, sizeof(Command *) * alloc_num);
  3746. }
  3747. }
  3748. /* If we reached a backslash, process that */
  3749. if (sr == PSCAN_BACKSLASH)
  3750. {
  3751. command = process_backslash_command(sstate, desc);
  3752. if (command)
  3753. {
  3754. ps.commands[index] = command;
  3755. index++;
  3756. if (index >= alloc_num)
  3757. {
  3758. alloc_num += COMMANDS_ALLOC_NUM;
  3759. ps.commands = (Command **)
  3760. pg_realloc(ps.commands, sizeof(Command *) * alloc_num);
  3761. }
  3762. }
  3763. }
  3764. /* Done if we reached EOF */
  3765. if (sr == PSCAN_INCOMPLETE || sr == PSCAN_EOL)
  3766. break;
  3767. }
  3768. ps.commands[index] = NULL;
  3769. addScript(ps);
  3770. termPQExpBuffer(&line_buf);
  3771. psql_scan_finish(sstate);
  3772. psql_scan_destroy(sstate);
  3773. }
  3774. /*
  3775. * Read the entire contents of file fd, and return it in a malloc'd buffer.
  3776. *
  3777. * The buffer will typically be larger than necessary, but we don't care
  3778. * in this program, because we'll free it as soon as we've parsed the script.
  3779. */
  3780. static char *
  3781. read_file_contents(FILE *fd)
  3782. {
  3783. char *buf;
  3784. size_t buflen = BUFSIZ;
  3785. size_t used = 0;
  3786. buf = (char *) pg_malloc(buflen);
  3787. for (;;)
  3788. {
  3789. size_t nread;
  3790. nread = fread(buf + used, 1, BUFSIZ, fd);
  3791. used += nread;
  3792. /* If fread() read less than requested, must be EOF or error */
  3793. if (nread < BUFSIZ)
  3794. break;
  3795. /* Enlarge buf so we can read some more */
  3796. buflen += BUFSIZ;
  3797. buf = (char *) pg_realloc(buf, buflen);
  3798. }
  3799. /* There is surely room for a terminator */
  3800. buf[used] = '\0';
  3801. return buf;
  3802. }
  3803. /*
  3804. * Given a file name, read it and add its script to the list.
  3805. * "-" means to read stdin.
  3806. * NB: filename must be storage that won't disappear.
  3807. */
  3808. static void
  3809. process_file(const char *filename, int weight)
  3810. {
  3811. FILE *fd;
  3812. char *buf;
  3813. /* Slurp the file contents into "buf" */
  3814. if (strcmp(filename, "-") == 0)
  3815. fd = stdin;
  3816. else if ((fd = fopen(filename, "r")) == NULL)
  3817. {
  3818. fprintf(stderr, "could not open file \"%s\": %s\n",
  3819. filename, strerror(errno));
  3820. exit(1);
  3821. }
  3822. buf = read_file_contents(fd);
  3823. if (ferror(fd))
  3824. {
  3825. fprintf(stderr, "could not read file \"%s\": %s\n",
  3826. filename, strerror(errno));
  3827. exit(1);
  3828. }
  3829. if (fd != stdin)
  3830. fclose(fd);
  3831. ParseScript(buf, filename, weight);
  3832. free(buf);
  3833. }
  3834. /* Parse the given builtin script and add it to the list. */
  3835. static void
  3836. process_builtin(const BuiltinScript *bi, int weight)
  3837. {
  3838. ParseScript(bi->script, bi->desc, weight);
  3839. }
  3840. /* show available builtin scripts */
  3841. static void
  3842. listAvailableScripts(void)
  3843. {
  3844. int i;
  3845. fprintf(stderr, "Available builtin scripts:\n");
  3846. for (i = 0; i < lengthof(builtin_script); i++)
  3847. fprintf(stderr, "\t%s\n", builtin_script[i].name);
  3848. fprintf(stderr, "\n");
  3849. }
  3850. /* return builtin script "name" if unambiguous, fails if not found */
  3851. static const BuiltinScript *
  3852. findBuiltin(const char *name)
  3853. {
  3854. int i,
  3855. found = 0,
  3856. len = strlen(name);
  3857. const BuiltinScript *result = NULL;
  3858. for (i = 0; i < lengthof(builtin_script); i++)
  3859. {
  3860. if (strncmp(builtin_script[i].name, name, len) == 0)
  3861. {
  3862. result = &builtin_script[i];
  3863. found++;
  3864. }
  3865. }
  3866. /* ok, unambiguous result */
  3867. if (found == 1)
  3868. return result;
  3869. /* error cases */
  3870. if (found == 0)
  3871. fprintf(stderr, "no builtin script found for name \"%s\"\n", name);
  3872. else /* found > 1 */
  3873. fprintf(stderr,
  3874. "ambiguous builtin name: %d builtin scripts found for prefix \"%s\"\n", found, name);
  3875. listAvailableScripts();
  3876. exit(1);
  3877. }
  3878. /*
  3879. * Determine the weight specification from a script option (-b, -f), if any,
  3880. * and return it as an integer (1 is returned if there's no weight). The
  3881. * script name is returned in *script as a malloc'd string.
  3882. */
  3883. static int
  3884. parseScriptWeight(const char *option, char **script)
  3885. {
  3886. char *sep;
  3887. int weight;
  3888. if ((sep = strrchr(option, WSEP)))
  3889. {
  3890. int namelen = sep - option;
  3891. long wtmp;
  3892. char *badp;
  3893. /* generate the script name */
  3894. *script = pg_malloc(namelen + 1);
  3895. strncpy(*script, option, namelen);
  3896. (*script)[namelen] = '\0';
  3897. /* process digits of the weight spec */
  3898. errno = 0;
  3899. wtmp = strtol(sep + 1, &badp, 10);
  3900. if (errno != 0 || badp == sep + 1 || *badp != '\0')
  3901. {
  3902. fprintf(stderr, "invalid weight specification: %s\n", sep);
  3903. exit(1);
  3904. }
  3905. if (wtmp > INT_MAX || wtmp < 0)
  3906. {
  3907. fprintf(stderr,
  3908. "weight specification out of range (0 .. %u): " INT64_FORMAT "\n",
  3909. INT_MAX, (int64) wtmp);
  3910. exit(1);
  3911. }
  3912. weight = wtmp;
  3913. }
  3914. else
  3915. {
  3916. *script = pg_strdup(option);
  3917. weight = 1;
  3918. }
  3919. return weight;
  3920. }
  3921. /* append a script to the list of scripts to process */
  3922. static void
  3923. addScript(ParsedScript script)
  3924. {
  3925. if (script.commands == NULL || script.commands[0] == NULL)
  3926. {
  3927. fprintf(stderr, "empty command list for script \"%s\"\n", script.desc);
  3928. exit(1);
  3929. }
  3930. if (num_scripts >= MAX_SCRIPTS)
  3931. {
  3932. fprintf(stderr, "at most %d SQL scripts are allowed\n", MAX_SCRIPTS);
  3933. exit(1);
  3934. }
  3935. CheckConditional(script);
  3936. sql_script[num_scripts] = script;
  3937. num_scripts++;
  3938. }
  3939. static void
  3940. printSimpleStats(const char *prefix, SimpleStats *ss)
  3941. {
  3942. if (ss->count > 0)
  3943. {
  3944. double latency = ss->sum / ss->count;
  3945. double stddev = sqrt(ss->sum2 / ss->count - latency * latency);
  3946. printf("%s average = %.3f ms\n", prefix, 0.001 * latency);
  3947. printf("%s stddev = %.3f ms\n", prefix, 0.001 * stddev);
  3948. }
  3949. }
  3950. /* print out results */
  3951. static void
  3952. printResults(TState *threads, StatsData *total, instr_time total_time,
  3953. instr_time conn_total_time, int64 latency_late)
  3954. {
  3955. double time_include,
  3956. tps_include,
  3957. tps_exclude;
  3958. int64 ntx = total->cnt - total->skipped;
  3959. int i,
  3960. totalCacheOverflows = 0;
  3961. time_include = INSTR_TIME_GET_DOUBLE(total_time);
  3962. /* tps is about actually executed transactions */
  3963. tps_include = ntx / time_include;
  3964. tps_exclude = ntx /
  3965. (time_include - (INSTR_TIME_GET_DOUBLE(conn_total_time) / nclients));
  3966. /* Report test parameters. */
  3967. printf("transaction type: %s\n",
  3968. num_scripts == 1 ? sql_script[0].desc : "multiple scripts");
  3969. printf("scaling factor: %d\n", scale);
  3970. printf("query mode: %s\n", QUERYMODE[querymode]);
  3971. printf("number of clients: %d\n", nclients);
  3972. printf("number of threads: %d\n", nthreads);
  3973. if (duration <= 0)
  3974. {
  3975. printf("number of transactions per client: %d\n", nxacts);
  3976. printf("number of transactions actually processed: " INT64_FORMAT "/%d\n",
  3977. ntx, nxacts * nclients);
  3978. }
  3979. else
  3980. {
  3981. printf("duration: %d s\n", duration);
  3982. printf("number of transactions actually processed: " INT64_FORMAT "\n",
  3983. ntx);
  3984. }
  3985. /* Report zipfian cache overflow */
  3986. for (i = 0; i < nthreads; i++)
  3987. {
  3988. totalCacheOverflows += threads[i].zipf_cache.overflowCount;
  3989. }
  3990. if (totalCacheOverflows > 0)
  3991. {
  3992. printf("zipfian cache array overflowed %d time(s)\n", totalCacheOverflows);
  3993. }
  3994. /* Remaining stats are nonsensical if we failed to execute any xacts */
  3995. if (total->cnt <= 0)
  3996. return;
  3997. if (throttle_delay && latency_limit)
  3998. printf("number of transactions skipped: " INT64_FORMAT " (%.3f %%)\n",
  3999. total->skipped,
  4000. 100.0 * total->skipped / total->cnt);
  4001. if (latency_limit)
  4002. printf("number of transactions above the %.1f ms latency limit: " INT64_FORMAT "/" INT64_FORMAT " (%.3f %%)\n",
  4003. latency_limit / 1000.0, latency_late, ntx,
  4004. (ntx > 0) ? 100.0 * latency_late / ntx : 0.0);
  4005. if (throttle_delay || progress || latency_limit)
  4006. printSimpleStats("latency", &total->latency);
  4007. else
  4008. {
  4009. /* no measurement, show average latency computed from run time */
  4010. printf("latency average = %.3f ms\n",
  4011. 1000.0 * time_include * nclients / total->cnt);
  4012. }
  4013. if (throttle_delay)
  4014. {
  4015. /*
  4016. * Report average transaction lag under rate limit throttling. This
  4017. * is the delay between scheduled and actual start times for the
  4018. * transaction. The measured lag may be caused by thread/client load,
  4019. * the database load, or the Poisson throttling process.
  4020. */
  4021. printf("rate limit schedule lag: avg %.3f (max %.3f) ms\n",
  4022. 0.001 * total->lag.sum / total->cnt, 0.001 * total->lag.max);
  4023. }
  4024. printf("tps = %f (including connections establishing)\n", tps_include);
  4025. printf("tps = %f (excluding connections establishing)\n", tps_exclude);
  4026. /* Report per-script/command statistics */
  4027. if (per_script_stats || is_latencies)
  4028. {
  4029. int i;
  4030. for (i = 0; i < num_scripts; i++)
  4031. {
  4032. if (per_script_stats)
  4033. {
  4034. StatsData *sstats = &sql_script[i].stats;
  4035. printf("SQL script %d: %s\n"
  4036. " - weight: %d (targets %.1f%% of total)\n"
  4037. " - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
  4038. i + 1, sql_script[i].desc,
  4039. sql_script[i].weight,
  4040. 100.0 * sql_script[i].weight / total_weight,
  4041. sstats->cnt,
  4042. 100.0 * sstats->cnt / total->cnt,
  4043. (sstats->cnt - sstats->skipped) / time_include);
  4044. if (throttle_delay && latency_limit && sstats->cnt > 0)
  4045. printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
  4046. sstats->skipped,
  4047. 100.0 * sstats->skipped / sstats->cnt);
  4048. printSimpleStats(" - latency", &sstats->latency);
  4049. }
  4050. /* Report per-command latencies */
  4051. if (is_latencies)
  4052. {
  4053. Command **commands;
  4054. if (per_script_stats)
  4055. printf(" - statement latencies in milliseconds:\n");
  4056. else
  4057. printf("statement latencies in milliseconds:\n");
  4058. for (commands = sql_script[i].commands;
  4059. *commands != NULL;
  4060. commands++)
  4061. {
  4062. SimpleStats *cstats = &(*commands)->stats;
  4063. printf(" %11.3f %s\n",
  4064. (cstats->count > 0) ?
  4065. 1000.0 * cstats->sum / cstats->count : 0.0,
  4066. (*commands)->line);
  4067. }
  4068. }
  4069. }
  4070. }
  4071. }
  4072. /* call srandom based on some seed. NULL triggers the default behavior. */
  4073. static bool
  4074. set_random_seed(const char *seed)
  4075. {
  4076. /* srandom expects an unsigned int */
  4077. unsigned int iseed;
  4078. if (seed == NULL || strcmp(seed, "time") == 0)
  4079. {
  4080. /* rely on current time */
  4081. instr_time now;
  4082. INSTR_TIME_SET_CURRENT(now);
  4083. iseed = (unsigned int) INSTR_TIME_GET_MICROSEC(now);
  4084. }
  4085. else if (strcmp(seed, "rand") == 0)
  4086. {
  4087. /* use some "strong" random source */
  4088. #ifdef HAVE_STRONG_RANDOM
  4089. if (!pg_strong_random(&iseed, sizeof(iseed)))
  4090. #endif
  4091. {
  4092. fprintf(stderr,
  4093. "cannot seed random from a strong source, none available: "
  4094. "use \"time\" or an unsigned integer value.\n");
  4095. return false;
  4096. }
  4097. }
  4098. else
  4099. {
  4100. /* parse seed unsigned int value */
  4101. char garbage;
  4102. if (sscanf(seed, "%u%c", &iseed, &garbage) != 1)
  4103. {
  4104. fprintf(stderr,
  4105. "unrecognized random seed option \"%s\": expecting an unsigned integer, \"time\" or \"rand\"\n",
  4106. seed);
  4107. return false;
  4108. }
  4109. }
  4110. if (seed != NULL)
  4111. fprintf(stderr, "setting random seed to %u\n", iseed);
  4112. srandom(iseed);
  4113. /* no precision loss: 32 bit unsigned int cast to 64 bit int */
  4114. random_seed = iseed;
  4115. return true;
  4116. }
  4117. int
  4118. main(int argc, char **argv)
  4119. {
  4120. static struct option long_options[] = {
  4121. /* systematic long/short named options */
  4122. {"builtin", required_argument, NULL, 'b'},
  4123. {"client", required_argument, NULL, 'c'},
  4124. {"connect", no_argument, NULL, 'C'},
  4125. {"debug", no_argument, NULL, 'd'},
  4126. {"define", required_argument, NULL, 'D'},
  4127. {"file", required_argument, NULL, 'f'},
  4128. {"fillfactor", required_argument, NULL, 'F'},
  4129. {"host", required_argument, NULL, 'h'},
  4130. {"initialize", no_argument, NULL, 'i'},
  4131. {"init-steps", required_argument, NULL, 'I'},
  4132. {"jobs", required_argument, NULL, 'j'},
  4133. {"log", no_argument, NULL, 'l'},
  4134. {"latency-limit", required_argument, NULL, 'L'},
  4135. {"no-vacuum", no_argument, NULL, 'n'},
  4136. {"port", required_argument, NULL, 'p'},
  4137. {"progress", required_argument, NULL, 'P'},
  4138. {"protocol", required_argument, NULL, 'M'},
  4139. {"quiet", no_argument, NULL, 'q'},
  4140. {"report-latencies", no_argument, NULL, 'r'},
  4141. {"rate", required_argument, NULL, 'R'},
  4142. {"scale", required_argument, NULL, 's'},
  4143. {"select-only", no_argument, NULL, 'S'},
  4144. {"skip-some-updates", no_argument, NULL, 'N'},
  4145. {"time", required_argument, NULL, 'T'},
  4146. {"transactions", required_argument, NULL, 't'},
  4147. {"username", required_argument, NULL, 'U'},
  4148. {"vacuum-all", no_argument, NULL, 'v'},
  4149. /* long-named only options */
  4150. {"unlogged-tables", no_argument, NULL, 1},
  4151. {"tablespace", required_argument, NULL, 2},
  4152. {"index-tablespace", required_argument, NULL, 3},
  4153. {"sampling-rate", required_argument, NULL, 4},
  4154. {"aggregate-interval", required_argument, NULL, 5},
  4155. {"progress-timestamp", no_argument, NULL, 6},
  4156. {"log-prefix", required_argument, NULL, 7},
  4157. {"foreign-keys", no_argument, NULL, 8},
  4158. {"random-seed", required_argument, NULL, 9},
  4159. {NULL, 0, NULL, 0}
  4160. };
  4161. int c;
  4162. bool is_init_mode = false; /* initialize mode? */
  4163. char *initialize_steps = NULL;
  4164. bool foreign_keys = false;
  4165. bool is_no_vacuum = false;
  4166. bool do_vacuum_accounts = false; /* vacuum accounts table? */
  4167. int optindex;
  4168. bool scale_given = false;
  4169. bool benchmarking_option_set = false;
  4170. bool initialization_option_set = false;
  4171. bool internal_script_used = false;
  4172. CState *state; /* status of clients */
  4173. TState *threads; /* array of thread */
  4174. instr_time start_time; /* start up time */
  4175. instr_time total_time;
  4176. instr_time conn_total_time;
  4177. int64 latency_late = 0;
  4178. StatsData stats;
  4179. int weight;
  4180. int i;
  4181. int nclients_dealt;
  4182. #ifdef HAVE_GETRLIMIT
  4183. struct rlimit rlim;
  4184. #endif
  4185. PGconn *con;
  4186. PGresult *res;
  4187. char *env;
  4188. progname = get_progname(argv[0]);
  4189. if (argc > 1)
  4190. {
  4191. if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
  4192. {
  4193. usage();
  4194. exit(0);
  4195. }
  4196. if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
  4197. {
  4198. puts("pgbench (PostgreSQL) " PG_VERSION);
  4199. exit(0);
  4200. }
  4201. }
  4202. #ifdef WIN32
  4203. /* stderr is buffered on Win32. */
  4204. setvbuf(stderr, NULL, _IONBF, 0);
  4205. #endif
  4206. if ((env = getenv("PGHOST")) != NULL && *env != '\0')
  4207. pghost = env;
  4208. if ((env = getenv("PGPORT")) != NULL && *env != '\0')
  4209. pgport = env;
  4210. else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
  4211. login = env;
  4212. state = (CState *) pg_malloc(sizeof(CState));
  4213. memset(state, 0, sizeof(CState));
  4214. /* set random seed early, because it may be used while parsing scripts. */
  4215. if (!set_random_seed(getenv("PGBENCH_RANDOM_SEED")))
  4216. {
  4217. fprintf(stderr, "error while setting random seed from PGBENCH_RANDOM_SEED environment variable\n");
  4218. exit(1);
  4219. }
  4220. while ((c = getopt_long(argc, argv, "iI:h:nvp:dqb:SNc:j:Crs:t:T:U:lf:D:F:M:P:R:L:", long_options, &optindex)) != -1)
  4221. {
  4222. char *script;
  4223. switch (c)
  4224. {
  4225. case 'i':
  4226. is_init_mode = true;
  4227. break;
  4228. case 'I':
  4229. if (initialize_steps)
  4230. pg_free(initialize_steps);
  4231. initialize_steps = pg_strdup(optarg);
  4232. checkInitSteps(initialize_steps);
  4233. initialization_option_set = true;
  4234. break;
  4235. case 'h':
  4236. pghost = pg_strdup(optarg);
  4237. break;
  4238. case 'n':
  4239. is_no_vacuum = true;
  4240. break;
  4241. case 'v':
  4242. benchmarking_option_set = true;
  4243. do_vacuum_accounts = true;
  4244. break;
  4245. case 'p':
  4246. pgport = pg_strdup(optarg);
  4247. break;
  4248. case 'd':
  4249. debug++;
  4250. break;
  4251. case 'c':
  4252. benchmarking_option_set = true;
  4253. nclients = atoi(optarg);
  4254. if (nclients <= 0 || nclients > MAXCLIENTS)
  4255. {
  4256. fprintf(stderr, "invalid number of clients: \"%s\"\n",
  4257. optarg);
  4258. exit(1);
  4259. }
  4260. #ifdef HAVE_GETRLIMIT
  4261. #ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */
  4262. if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
  4263. #else /* but BSD doesn't ... */
  4264. if (getrlimit(RLIMIT_OFILE, &rlim) == -1)
  4265. #endif /* RLIMIT_NOFILE */
  4266. {
  4267. fprintf(stderr, "getrlimit failed: %s\n", strerror(errno));
  4268. exit(1);
  4269. }
  4270. if (rlim.rlim_cur < nclients + 3)
  4271. {
  4272. fprintf(stderr, "need at least %d open files, but system limit is %ld\n",
  4273. nclients + 3, (long) rlim.rlim_cur);
  4274. fprintf(stderr, "Reduce number of clients, or use limit/ulimit to increase the system limit.\n");
  4275. exit(1);
  4276. }
  4277. #endif /* HAVE_GETRLIMIT */
  4278. break;
  4279. case 'j': /* jobs */
  4280. benchmarking_option_set = true;
  4281. nthreads = atoi(optarg);
  4282. if (nthreads <= 0)
  4283. {
  4284. fprintf(stderr, "invalid number of threads: \"%s\"\n",
  4285. optarg);
  4286. exit(1);
  4287. }
  4288. #ifndef ENABLE_THREAD_SAFETY
  4289. if (nthreads != 1)
  4290. {
  4291. fprintf(stderr, "threads are not supported on this platform; use -j1\n");
  4292. exit(1);
  4293. }
  4294. #endif /* !ENABLE_THREAD_SAFETY */
  4295. break;
  4296. case 'C':
  4297. benchmarking_option_set = true;
  4298. is_connect = true;
  4299. break;
  4300. case 'r':
  4301. benchmarking_option_set = true;
  4302. is_latencies = true;
  4303. break;
  4304. case 's':
  4305. scale_given = true;
  4306. scale = atoi(optarg);
  4307. if (scale <= 0)
  4308. {
  4309. fprintf(stderr, "invalid scaling factor: \"%s\"\n", optarg);
  4310. exit(1);
  4311. }
  4312. break;
  4313. case 't':
  4314. benchmarking_option_set = true;
  4315. nxacts = atoi(optarg);
  4316. if (nxacts <= 0)
  4317. {
  4318. fprintf(stderr, "invalid number of transactions: \"%s\"\n",
  4319. optarg);
  4320. exit(1);
  4321. }
  4322. break;
  4323. case 'T':
  4324. benchmarking_option_set = true;
  4325. duration = atoi(optarg);
  4326. if (duration <= 0)
  4327. {
  4328. fprintf(stderr, "invalid duration: \"%s\"\n", optarg);
  4329. exit(1);
  4330. }
  4331. break;
  4332. case 'U':
  4333. login = pg_strdup(optarg);
  4334. break;
  4335. case 'l':
  4336. benchmarking_option_set = true;
  4337. use_log = true;
  4338. break;
  4339. case 'q':
  4340. initialization_option_set = true;
  4341. use_quiet = true;
  4342. break;
  4343. case 'b':
  4344. if (strcmp(optarg, "list") == 0)
  4345. {
  4346. listAvailableScripts();
  4347. exit(0);
  4348. }
  4349. weight = parseScriptWeight(optarg, &script);
  4350. process_builtin(findBuiltin(script), weight);
  4351. benchmarking_option_set = true;
  4352. internal_script_used = true;
  4353. break;
  4354. case 'S':
  4355. process_builtin(findBuiltin("select-only"), 1);
  4356. benchmarking_option_set = true;
  4357. internal_script_used = true;
  4358. break;
  4359. case 'N':
  4360. process_builtin(findBuiltin("simple-update"), 1);
  4361. benchmarking_option_set = true;
  4362. internal_script_used = true;
  4363. break;
  4364. case 'f':
  4365. weight = parseScriptWeight(optarg, &script);
  4366. process_file(script, weight);
  4367. benchmarking_option_set = true;
  4368. break;
  4369. case 'D':
  4370. {
  4371. char *p;
  4372. benchmarking_option_set = true;
  4373. if ((p = strchr(optarg, '=')) == NULL || p == optarg || *(p + 1) == '\0')
  4374. {
  4375. fprintf(stderr, "invalid variable definition: \"%s\"\n",
  4376. optarg);
  4377. exit(1);
  4378. }
  4379. *p++ = '\0';
  4380. if (!putVariable(&state[0], "option", optarg, p))
  4381. exit(1);
  4382. }
  4383. break;
  4384. case 'F':
  4385. initialization_option_set = true;
  4386. fillfactor = atoi(optarg);
  4387. if (fillfactor < 10 || fillfactor > 100)
  4388. {
  4389. fprintf(stderr, "invalid fillfactor: \"%s\"\n", optarg);
  4390. exit(1);
  4391. }
  4392. break;
  4393. case 'M':
  4394. benchmarking_option_set = true;
  4395. for (querymode = 0; querymode < NUM_QUERYMODE; querymode++)
  4396. if (strcmp(optarg, QUERYMODE[querymode]) == 0)
  4397. break;
  4398. if (querymode >= NUM_QUERYMODE)
  4399. {
  4400. fprintf(stderr, "invalid query mode (-M): \"%s\"\n",
  4401. optarg);
  4402. exit(1);
  4403. }
  4404. break;
  4405. case 'P':
  4406. benchmarking_option_set = true;
  4407. progress = atoi(optarg);
  4408. if (progress <= 0)
  4409. {
  4410. fprintf(stderr, "invalid thread progress delay: \"%s\"\n",
  4411. optarg);
  4412. exit(1);
  4413. }
  4414. break;
  4415. case 'R':
  4416. {
  4417. /* get a double from the beginning of option value */
  4418. double throttle_value = atof(optarg);
  4419. benchmarking_option_set = true;
  4420. if (throttle_value <= 0.0)
  4421. {
  4422. fprintf(stderr, "invalid rate limit: \"%s\"\n", optarg);
  4423. exit(1);
  4424. }
  4425. /* Invert rate limit into a time offset */
  4426. throttle_delay = (int64) (1000000.0 / throttle_value);
  4427. }
  4428. break;
  4429. case 'L':
  4430. {
  4431. double limit_ms = atof(optarg);
  4432. if (limit_ms <= 0.0)
  4433. {
  4434. fprintf(stderr, "invalid latency limit: \"%s\"\n",
  4435. optarg);
  4436. exit(1);
  4437. }
  4438. benchmarking_option_set = true;
  4439. latency_limit = (int64) (limit_ms * 1000);
  4440. }
  4441. break;
  4442. case 1: /* unlogged-tables */
  4443. initialization_option_set = true;
  4444. unlogged_tables = true;
  4445. break;
  4446. case 2: /* tablespace */
  4447. initialization_option_set = true;
  4448. tablespace = pg_strdup(optarg);
  4449. break;
  4450. case 3: /* index-tablespace */
  4451. initialization_option_set = true;
  4452. index_tablespace = pg_strdup(optarg);
  4453. break;
  4454. case 4: /* sampling-rate */
  4455. benchmarking_option_set = true;
  4456. sample_rate = atof(optarg);
  4457. if (sample_rate <= 0.0 || sample_rate > 1.0)
  4458. {
  4459. fprintf(stderr, "invalid sampling rate: \"%s\"\n", optarg);
  4460. exit(1);
  4461. }
  4462. break;
  4463. case 5: /* aggregate-interval */
  4464. benchmarking_option_set = true;
  4465. agg_interval = atoi(optarg);
  4466. if (agg_interval <= 0)
  4467. {
  4468. fprintf(stderr, "invalid number of seconds for aggregation: \"%s\"\n",
  4469. optarg);
  4470. exit(1);
  4471. }
  4472. break;
  4473. case 6: /* progress-timestamp */
  4474. progress_timestamp = true;
  4475. benchmarking_option_set = true;
  4476. break;
  4477. case 7: /* log-prefix */
  4478. benchmarking_option_set = true;
  4479. logfile_prefix = pg_strdup(optarg);
  4480. break;
  4481. case 8: /* foreign-keys */
  4482. initialization_option_set = true;
  4483. foreign_keys = true;
  4484. break;
  4485. case 9: /* random-seed */
  4486. benchmarking_option_set = true;
  4487. if (!set_random_seed(optarg))
  4488. {
  4489. fprintf(stderr, "error while setting random seed from --random-seed option\n");
  4490. exit(1);
  4491. }
  4492. break;
  4493. default:
  4494. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  4495. exit(1);
  4496. break;
  4497. }
  4498. }
  4499. /* set default script if none */
  4500. if (num_scripts == 0 && !is_init_mode)
  4501. {
  4502. process_builtin(findBuiltin("tpcb-like"), 1);
  4503. benchmarking_option_set = true;
  4504. internal_script_used = true;
  4505. }
  4506. /* if not simple query mode, parse the script(s) to find parameters */
  4507. if (querymode != QUERY_SIMPLE)
  4508. {
  4509. for (i = 0; i < num_scripts; i++)
  4510. {
  4511. Command **commands = sql_script[i].commands;
  4512. int j;
  4513. for (j = 0; commands[j] != NULL; j++)
  4514. {
  4515. if (commands[j]->type != SQL_COMMAND)
  4516. continue;
  4517. if (!parseQuery(commands[j]))
  4518. exit(1);
  4519. }
  4520. }
  4521. }
  4522. /* compute total_weight */
  4523. for (i = 0; i < num_scripts; i++)
  4524. /* cannot overflow: weight is 32b, total_weight 64b */
  4525. total_weight += sql_script[i].weight;
  4526. if (total_weight == 0 && !is_init_mode)
  4527. {
  4528. fprintf(stderr, "total script weight must not be zero\n");
  4529. exit(1);
  4530. }
  4531. /* show per script stats if several scripts are used */
  4532. if (num_scripts > 1)
  4533. per_script_stats = true;
  4534. /*
  4535. * Don't need more threads than there are clients. (This is not merely an
  4536. * optimization; throttle_delay is calculated incorrectly below if some
  4537. * threads have no clients assigned to them.)
  4538. */
  4539. if (nthreads > nclients)
  4540. nthreads = nclients;
  4541. /* compute a per thread delay */
  4542. throttle_delay *= nthreads;
  4543. if (argc > optind)
  4544. dbName = argv[optind];
  4545. else
  4546. {
  4547. if ((env = getenv("PGDATABASE")) != NULL && *env != '\0')
  4548. dbName = env;
  4549. else if (login != NULL && *login != '\0')
  4550. dbName = login;
  4551. else
  4552. dbName = "";
  4553. }
  4554. if (is_init_mode)
  4555. {
  4556. if (benchmarking_option_set)
  4557. {
  4558. fprintf(stderr, "some of the specified options cannot be used in initialization (-i) mode\n");
  4559. exit(1);
  4560. }
  4561. if (initialize_steps == NULL)
  4562. initialize_steps = pg_strdup(DEFAULT_INIT_STEPS);
  4563. if (is_no_vacuum)
  4564. {
  4565. /* Remove any vacuum step in initialize_steps */
  4566. char *p;
  4567. while ((p = strchr(initialize_steps, 'v')) != NULL)
  4568. *p = ' ';
  4569. }
  4570. if (foreign_keys)
  4571. {
  4572. /* Add 'f' to end of initialize_steps, if not already there */
  4573. if (strchr(initialize_steps, 'f') == NULL)
  4574. {
  4575. initialize_steps = (char *)
  4576. pg_realloc(initialize_steps,
  4577. strlen(initialize_steps) + 2);
  4578. strcat(initialize_steps, "f");
  4579. }
  4580. }
  4581. runInitSteps(initialize_steps);
  4582. exit(0);
  4583. }
  4584. else
  4585. {
  4586. if (initialization_option_set)
  4587. {
  4588. fprintf(stderr, "some of the specified options cannot be used in benchmarking mode\n");
  4589. exit(1);
  4590. }
  4591. }
  4592. if (nxacts > 0 && duration > 0)
  4593. {
  4594. fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both\n");
  4595. exit(1);
  4596. }
  4597. /* Use DEFAULT_NXACTS if neither nxacts nor duration is specified. */
  4598. if (nxacts <= 0 && duration <= 0)
  4599. nxacts = DEFAULT_NXACTS;
  4600. /* --sampling-rate may be used only with -l */
  4601. if (sample_rate > 0.0 && !use_log)
  4602. {
  4603. fprintf(stderr, "log sampling (--sampling-rate) is allowed only when logging transactions (-l)\n");
  4604. exit(1);
  4605. }
  4606. /* --sampling-rate may not be used with --aggregate-interval */
  4607. if (sample_rate > 0.0 && agg_interval > 0)
  4608. {
  4609. fprintf(stderr, "log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time\n");
  4610. exit(1);
  4611. }
  4612. if (agg_interval > 0 && !use_log)
  4613. {
  4614. fprintf(stderr, "log aggregation is allowed only when actually logging transactions\n");
  4615. exit(1);
  4616. }
  4617. if (!use_log && logfile_prefix)
  4618. {
  4619. fprintf(stderr, "log file prefix (--log-prefix) is allowed only when logging transactions (-l)\n");
  4620. exit(1);
  4621. }
  4622. if (duration > 0 && agg_interval > duration)
  4623. {
  4624. fprintf(stderr, "number of seconds for aggregation (%d) must not be higher than test duration (%d)\n", agg_interval, duration);
  4625. exit(1);
  4626. }
  4627. if (duration > 0 && agg_interval > 0 && duration % agg_interval != 0)
  4628. {
  4629. fprintf(stderr, "duration (%d) must be a multiple of aggregation interval (%d)\n", duration, agg_interval);
  4630. exit(1);
  4631. }
  4632. if (progress_timestamp && progress == 0)
  4633. {
  4634. fprintf(stderr, "--progress-timestamp is allowed only under --progress\n");
  4635. exit(1);
  4636. }
  4637. /*
  4638. * save main process id in the global variable because process id will be
  4639. * changed after fork.
  4640. */
  4641. main_pid = (int) getpid();
  4642. if (nclients > 1)
  4643. {
  4644. state = (CState *) pg_realloc(state, sizeof(CState) * nclients);
  4645. memset(state + 1, 0, sizeof(CState) * (nclients - 1));
  4646. /* copy any -D switch values to all clients */
  4647. for (i = 1; i < nclients; i++)
  4648. {
  4649. int j;
  4650. state[i].id = i;
  4651. for (j = 0; j < state[0].nvariables; j++)
  4652. {
  4653. Variable *var = &state[0].variables[j];
  4654. if (var->value.type != PGBT_NO_VALUE)
  4655. {
  4656. if (!putVariableValue(&state[i], "startup",
  4657. var->name, &var->value))
  4658. exit(1);
  4659. }
  4660. else
  4661. {
  4662. if (!putVariable(&state[i], "startup",
  4663. var->name, var->svalue))
  4664. exit(1);
  4665. }
  4666. }
  4667. }
  4668. }
  4669. /* other CState initializations */
  4670. for (i = 0; i < nclients; i++)
  4671. {
  4672. state[i].cstack = conditional_stack_create();
  4673. }
  4674. if (debug)
  4675. {
  4676. if (duration <= 0)
  4677. printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
  4678. pghost, pgport, nclients, nxacts, dbName);
  4679. else
  4680. printf("pghost: %s pgport: %s nclients: %d duration: %d dbName: %s\n",
  4681. pghost, pgport, nclients, duration, dbName);
  4682. }
  4683. /* opening connection... */
  4684. con = doConnect();
  4685. if (con == NULL)
  4686. exit(1);
  4687. if (PQstatus(con) == CONNECTION_BAD)
  4688. {
  4689. fprintf(stderr, "connection to database \"%s\" failed\n", dbName);
  4690. fprintf(stderr, "%s", PQerrorMessage(con));
  4691. exit(1);
  4692. }
  4693. if (internal_script_used)
  4694. {
  4695. /*
  4696. * get the scaling factor that should be same as count(*) from
  4697. * pgbench_branches if this is not a custom query
  4698. */
  4699. res = PQexec(con, "select count(*) from pgbench_branches");
  4700. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  4701. {
  4702. char *sqlState = PQresultErrorField(res, PG_DIAG_SQLSTATE);
  4703. fprintf(stderr, "%s", PQerrorMessage(con));
  4704. if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) == 0)
  4705. {
  4706. fprintf(stderr, "Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\"\n", PQdb(con));
  4707. }
  4708. exit(1);
  4709. }
  4710. scale = atoi(PQgetvalue(res, 0, 0));
  4711. if (scale < 0)
  4712. {
  4713. fprintf(stderr, "invalid count(*) from pgbench_branches: \"%s\"\n",
  4714. PQgetvalue(res, 0, 0));
  4715. exit(1);
  4716. }
  4717. PQclear(res);
  4718. /* warn if we override user-given -s switch */
  4719. if (scale_given)
  4720. fprintf(stderr,
  4721. "scale option ignored, using count from pgbench_branches table (%d)\n",
  4722. scale);
  4723. }
  4724. /*
  4725. * :scale variables normally get -s or database scale, but don't override
  4726. * an explicit -D switch
  4727. */
  4728. if (lookupVariable(&state[0], "scale") == NULL)
  4729. {
  4730. for (i = 0; i < nclients; i++)
  4731. {
  4732. if (!putVariableInt(&state[i], "startup", "scale", scale))
  4733. exit(1);
  4734. }
  4735. }
  4736. /*
  4737. * Define a :client_id variable that is unique per connection. But don't
  4738. * override an explicit -D switch.
  4739. */
  4740. if (lookupVariable(&state[0], "client_id") == NULL)
  4741. {
  4742. for (i = 0; i < nclients; i++)
  4743. if (!putVariableInt(&state[i], "startup", "client_id", i))
  4744. exit(1);
  4745. }
  4746. /* set default seed for hash functions */
  4747. if (lookupVariable(&state[0], "default_seed") == NULL)
  4748. {
  4749. uint64 seed = ((uint64) (random() & 0xFFFF) << 48) |
  4750. ((uint64) (random() & 0xFFFF) << 32) |
  4751. ((uint64) (random() & 0xFFFF) << 16) |
  4752. (uint64) (random() & 0xFFFF);
  4753. for (i = 0; i < nclients; i++)
  4754. if (!putVariableInt(&state[i], "startup", "default_seed", (int64) seed))
  4755. exit(1);
  4756. }
  4757. /* set random seed unless overwritten */
  4758. if (lookupVariable(&state[0], "random_seed") == NULL)
  4759. {
  4760. for (i = 0; i < nclients; i++)
  4761. if (!putVariableInt(&state[i], "startup", "random_seed", random_seed))
  4762. exit(1);
  4763. }
  4764. if (!is_no_vacuum)
  4765. {
  4766. fprintf(stderr, "starting vacuum...");
  4767. tryExecuteStatement(con, "vacuum pgbench_branches");
  4768. tryExecuteStatement(con, "vacuum pgbench_tellers");
  4769. tryExecuteStatement(con, "truncate pgbench_history");
  4770. fprintf(stderr, "end.\n");
  4771. if (do_vacuum_accounts)
  4772. {
  4773. fprintf(stderr, "starting vacuum pgbench_accounts...");
  4774. tryExecuteStatement(con, "vacuum analyze pgbench_accounts");
  4775. fprintf(stderr, "end.\n");
  4776. }
  4777. }
  4778. PQfinish(con);
  4779. /* set up thread data structures */
  4780. threads = (TState *) pg_malloc(sizeof(TState) * nthreads);
  4781. nclients_dealt = 0;
  4782. for (i = 0; i < nthreads; i++)
  4783. {
  4784. TState *thread = &threads[i];
  4785. thread->tid = i;
  4786. thread->state = &state[nclients_dealt];
  4787. thread->nstate =
  4788. (nclients - nclients_dealt + nthreads - i - 1) / (nthreads - i);
  4789. thread->random_state[0] = random();
  4790. thread->random_state[1] = random();
  4791. thread->random_state[2] = random();
  4792. thread->logfile = NULL; /* filled in later */
  4793. thread->latency_late = 0;
  4794. thread->zipf_cache.nb_cells = 0;
  4795. thread->zipf_cache.current = 0;
  4796. thread->zipf_cache.overflowCount = 0;
  4797. initStats(&thread->stats, 0);
  4798. nclients_dealt += thread->nstate;
  4799. }
  4800. /* all clients must be assigned to a thread */
  4801. Assert(nclients_dealt == nclients);
  4802. /* get start up time */
  4803. INSTR_TIME_SET_CURRENT(start_time);
  4804. /* set alarm if duration is specified. */
  4805. if (duration > 0)
  4806. setalarm(duration);
  4807. /* start threads */
  4808. #ifdef ENABLE_THREAD_SAFETY
  4809. for (i = 0; i < nthreads; i++)
  4810. {
  4811. TState *thread = &threads[i];
  4812. INSTR_TIME_SET_CURRENT(thread->start_time);
  4813. /* compute when to stop */
  4814. if (duration > 0)
  4815. end_time = INSTR_TIME_GET_MICROSEC(thread->start_time) +
  4816. (int64) 1000000 * duration;
  4817. /* the first thread (i = 0) is executed by main thread */
  4818. if (i > 0)
  4819. {
  4820. int err = pthread_create(&thread->thread, NULL, threadRun, thread);
  4821. if (err != 0 || thread->thread == INVALID_THREAD)
  4822. {
  4823. fprintf(stderr, "could not create thread: %s\n", strerror(err));
  4824. exit(1);
  4825. }
  4826. }
  4827. else
  4828. {
  4829. thread->thread = INVALID_THREAD;
  4830. }
  4831. }
  4832. #else
  4833. INSTR_TIME_SET_CURRENT(threads[0].start_time);
  4834. /* compute when to stop */
  4835. if (duration > 0)
  4836. end_time = INSTR_TIME_GET_MICROSEC(threads[0].start_time) +
  4837. (int64) 1000000 * duration;
  4838. threads[0].thread = INVALID_THREAD;
  4839. #endif /* ENABLE_THREAD_SAFETY */
  4840. /* wait for threads and accumulate results */
  4841. initStats(&stats, 0);
  4842. INSTR_TIME_SET_ZERO(conn_total_time);
  4843. for (i = 0; i < nthreads; i++)
  4844. {
  4845. TState *thread = &threads[i];
  4846. #ifdef ENABLE_THREAD_SAFETY
  4847. if (threads[i].thread == INVALID_THREAD)
  4848. /* actually run this thread directly in the main thread */
  4849. (void) threadRun(thread);
  4850. else
  4851. /* wait of other threads. should check that 0 is returned? */
  4852. pthread_join(thread->thread, NULL);
  4853. #else
  4854. (void) threadRun(thread);
  4855. #endif /* ENABLE_THREAD_SAFETY */
  4856. /* aggregate thread level stats */
  4857. mergeSimpleStats(&stats.latency, &thread->stats.latency);
  4858. mergeSimpleStats(&stats.lag, &thread->stats.lag);
  4859. stats.cnt += thread->stats.cnt;
  4860. stats.skipped += thread->stats.skipped;
  4861. latency_late += thread->latency_late;
  4862. INSTR_TIME_ADD(conn_total_time, thread->conn_time);
  4863. }
  4864. disconnect_all(state, nclients);
  4865. /*
  4866. * XXX We compute results as though every client of every thread started
  4867. * and finished at the same time. That model can diverge noticeably from
  4868. * reality for a short benchmark run involving relatively many threads.
  4869. * The first thread may process notably many transactions before the last
  4870. * thread begins. Improving the model alone would bring limited benefit,
  4871. * because performance during those periods of partial thread count can
  4872. * easily exceed steady state performance. This is one of the many ways
  4873. * short runs convey deceptive performance figures.
  4874. */
  4875. INSTR_TIME_SET_CURRENT(total_time);
  4876. INSTR_TIME_SUBTRACT(total_time, start_time);
  4877. printResults(threads, &stats, total_time, conn_total_time, latency_late);
  4878. return 0;
  4879. }
  4880. static void *
  4881. threadRun(void *arg)
  4882. {
  4883. TState *thread = (TState *) arg;
  4884. CState *state = thread->state;
  4885. instr_time start,
  4886. end;
  4887. int nstate = thread->nstate;
  4888. int remains = nstate; /* number of remaining clients */
  4889. int i;
  4890. /* for reporting progress: */
  4891. int64 thread_start = INSTR_TIME_GET_MICROSEC(thread->start_time);
  4892. int64 last_report = thread_start;
  4893. int64 next_report = last_report + (int64) progress * 1000000;
  4894. StatsData last,
  4895. aggs;
  4896. /*
  4897. * Initialize throttling rate target for all of the thread's clients. It
  4898. * might be a little more accurate to reset thread->start_time here too.
  4899. * The possible drift seems too small relative to typical throttle delay
  4900. * times to worry about it.
  4901. */
  4902. INSTR_TIME_SET_CURRENT(start);
  4903. thread->throttle_trigger = INSTR_TIME_GET_MICROSEC(start);
  4904. INSTR_TIME_SET_ZERO(thread->conn_time);
  4905. initStats(&aggs, time(NULL));
  4906. last = aggs;
  4907. /* open log file if requested */
  4908. if (use_log)
  4909. {
  4910. char logpath[MAXPGPATH];
  4911. char *prefix = logfile_prefix ? logfile_prefix : "pgbench_log";
  4912. if (thread->tid == 0)
  4913. snprintf(logpath, sizeof(logpath), "%s.%d", prefix, main_pid);
  4914. else
  4915. snprintf(logpath, sizeof(logpath), "%s.%d.%d", prefix, main_pid, thread->tid);
  4916. thread->logfile = fopen(logpath, "w");
  4917. if (thread->logfile == NULL)
  4918. {
  4919. fprintf(stderr, "could not open logfile \"%s\": %s\n",
  4920. logpath, strerror(errno));
  4921. goto done;
  4922. }
  4923. }
  4924. if (!is_connect)
  4925. {
  4926. /* make connections to the database */
  4927. for (i = 0; i < nstate; i++)
  4928. {
  4929. if ((state[i].con = doConnect()) == NULL)
  4930. goto done;
  4931. }
  4932. }
  4933. /* time after thread and connections set up */
  4934. INSTR_TIME_SET_CURRENT(thread->conn_time);
  4935. INSTR_TIME_SUBTRACT(thread->conn_time, thread->start_time);
  4936. /* explicitly initialize the state machines */
  4937. for (i = 0; i < nstate; i++)
  4938. {
  4939. state[i].state = CSTATE_CHOOSE_SCRIPT;
  4940. }
  4941. /* loop till all clients have terminated */
  4942. while (remains > 0)
  4943. {
  4944. fd_set input_mask;
  4945. int maxsock; /* max socket number to be waited for */
  4946. int64 min_usec;
  4947. int64 now_usec = 0; /* set this only if needed */
  4948. /* identify which client sockets should be checked for input */
  4949. FD_ZERO(&input_mask);
  4950. maxsock = -1;
  4951. min_usec = PG_INT64_MAX;
  4952. for (i = 0; i < nstate; i++)
  4953. {
  4954. CState *st = &state[i];
  4955. if (st->state == CSTATE_THROTTLE && timer_exceeded)
  4956. {
  4957. /* interrupt client that has not started a transaction */
  4958. st->state = CSTATE_FINISHED;
  4959. finishCon(st);
  4960. remains--;
  4961. }
  4962. else if (st->state == CSTATE_SLEEP || st->state == CSTATE_THROTTLE)
  4963. {
  4964. /* a nap from the script, or under throttling */
  4965. int64 this_usec;
  4966. /* get current time if needed */
  4967. if (now_usec == 0)
  4968. {
  4969. instr_time now;
  4970. INSTR_TIME_SET_CURRENT(now);
  4971. now_usec = INSTR_TIME_GET_MICROSEC(now);
  4972. }
  4973. /* min_usec should be the minimum delay across all clients */
  4974. this_usec = (st->state == CSTATE_SLEEP ?
  4975. st->sleep_until : st->txn_scheduled) - now_usec;
  4976. if (min_usec > this_usec)
  4977. min_usec = this_usec;
  4978. }
  4979. else if (st->state == CSTATE_WAIT_RESULT)
  4980. {
  4981. /*
  4982. * waiting for result from server - nothing to do unless the
  4983. * socket is readable
  4984. */
  4985. int sock = PQsocket(st->con);
  4986. if (sock < 0)
  4987. {
  4988. fprintf(stderr, "invalid socket: %s",
  4989. PQerrorMessage(st->con));
  4990. goto done;
  4991. }
  4992. FD_SET(sock, &input_mask);
  4993. if (maxsock < sock)
  4994. maxsock = sock;
  4995. }
  4996. else if (st->state != CSTATE_ABORTED &&
  4997. st->state != CSTATE_FINISHED)
  4998. {
  4999. /*
  5000. * This client thread is ready to do something, so we don't
  5001. * want to wait. No need to examine additional clients.
  5002. */
  5003. min_usec = 0;
  5004. break;
  5005. }
  5006. }
  5007. /* also wake up to print the next progress report on time */
  5008. if (progress && min_usec > 0 && thread->tid == 0)
  5009. {
  5010. /* get current time if needed */
  5011. if (now_usec == 0)
  5012. {
  5013. instr_time now;
  5014. INSTR_TIME_SET_CURRENT(now);
  5015. now_usec = INSTR_TIME_GET_MICROSEC(now);
  5016. }
  5017. if (now_usec >= next_report)
  5018. min_usec = 0;
  5019. else if ((next_report - now_usec) < min_usec)
  5020. min_usec = next_report - now_usec;
  5021. }
  5022. /*
  5023. * If no clients are ready to execute actions, sleep until we receive
  5024. * data from the server, or a nap-time specified in the script ends,
  5025. * or it's time to print a progress report. Update input_mask to show
  5026. * which client(s) received data.
  5027. */
  5028. if (min_usec > 0)
  5029. {
  5030. int nsocks = 0; /* return from select(2) if called */
  5031. if (min_usec != PG_INT64_MAX)
  5032. {
  5033. if (maxsock != -1)
  5034. {
  5035. struct timeval timeout;
  5036. timeout.tv_sec = min_usec / 1000000;
  5037. timeout.tv_usec = min_usec % 1000000;
  5038. nsocks = select(maxsock + 1, &input_mask, NULL, NULL, &timeout);
  5039. }
  5040. else /* nothing active, simple sleep */
  5041. {
  5042. pg_usleep(min_usec);
  5043. }
  5044. }
  5045. else /* no explicit delay, select without timeout */
  5046. {
  5047. nsocks = select(maxsock + 1, &input_mask, NULL, NULL, NULL);
  5048. }
  5049. if (nsocks < 0)
  5050. {
  5051. if (errno == EINTR)
  5052. {
  5053. /* On EINTR, go back to top of loop */
  5054. continue;
  5055. }
  5056. /* must be something wrong */
  5057. fprintf(stderr, "select() failed: %s\n", strerror(errno));
  5058. goto done;
  5059. }
  5060. }
  5061. else
  5062. {
  5063. /* min_usec == 0, i.e. something needs to be executed */
  5064. /* If we didn't call select(), don't try to read any data */
  5065. FD_ZERO(&input_mask);
  5066. }
  5067. /* ok, advance the state machine of each connection */
  5068. for (i = 0; i < nstate; i++)
  5069. {
  5070. CState *st = &state[i];
  5071. if (st->state == CSTATE_WAIT_RESULT)
  5072. {
  5073. /* don't call doCustom unless data is available */
  5074. int sock = PQsocket(st->con);
  5075. if (sock < 0)
  5076. {
  5077. fprintf(stderr, "invalid socket: %s",
  5078. PQerrorMessage(st->con));
  5079. goto done;
  5080. }
  5081. if (!FD_ISSET(sock, &input_mask))
  5082. continue;
  5083. }
  5084. else if (st->state == CSTATE_FINISHED ||
  5085. st->state == CSTATE_ABORTED)
  5086. {
  5087. /* this client is done, no need to consider it anymore */
  5088. continue;
  5089. }
  5090. doCustom(thread, st, &aggs);
  5091. /* If doCustom changed client to finished state, reduce remains */
  5092. if (st->state == CSTATE_FINISHED || st->state == CSTATE_ABORTED)
  5093. remains--;
  5094. }
  5095. /* progress report is made by thread 0 for all threads */
  5096. if (progress && thread->tid == 0)
  5097. {
  5098. instr_time now_time;
  5099. int64 now;
  5100. INSTR_TIME_SET_CURRENT(now_time);
  5101. now = INSTR_TIME_GET_MICROSEC(now_time);
  5102. if (now >= next_report)
  5103. {
  5104. /* generate and show report */
  5105. StatsData cur;
  5106. int64 run = now - last_report,
  5107. ntx;
  5108. double tps,
  5109. total_run,
  5110. latency,
  5111. sqlat,
  5112. lag,
  5113. stdev;
  5114. char tbuf[315];
  5115. /*
  5116. * Add up the statistics of all threads.
  5117. *
  5118. * XXX: No locking. There is no guarantee that we get an
  5119. * atomic snapshot of the transaction count and latencies, so
  5120. * these figures can well be off by a small amount. The
  5121. * progress report's purpose is to give a quick overview of
  5122. * how the test is going, so that shouldn't matter too much.
  5123. * (If a read from a 64-bit integer is not atomic, you might
  5124. * get a "torn" read and completely bogus latencies though!)
  5125. */
  5126. initStats(&cur, 0);
  5127. for (i = 0; i < nthreads; i++)
  5128. {
  5129. mergeSimpleStats(&cur.latency, &thread[i].stats.latency);
  5130. mergeSimpleStats(&cur.lag, &thread[i].stats.lag);
  5131. cur.cnt += thread[i].stats.cnt;
  5132. cur.skipped += thread[i].stats.skipped;
  5133. }
  5134. /* we count only actually executed transactions */
  5135. ntx = (cur.cnt - cur.skipped) - (last.cnt - last.skipped);
  5136. total_run = (now - thread_start) / 1000000.0;
  5137. tps = 1000000.0 * ntx / run;
  5138. if (ntx > 0)
  5139. {
  5140. latency = 0.001 * (cur.latency.sum - last.latency.sum) / ntx;
  5141. sqlat = 1.0 * (cur.latency.sum2 - last.latency.sum2) / ntx;
  5142. stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
  5143. lag = 0.001 * (cur.lag.sum - last.lag.sum) / ntx;
  5144. }
  5145. else
  5146. {
  5147. latency = sqlat = stdev = lag = 0;
  5148. }
  5149. if (progress_timestamp)
  5150. {
  5151. /*
  5152. * On some platforms the current system timestamp is
  5153. * available in now_time, but rather than get entangled
  5154. * with that, we just eat the cost of an extra syscall in
  5155. * all cases.
  5156. */
  5157. struct timeval tv;
  5158. gettimeofday(&tv, NULL);
  5159. snprintf(tbuf, sizeof(tbuf), "%ld.%03ld s",
  5160. (long) tv.tv_sec, (long) (tv.tv_usec / 1000));
  5161. }
  5162. else
  5163. {
  5164. /* round seconds are expected, but the thread may be late */
  5165. snprintf(tbuf, sizeof(tbuf), "%.1f s", total_run);
  5166. }
  5167. fprintf(stderr,
  5168. "progress: %s, %.1f tps, lat %.3f ms stddev %.3f",
  5169. tbuf, tps, latency, stdev);
  5170. if (throttle_delay)
  5171. {
  5172. fprintf(stderr, ", lag %.3f ms", lag);
  5173. if (latency_limit)
  5174. fprintf(stderr, ", " INT64_FORMAT " skipped",
  5175. cur.skipped - last.skipped);
  5176. }
  5177. fprintf(stderr, "\n");
  5178. last = cur;
  5179. last_report = now;
  5180. /*
  5181. * Ensure that the next report is in the future, in case
  5182. * pgbench/postgres got stuck somewhere.
  5183. */
  5184. do
  5185. {
  5186. next_report += (int64) progress * 1000000;
  5187. } while (now >= next_report);
  5188. }
  5189. }
  5190. }
  5191. done:
  5192. INSTR_TIME_SET_CURRENT(start);
  5193. disconnect_all(state, nstate);
  5194. INSTR_TIME_SET_CURRENT(end);
  5195. INSTR_TIME_ACCUM_DIFF(thread->conn_time, end, start);
  5196. if (thread->logfile)
  5197. {
  5198. if (agg_interval > 0)
  5199. {
  5200. /* log aggregated but not yet reported transactions */
  5201. doLog(thread, state, &aggs, false, 0, 0);
  5202. }
  5203. fclose(thread->logfile);
  5204. thread->logfile = NULL;
  5205. }
  5206. return NULL;
  5207. }
  5208. static void
  5209. finishCon(CState *st)
  5210. {
  5211. if (st->con != NULL)
  5212. {
  5213. PQfinish(st->con);
  5214. st->con = NULL;
  5215. }
  5216. }
  5217. /*
  5218. * Support for duration option: set timer_exceeded after so many seconds.
  5219. */
  5220. #ifndef WIN32
  5221. static void
  5222. handle_sig_alarm(SIGNAL_ARGS)
  5223. {
  5224. timer_exceeded = true;
  5225. }
  5226. static void
  5227. setalarm(int seconds)
  5228. {
  5229. pqsignal(SIGALRM, handle_sig_alarm);
  5230. alarm(seconds);
  5231. }
  5232. #else /* WIN32 */
  5233. static VOID CALLBACK
  5234. win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
  5235. {
  5236. timer_exceeded = true;
  5237. }
  5238. static void
  5239. setalarm(int seconds)
  5240. {
  5241. HANDLE queue;
  5242. HANDLE timer;
  5243. /* This function will be called at most once, so we can cheat a bit. */
  5244. queue = CreateTimerQueue();
  5245. if (seconds > ((DWORD) -1) / 1000 ||
  5246. !CreateTimerQueueTimer(&timer, queue,
  5247. win32_timer_callback, NULL, seconds * 1000, 0,
  5248. WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
  5249. {
  5250. fprintf(stderr, "failed to set timer\n");
  5251. exit(1);
  5252. }
  5253. }
  5254. /* partial pthread implementation for Windows */
  5255. typedef struct win32_pthread
  5256. {
  5257. HANDLE handle;
  5258. void *(*routine) (void *);
  5259. void *arg;
  5260. void *result;
  5261. } win32_pthread;
  5262. static unsigned __stdcall
  5263. win32_pthread_run(void *arg)
  5264. {
  5265. win32_pthread *th = (win32_pthread *) arg;
  5266. th->result = th->routine(th->arg);
  5267. return 0;
  5268. }
  5269. static int
  5270. pthread_create(pthread_t *thread,
  5271. pthread_attr_t *attr,
  5272. void *(*start_routine) (void *),
  5273. void *arg)
  5274. {
  5275. int save_errno;
  5276. win32_pthread *th;
  5277. th = (win32_pthread *) pg_malloc(sizeof(win32_pthread));
  5278. th->routine = start_routine;
  5279. th->arg = arg;
  5280. th->result = NULL;
  5281. th->handle = (HANDLE) _beginthreadex(NULL, 0, win32_pthread_run, th, 0, NULL);
  5282. if (th->handle == NULL)
  5283. {
  5284. save_errno = errno;
  5285. free(th);
  5286. return save_errno;
  5287. }
  5288. *thread = th;
  5289. return 0;
  5290. }
  5291. static int
  5292. pthread_join(pthread_t th, void **thread_return)
  5293. {
  5294. if (th == NULL || th->handle == NULL)
  5295. return errno = EINVAL;
  5296. if (WaitForSingleObject(th->handle, INFINITE) != WAIT_OBJECT_0)
  5297. {
  5298. _dosmaperr(GetLastError());
  5299. return errno;
  5300. }
  5301. if (thread_return)
  5302. *thread_return = th->result;
  5303. CloseHandle(th->handle);
  5304. free(th);
  5305. return 0;
  5306. }
  5307. #endif /* WIN32 */