11 #ifdef HAVE_SYS_SELECT_H 12 #include <sys/select.h> 21 #define PREP_WAITING "isolationtester_waiting" 44 #define STEP_NONBLOCK 0x1 45 #define STEP_RETRY 0x2 60 for (i = 0; i <
nconns; i++)
66 main(
int argc,
char **argv)
80 while ((opt =
getopt(argc, argv,
"V")) != -1)
85 puts(
"isolationtester (PostgreSQL) " PG_VERSION);
88 fprintf(stderr,
"Usage: isolationtester [CONNINFO]\n");
109 conninfo =
"dbname = postgres";
115 env_wait = getenv(
"PGISOLATIONTIMEOUT");
116 if (env_wait != NULL)
125 for (i = 0; i < testspec->
nsessions; i++)
131 for (i = 0; i < testspec->
nsessions; i++)
142 for (i = 1; i < testspec->
nallsteps; i++)
147 fprintf(stderr,
"duplicate step name: %s\n",
165 for (i = 0; i <
nconns; i++)
170 fprintf(stderr,
"Connection %d to database failed: %s",
196 for (i = 0; i < testspec->
nsessions; i++)
201 for (stepindex = 0; stepindex < session->
nsteps; stepindex++)
215 "SELECT pg_catalog.pg_isolation_test_session_is_blocked($1, '{");
218 for (i = 2; i <
nconns; i++)
225 fprintf(stderr,
"prepare of lock wait query failed: %s",
261 for (i = 0; i < testspec->
nallsteps; i++)
264 fprintf(stderr,
"unused step name: %s\n",
281 for (i = 0; i < testspec->
nsessions; i++)
296 for (i = 0; i < testspec->
nsessions; i++)
308 for (i = 0; i < testspec->
nsessions; i++)
346 for (j = 0; j < p->
nsteps; j++)
356 fprintf(stderr,
"undefined step \"%s\" specified in permutation\n",
376 return strcmp(stepa->
name, stepb->
name);
382 char *stepname = (
char *) a;
385 return strcmp(stepname, step->
name);
423 for (n = 0; n < nextra; ++n)
434 for (n = 0; n < nextra; ++n)
436 if (extrastep[n]->errormsg == NULL)
440 free(extrastep[n]->errormsg);
464 printf(
"\nstarting permutation:");
465 for (i = 0; i < nsteps; i++)
468 steps[
i]->
used =
true;
490 for (i = 0; i < testspec->
nsessions; i++)
501 fprintf(stderr,
"setup of session %s failed: %s",
511 for (i = 0; i < nsteps; i++)
513 Step *step = steps[
i];
515 Step *oldstep = NULL;
532 for (w = 0; w < nwaiting; ++w)
536 oldstep = waiting[w];
542 if (w + 1 < nwaiting)
543 memmove(&waiting[w], &waiting[w + 1],
544 (nwaiting - (w + 1)) *
sizeof(
Step *));
570 errorstep[nerrorstep++] = waiting[w];
571 if (w + 1 < nwaiting)
572 memmove(&waiting[w], &waiting[w + 1],
573 (nwaiting - (w + 1)) *
sizeof(
Step *));
603 errorstep[nerrorstep++] = waiting[w];
604 if (w + 1 < nwaiting)
605 memmove(&waiting[w], &waiting[w + 1],
606 (nwaiting - (w + 1)) *
sizeof(
Step *));
616 waiting[nwaiting++] = step;
620 for (w = 0; w < nwaiting; ++w)
627 for (i = 0; i < testspec->
nsessions; i++)
638 fprintf(stderr,
"teardown of session %s failed: %s",
657 fprintf(stderr,
"teardown failed: %s",
689 struct timeval start_time;
690 struct timeval timeout;
695 bool canceled =
false;
708 FD_SET(sock, &read_set);
710 timeout.tv_usec = 10000;
712 ret =
select(sock + 1, &read_set, NULL, NULL, &timeout);
722 struct timeval current_time;
736 fprintf(stderr,
"lock wait query failed: %s",
740 waiting = ((
PQgetvalue(res, 0, 0))[0] ==
't');
756 fprintf(stderr,
"PQconsumeInput failed: %s\n",
768 printf(
"step %s: %s <waiting ...>\n",
777 td = (int64) current_time.tv_sec - (int64) start_time.tv_sec;
779 td += (int64) current_time.tv_usec - (int64) start_time.tv_usec;
798 if (
PQcancel(cancel, buf,
sizeof(buf)))
804 printf(
"isolationtester: canceling step %s after %d seconds\n",
809 fprintf(stderr,
"PQcancel failed: %s\n", buf);
823 fprintf(stderr,
"step %s timed out after %d seconds\n",
830 fprintf(stderr,
"PQconsumeInput failed: %s\n",
837 printf(
"step %s: <... completed>\n", step->
name);
853 printf(
"WARNING: this step had a leftover error message\n");
875 printf(
"unexpected result status: %s\n",
886 const char *sendername = NULL;
897 if (sendername == NULL)
901 sendername = pidstring;
903 printf(
"%s: NOTIFY \"%s\" with payload \"%s\" from %s\n",
922 for (i = 0; i < nFields; i++)
929 for (j = 0; j < nFields; j++)
939 printf(
"%s: %s", (
char *) arg, message);
PGresult * PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
int PQnfields(const PGresult *res)
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
char * PQerrorMessage(const PGconn *conn)
int gettimeofday(struct timeval *tp, struct timezone *tzp)
static int64 max_step_wait
#define PG_DIAG_MESSAGE_PRIMARY
PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
PGnotify * PQnotifies(PGconn *conn)
char * PQfname(const PGresult *res, int field_num)
void * pg_malloc(size_t size)
static void run_named_permutations(TestSpec *testspec)
void termPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void PQfreeCancel(PGcancel *cancel)
int main(int argc, char **argv)
char * psprintf(const char *fmt,...)
static void run_all_permutations(TestSpec *testspec)
static void report_multiple_error_messages(Step *step, int nextra, Step **extrastep)
char * PQresStatus(ExecStatusType status)
void PQfinish(PGconn *conn)
Permutation ** permutations
int PQntuples(const PGresult *res)
static int step_qsort_cmp(const void *a, const void *b)
int getopt(int nargc, char *const *nargv, const char *ostr)
ExecStatusType PQresultStatus(const PGresult *res)
static void blackholeNoticeProcessor(void *arg, const char *message)
int PQsendQuery(PGconn *conn, const char *query)
static bool try_complete_step(TestSpec *testspec, Step *step, int flags)
void * pg_malloc0(size_t size)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
static int * backend_pids
static int step_bsearch_cmp(const void *a, const void *b)
static void disconnect_atexit(void)
PGcancel * PQgetCancel(PGconn *conn)
char * pg_strdup(const char *in)
#define select(n, r, w, e, timeout)
int PQbackendPID(const PGconn *conn)
int PQconsumeInput(PGconn *conn)
void PQclear(PGresult *res)
char * PQresultErrorField(const PGresult *res, int fieldcode)
static const char ** backend_pid_strs
static void run_permutation(TestSpec *testspec, int nsteps, Step **steps)
static void run_all_permutations_recurse(TestSpec *testspec, int nsteps, Step **steps)
int PQisBusy(PGconn *conn)
static void isotesterNoticeProcessor(void *arg, const char *message)
static void report_error_message(Step *step)
static void run_testspec(TestSpec *testspec)
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
char * PQresultErrorMessage(const PGresult *res)
PGresult * PQexec(PGconn *conn, const char *query)
#define qsort(a, b, c, d)
ConnStatusType PQstatus(const PGconn *conn)
void PQfreemem(void *ptr)
static volatile sig_atomic_t waiting
int PQsocket(const PGconn *conn)
PGresult * PQgetResult(PGconn *conn)
void initPQExpBuffer(PQExpBuffer str)
static void printResultSet(PGresult *res)
PGconn * PQconnectdb(const char *conninfo)