@@ -338,16 +338,14 @@ replorigin_create(const char *roname)
338338 * Helper function to drop a replication origin.
339339 */
340340static void
341- replorigin_drop_guts ( Relation rel , RepOriginId roident ,bool nowait )
341+ replorigin_state_clear ( RepOriginId roident ,bool nowait )
342342{
343- HeapTuple tuple ;
344343int i ;
345344
346345/*
347- *First, clean up the slot state info, if there is any matching slot.
346+ *Clean up the slot state info, if there is any matching slot.
348347 */
349348restart :
350- tuple = NULL ;
351349LWLockAcquire (ReplicationOriginLock ,LW_EXCLUSIVE );
352350
353351for (i = 0 ;i < max_replication_slots ;i ++ )
@@ -402,19 +400,6 @@ replorigin_drop_guts(Relation rel, RepOriginId roident, bool nowait)
402400}
403401LWLockRelease (ReplicationOriginLock );
404402ConditionVariableCancelSleep ();
405-
406- /*
407- * Now, we can delete the catalog entry.
408- */
409- tuple = SearchSysCache1 (REPLORIGIDENT ,ObjectIdGetDatum (roident ));
410- if (!HeapTupleIsValid (tuple ))
411- elog (ERROR ,"cache lookup failed for replication origin with ID %d" ,
412- roident );
413-
414- CatalogTupleDelete (rel ,& tuple -> t_self );
415- ReleaseSysCache (tuple );
416-
417- CommandCounterIncrement ();
418403}
419404
420405/*
@@ -427,24 +412,43 @@ replorigin_drop_by_name(const char *name, bool missing_ok, bool nowait)
427412{
428413RepOriginId roident ;
429414Relation rel ;
415+ HeapTuple tuple ;
430416
431417Assert (IsTransactionState ());
432418
433- /*
434- * To interlock against concurrent drops, we hold ExclusiveLock on
435- * pg_replication_origin till xact commit.
436- *
437- * XXX We can optimize this by acquiring the lock on a specific origin by
438- * using LockSharedObject if required. However, for that, we first to
439- * acquire a lock on ReplicationOriginRelationId, get the origin_id, lock
440- * the specific origin and then re-check if the origin still exists.
441- */
442- rel = table_open (ReplicationOriginRelationId ,ExclusiveLock );
419+ rel = table_open (ReplicationOriginRelationId ,RowExclusiveLock );
443420
444421roident = replorigin_by_name (name ,missing_ok );
445422
446- if (OidIsValid (roident ))
447- replorigin_drop_guts (rel ,roident ,nowait );
423+ /* Lock the origin to prevent concurrent drops. */
424+ LockSharedObject (ReplicationOriginRelationId ,roident ,0 ,
425+ AccessExclusiveLock );
426+
427+ tuple = SearchSysCache1 (REPLORIGIDENT ,ObjectIdGetDatum (roident ));
428+ if (!HeapTupleIsValid (tuple ))
429+ {
430+ if (!missing_ok )
431+ elog (ERROR ,"cache lookup failed for replication origin with ID %d" ,
432+ roident );
433+
434+ /*
435+ * We don't need to retain the locks if the origin is already dropped.
436+ */
437+ UnlockSharedObject (ReplicationOriginRelationId ,roident ,0 ,
438+ AccessExclusiveLock );
439+ table_close (rel ,RowExclusiveLock );
440+ return ;
441+ }
442+
443+ replorigin_state_clear (roident ,nowait );
444+
445+ /*
446+ * Now, we can delete the catalog entry.
447+ */
448+ CatalogTupleDelete (rel ,& tuple -> t_self );
449+ ReleaseSysCache (tuple );
450+
451+ CommandCounterIncrement ();
448452
449453/* We keep the lock on pg_replication_origin until commit */
450454table_close (rel ,NoLock );