@ -40,6 +40,7 @@
# include <sys/stat.h>
# include "access/transam.h"
# include "access/xlog_internal.h"
# include "common/string.h"
# include "miscadmin.h"
# include "replication/slot.h"
@ -781,6 +782,76 @@ CheckSlotRequirements(void)
errmsg ( " replication slots can only be used if wal_level >= archive " ) ) ) ;
}
/*
* Reserve WAL for the currently active slot .
*
* Compute and set restart_lsn in a manner that ' s appropriate for the type of
* the slot and concurrency safe .
*/
void
ReplicationSlotReserveWal ( void )
{
ReplicationSlot * slot = MyReplicationSlot ;
Assert ( slot ! = NULL ) ;
Assert ( slot - > data . restart_lsn = = InvalidXLogRecPtr ) ;
/*
* The replication slot mechanism is used to prevent removal of required
* WAL . As there is no interlock between this routine and checkpoints , WAL
* segments could concurrently be removed when a now stale return value of
* ReplicationSlotsComputeRequiredLSN ( ) is used . In the unlikely case that
* this happens we ' ll just retry .
*/
while ( true )
{
XLogSegNo segno ;
/*
* For logical slots log a standby snapshot and start logical decoding
* at exactly that position . That allows the slot to start up more
* quickly .
*
* That ' s not needed ( or indeed helpful ) for physical slots as they ' ll
* start replay at the last logged checkpoint anyway . Instead return
* the location of the last redo LSN . While that slightly increases
* the chance that we have to retry , it ' s where a base backup has to
* start replay at .
*/
if ( ! RecoveryInProgress ( ) & & SlotIsLogical ( slot ) )
{
XLogRecPtr flushptr ;
/* start at current insert position */
slot - > data . restart_lsn = GetXLogInsertRecPtr ( ) ;
/* make sure we have enough information to start */
flushptr = LogStandbySnapshot ( ) ;
/* and make sure it's fsynced to disk */
XLogFlush ( flushptr ) ;
}
else
{
slot - > data . restart_lsn = GetRedoRecPtr ( ) ;
}
/* prevent WAL removal as fast as possible */
ReplicationSlotsComputeRequiredLSN ( ) ;
/*
* If all required WAL is still there , great , otherwise retry . The
* slot should prevent further removal of WAL , unless there ' s a
* concurrent ReplicationSlotsComputeRequiredLSN ( ) after we ' ve written
* the new restart_lsn above , so normally we should never need to loop
* more than twice .
*/
XLByteToSeg ( slot - > data . restart_lsn , segno ) ;
if ( XLogGetLastRemovedSegno ( ) < segno )
break ;
}
}
/*
* Flush all replication slots to disk .
*