@ -278,18 +278,9 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
for ( slotno = 0 ; slotno < max_replication_slots ; slotno + + )
for ( slotno = 0 ; slotno < max_replication_slots ; slotno + + )
{
{
ReplicationSlot * slot = & ReplicationSlotCtl - > replication_slots [ slotno ] ;
ReplicationSlot * slot = & ReplicationSlotCtl - > replication_slots [ slotno ] ;
ReplicationSlot slot_contents ;
Datum values [ PG_GET_REPLICATION_SLOTS_COLS ] ;
Datum values [ PG_GET_REPLICATION_SLOTS_COLS ] ;
bool nulls [ PG_GET_REPLICATION_SLOTS_COLS ] ;
bool nulls [ PG_GET_REPLICATION_SLOTS_COLS ] ;
ReplicationSlotPersistency persistency ;
TransactionId xmin ;
TransactionId catalog_xmin ;
XLogRecPtr restart_lsn ;
XLogRecPtr confirmed_flush_lsn ;
pid_t active_pid ;
Oid database ;
NameData slot_name ;
NameData plugin ;
WALAvailability walstate ;
WALAvailability walstate ;
XLogSegNo last_removed_seg ;
XLogSegNo last_removed_seg ;
int i ;
int i ;
@ -297,69 +288,61 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
if ( ! slot - > in_use )
if ( ! slot - > in_use )
continue ;
continue ;
/* Copy slot contents while holding spinlock, then examine at leisure */
SpinLockAcquire ( & slot - > mutex ) ;
SpinLockAcquire ( & slot - > mutex ) ;
slot_contents = * slot ;
xmin = slot - > data . xmin ;
catalog_xmin = slot - > data . catalog_xmin ;
database = slot - > data . database ;
restart_lsn = slot - > data . restart_lsn ;
confirmed_flush_lsn = slot - > data . confirmed_flush ;
namecpy ( & slot_name , & slot - > data . name ) ;
namecpy ( & plugin , & slot - > data . plugin ) ;
active_pid = slot - > active_pid ;
persistency = slot - > data . persistency ;
SpinLockRelease ( & slot - > mutex ) ;
SpinLockRelease ( & slot - > mutex ) ;
memset ( values , 0 , sizeof ( values ) ) ;
memset ( nulls , 0 , sizeof ( nulls ) ) ;
memset ( nulls , 0 , sizeof ( nulls ) ) ;
i = 0 ;
i = 0 ;
values [ i + + ] = NameGetDatum ( & slot_name ) ;
values [ i + + ] = NameGetDatum ( & slot_contents . data . name ) ;
if ( database = = InvalidOid )
if ( slot_contents . data . database = = InvalidOid )
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
else
else
values [ i + + ] = NameGetDatum ( & plugin ) ;
values [ i + + ] = NameGetDatum ( & slot_contents . data . plugin ) ;
if ( database = = InvalidOid )
if ( slot_contents . data . database = = InvalidOid )
values [ i + + ] = CStringGetTextDatum ( " physical " ) ;
values [ i + + ] = CStringGetTextDatum ( " physical " ) ;
else
else
values [ i + + ] = CStringGetTextDatum ( " logical " ) ;
values [ i + + ] = CStringGetTextDatum ( " logical " ) ;
if ( database = = InvalidOid )
if ( slot_contents . data . database = = InvalidOid )
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
else
else
values [ i + + ] = database ;
values [ i + + ] = ObjectIdGetDatum ( slot_contents . data . database ) ;
values [ i + + ] = BoolGetDatum ( persistency = = RS_TEMPORARY ) ;
values [ i + + ] = BoolGetDatum ( slot_contents . data . persistency = = RS_TEMPORARY ) ;
values [ i + + ] = BoolGetDatum ( active_pid ! = 0 ) ;
values [ i + + ] = BoolGetDatum ( slot_contents . active_pid ! = 0 ) ;
if ( active_pid ! = 0 )
if ( slot_contents . active_pid ! = 0 )
values [ i + + ] = Int32GetDatum ( active_pid ) ;
values [ i + + ] = Int32GetDatum ( slot_contents . active_pid ) ;
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
if ( xmin ! = InvalidTransactionId )
if ( slot_contents . data . xmin ! = InvalidTransactionId )
values [ i + + ] = TransactionIdGetDatum ( xmin ) ;
values [ i + + ] = TransactionIdGetDatum ( slot_contents . data . xmin ) ;
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
if ( catalog_xmin ! = InvalidTransactionId )
if ( slot_contents . data . catalog_xmin ! = InvalidTransactionId )
values [ i + + ] = TransactionIdGetDatum ( catalog_xmin ) ;
values [ i + + ] = TransactionIdGetDatum ( slot_contents . data . catalog_xmin ) ;
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
if ( restart_lsn ! = InvalidXLogRecPtr )
if ( slot_contents . data . restart_lsn ! = InvalidXLogRecPtr )
values [ i + + ] = LSNGetDatum ( restart_lsn ) ;
values [ i + + ] = LSNGetDatum ( slot_contents . data . restart_lsn ) ;
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
if ( confirmed_flush_lsn ! = InvalidXLogRecPtr )
if ( slot_contents . data . confirmed_flush ! = InvalidXLogRecPtr )
values [ i + + ] = LSNGetDatum ( confirmed_flush_lsn ) ;
values [ i + + ] = LSNGetDatum ( slot_contents . data . confirmed_flush ) ;
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
walstate = GetWALAvailability ( restart_lsn ) ;
walstate = GetWALAvailability ( slot_contents . data . restart_lsn ) ;
switch ( walstate )
switch ( walstate )
{
{
@ -378,6 +361,9 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
case WALAVAIL_REMOVED :
case WALAVAIL_REMOVED :
values [ i + + ] = CStringGetTextDatum ( " lost " ) ;
values [ i + + ] = CStringGetTextDatum ( " lost " ) ;
break ;
break ;
default :
elog ( ERROR , " invalid walstate: %d " , ( int ) walstate ) ;
}
}
if ( max_slot_wal_keep_size_mb > = 0 & &
if ( max_slot_wal_keep_size_mb > = 0 & &
@ -393,8 +379,11 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
else
else
nulls [ i + + ] = true ;
nulls [ i + + ] = true ;
Assert ( i = = PG_GET_REPLICATION_SLOTS_COLS ) ;
tuplestore_putvalues ( tupstore , tupdesc , values , nulls ) ;
tuplestore_putvalues ( tupstore , tupdesc , values , nulls ) ;
}
}
LWLockRelease ( ReplicationSlotControlLock ) ;
LWLockRelease ( ReplicationSlotControlLock ) ;
tuplestore_donestoring ( tupstore ) ;
tuplestore_donestoring ( tupstore ) ;
@ -653,6 +642,8 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot)
Name src_name = PG_GETARG_NAME ( 0 ) ;
Name src_name = PG_GETARG_NAME ( 0 ) ;
Name dst_name = PG_GETARG_NAME ( 1 ) ;
Name dst_name = PG_GETARG_NAME ( 1 ) ;
ReplicationSlot * src = NULL ;
ReplicationSlot * src = NULL ;
ReplicationSlot first_slot_contents ;
ReplicationSlot second_slot_contents ;
XLogRecPtr src_restart_lsn ;
XLogRecPtr src_restart_lsn ;
bool src_islogical ;
bool src_islogical ;
bool temporary ;
bool temporary ;
@ -692,13 +683,10 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot)
if ( s - > in_use & & strcmp ( NameStr ( s - > data . name ) , NameStr ( * src_name ) ) = = 0 )
if ( s - > in_use & & strcmp ( NameStr ( s - > data . name ) , NameStr ( * src_name ) ) = = 0 )
{
{
/* Copy the slot contents while holding spinlock */
SpinLockAcquire ( & s - > mutex ) ;
SpinLockAcquire ( & s - > mutex ) ;
src_islogical = SlotIsLogical ( s ) ;
first_slot_contents = * s ;
src_restart_lsn = s - > data . restart_lsn ;
temporary = s - > data . persistency = = RS_TEMPORARY ;
plugin = logical_slot ? pstrdup ( NameStr ( s - > data . plugin ) ) : NULL ;
SpinLockRelease ( & s - > mutex ) ;
SpinLockRelease ( & s - > mutex ) ;
src = s ;
src = s ;
break ;
break ;
}
}
@ -711,6 +699,11 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot)
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
errmsg ( " replication slot \" %s \" does not exist " , NameStr ( * src_name ) ) ) ) ;
errmsg ( " replication slot \" %s \" does not exist " , NameStr ( * src_name ) ) ) ) ;
src_islogical = SlotIsLogical ( & first_slot_contents ) ;
src_restart_lsn = first_slot_contents . data . restart_lsn ;
temporary = ( first_slot_contents . data . persistency = = RS_TEMPORARY ) ;
plugin = logical_slot ? NameStr ( first_slot_contents . data . plugin ) : NULL ;
/* Check type of replication slot */
/* Check type of replication slot */
if ( src_islogical ! = logical_slot )
if ( src_islogical ! = logical_slot )
ereport ( ERROR ,
ereport ( ERROR ,
@ -775,18 +768,20 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot)
/* Copy data of source slot again */
/* Copy data of source slot again */
SpinLockAcquire ( & src - > mutex ) ;
SpinLockAcquire ( & src - > mutex ) ;
copy_effective_xmin = src - > effective_xmin ;
second_slot_contents = * src ;
copy_effective_catalog_xmin = src - > effective_catalog_xmin ;
SpinLockRelease ( & src - > mutex ) ;
copy_xmin = src - > data . xmin ;
copy_effective_xmin = second_slot_contents . effective_xmin ;
copy_catalog_xmin = src - > data . catalog_xmin ;
copy_effective_catalog_xmin = second_slot_contents . effective_catalog_xmin ;
copy_restart_lsn = src - > data . restart_lsn ;
copy_confirmed_flush = src - > data . confirmed_flush ;
copy_xmin = second_slot_contents . data . xmin ;
copy_catalog_xmin = second_slot_contents . data . catalog_xmin ;
copy_restart_lsn = second_slot_contents . data . restart_lsn ;
copy_confirmed_flush = second_slot_contents . data . confirmed_flush ;
/* for existence check */
/* for existence check */
copy_name = pstrdup ( NameStr ( src - > data . name ) ) ;
copy_name = NameStr ( second_slot_contents . data . name ) ;
copy_islogical = SlotIsLogical ( src ) ;
copy_islogical = SlotIsLogical ( & second_slot_contents ) ;
SpinLockRelease ( & src - > mutex ) ;
/*
/*
* Check if the source slot still exists and is valid . We regard it as
* Check if the source slot still exists and is valid . We regard it as