Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9c9782f

Browse files
committed
isolationtester: don't repeat the is-it-waiting query when retrying a step.
If we're retrying a step, then we already decided it was blocked on a lock, and there's no need to recheck that. The original coding of commit 38f8bdc resulted in a large number of is-it-waiting queries when dealing with multiple concurrently-blocked sessions, which is fairly pointless and also results in test failures in CLOBBER_CACHE_ALWAYS builds, where the is-it-waiting query is quite slow. This definition also permits appending pg_sleep() calls to steps where it's needed to control the order of finish of concurrent steps. Before, that did not work nicely because we'd decide that a step performing a sleep was not blocked and hang up waiting for it to finish, rather than noticing the completion of the concurrent step we're supposed to notice first. In passing, revise handling of removal of completed waiting steps to make it a bit less messy.
1 parent a361490 commit 9c9782f

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

src/test/isolation/isolationtester.c

+29-24
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,8 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
540540
for (i = 0; i < nsteps; i++)
541541
{
542542
Step *step = steps[i];
543-
Step *oldstep = NULL;
544543
PGconn *conn = conns[1 + step->session];
544+
Step *oldstep = NULL;
545545
bool mustwait;
546546

547547
/*
@@ -563,33 +563,30 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
563563
if (step->session == waiting[w]->session)
564564
{
565565
oldstep = waiting[w];
566+
567+
/* Wait for previous step on this connection. */
568+
try_complete_step(oldstep, STEP_RETRY);
569+
570+
/* Remove that step from the waiting[] array. */
571+
if (w + 1 < nwaiting)
572+
memcpy(&waiting[w], &waiting[w + 1],
573+
(nwaiting - (w + 1)) * sizeof(Step *));
574+
nwaiting--;
575+
566576
break;
567577
}
568578
}
569579
if (oldstep != NULL)
570580
{
571-
/* Wait for previous step on this connection. */
572-
try_complete_step(oldstep, STEP_RETRY);
573-
574581
/*
575-
* Attempt to complete any steps that were previously waiting.
576-
* Remove any that have completed, and also remove the one for
577-
* which we just waited.
582+
* Check for completion of any steps that were previously waiting.
583+
* Remove any that have completed from waiting[], and include them
584+
* in the list for report_multiple_error_messages().
578585
*/
579586
w = 0;
580587
nerrorstep = 0;
581588
while (w < nwaiting)
582589
{
583-
if (waiting[w] == oldstep)
584-
{
585-
/* We just waited for this; remove it. */
586-
if (w + 1 < nwaiting)
587-
memcpy(&waiting[w], &waiting[w + 1],
588-
(nwaiting - (w + 1)) * sizeof(Step *));
589-
nwaiting--;
590-
continue;
591-
}
592-
593590
if (try_complete_step(waiting[w], STEP_NONBLOCK | STEP_RETRY))
594591
{
595592
/* Still blocked on a lock, leave it alone. */
@@ -621,7 +618,7 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
621618
/* Try to complete this step without blocking. */
622619
mustwait = try_complete_step(step, STEP_NONBLOCK);
623620

624-
/* Attempt to complete any steps that were previously waiting. */
621+
/* Check for completion of any steps that were previously waiting. */
625622
w = 0;
626623
nerrorstep = 0;
627624
while (w < nwaiting)
@@ -646,7 +643,7 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
646643
waiting[nwaiting++] = step;
647644
}
648645

649-
/* Finish any waiting query. */
646+
/* Wait for any remaining queries. */
650647
for (w = 0; w < nwaiting; ++w)
651648
{
652649
try_complete_step(waiting[w], STEP_RETRY);
@@ -702,9 +699,10 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
702699
* have executed additional steps in the permutation.
703700
*
704701
* When calling this function on behalf of a given step for a second or later
705-
* time, pass the STEP_RETRY flag. This only affects the messages printed.
702+
* time, pass the STEP_RETRY flag. In this case we don't need to recheck
703+
* whether it's waiting for a lock.
706704
*
707-
* If the connection returns an error, the message is saved in step->errormsg.
705+
* If the query returns an error, the message is saved in step->errormsg.
708706
* Caller should call report_error_message shortly after this, to have it
709707
* printed and cleared.
710708
*
@@ -750,6 +748,14 @@ try_complete_step(Step *step, int flags)
750748
{
751749
int ntuples;
752750

751+
/*
752+
* If this is a retry, assume without checking that the step
753+
* is still blocked. This rule saves a lot of PREP_WAITING
754+
* queries and avoids any possible flappiness in the answer.
755+
*/
756+
if (flags & STEP_RETRY)
757+
return true;
758+
753759
res = PQexecPrepared(conns[0], PREP_WAITING, 1,
754760
&backend_pids[step->session + 1],
755761
NULL, NULL, 0);
@@ -764,9 +770,8 @@ try_complete_step(Step *step, int flags)
764770

765771
if (ntuples >= 1) /* waiting to acquire a lock */
766772
{
767-
if (!(flags & STEP_RETRY))
768-
printf("step %s: %s <waiting ...>\n",
769-
step->name, step->sql);
773+
printf("step %s: %s <waiting ...>\n",
774+
step->name, step->sql);
770775
return true;
771776
}
772777
/* else, not waiting */

0 commit comments

Comments
 (0)