10
10
*
11
11
* NOTES
12
12
* See xlogreader.h for more notes on this facility.
13
+ *
14
+ * This file is compiled as both front-end and backend code, so it
15
+ * may not use ereport, server-defined static variables, etc.
13
16
*-------------------------------------------------------------------------
14
17
*/
15
-
16
18
#include "postgres.h"
17
19
18
20
#include "access/transam.h"
@@ -192,14 +194,21 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
192
194
{
193
195
XLogRecord * record ;
194
196
XLogRecPtr targetPagePtr ;
195
- bool randAccess = false ;
197
+ bool randAccess ;
196
198
uint32 len ,
197
199
total_len ;
198
200
uint32 targetRecOff ;
199
201
uint32 pageHeaderSize ;
200
202
bool gotheader ;
201
203
int readOff ;
202
204
205
+ /*
206
+ * randAccess indicates whether to verify the previous-record pointer of
207
+ * the record we're reading. We only do this if we're reading
208
+ * sequentially, which is what we initially assume.
209
+ */
210
+ randAccess = false;
211
+
203
212
/* reset error state */
204
213
* errormsg = NULL ;
205
214
state -> errormsg_buf [0 ] = '\0' ;
@@ -208,6 +217,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
208
217
209
218
if (RecPtr == InvalidXLogRecPtr )
210
219
{
220
+ /* No explicit start point; read the record after the one we just read */
211
221
RecPtr = state -> EndRecPtr ;
212
222
213
223
if (state -> ReadRecPtr == InvalidXLogRecPtr )
@@ -223,11 +233,13 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
223
233
else
224
234
{
225
235
/*
236
+ * Caller supplied a position to start at.
237
+ *
226
238
* In this case, the passed-in record pointer should already be
227
239
* pointing to a valid record starting position.
228
240
*/
229
241
Assert (XRecOffIsValid (RecPtr ));
230
- randAccess = true; /* allow readPageTLI to go backwards too */
242
+ randAccess = true;
231
243
}
232
244
233
245
state -> currRecPtr = RecPtr ;
@@ -309,8 +321,10 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
309
321
/* XXX: more validation should be done here */
310
322
if (total_len < SizeOfXLogRecord )
311
323
{
312
- report_invalid_record (state , "invalid record length at %X/%X" ,
313
- (uint32 ) (RecPtr >> 32 ), (uint32 ) RecPtr );
324
+ report_invalid_record (state ,
325
+ "invalid record length at %X/%X: wanted %lu, got %u" ,
326
+ (uint32 ) (RecPtr >> 32 ), (uint32 ) RecPtr ,
327
+ SizeOfXLogRecord , total_len );
314
328
goto err ;
315
329
}
316
330
gotheader = false;
@@ -463,12 +477,10 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
463
477
err :
464
478
465
479
/*
466
- * Invalidate the xlog page we've cached . We might read from a different
467
- * source after failure.
480
+ * Invalidate the read state . We might read from a different source after
481
+ * failure.
468
482
*/
469
- state -> readSegNo = 0 ;
470
- state -> readOff = 0 ;
471
- state -> readLen = 0 ;
483
+ XLogReaderInvalReadState (state );
472
484
473
485
if (state -> errormsg_buf [0 ] != '\0' )
474
486
* errormsg = state -> errormsg_buf ;
@@ -572,18 +584,27 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
572
584
if (!ValidXLogPageHeader (state , pageptr , hdr ))
573
585
goto err ;
574
586
575
- /* update cache information */
587
+ /* update read state information */
576
588
state -> readSegNo = targetSegNo ;
577
589
state -> readOff = targetPageOff ;
578
590
state -> readLen = readLen ;
579
591
580
592
return readLen ;
581
593
582
594
err :
595
+ XLogReaderInvalReadState (state );
596
+ return -1 ;
597
+ }
598
+
599
+ /*
600
+ * Invalidate the xlogreader's read state to force a re-read.
601
+ */
602
+ void
603
+ XLogReaderInvalReadState (XLogReaderState * state )
604
+ {
583
605
state -> readSegNo = 0 ;
584
606
state -> readOff = 0 ;
585
607
state -> readLen = 0 ;
586
- return -1 ;
587
608
}
588
609
589
610
/*
@@ -600,8 +621,9 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
600
621
if (record -> xl_tot_len < SizeOfXLogRecord )
601
622
{
602
623
report_invalid_record (state ,
603
- "invalid record length at %X/%X" ,
604
- (uint32 ) (RecPtr >> 32 ), (uint32 ) RecPtr );
624
+ "invalid record length at %X/%X: wanted %lu, got %u" ,
625
+ (uint32 ) (RecPtr >> 32 ), (uint32 ) RecPtr ,
626
+ SizeOfXLogRecord , record -> xl_tot_len );
605
627
return false;
606
628
}
607
629
if (record -> xl_rmid > RM_MAX_ID )
@@ -907,11 +929,9 @@ XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
907
929
err :
908
930
out :
909
931
/* Reset state to what we had before finding the record */
910
- state -> readSegNo = 0 ;
911
- state -> readOff = 0 ;
912
- state -> readLen = 0 ;
913
932
state -> ReadRecPtr = saved_state .ReadRecPtr ;
914
933
state -> EndRecPtr = saved_state .EndRecPtr ;
934
+ XLogReaderInvalReadState (state );
915
935
916
936
return found ;
917
937
}
0 commit comments