* database drop by the startup process and the creation of a new
* slot by the user. This new user-created slot may end up using
* the same shared memory as that of 'local_slot'. Thus check if
- * local_slot is still the synced one before performing actual
+ * local_slot is still the synced one before performing the actual
* drop.
*/
SpinLockAcquire(&local_slot->mutex);
if (synced_slot)
{
+ /*
+ * Now acquire and drop the slot. Note we purposely don't
+ * request logical decoding to be disabled here: since this is
+ * a standby, which derives its logical decoding state from
+ * the primary, it would be wrong to do so.
+ */
ReplicationSlotAcquire(NameStr(local_slot->data.name), true, false);
- ReplicationSlotDropAcquired();
+ ReplicationSlotDropAcquired(false);
}
UnlockSharedObject(DatabaseRelationId, local_slot->data.database,
if (slot->data.persistency == RS_EPHEMERAL)
{
/*
- * Delete the slot. There is no !PANIC case where this is allowed to
- * fail, all that may happen is an incomplete cleanup of the on-disk
- * data.
+ * If slot is ephemeral, we drop it upon release, and request logical
+ * decoding be disabled.
*/
- ReplicationSlotDropAcquired();
-
- /*
- * Request to disable logical decoding, even though this slot may not
- * have been the last logical slot. The checkpointer will verify if
- * logical decoding should actually be disabled.
- */
- if (is_logical)
- RequestDisableLogicalDecoding();
+ ReplicationSlotDropAcquired(is_logical);
}
/*
}
/*
- * Permanently drop replication slot identified by the passed in name.
+ * Permanently drop the replication slot identified by the passed-in name.
+ *
+ * If this is a logical slot, request that logical decoding be disabled.
*/
void
ReplicationSlotDrop(const char *name, bool nowait)
{
- bool is_logical;
-
- Assert(MyReplicationSlot == NULL);
-
ReplicationSlotAcquire(name, nowait, false);
/*
errmsg("cannot drop replication slot \"%s\"", name),
errdetail("This replication slot is being synchronized from the primary server."));
- is_logical = SlotIsLogical(MyReplicationSlot);
-
- ReplicationSlotDropAcquired();
-
- if (is_logical)
- RequestDisableLogicalDecoding();
+ ReplicationSlotDropAcquired(SlotIsLogical(MyReplicationSlot));
}
/*
/*
* Permanently drop the currently acquired replication slot.
+ *
+ * If caller requests it, have checkpointer attempt to disable logical
+ * decoding. Obviously, this should only be done if the slot is logical.
*/
void
-ReplicationSlotDropAcquired(void)
+ReplicationSlotDropAcquired(bool try_disable)
{
- ReplicationSlot *slot = MyReplicationSlot;
+ ReplicationSlot *slot;
Assert(MyReplicationSlot != NULL);
+ slot = MyReplicationSlot;
+
+ /* Can only disable logical decoding if slot is logical */
+ Assert(!try_disable || SlotIsLogical(slot));
/* slot isn't acquired anymore */
MyReplicationSlot = NULL;
ReplicationSlotDropPtr(slot);
+
+ if (try_disable)
+ RequestDisableLogicalDecoding();
}
/*
* This routine isn't as efficient as it could be - but we don't drop
* databases often, especially databases with lots of slots.
*
- * If it drops the last logical slot in the cluster, it requests to disable
+ * If the last logical slot in the cluster is dropped, request to disable
* logical decoding.
*/
void
* beginning each time we release the lock.
*/
LWLockRelease(ReplicationSlotControlLock);
- ReplicationSlotDropAcquired();
+ ReplicationSlotDropAcquired(false);
dropped = true;
goto restart;
}
"the activation process aborted");
}
+# Test that logical decoding is disabled after repack
+$primary->safe_psql('postgres', qq[create table foo(a int primary key)]);
+$primary->safe_psql('postgres', qq[repack (concurrently) foo;]);
+ok( $primary->log_contains(
+ "logical decoding is enabled upon creating a new logical replication slot"
+ ),
+ "logical decoding enabled by repack");
+
+# Wait for the checkpointer to disable logical decoding.
+wait_for_logical_decoding_disabled($primary);
+test_wal_level($primary, "replica|replica",
+ "logical decoding disabled after repack"
+);
+
$primary->stop;
done_testing();