19 #define PREP_WAITING "isolationtester_waiting"
60 #define STEP_NONBLOCK 0x1
61 #define STEP_RETRY 0x2
64 int nwaiting,
int flags);
87 main(
int argc,
char **argv)
97 while ((opt =
getopt(argc, argv,
"V")) != -1)
102 puts(
"isolationtester (PostgreSQL) " PG_VERSION);
105 fprintf(stderr,
"Usage: isolationtester [CONNINFO]\n");
115 setbuf(stderr, NULL);
126 conninfo =
"dbname = postgres";
132 env_wait = getenv(
"PG_TEST_TIMEOUT_DEFAULT");
133 if (env_wait != NULL)
155 const char *sessionname;
158 sessionname =
"control connection";
167 fprintf(stderr,
"Connection %d failed: %s",
194 "SELECT set_config('application_name',\n"
195 " current_setting('application_name') || '/' || $1,\n"
202 fprintf(stderr,
"setting of application name failed: %s",
222 "SELECT pg_catalog.pg_isolation_test_session_is_blocked($1, '{");
232 fprintf(stderr,
"prepare of lock wait query failed: %s",
277 for (
i = 1;
i < nallsteps;
i++)
279 if (strcmp(allsteps[
i - 1]->
name,
280 allsteps[
i]->
name) == 0)
282 fprintf(stderr,
"duplicate step name: %s\n",
316 fprintf(stderr,
"undefined step \"%s\" specified in permutation\n",
344 blocker->
step = NULL;
345 for (n = 0; n < p->
nsteps; n++)
355 if (blocker->
step == NULL)
357 fprintf(stderr,
"undefined blocking step \"%s\" referenced in permutation step \"%s\"\n",
364 fprintf(stderr,
"permutation step \"%s\" cannot block on its own session\n",
379 for (
i = 0;
i < nallsteps;
i++)
381 if (!allsteps[
i]->used)
382 fprintf(stderr,
"unused step name: %s\n", allsteps[
i]->
name);
422 for (
i = 0;
i < nsteps;
i++)
423 stepptrs[
i] = steps +
i;
464 steps[nsteps]->
name = newstep->
name;
465 steps[nsteps]->
step = newstep;
504 return strcmp(stepa->
name, stepb->
name);
510 char *stepname = (
char *)
a;
513 return strcmp(stepname, step->
name);
529 printf(
"\nstarting permutation:");
530 for (
i = 0;
i < nsteps;
i++)
562 fprintf(stderr,
"setup of session %s failed: %s",
572 for (
i = 0;
i < nsteps;
i++)
605 for (w = 0; w < nwaiting; w++)
612 if (w + 1 < nwaiting)
638 struct timeval current_time;
647 fprintf(stderr,
"step %s timed out after %d seconds\n",
650 fprintf(stderr,
"active steps are:");
703 fprintf(stderr,
"failed to complete permutation due to mutually-blocking steps\n");
719 fprintf(stderr,
"teardown of session %s failed: %s",
738 fprintf(stderr,
"teardown failed: %s",
756 int nwaiting,
int flags)
769 old_nwaiting = nwaiting;
770 have_blocker =
false;
785 if (w + 1 < nwaiting)
800 }
while (have_blocker && (nwaiting < old_nwaiting ||
any_new_notice));
825 struct timeval timeout;
830 bool canceled =
false;
847 printf(
"step %s: %s <waiting ...>\n",
865 FD_SET(sock, &read_set);
867 timeout.tv_usec = 10000;
869 ret =
select(sock + 1, &read_set, NULL, NULL, &timeout);
874 fprintf(stderr,
"select failed: %m\n");
879 struct timeval current_time;
893 fprintf(stderr,
"lock wait query failed: %s",
913 fprintf(stderr,
"PQconsumeInput failed: %s\n",
925 printf(
"step %s: %s <waiting ...>\n",
957 printf(
"isolationtester: canceling step %s after %d seconds\n",
975 fprintf(stderr,
"step %s timed out after %d seconds\n",
982 fprintf(stderr,
"PQconsumeInput failed: %s\n",
995 printf(
"step %s: %s <waiting ...>\n",
1002 printf(
"step %s: <... completed>\n", step->
name);
1030 printf(
"%s: %s\n", sev, msg);
1036 printf(
"unexpected result status: %s\n",
1047 const char *sendername = NULL;
1059 if (sendername == NULL)
1062 snprintf(pidstring,
sizeof(pidstring),
"PID %d", notify->
be_pid);
1063 sendername = pidstring;
1065 printf(
"%s: NOTIFY \"%s\" with payload \"%s\" from %s\n",
1117 memset(&popt, 0,
sizeof(popt));
static void PGresult * res
PGcancelConn * PQcancelCreate(PGconn *conn)
int PQcancelBlocking(PGcancelConn *cancelConn)
char * PQcancelErrorMessage(const PGcancelConn *cancelConn)
void PQcancelFinish(PGcancelConn *cancelConn)
char * PQerrorMessage(const PGconn *conn)
ConnStatusType PQstatus(const PGconn *conn)
void PQfinish(PGconn *conn)
PGconn * PQconnectdb(const char *conninfo)
int PQbackendPID(const PGconn *conn)
PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
int PQsocket(const PGconn *conn)
void PQfreemem(void *ptr)
PGnotify * PQnotifies(PGconn *conn)
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
PGresult * PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
ExecStatusType PQresultStatus(const PGresult *res)
char * PQresultErrorMessage(const PGresult *res)
int PQntuples(const PGresult *res)
PGresult * PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
PGresult * PQexec(PGconn *conn, const char *query)
int PQconsumeInput(PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQsendQuery(PGconn *conn, const char *query)
char * PQresStatus(ExecStatusType status)
int PQisBusy(PGconn *conn)
char * PQresultErrorField(const PGresult *res, int fieldcode)
PGresult * PQgetResult(PGconn *conn)
void PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
void * pg_malloc0(size_t size)
void * pg_malloc(size_t size)
static void printResultSet(PGresult *res)
static int step_bsearch_cmp(const void *a, const void *b)
static IsoConnInfo * conns
static int step_qsort_cmp(const void *a, const void *b)
static void run_testspec(TestSpec *testspec)
static void run_named_permutations(TestSpec *testspec)
static int try_complete_steps(TestSpec *testspec, PermutationStep **waiting, int nwaiting, int flags)
int main(int argc, char **argv)
static void run_all_permutations_recurse(TestSpec *testspec, int *piles, int nsteps, PermutationStep **steps)
static bool try_complete_step(TestSpec *testspec, PermutationStep *pstep, int flags)
static void run_all_permutations(TestSpec *testspec)
static void blackholeNoticeProcessor(void *arg, const char *message)
struct IsoConnInfo IsoConnInfo
static void check_testspec(TestSpec *testspec)
static void run_permutation(TestSpec *testspec, int nsteps, PermutationStep **steps)
static void isotesterNoticeProcessor(void *arg, const char *message)
static int64 max_step_wait
static bool step_has_blocker(PermutationStep *pstep)
static void disconnect_atexit(void)
static bool any_new_notice
static volatile sig_atomic_t waiting
int getopt(int nargc, char *const *nargv, const char *ostr)
#define qsort(a, b, c, d)
#define PG_DIAG_MESSAGE_PRIMARY
void initPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * psprintf(const char *fmt,...)
PermutationStep * active_step
const char * backend_pid_str
PermutationStepBlockerType blocktype
PermutationStepBlocker ** blockers
Permutation ** permutations
#define select(n, r, w, e, timeout)
int gettimeofday(struct timeval *tp, void *tzp)