7
7
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.343 2009/06/11 14:48:54 momjian Exp $
10
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.344 2009/06/25 21:36:00 heikki Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -4912,12 +4912,18 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
4912
4912
{
4913
4913
char recoveryPath [MAXPGPATH ];
4914
4914
char xlogpath [MAXPGPATH ];
4915
+ XLogRecPtr InvalidXLogRecPtr = {0 , 0 };
4915
4916
4916
4917
/*
4917
4918
* We are no longer in archive recovery state.
4918
4919
*/
4919
4920
InArchiveRecovery = false;
4920
4921
4922
+ /*
4923
+ * Update min recovery point one last time.
4924
+ */
4925
+ UpdateMinRecoveryPoint (InvalidXLogRecPtr , true);
4926
+
4921
4927
/*
4922
4928
* We should have the ending log segment currently open. Verify, and then
4923
4929
* close it (to avoid problems on Windows with trying to rename or delete
@@ -5156,6 +5162,7 @@ StartupXLOG(void)
5156
5162
XLogRecord * record ;
5157
5163
uint32 freespace ;
5158
5164
TransactionId oldestActiveXID ;
5165
+ bool bgwriterLaunched = false;
5159
5166
5160
5167
XLogCtl -> SharedRecoveryInProgress = true;
5161
5168
@@ -5472,7 +5479,11 @@ StartupXLOG(void)
5472
5479
* process in addition to postmaster!
5473
5480
*/
5474
5481
if (InArchiveRecovery && IsUnderPostmaster )
5482
+ {
5483
+ SetForwardFsyncRequests ();
5475
5484
SendPostmasterSignal (PMSIGNAL_RECOVERY_STARTED );
5485
+ bgwriterLaunched = true;
5486
+ }
5476
5487
5477
5488
/*
5478
5489
* main redo apply loop
@@ -5709,12 +5720,6 @@ StartupXLOG(void)
5709
5720
/* Pre-scan prepared transactions to find out the range of XIDs present */
5710
5721
oldestActiveXID = PrescanPreparedTransactions ();
5711
5722
5712
- /*
5713
- * Allow writing WAL for us, so that we can create a checkpoint record.
5714
- * But not yet for other backends!
5715
- */
5716
- LocalRecoveryInProgress = false;
5717
-
5718
5723
if (InRecovery )
5719
5724
{
5720
5725
int rmid ;
@@ -5743,7 +5748,12 @@ StartupXLOG(void)
5743
5748
* the rule that TLI only changes in shutdown checkpoints, which
5744
5749
* allows some extra error checking in xlog_redo.
5745
5750
*/
5746
- CreateCheckPoint (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE );
5751
+ if (bgwriterLaunched )
5752
+ RequestCheckpoint (CHECKPOINT_END_OF_RECOVERY |
5753
+ CHECKPOINT_IMMEDIATE |
5754
+ CHECKPOINT_WAIT );
5755
+ else
5756
+ CreateCheckPoint (CHECKPOINT_END_OF_RECOVERY | CHECKPOINT_IMMEDIATE );
5747
5757
5748
5758
/*
5749
5759
* And finally, execute the recovery_end_command, if any.
@@ -5806,7 +5816,7 @@ StartupXLOG(void)
5806
5816
}
5807
5817
5808
5818
/*
5809
- * All done. Allow others to write WAL.
5819
+ * All done. Allow backends to write WAL.
5810
5820
*/
5811
5821
XLogCtl -> SharedRecoveryInProgress = false;
5812
5822
}
@@ -6123,12 +6133,13 @@ LogCheckpointStart(int flags, bool restartpoint)
6123
6133
* the main message, but what about all the flags?
6124
6134
*/
6125
6135
if (restartpoint )
6126
- msg = "restartpoint starting:%s%s%s%s%s%s" ;
6136
+ msg = "restartpoint starting:%s%s%s%s%s%s%s " ;
6127
6137
else
6128
- msg = "checkpoint starting:%s%s%s%s%s%s" ;
6138
+ msg = "checkpoint starting:%s%s%s%s%s%s%s " ;
6129
6139
6130
6140
elog (LOG , msg ,
6131
6141
(flags & CHECKPOINT_IS_SHUTDOWN ) ? " shutdown" : "" ,
6142
+ (flags & CHECKPOINT_END_OF_RECOVERY ) ? " end-of-recovery" : "" ,
6132
6143
(flags & CHECKPOINT_IMMEDIATE ) ? " immediate" : "" ,
6133
6144
(flags & CHECKPOINT_FORCE ) ? " force" : "" ,
6134
6145
(flags & CHECKPOINT_WAIT ) ? " wait" : "" ,
@@ -6190,10 +6201,12 @@ LogCheckpointEnd(bool restartpoint)
6190
6201
*
6191
6202
* flags is a bitwise OR of the following:
6192
6203
* CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.
6204
+ * CHECKPOINT_END_OF_RECOVERY: checkpoint is for end of WAL recovery.
6193
6205
* CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,
6194
6206
* ignoring checkpoint_completion_target parameter.
6195
6207
* CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occured
6196
- * since the last one (implied by CHECKPOINT_IS_SHUTDOWN).
6208
+ * since the last one (implied by CHECKPOINT_IS_SHUTDOWN and
6209
+ * CHECKPOINT_END_OF_RECOVERY).
6197
6210
*
6198
6211
* Note: flags contains other bits, of interest here only for logging purposes.
6199
6212
* In particular note that this routine is synchronous and does not pay
@@ -6202,7 +6215,7 @@ LogCheckpointEnd(bool restartpoint)
6202
6215
void
6203
6216
CreateCheckPoint (int flags )
6204
6217
{
6205
- bool shutdown = ( flags & CHECKPOINT_IS_SHUTDOWN ) != 0 ;
6218
+ bool shutdown ;
6206
6219
CheckPoint checkPoint ;
6207
6220
XLogRecPtr recptr ;
6208
6221
XLogCtlInsert * Insert = & XLogCtl -> Insert ;
@@ -6212,35 +6225,53 @@ CreateCheckPoint(int flags)
6212
6225
uint32 _logSeg ;
6213
6226
TransactionId * inCommitXids ;
6214
6227
int nInCommit ;
6228
+ bool OldInRecovery = InRecovery ;
6215
6229
6216
- /* shouldn't happen */
6217
- if (RecoveryInProgress ())
6218
- elog (ERROR , "can't create a checkpoint during recovery" );
6230
+ /*
6231
+ * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6232
+ * issued at a different time.
6233
+ */
6234
+ if (flags & ((CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY ) != 0 ))
6235
+ shutdown = true;
6236
+ else
6237
+ shutdown = false;
6219
6238
6220
6239
/*
6221
- * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
6222
- * During normal operation, bgwriter is the only process that creates
6223
- * checkpoints, but at the end of archive recovery, the bgwriter can be
6224
- * busy creating a restartpoint while the startup process tries to perform
6225
- * the startup checkpoint.
6240
+ * A startup checkpoint is created before anyone else is allowed to
6241
+ * write WAL. To allow us to write the checkpoint record, set
6242
+ * LocalRecoveryInProgress to false. This lets us write WAL, but others
6243
+ * are still not allowed to do so.
6226
6244
*/
6227
- if (! LWLockConditionalAcquire ( CheckpointLock , LW_EXCLUSIVE ) )
6245
+ if (flags & CHECKPOINT_END_OF_RECOVERY )
6228
6246
{
6229
- Assert (InRecovery );
6247
+ Assert (RecoveryInProgress ());
6248
+ LocalRecoveryInProgress = false;
6249
+ InitXLOGAccess ();
6230
6250
6231
6251
/*
6232
- * A restartpoint is in progress. Wait until it finishes. This can
6233
- * cause an extra restartpoint to be performed, but that's OK because
6234
- * we're just about to perform a checkpoint anyway. Flushing the
6235
- * buffers in this restartpoint can take some time, but that time is
6236
- * saved from the upcoming checkpoint so the net effect is zero .
6252
+ * Before 8.4, end-of-recovery checkpoints were always performed by
6253
+ * the startup process, and InRecovery was set true. InRecovery is not
6254
+ * normally set in bgwriter, but we set it here temporarily to avoid
6255
+ * confusing old code in the end-of-recovery checkpoint code path that
6256
+ * rely on it .
6237
6257
*/
6238
- ereport (DEBUG2 , (errmsg ("hurrying in-progress restartpoint" )));
6239
- RequestCheckpoint (CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT );
6240
-
6241
- LWLockAcquire (CheckpointLock , LW_EXCLUSIVE );
6258
+ InRecovery = true;
6259
+ }
6260
+ else
6261
+ {
6262
+ /* shouldn't happen */
6263
+ if (RecoveryInProgress ())
6264
+ elog (ERROR , "can't create a checkpoint during recovery" );
6242
6265
}
6243
6266
6267
+ /*
6268
+ * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
6269
+ * (This is just pro forma, since in the present system structure there is
6270
+ * only one process that is allowed to issue checkpoints at any given
6271
+ * time.)
6272
+ */
6273
+ LWLockAcquire (CheckpointLock , LW_EXCLUSIVE );
6274
+
6244
6275
/*
6245
6276
* Prepare to accumulate statistics.
6246
6277
*
@@ -6298,7 +6329,8 @@ CreateCheckPoint(int flags)
6298
6329
* the end of the last checkpoint record, and its redo pointer must point
6299
6330
* to itself.
6300
6331
*/
6301
- if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FORCE )) == 0 )
6332
+ if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
6333
+ CHECKPOINT_FORCE )) == 0 )
6302
6334
{
6303
6335
XLogRecPtr curInsert ;
6304
6336
@@ -6542,6 +6574,9 @@ CreateCheckPoint(int flags)
6542
6574
CheckpointStats .ckpt_segs_recycled );
6543
6575
6544
6576
LWLockRelease (CheckpointLock );
6577
+
6578
+ /* Restore old value */
6579
+ InRecovery = OldInRecovery ;
6545
6580
}
6546
6581
6547
6582
/*
0 commit comments