@@ -93,13 +93,23 @@ CommitTimestampShared *commitTsShared;
93
93
/* GUC variable */
94
94
bool track_commit_timestamp ;
95
95
96
+ /*
97
+ * When this is set, commit_ts is force-enabled during recovery. This is so
98
+ * that a standby can replay WAL records coming from a master with the setting
99
+ * enabled. (Note that this doesn't enable SQL access to the data; it's
100
+ * effectively write-only until the GUC itself is enabled.)
101
+ */
102
+ static bool enable_during_recovery ;
103
+
96
104
static void SetXidCommitTsInPage (TransactionId xid , int nsubxids ,
97
105
TransactionId * subxids , TimestampTz ts ,
98
106
RepOriginId nodeid , int pageno );
99
107
static void TransactionIdSetCommitTs (TransactionId xid , TimestampTz ts ,
100
108
RepOriginId nodeid , int slotno );
101
109
static int ZeroCommitTsPage (int pageno , bool writeXlog );
102
110
static bool CommitTsPagePrecedes (int page1 , int page2 );
111
+ static void ActivateCommitTs (void );
112
+ static void DeactivateCommitTs (bool do_wal );
103
113
static void WriteZeroPageXlogRec (int pageno );
104
114
static void WriteTruncateXlogRec (int pageno );
105
115
static void WriteSetTimestampXlogRec (TransactionId mainxid , int nsubxids ,
@@ -122,10 +132,6 @@ static void WriteSetTimestampXlogRec(TransactionId mainxid, int nsubxids,
122
132
* subtrans implementation changes in the future, we might want to revisit the
123
133
* decision of storing timestamp info for each subxid.
124
134
*
125
- * The replaying_xlog parameter indicates whether the module should execute
126
- * its write even if the feature is nominally disabled, because we're replaying
127
- * a record generated from a master where the feature is enabled.
128
- *
129
135
* The write_xlog parameter tells us whether to include an XLog record of this
130
136
* or not. Normally, this is called from transaction commit routines (both
131
137
* normal and prepared) and the information will be stored in the transaction
@@ -136,18 +142,17 @@ static void WriteSetTimestampXlogRec(TransactionId mainxid, int nsubxids,
136
142
void
137
143
TransactionTreeSetCommitTsData (TransactionId xid , int nsubxids ,
138
144
TransactionId * subxids , TimestampTz timestamp ,
139
- RepOriginId nodeid ,
140
- bool replaying_xlog , bool write_xlog )
145
+ RepOriginId nodeid , bool write_xlog )
141
146
{
142
147
int i ;
143
148
TransactionId headxid ;
144
149
TransactionId newestXact ;
145
150
146
- /* We'd better not try to write xlog during replay */
147
- Assert (!( write_xlog && replaying_xlog ));
148
-
149
- /* No-op if feature not enabled, unless replaying WAL */
150
- if (!track_commit_timestamp && !replaying_xlog )
151
+ /*
152
+ * No-op if the module is not enabled, but allow writes in a standby
153
+ * during recovery.
154
+ */
155
+ if (!track_commit_timestamp && !enable_during_recovery )
151
156
return ;
152
157
153
158
/*
@@ -534,40 +539,61 @@ ZeroCommitTsPage(int pageno, bool writeXlog)
534
539
/*
535
540
* This must be called ONCE during postmaster or standalone-backend startup,
536
541
* after StartupXLOG has initialized ShmemVariableCache->nextXid.
542
+ *
543
+ * Caller may choose to enable the feature even when it is turned off in the
544
+ * configuration.
537
545
*/
538
546
void
539
- StartupCommitTs (void )
547
+ StartupCommitTs (bool force_enable )
540
548
{
541
- TransactionId xid = ShmemVariableCache -> nextXid ;
542
- int pageno = TransactionIdToCTsPage (xid );
543
-
544
- if (track_commit_timestamp )
545
- {
546
- ActivateCommitTs ();
547
- return ;
548
- }
549
-
550
- LWLockAcquire (CommitTsControlLock , LW_EXCLUSIVE );
551
-
552
549
/*
553
- * Initialize our idea of the latest page number.
550
+ * If the module is not enabled, there's nothing to do here. The module
551
+ * could still be activated from elsewhere.
554
552
*/
555
- CommitTsCtl -> shared -> latest_page_number = pageno ;
556
-
557
- LWLockRelease (CommitTsControlLock );
553
+ if (track_commit_timestamp || force_enable )
554
+ ActivateCommitTs ();
558
555
}
559
556
560
557
/*
561
558
* This must be called ONCE during postmaster or standalone-backend startup,
562
- * when commit timestamp is enabled, after recovery has finished.
559
+ * after recovery has finished.
563
560
*/
564
561
void
565
562
CompleteCommitTsInitialization (void )
566
563
{
564
+ /*
565
+ * If the feature is not enabled, turn it off for good. This also removes
566
+ * any leftover data.
567
+ */
567
568
if (!track_commit_timestamp )
568
569
DeactivateCommitTs (true);
569
570
}
570
571
572
+ /*
573
+ * Activate or deactivate CommitTs' upon reception of a XLOG_PARAMETER_CHANGE
574
+ * XLog record in a standby.
575
+ */
576
+ void
577
+ CommitTsParameterChange (bool newvalue , bool oldvalue )
578
+ {
579
+ /*
580
+ * If the commit_ts module is disabled in this server and we get word from
581
+ * the master server that it is enabled there, activate it so that we can
582
+ * replay future WAL records involving it; also mark it as active on
583
+ * pg_control. If the old value was already set, we already did this, so
584
+ * don't do anything.
585
+ *
586
+ * If the module is disabled in the master, disable it here too.
587
+ */
588
+ if (newvalue )
589
+ {
590
+ if (!track_commit_timestamp && !oldvalue )
591
+ ActivateCommitTs ();
592
+ }
593
+ else if (oldvalue )
594
+ DeactivateCommitTs (false);
595
+ }
596
+
571
597
/*
572
598
* Activate this module whenever necessary.
573
599
* This must happen during postmaster or standalong-backend startup,
@@ -584,7 +610,7 @@ CompleteCommitTsInitialization(void)
584
610
* running with this module disabled for a while and thus might have skipped
585
611
* the normal creation point.
586
612
*/
587
- void
613
+ static void
588
614
ActivateCommitTs (void )
589
615
{
590
616
TransactionId xid = ShmemVariableCache -> nextXid ;
@@ -629,6 +655,9 @@ ActivateCommitTs(void)
629
655
Assert (!CommitTsCtl -> shared -> page_dirty [slotno ]);
630
656
LWLockRelease (CommitTsControlLock );
631
657
}
658
+
659
+ /* We can now replay xlog records from this module */
660
+ enable_during_recovery = true;
632
661
}
633
662
634
663
/*
@@ -641,7 +670,7 @@ ActivateCommitTs(void)
641
670
* Resets CommitTs into invalid state to make sure we don't hand back
642
671
* possibly-invalid data; also removes segments of old data.
643
672
*/
644
- void
673
+ static void
645
674
DeactivateCommitTs (bool do_wal )
646
675
{
647
676
TransactionId xid = ShmemVariableCache -> nextXid ;
@@ -659,7 +688,18 @@ DeactivateCommitTs(bool do_wal)
659
688
ShmemVariableCache -> newestCommitTs = InvalidTransactionId ;
660
689
LWLockRelease (CommitTsLock );
661
690
662
- TruncateCommitTs (ReadNewTransactionId (), do_wal );
691
+ /*
692
+ * Remove *all* files. This is necessary so that there are no leftover
693
+ * files; in the case where this feature is later enabled after running
694
+ * with it disabled for some time there may be a gap in the file sequence.
695
+ * (We can probably tolerate out-of-sequence files, as they are going to
696
+ * be overwritten anyway when we wrap around, but it seems better to be
697
+ * tidy.)
698
+ */
699
+ (void ) SlruScanDirectory (CommitTsCtl , SlruScanDirCbDeleteAll , NULL );
700
+
701
+ /* No longer enabled on recovery */
702
+ enable_during_recovery = false;
663
703
}
664
704
665
705
/*
@@ -699,7 +739,7 @@ ExtendCommitTs(TransactionId newestXact)
699
739
int pageno ;
700
740
701
741
/* nothing to do if module not enabled */
702
- if (!track_commit_timestamp )
742
+ if (!track_commit_timestamp && ! enable_during_recovery )
703
743
return ;
704
744
705
745
/*
@@ -916,8 +956,7 @@ commit_ts_redo(XLogReaderState *record)
916
956
subxids = NULL ;
917
957
918
958
TransactionTreeSetCommitTsData (setts -> mainxid , nsubxids , subxids ,
919
- setts -> timestamp , setts -> nodeid , false,
920
- true);
959
+ setts -> timestamp , setts -> nodeid , true);
921
960
if (subxids )
922
961
pfree (subxids );
923
962
}
0 commit comments