7
7
* Portions Copyright (c) 1996-2010, 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.396 2010/04/15 03:05:59 momjian Exp $
10
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.397 2010/04/16 08:58:16 heikki Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -539,7 +539,7 @@ static int XLogFileReadAnyTLI(uint32 log, uint32 seg, int emode,
539
539
int sources );
540
540
static bool XLogPageRead (XLogRecPtr * RecPtr , int emode , bool fetching_ckpt ,
541
541
bool randAccess );
542
- static int emode_for_corrupt_record (int emode );
542
+ static int emode_for_corrupt_record (int emode , XLogRecPtr RecPtr );
543
543
static void XLogFileClose (void );
544
544
static bool RestoreArchivedFile (char * path , const char * xlogfname ,
545
545
const char * recovername , off_t expectedSize );
@@ -3543,7 +3543,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
3543
3543
memcpy (& bkpb , blk , sizeof (BkpBlock ));
3544
3544
if (bkpb .hole_offset + bkpb .hole_length > BLCKSZ )
3545
3545
{
3546
- ereport (emode ,
3546
+ ereport (emode_for_corrupt_record ( emode , recptr ) ,
3547
3547
(errmsg ("incorrect hole size in record at %X/%X" ,
3548
3548
recptr .xlogid , recptr .xrecoff )));
3549
3549
return false;
@@ -3556,7 +3556,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
3556
3556
/* Check that xl_tot_len agrees with our calculation */
3557
3557
if (blk != (char * ) record + record -> xl_tot_len )
3558
3558
{
3559
- ereport (emode ,
3559
+ ereport (emode_for_corrupt_record ( emode , recptr ) ,
3560
3560
(errmsg ("incorrect total length in record at %X/%X" ,
3561
3561
recptr .xlogid , recptr .xrecoff )));
3562
3562
return false;
@@ -3569,7 +3569,7 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
3569
3569
3570
3570
if (!EQ_CRC32 (record -> xl_crc , crc ))
3571
3571
{
3572
- ereport (emode ,
3572
+ ereport (emode_for_corrupt_record ( emode , recptr ) ,
3573
3573
(errmsg ("incorrect resource manager data checksum in record at %X/%X" ,
3574
3574
recptr .xlogid , recptr .xrecoff )));
3575
3575
return false;
@@ -3674,15 +3674,15 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3674
3674
}
3675
3675
else if (targetRecOff < pageHeaderSize )
3676
3676
{
3677
- ereport (emode_for_corrupt_record (emode ),
3677
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3678
3678
(errmsg ("invalid record offset at %X/%X" ,
3679
3679
RecPtr -> xlogid , RecPtr -> xrecoff )));
3680
3680
goto next_record_is_invalid ;
3681
3681
}
3682
3682
if ((((XLogPageHeader ) readBuf )-> xlp_info & XLP_FIRST_IS_CONTRECORD ) &&
3683
3683
targetRecOff == pageHeaderSize )
3684
3684
{
3685
- ereport (emode_for_corrupt_record (emode ),
3685
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3686
3686
(errmsg ("contrecord is requested by %X/%X" ,
3687
3687
RecPtr -> xlogid , RecPtr -> xrecoff )));
3688
3688
goto next_record_is_invalid ;
@@ -3697,15 +3697,15 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3697
3697
{
3698
3698
if (record -> xl_len != 0 )
3699
3699
{
3700
- ereport (emode_for_corrupt_record (emode ),
3700
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3701
3701
(errmsg ("invalid xlog switch record at %X/%X" ,
3702
3702
RecPtr -> xlogid , RecPtr -> xrecoff )));
3703
3703
goto next_record_is_invalid ;
3704
3704
}
3705
3705
}
3706
3706
else if (record -> xl_len == 0 )
3707
3707
{
3708
- ereport (emode_for_corrupt_record (emode ),
3708
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3709
3709
(errmsg ("record with zero length at %X/%X" ,
3710
3710
RecPtr -> xlogid , RecPtr -> xrecoff )));
3711
3711
goto next_record_is_invalid ;
@@ -3714,14 +3714,14 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3714
3714
record -> xl_tot_len > SizeOfXLogRecord + record -> xl_len +
3715
3715
XLR_MAX_BKP_BLOCKS * (sizeof (BkpBlock ) + BLCKSZ ))
3716
3716
{
3717
- ereport (emode_for_corrupt_record (emode ),
3717
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3718
3718
(errmsg ("invalid record length at %X/%X" ,
3719
3719
RecPtr -> xlogid , RecPtr -> xrecoff )));
3720
3720
goto next_record_is_invalid ;
3721
3721
}
3722
3722
if (record -> xl_rmid > RM_MAX_ID )
3723
3723
{
3724
- ereport (emode_for_corrupt_record (emode ),
3724
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3725
3725
(errmsg ("invalid resource manager ID %u at %X/%X" ,
3726
3726
record -> xl_rmid , RecPtr -> xlogid , RecPtr -> xrecoff )));
3727
3727
goto next_record_is_invalid ;
@@ -3734,7 +3734,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3734
3734
*/
3735
3735
if (!XLByteLT (record -> xl_prev , * RecPtr ))
3736
3736
{
3737
- ereport (emode_for_corrupt_record (emode ),
3737
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3738
3738
(errmsg ("record with incorrect prev-link %X/%X at %X/%X" ,
3739
3739
record -> xl_prev .xlogid , record -> xl_prev .xrecoff ,
3740
3740
RecPtr -> xlogid , RecPtr -> xrecoff )));
@@ -3750,7 +3750,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3750
3750
*/
3751
3751
if (!XLByteEQ (record -> xl_prev , ReadRecPtr ))
3752
3752
{
3753
- ereport (emode_for_corrupt_record (emode ),
3753
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3754
3754
(errmsg ("record with incorrect prev-link %X/%X at %X/%X" ,
3755
3755
record -> xl_prev .xlogid , record -> xl_prev .xrecoff ,
3756
3756
RecPtr -> xlogid , RecPtr -> xrecoff )));
@@ -3779,7 +3779,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3779
3779
{
3780
3780
readRecordBufSize = 0 ;
3781
3781
/* We treat this as a "bogus data" condition */
3782
- ereport (emode_for_corrupt_record (emode ),
3782
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3783
3783
(errmsg ("record length %u at %X/%X too long" ,
3784
3784
total_len , RecPtr -> xlogid , RecPtr -> xrecoff )));
3785
3785
goto next_record_is_invalid ;
@@ -3819,7 +3819,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3819
3819
/* Check that the continuation record looks valid */
3820
3820
if (!(((XLogPageHeader ) readBuf )-> xlp_info & XLP_FIRST_IS_CONTRECORD ))
3821
3821
{
3822
- ereport (emode_for_corrupt_record (emode ),
3822
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3823
3823
(errmsg ("there is no contrecord flag in log file %u, segment %u, offset %u" ,
3824
3824
readId , readSeg , readOff )));
3825
3825
goto next_record_is_invalid ;
@@ -3829,7 +3829,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3829
3829
if (contrecord -> xl_rem_len == 0 ||
3830
3830
total_len != (contrecord -> xl_rem_len + gotlen ))
3831
3831
{
3832
- ereport (emode_for_corrupt_record (emode ),
3832
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
3833
3833
(errmsg ("invalid contrecord length %u in log file %u, segment %u, offset %u" ,
3834
3834
contrecord -> xl_rem_len ,
3835
3835
readId , readSeg , readOff )));
@@ -3847,7 +3847,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3847
3847
contrecord -> xl_rem_len );
3848
3848
break ;
3849
3849
}
3850
- if (!RecordIsValid (record , * RecPtr , emode_for_corrupt_record ( emode ) ))
3850
+ if (!RecordIsValid (record , * RecPtr , emode ))
3851
3851
goto next_record_is_invalid ;
3852
3852
pageHeaderSize = XLogPageHeaderSize ((XLogPageHeader ) readBuf );
3853
3853
EndRecPtr .xlogid = readId ;
@@ -3861,7 +3861,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
3861
3861
}
3862
3862
3863
3863
/* Record does not cross a page boundary */
3864
- if (!RecordIsValid (record , * RecPtr , emode_for_corrupt_record ( emode ) ))
3864
+ if (!RecordIsValid (record , * RecPtr , emode ))
3865
3865
goto next_record_is_invalid ;
3866
3866
EndRecPtr .xlogid = RecPtr -> xlogid ;
3867
3867
EndRecPtr .xrecoff = RecPtr -> xrecoff + MAXALIGN (total_len );
@@ -3914,16 +3914,19 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
3914
3914
{
3915
3915
XLogRecPtr recaddr ;
3916
3916
3917
+ recaddr .xlogid = readId ;
3918
+ recaddr .xrecoff = readSeg * XLogSegSize + readOff ;
3919
+
3917
3920
if (hdr -> xlp_magic != XLOG_PAGE_MAGIC )
3918
3921
{
3919
- ereport (emode ,
3922
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3920
3923
(errmsg ("invalid magic number %04X in log file %u, segment %u, offset %u" ,
3921
3924
hdr -> xlp_magic , readId , readSeg , readOff )));
3922
3925
return false;
3923
3926
}
3924
3927
if ((hdr -> xlp_info & ~XLP_ALL_FLAGS ) != 0 )
3925
3928
{
3926
- ereport (emode ,
3929
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3927
3930
(errmsg ("invalid info bits %04X in log file %u, segment %u, offset %u" ,
3928
3931
hdr -> xlp_info , readId , readSeg , readOff )));
3929
3932
return false;
@@ -3945,22 +3948,22 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
3945
3948
longhdr -> xlp_sysid );
3946
3949
snprintf (sysident_str , sizeof (sysident_str ), UINT64_FORMAT ,
3947
3950
ControlFile -> system_identifier );
3948
- ereport (emode ,
3951
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3949
3952
(errmsg ("WAL file is from different database system" ),
3950
3953
errdetail ("WAL file database system identifier is %s, pg_control database system identifier is %s." ,
3951
3954
fhdrident_str , sysident_str )));
3952
3955
return false;
3953
3956
}
3954
3957
if (longhdr -> xlp_seg_size != XLogSegSize )
3955
3958
{
3956
- ereport (emode ,
3959
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3957
3960
(errmsg ("WAL file is from different database system" ),
3958
3961
errdetail ("Incorrect XLOG_SEG_SIZE in page header." )));
3959
3962
return false;
3960
3963
}
3961
3964
if (longhdr -> xlp_xlog_blcksz != XLOG_BLCKSZ )
3962
3965
{
3963
- ereport (emode ,
3966
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3964
3967
(errmsg ("WAL file is from different database system" ),
3965
3968
errdetail ("Incorrect XLOG_BLCKSZ in page header." )));
3966
3969
return false;
@@ -3969,17 +3972,15 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
3969
3972
else if (readOff == 0 )
3970
3973
{
3971
3974
/* hmm, first page of file doesn't have a long header? */
3972
- ereport (emode ,
3975
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3973
3976
(errmsg ("invalid info bits %04X in log file %u, segment %u, offset %u" ,
3974
3977
hdr -> xlp_info , readId , readSeg , readOff )));
3975
3978
return false;
3976
3979
}
3977
3980
3978
- recaddr .xlogid = readId ;
3979
- recaddr .xrecoff = readSeg * XLogSegSize + readOff ;
3980
3981
if (!XLByteEQ (hdr -> xlp_pageaddr , recaddr ))
3981
3982
{
3982
- ereport (emode ,
3983
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3983
3984
(errmsg ("unexpected pageaddr %X/%X in log file %u, segment %u, offset %u" ,
3984
3985
hdr -> xlp_pageaddr .xlogid , hdr -> xlp_pageaddr .xrecoff ,
3985
3986
readId , readSeg , readOff )));
@@ -3991,7 +3992,7 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
3991
3992
*/
3992
3993
if (!list_member_int (expectedTLIs , (int ) hdr -> xlp_tli ))
3993
3994
{
3994
- ereport (emode ,
3995
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
3995
3996
(errmsg ("unexpected timeline ID %u in log file %u, segment %u, offset %u" ,
3996
3997
hdr -> xlp_tli ,
3997
3998
readId , readSeg , readOff )));
@@ -4009,7 +4010,7 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode)
4009
4010
*/
4010
4011
if (hdr -> xlp_tli < lastPageTLI )
4011
4012
{
4012
- ereport (emode ,
4013
+ ereport (emode_for_corrupt_record ( emode , recaddr ) ,
4013
4014
(errmsg ("out-of-sequence timeline ID %u (after %u) in log file %u, segment %u, offset %u" ,
4014
4015
hdr -> xlp_tli , lastPageTLI ,
4015
4016
readId , readSeg , readOff )));
@@ -9245,36 +9246,35 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
9245
9246
readOff = 0 ;
9246
9247
if (read (readFile , readBuf , XLOG_BLCKSZ ) != XLOG_BLCKSZ )
9247
9248
{
9248
- ereport (emode_for_corrupt_record (emode ),
9249
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
9249
9250
(errcode_for_file_access (),
9250
9251
errmsg ("could not read from log file %u, segment %u, offset %u: %m" ,
9251
9252
readId , readSeg , readOff )));
9252
9253
goto next_record_is_invalid ;
9253
9254
}
9254
- if (!ValidXLOGHeader ((XLogPageHeader ) readBuf ,
9255
- emode_for_corrupt_record (emode )))
9255
+ if (!ValidXLOGHeader ((XLogPageHeader ) readBuf , emode ))
9256
9256
goto next_record_is_invalid ;
9257
9257
}
9258
9258
9259
9259
/* Read the requested page */
9260
9260
readOff = targetPageOff ;
9261
9261
if (lseek (readFile , (off_t ) readOff , SEEK_SET ) < 0 )
9262
9262
{
9263
- ereport (emode_for_corrupt_record (emode ),
9263
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
9264
9264
(errcode_for_file_access (),
9265
9265
errmsg ("could not seek in log file %u, segment %u to offset %u: %m" ,
9266
9266
readId , readSeg , readOff )));
9267
9267
goto next_record_is_invalid ;
9268
9268
}
9269
9269
if (read (readFile , readBuf , XLOG_BLCKSZ ) != XLOG_BLCKSZ )
9270
9270
{
9271
- ereport (emode_for_corrupt_record (emode ),
9271
+ ereport (emode_for_corrupt_record (emode , * RecPtr ),
9272
9272
(errcode_for_file_access (),
9273
9273
errmsg ("could not read from log file %u, segment %u, offset %u: %m" ,
9274
9274
readId , readSeg , readOff )));
9275
9275
goto next_record_is_invalid ;
9276
9276
}
9277
- if (!ValidXLOGHeader ((XLogPageHeader ) readBuf , emode_for_corrupt_record ( emode ) ))
9277
+ if (!ValidXLOGHeader ((XLogPageHeader ) readBuf , emode ))
9278
9278
goto next_record_is_invalid ;
9279
9279
9280
9280
Assert (targetId == readId );
@@ -9316,10 +9316,17 @@ XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
9316
9316
* 'emode' is the error mode that would be used to report a file-not-found
9317
9317
* or legitimate end-of-WAL situation. It is upgraded to WARNING or PANIC
9318
9318
* if a corrupt record is not expected at this point.
9319
+ *
9320
+ * NOTE: This function remembers the RecPtr value it was last called with,
9321
+ * to suppress repeated messages about the same record. Only call this when
9322
+ * you are about to ereport(), or you might cause a later message to be
9323
+ * erroneously suppressed.
9319
9324
*/
9320
9325
static int
9321
- emode_for_corrupt_record (int emode )
9326
+ emode_for_corrupt_record (int emode , XLogRecPtr RecPtr )
9322
9327
{
9328
+ static XLogRecPtr lastComplaint = {0 , 0 };
9329
+
9323
9330
/*
9324
9331
* We don't expect any invalid records in archive or in records streamed
9325
9332
* from master. Files in the archive should be complete, and we should
@@ -9340,6 +9347,17 @@ emode_for_corrupt_record(int emode)
9340
9347
if (emode < WARNING )
9341
9348
emode = WARNING ;
9342
9349
}
9350
+ /*
9351
+ * If we retry reading a record in pg_xlog, only complain on the first
9352
+ * time to keep the noise down.
9353
+ */
9354
+ else if (emode == LOG )
9355
+ {
9356
+ if (XLByteEQ (RecPtr , lastComplaint ))
9357
+ emode = DEBUG1 ;
9358
+ else
9359
+ lastComplaint = RecPtr ;
9360
+ }
9343
9361
return emode ;
9344
9362
}
9345
9363
0 commit comments