PostgreSQL Source Code: src/backend/access/transam/xlogutils.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
19
21
31
32
33
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
51
52
54
55
56
57
58
59
60
61
62
63
64
66{
71
73{
77
79
82 char *cur_page, bool wait_for_wal);
83
84
85static void
88{
90
91 if (present)
92 elog(elevel, "page %u of relation %s is uninitialized",
93 blkno, path.str);
94 else
95 elog(elevel, "page %u of relation %s does not exist",
96 blkno, path.str);
97}
98
99
100static void
102 bool present)
103{
106 bool found;
107
108
109
110
111
112
113
114
115
117 {
120 "WAL contains references to invalid pages");
121 }
122
123
124
125
126
127
130
132 {
133
135
138
140 100,
143 }
144
145
146 key.locator = locator;
147 key.forkno = forkno;
148 key.blkno = blkno;
151
152 if (!found)
153 {
154
155 hentry->present = present;
156 }
157 else
158 {
159
160 }
161}
162
163
164static void
167{
170
172 return;
173
175
177 {
180 hentry->key.blkno >= minblkno)
181 {
182 elog(DEBUG2, "page %u of relation %s has been dropped",
185
187 &hentry->key,
189 elog(ERROR, "hash table corrupted");
190 }
191 }
192}
193
194
195static void
197{
200
202 return;
203
205
207 {
209 {
210 elog(DEBUG2, "page %u of relation %s has been dropped",
213
215 &hentry->key,
217 elog(ERROR, "hash table corrupted");
218 }
219 }
220}
221
222
223bool
225{
228 return true;
229 return false;
230}
231
232
233void
235{
238 bool foundone = false;
239
241 return;
242
244
245
246
247
248
250 {
253 foundone = true;
254 }
255
256 if (foundone)
258 "WAL contains references to invalid pages");
259
262}
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
305{
307 false, buf);
308}
309
310
311
312
313
316{
318
321 return buf;
322}
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
344{
349 Buffer prefetch_buffer;
351 bool zeromode;
352 bool willinit;
353
355 &prefetch_buffer))
356 {
357
358 elog(PANIC, "failed to locate backup block with ID %d in WAL record",
359 block_id);
360 }
361
362
363
364
365
368 if (willinit && !zeromode)
369 elog(PANIC, "block with WILL_INIT flag in WAL record must be zeroed by redo routine");
370 if (!willinit && zeromode)
371 elog(PANIC, "block to be initialized in redo routine must be marked with WILL_INIT flag in the WAL record");
372
373
375 {
379 prefetch_buffer);
383 (errcode(ERRCODE_INTERNAL_ERROR),
385
386
387
388
389
391 {
393 }
394
396
397
398
399
400
401
402
405
407 }
408 else
409 {
412 {
414 {
415 if (get_cleanup_lock)
417 else
419 }
422 else
424 }
425 else
427 }
428}
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
462 Buffer recent_buffer)
463{
467
469
470
474 {
475 buffer = recent_buffer;
476 goto recent_buffer_fast_path;
477 }
478
479
481
482
483
484
485
486
487
488
489
491
493
494 if (blkno < lastblock)
495 {
496
498 mode, NULL, true);
499 }
500 else
501 {
502
504 {
507 }
510
511
514 forknum,
515 NULL,
518 blkno + 1,
520 }
521
522recent_buffer_fast_path:
524 {
525
527
528
529
530
531
532
534 {
538 }
539 }
540
541 return buffer;
542}
543
544
545
546
547
548typedef struct
549{
553
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
572{
575
576
579
582
583
584
585
586
588
589
590 rel->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
591
592
594
595
596
597
598
599
600
601
604
605
606
607
608
610
611 return rel;
612}
613
614
615
616
617void
619{
621}
622
623
624
625
626
627
628
629void
631{
633}
634
635
636
637
638
639
640void
642{
643
644
645
646
647
648
650
652}
653
654
655
656
657
658
659void
662{
664}
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706void
709{
711 state->segcxt.ws_segsize + state->segoff);
712
714 Assert(wantLength <= XLOG_BLCKSZ);
715 Assert(state->readLen == 0 || state->readLen <= XLOG_BLCKSZ);
716 Assert(currTLI != 0);
717
718
719
720
721
722
723
724
725
726 if (lastReadPage == wantPage &&
727 state->readLen != 0 &&
728 lastReadPage + state->readLen >= wantPage + Min(wantLength, XLOG_BLCKSZ - 1))
729 return;
730
731
732
733
734
735
736
737
738
739
740
741
742 if (state->currTLI == currTLI && wantPage >= lastReadPage)
743 {
745 return;
746 }
747
748
749
750
751
752
754 state->currTLI != currTLI &&
755 state->currTLI != 0 &&
756 ((wantPage + wantLength) / state->segcxt.ws_segsize) <
757 (state->currTLIValidUntil / state->segcxt.ws_segsize))
758 return;
759
760
761
762
763
764
765
766
767
768
769
770
771
772 {
773
774
775
776
779
780 endOfSegment = ((wantPage / state->segcxt.ws_segsize) + 1) *
781 state->segcxt.ws_segsize - 1;
782 Assert(wantPage / state->segcxt.ws_segsize ==
783 endOfSegment / state->segcxt.ws_segsize);
784
785
786
787
788
791 &state->nextTLI);
792
794 wantPage + wantLength < state->currTLIValidUntil);
795
797
798 elog(DEBUG3, "switched to timeline %u valid until %X/%X",
801 }
802}
803
804
805void
808{
811
814 if (state->seg.ws_file >= 0)
815 return;
816
817 if (errno == ENOENT)
820 errmsg("requested WAL segment %s has already been removed",
821 path)));
822 else
825 errmsg("could not open file \"%s\": %m",
826 path)));
827}
828
829
830void
832{
834
835 state->seg.ws_file = -1;
836}
837
838
839
840
841
842
843
844int
846 int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
847{
849 targetRecPtr, cur_page, true);
850}
851
852
853
854
855
856int
859 char *cur_page)
860{
862 targetRecPtr, cur_page, false);
863}
864
865
866
867
868static int
871 char *cur_page, bool wait_for_wal)
872{
874 loc;
876 int count;
879
880 loc = targetPagePtr + reqLen;
881
882
883
884
885
886
887
888
889
890 while (1)
891 {
892
893
894
895
898 else
900 tli = currTLI;
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
927
928 if (state->currTLI == currTLI)
929 {
930
931 if (loc <= read_upto)
932 break;
933
934
935 if (!wait_for_wal)
936 {
938
939
940
941
942
944 state->private_data;
946 break;
947 }
948
951 }
952 else
953 {
954
955
956
957
958
959
960
961
962 read_upto = state->currTLIValidUntil;
963
964
965
966
967
968
969
970
971
972 tli = state->currTLI;
973
974
975 break;
976 }
977 }
978
979 if (targetPagePtr + XLOG_BLCKSZ <= read_upto)
980 {
981
982
983
984
985 count = XLOG_BLCKSZ;
986 }
987 else if (targetPagePtr + reqLen > read_upto)
988 {
989
990 return -1;
991 }
992 else
993 {
994
995 count = read_upto - targetPagePtr;
996 }
997
998 if ((state, cur_page, targetPagePtr, count, tli,
999 &errinfo))
1001
1002
1003 return count;
1004}
1005
1006
1007
1008
1009
1010void
1012{
1015
1017
1019 {
1023 errmsg("could not read from WAL segment %s, offset %d: %m",
1024 fname, errinfo->wre_off)));
1025 }
1026 else if (errinfo->wre_read == 0)
1027 {
1030 errmsg("could not read from WAL segment %s, offset %d: read %d of %d",
1033 }
1034}
List * readTimeLineHistory(TimeLineID targetTLI)
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Buffer ExtendBufferedRelTo(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, BlockNumber extend_to, ReadBufferMode mode)
void ReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void LockBufferForCleanup(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)
bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)
void FlushOneBuffer(Buffer buffer)
static Page BufferGetPage(Buffer buffer)
#define BMR_SMGR(p_smgr, p_relpersistence)
#define BUFFER_LOCK_EXCLUSIVE
@ RBM_ZERO_AND_CLEANUP_LOCK
static bool BufferIsValid(Buffer bufnum)
static bool PageIsNew(const PageData *page)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(const PageData *page)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
void hash_destroy(HTAB *hashp)
void * hash_seq_search(HASH_SEQ_STATUS *status)
long hash_get_num_entries(HTAB *hashp)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
bool message_level_is_interesting(int elevel)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int BasicOpenFile(const char *fileName, int fileFlags)
Assert(PointerIsAligned(start, uint64))
void list_free_deep(List *list)
void pfree(void *pointer)
void * palloc0(Size size)
#define CHECK_FOR_INTERRUPTS()
#define ERRCODE_DATA_CORRUPTED
static PgChecksumMode mode
#define INVALID_PROC_NUMBER
#define RelationGetRelationName(relation)
struct RelationData * Relation
#define RelFileLocatorEquals(locator1, locator2)
#define relpathperm(rlocator, forknum)
void pg_usleep(long microsec)
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
void smgrdestroyall(void)
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
char str[REL_PATH_STR_MAXLEN+1]
RelFileLocator rd_locator
bool RecoveryInProgress(void)
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
static void XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define LSN_FORMAT_ARGS(lsn)
#define InvalidXLogRecPtr
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#define XLogRecBlockImageApply(decoder, block_id)
#define XLogRecGetBlock(decoder, i)
#define XLogRecHasBlockImage(decoder, block_id)
#define BKPBLOCK_WILL_INIT
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
void wal_segment_close(XLogReaderState *state)
void FreeFakeRelcacheEntry(Relation fakerel)
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
bool ignore_invalid_pages
static void report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno, BlockNumber blkno, bool present)
void XLogReadDetermineTimeline(XLogReaderState *state, XLogRecPtr wantPage, uint32 wantLength, TimeLineID currTLI)
FakeRelCacheEntryData * FakeRelCacheEntry
bool XLogHaveInvalidPages(void)
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)
void XLogTruncateRelation(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nblocks)
struct xl_invalid_page xl_invalid_page
Relation CreateFakeRelcacheEntry(RelFileLocator rlocator)
HotStandbyState standbyState
struct xl_invalid_page_key xl_invalid_page_key
int read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
void XLogCheckInvalidPages(void)
static void forget_invalid_pages(RelFileLocator locator, ForkNumber forkno, BlockNumber minblkno)
void WALReadRaiseError(WALReadError *errinfo)
static void log_invalid_page(RelFileLocator locator, ForkNumber forkno, BlockNumber blkno, bool present)
static int read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page, bool wait_for_wal)
void XLogDropRelation(RelFileLocator rlocator, ForkNumber forknum)
int read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
static HTAB * invalid_page_tab
XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
static void forget_invalid_pages_db(Oid dbid)
void XLogDropDatabase(Oid dbid)