11 #ifdef HAVE_SYS_SELECT_H
12 #include <sys/select.h>
21 #define PREP_WAITING "isolationtester_waiting"
62 #define STEP_NONBLOCK 0x1
63 #define STEP_RETRY 0x2
66 int nwaiting,
int flags);
89 main(
int argc,
char **argv)
99 while ((opt =
getopt(argc, argv,
"V")) != -1)
104 puts(
"isolationtester (PostgreSQL) " PG_VERSION);
107 fprintf(stderr,
"Usage: isolationtester [CONNINFO]\n");
117 setbuf(stderr, NULL);
128 conninfo =
"dbname = postgres";
134 env_wait = getenv(
"PG_TEST_TIMEOUT_DEFAULT");
135 if (env_wait != NULL)
157 const char *sessionname;
160 sessionname =
"control connection";
169 fprintf(stderr,
"Connection %d failed: %s",
196 "SELECT set_config('application_name',\n"
197 " current_setting('application_name') || '/' || $1,\n"
204 fprintf(stderr,
"setting of application name failed: %s",
224 "SELECT pg_catalog.pg_isolation_test_session_is_blocked($1, '{");
234 fprintf(stderr,
"prepare of lock wait query failed: %s",
279 for (
i = 1;
i < nallsteps;
i++)
281 if (strcmp(allsteps[
i - 1]->
name,
282 allsteps[
i]->
name) == 0)
284 fprintf(stderr,
"duplicate step name: %s\n",
318 fprintf(stderr,
"undefined step \"%s\" specified in permutation\n",
346 blocker->
step = NULL;
347 for (n = 0; n < p->
nsteps; n++)
357 if (blocker->
step == NULL)
359 fprintf(stderr,
"undefined blocking step \"%s\" referenced in permutation step \"%s\"\n",
366 fprintf(stderr,
"permutation step \"%s\" cannot block on its own session\n",
381 for (
i = 0;
i < nallsteps;
i++)
383 if (!allsteps[
i]->used)
384 fprintf(stderr,
"unused step name: %s\n", allsteps[
i]->
name);
424 for (
i = 0;
i < nsteps;
i++)
425 stepptrs[
i] = steps +
i;
466 steps[nsteps]->
name = newstep->
name;
467 steps[nsteps]->
step = newstep;
506 return strcmp(stepa->
name, stepb->
name);
512 char *stepname = (
char *)
a;
515 return strcmp(stepname, step->
name);
531 printf(
"\nstarting permutation:");
532 for (
i = 0;
i < nsteps;
i++)
564 fprintf(stderr,
"setup of session %s failed: %s",
574 for (
i = 0;
i < nsteps;
i++)
607 for (w = 0; w < nwaiting; w++)
614 if (w + 1 < nwaiting)
640 struct timeval current_time;
644 td = (int64) current_time.tv_sec - (int64)
start_time.tv_sec;
646 td += (int64) current_time.tv_usec - (int64)
start_time.tv_usec;
649 fprintf(stderr,
"step %s timed out after %d seconds\n",
652 fprintf(stderr,
"active steps are:");
705 fprintf(stderr,
"failed to complete permutation due to mutually-blocking steps\n");
721 fprintf(stderr,
"teardown of session %s failed: %s",
740 fprintf(stderr,
"teardown failed: %s",
758 int nwaiting,
int flags)
771 old_nwaiting = nwaiting;
772 have_blocker =
false;
787 if (w + 1 < nwaiting)
802 }
while (have_blocker && (nwaiting < old_nwaiting ||
any_new_notice));
827 struct timeval timeout;
832 bool canceled =
false;
849 printf(
"step %s: %s <waiting ...>\n",
867 FD_SET(sock, &read_set);
869 timeout.tv_usec = 10000;
871 ret =
select(sock + 1, &read_set, NULL, NULL, &timeout);
881 struct timeval current_time;
895 fprintf(stderr,
"lock wait query failed: %s",
915 fprintf(stderr,
"PQconsumeInput failed: %s\n",
927 printf(
"step %s: %s <waiting ...>\n",
936 td = (int64) current_time.tv_sec - (int64)
start_time.tv_sec;
938 td += (int64) current_time.tv_usec - (int64)
start_time.tv_usec;
963 printf(
"isolationtester: canceling step %s after %d seconds\n",
968 fprintf(stderr,
"PQcancel failed: %s\n",
buf);
982 fprintf(stderr,
"step %s timed out after %d seconds\n",
989 fprintf(stderr,
"PQconsumeInput failed: %s\n",
1002 printf(
"step %s: %s <waiting ...>\n",
1009 printf(
"step %s: <... completed>\n", step->
name);
1037 printf(
"%s: %s\n", sev, msg);
1043 printf(
"unexpected result status: %s\n",
1054 const char *sendername = NULL;
1066 if (sendername == NULL)
1069 snprintf(pidstring,
sizeof(pidstring),
"PID %d", notify->
be_pid);
1070 sendername = pidstring;
1072 printf(
"%s: NOTIFY \"%s\" with payload \"%s\" from %s\n",
1124 memset(&popt, 0,
sizeof(popt));
static void PGresult * res
PGcancel * PQgetCancel(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
ConnStatusType PQstatus(const PGconn *conn)
void PQfinish(PGconn *conn)
PGconn * PQconnectdb(const char *conninfo)
int PQbackendPID(const PGconn *conn)
void PQfreeCancel(PGcancel *cancel)
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)
int gettimeofday(struct timeval *tp, struct timezone *tzp)
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)