Skip to content

Commit

Permalink
Code review for recent slot.c changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
anarazel committed Apr 6, 2017
1 parent df1a699 commit 5c21ad0
Showing 1 changed file with 22 additions and 26 deletions.
48 changes: 22 additions & 26 deletions src/backend/replication/slot.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ ReplicationSlotRelease(void)
* Cleanup all temporary slots created in current session.
*/
void
ReplicationSlotCleanup()
ReplicationSlotCleanup(void)
{
int i;

Expand Down Expand Up @@ -802,12 +802,12 @@ ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive)
* pg_database oid for the database to prevent creation of new slots on the db
* or replay from existing slots.
*
* This routine isn't as efficient as it could be - but we don't drop databases
* often, especially databases with lots of slots.
*
* Another session that concurrently acquires an existing slot on the target DB
* (most likely to drop it) may cause this function to ERROR. If that happens
* it may have dropped some but not all slots.
*
* This routine isn't as efficient as it could be - but we don't drop
* databases often, especially databases with lots of slots.
*/
void
ReplicationSlotsDropDBSlots(Oid dboid)
Expand All @@ -822,7 +822,7 @@ ReplicationSlotsDropDBSlots(Oid dboid)
for (i = 0; i < max_replication_slots; i++)
{
ReplicationSlot *s;
NameData slotname;
char *slotname;
int active_pid;

s = &ReplicationSlotCtl->replication_slots[i];
Expand All @@ -839,10 +839,10 @@ ReplicationSlotsDropDBSlots(Oid dboid)
if (s->data.database != dboid)
continue;

/* Claim the slot, as if ReplicationSlotAcquire()ing. */
/* acquire slot, so ReplicationSlotDropAcquired can be reused */
SpinLockAcquire(&s->mutex);
strncpy(NameStr(slotname), NameStr(s->data.name), NAMEDATALEN);
NameStr(slotname)[NAMEDATALEN-1] = '\0';
/* can't change while ReplicationSlotControlLock is held */
slotname = NameStr(s->data.name);
active_pid = s->active_pid;
if (active_pid == 0)
{
Expand All @@ -852,36 +852,32 @@ ReplicationSlotsDropDBSlots(Oid dboid)
SpinLockRelease(&s->mutex);

/*
* We might fail here if the slot was active. Even though we hold an
* exclusive lock on the database object a logical slot for that DB can
* still be active if it's being dropped by a backend connected to
* another DB or is otherwise acquired.
* Even though we hold an exclusive lock on the database object a
* logical slot for that DB can still be active, e.g. if it's
* concurrently being dropped by a backend connected to another DB.
*
* It's an unlikely race that'll only arise from concurrent user action,
* so we'll just bail out.
* That's fairly unlikely in practice, so we'll just bail out.
*/
if (active_pid)
elog(ERROR, "replication slot %s is in use by pid %d",
NameStr(slotname), active_pid);
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("replication slot \"%s\" is active for PID %d",
slotname, active_pid)));

/*
* To avoid largely duplicating ReplicationSlotDropAcquired() or
* complicating it with already_locked flags for ProcArrayLock,
* ReplicationSlotControlLock and ReplicationSlotAllocationLock, we
* just release our ReplicationSlotControlLock to drop the slot.
* To avoid duplicating ReplicationSlotDropAcquired() and to avoid
* holding ReplicationSlotControlLock over filesystem operations,
* release ReplicationSlotControlLock and use
* ReplicationSlotDropAcquired.
*
* For safety we'll restart our scan from the beginning each
* time we release the lock.
* As that means the set of slots could change, restart scan from the
* beginning each time we release the lock.
*/
LWLockRelease(ReplicationSlotControlLock);
ReplicationSlotDropAcquired();
goto restart;
}
LWLockRelease(ReplicationSlotControlLock);

/* recompute limits once after all slots are dropped */
ReplicationSlotsComputeRequiredXmin(false);
ReplicationSlotsComputeRequiredLSN();
}


Expand Down

0 comments on commit 5c21ad0

Please sign in to comment.