Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * bufmask.c
4 : * Routines for buffer masking. Used to mask certain bits
5 : * in a page which can be different when the WAL is generated
6 : * and when the WAL is applied.
7 : *
8 : * Portions Copyright (c) 2016-2017, PostgreSQL Global Development Group
9 : *
10 : * Contains common routines required for masking a page.
11 : *
12 : * IDENTIFICATION
13 : * src/backend/storage/buffer/bufmask.c
14 : *
15 : *-------------------------------------------------------------------------
16 : */
17 :
18 : #include "postgres.h"
19 :
20 : #include "access/bufmask.h"
21 :
22 : /*
23 : * mask_page_lsn
24 : *
25 : * In consistency checks, the LSN of the two pages compared will likely be
26 : * different because of concurrent operations when the WAL is generated
27 : * and the state of the page when WAL is applied.
28 : */
29 : void
30 0 : mask_page_lsn(Page page)
31 : {
32 0 : PageHeader phdr = (PageHeader) page;
33 :
34 0 : PageXLogRecPtrSet(phdr->pd_lsn, (uint64) MASK_MARKER);
35 0 : }
36 :
37 : /*
38 : * mask_page_hint_bits
39 : *
40 : * Mask hint bits in PageHeader. We want to ignore differences in hint bits,
41 : * since they can be set without emitting any WAL.
42 : */
43 : void
44 0 : mask_page_hint_bits(Page page)
45 : {
46 0 : PageHeader phdr = (PageHeader) page;
47 :
48 : /* Ignore prune_xid (it's like a hint-bit) */
49 0 : phdr->pd_prune_xid = MASK_MARKER;
50 :
51 : /* Ignore PD_PAGE_FULL and PD_HAS_FREE_LINES flags, they are just hints. */
52 0 : PageClearFull(page);
53 0 : PageClearHasFreeLinePointers(page);
54 :
55 : /*
56 : * During replay, if the page LSN has advanced past our XLOG record's LSN,
57 : * we don't mark the page all-visible. See heap_xlog_visible() for
58 : * details.
59 : */
60 0 : PageClearAllVisible(page);
61 0 : }
62 :
63 : /*
64 : * mask_unused_space
65 : *
66 : * Mask the unused space of a page between pd_lower and pd_upper.
67 : */
68 : void
69 0 : mask_unused_space(Page page)
70 : {
71 0 : int pd_lower = ((PageHeader) page)->pd_lower;
72 0 : int pd_upper = ((PageHeader) page)->pd_upper;
73 0 : int pd_special = ((PageHeader) page)->pd_special;
74 :
75 : /* Sanity check */
76 0 : if (pd_lower > pd_upper || pd_special < pd_upper ||
77 0 : pd_lower < SizeOfPageHeaderData || pd_special > BLCKSZ)
78 : {
79 0 : elog(ERROR, "invalid page pd_lower %u pd_upper %u pd_special %u\n",
80 : pd_lower, pd_upper, pd_special);
81 : }
82 :
83 0 : memset(page + pd_lower, MASK_MARKER, pd_upper - pd_lower);
84 0 : }
85 :
86 : /*
87 : * mask_lp_flags
88 : *
89 : * In some index AMs, line pointer flags can be modified in master without
90 : * emitting any WAL record.
91 : */
92 : void
93 0 : mask_lp_flags(Page page)
94 : {
95 : OffsetNumber offnum,
96 : maxoff;
97 :
98 0 : maxoff = PageGetMaxOffsetNumber(page);
99 0 : for (offnum = FirstOffsetNumber;
100 : offnum <= maxoff;
101 0 : offnum = OffsetNumberNext(offnum))
102 : {
103 0 : ItemId itemId = PageGetItemId(page, offnum);
104 :
105 0 : if (ItemIdIsUsed(itemId))
106 0 : itemId->lp_flags = LP_UNUSED;
107 : }
108 0 : }
109 :
110 : /*
111 : * mask_page_content
112 : *
113 : * In some index AMs, the contents of deleted pages need to be almost
114 : * completely ignored.
115 : */
116 : void
117 0 : mask_page_content(Page page)
118 : {
119 : /* Mask Page Content */
120 0 : memset(page + SizeOfPageHeaderData, MASK_MARKER,
121 : BLCKSZ - SizeOfPageHeaderData);
122 :
123 : /* Mask pd_lower and pd_upper */
124 0 : memset(&((PageHeader) page)->pd_lower, MASK_MARKER,
125 : sizeof(uint16));
126 0 : memset(&((PageHeader) page)->pd_upper, MASK_MARKER,
127 : sizeof(uint16));
128 0 : }
|