7
7
* Portions Copyright (c) 1996-2003, 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.150 2004/07/21 22:31:20 tgl Exp $
10
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.151 2004/07/22 20:18:40 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -432,7 +432,7 @@ static bool InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath,
432
432
static int XLogFileOpen (uint32 log , uint32 seg );
433
433
static int XLogFileRead (uint32 log , uint32 seg , int emode );
434
434
static bool RestoreArchivedFile (char * path , const char * xlogfname ,
435
- const char * recovername );
435
+ const char * recovername , off_t expectedSize );
436
436
static void PreallocXlogFiles (XLogRecPtr endptr );
437
437
static void MoveOfflineLogs (uint32 log , uint32 seg , XLogRecPtr endptr );
438
438
static XLogRecord * ReadRecord (XLogRecPtr * RecPtr , int emode , char * buffer );
@@ -1838,7 +1838,8 @@ XLogFileRead(uint32 log, uint32 seg, int emode)
1838
1838
{
1839
1839
XLogFileName (xlogfname , tli , log , seg );
1840
1840
restoredFromArchive = RestoreArchivedFile (path , xlogfname ,
1841
- "RECOVERYXLOG" );
1841
+ "RECOVERYXLOG" ,
1842
+ XLogSegSize );
1842
1843
}
1843
1844
else
1844
1845
XLogFilePath (path , tli , log , seg );
@@ -1876,10 +1877,14 @@ XLogFileRead(uint32 log, uint32 seg, int emode)
1876
1877
* If not successful, fill "path" with the name of the normal on-line file
1877
1878
* (which may or may not actually exist, but we'll try to use it), and return
1878
1879
* FALSE.
1880
+ *
1881
+ * For fixed-size files, the caller may pass the expected size as an
1882
+ * additional crosscheck on successful recovery. If the file size is not
1883
+ * known, set expectedSize = 0.
1879
1884
*/
1880
1885
static bool
1881
1886
RestoreArchivedFile (char * path , const char * xlogfname ,
1882
- const char * recovername )
1887
+ const char * recovername , off_t expectedSize )
1883
1888
{
1884
1889
char xlogpath [MAXPGPATH ];
1885
1890
char xlogRestoreCmd [MAXPGPATH ];
@@ -1991,19 +1996,42 @@ RestoreArchivedFile(char *path, const char *xlogfname,
1991
1996
rc = system (xlogRestoreCmd );
1992
1997
if (rc == 0 )
1993
1998
{
1994
- /* restore success ... assuming file is really there now ... */
1995
- if (stat (xlogpath , & stat_buf ) == 0 ) {
1996
- ereport (LOG ,
1997
- (errmsg ("restored log file \"%s\" from archive" ,
1998
- xlogfname )));
1999
- strcpy (path , xlogpath );
2000
- return true;
1999
+ /*
2000
+ * command apparently succeeded, but let's make sure the file is
2001
+ * really there now and has the correct size.
2002
+ *
2003
+ * XXX I made wrong-size a fatal error to ensure the DBA would
2004
+ * notice it, but is that too strong? We could try to plow ahead
2005
+ * with a local copy of the file ... but the problem is that there
2006
+ * probably isn't one, and we'd incorrectly conclude we've reached
2007
+ * the end of WAL and we're done recovering ...
2008
+ */
2009
+ if (stat (xlogpath , & stat_buf ) == 0 )
2010
+ {
2011
+ if (expectedSize > 0 && stat_buf .st_size != expectedSize )
2012
+ ereport (FATAL ,
2013
+ (errmsg ("archive file \"%s\" has wrong size: %lu instead of %lu" ,
2014
+ xlogfname ,
2015
+ (unsigned long ) stat_buf .st_size ,
2016
+ (unsigned long ) expectedSize )));
2017
+ else
2018
+ {
2019
+ ereport (LOG ,
2020
+ (errmsg ("restored log file \"%s\" from archive" ,
2021
+ xlogfname )));
2022
+ strcpy (path , xlogpath );
2023
+ return true;
2024
+ }
2025
+ }
2026
+ else
2027
+ {
2028
+ /* stat failed */
2029
+ if (errno != ENOENT )
2030
+ ereport (FATAL ,
2031
+ (errcode_for_file_access (),
2032
+ errmsg ("could not stat \"%s\": %m" ,
2033
+ xlogpath )));
2001
2034
}
2002
- if (errno != ENOENT )
2003
- ereport (FATAL ,
2004
- (errcode_for_file_access (),
2005
- errmsg ("could not stat \"%s\": %m" ,
2006
- xlogpath )));
2007
2035
}
2008
2036
2009
2037
/*
@@ -2664,7 +2692,7 @@ readTimeLineHistory(TimeLineID targetTLI)
2664
2692
if (InArchiveRecovery )
2665
2693
{
2666
2694
TLHistoryFileName (histfname , targetTLI );
2667
- RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" );
2695
+ RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" , 0 );
2668
2696
}
2669
2697
else
2670
2698
TLHistoryFilePath (path , targetTLI );
@@ -2749,7 +2777,7 @@ existsTimeLineHistory(TimeLineID probeTLI)
2749
2777
if (InArchiveRecovery )
2750
2778
{
2751
2779
TLHistoryFileName (histfname , probeTLI );
2752
- RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" );
2780
+ RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" , 0 );
2753
2781
}
2754
2782
else
2755
2783
TLHistoryFilePath (path , probeTLI );
@@ -2853,7 +2881,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
2853
2881
if (InArchiveRecovery )
2854
2882
{
2855
2883
TLHistoryFileName (histfname , parentTLI );
2856
- RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" );
2884
+ RestoreArchivedFile (path , histfname , "RECOVERYHISTORY" , 0 );
2857
2885
}
2858
2886
else
2859
2887
TLHistoryFilePath (path , parentTLI );
@@ -4042,6 +4070,11 @@ StartupXLOG(void)
4042
4070
if (checkPoint .undo .xrecoff == 0 )
4043
4071
checkPoint .undo = RecPtr ;
4044
4072
4073
+ /*
4074
+ * Check whether we need to force recovery from WAL. If it appears
4075
+ * to have been a clean shutdown and we did not have a recovery.conf
4076
+ * file, then assume no recovery needed.
4077
+ */
4045
4078
if (XLByteLT (checkPoint .undo , RecPtr ) ||
4046
4079
XLByteLT (checkPoint .redo , RecPtr ))
4047
4080
{
@@ -4054,13 +4087,23 @@ StartupXLOG(void)
4054
4087
InRecovery = true;
4055
4088
4056
4089
/* REDO */
4057
- if (InRecovery )
4090
+ if (InRecovery || InArchiveRecovery )
4058
4091
{
4059
4092
int rmid ;
4060
4093
4061
- ereport (LOG ,
4062
- (errmsg ("database system was not properly shut down; "
4063
- "automatic recovery in progress" )));
4094
+ if (InRecovery )
4095
+ {
4096
+ ereport (LOG ,
4097
+ (errmsg ("database system was not properly shut down; "
4098
+ "automatic recovery in progress" )));
4099
+ }
4100
+ else
4101
+ {
4102
+ /* force recovery due to presence of recovery.conf */
4103
+ InRecovery = true;
4104
+ ereport (LOG ,
4105
+ (errmsg ("automatic recovery in progress" )));
4106
+ }
4064
4107
ControlFile -> state = DB_IN_RECOVERY ;
4065
4108
ControlFile -> time = time (NULL );
4066
4109
UpdateControlFile ();
@@ -4158,8 +4201,11 @@ StartupXLOG(void)
4158
4201
InRedo = false;
4159
4202
}
4160
4203
else
4204
+ {
4205
+ /* there are no WAL records following the checkpoint */
4161
4206
ereport (LOG ,
4162
4207
(errmsg ("redo is not required" )));
4208
+ }
4163
4209
}
4164
4210
4165
4211
/*
0 commit comments