00001 /*------------------------------------------------------------------------- 00002 * 00003 * bufpage.h 00004 * Standard POSTGRES buffer page definitions. 00005 * 00006 * 00007 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00008 * Portions Copyright (c) 1994, Regents of the University of California 00009 * 00010 * src/include/storage/bufpage.h 00011 * 00012 *------------------------------------------------------------------------- 00013 */ 00014 #ifndef BUFPAGE_H 00015 #define BUFPAGE_H 00016 00017 #include "access/xlogdefs.h" 00018 #include "storage/block.h" 00019 #include "storage/item.h" 00020 #include "storage/off.h" 00021 00022 /* 00023 * A postgres disk page is an abstraction layered on top of a postgres 00024 * disk block (which is simply a unit of i/o, see block.h). 00025 * 00026 * specifically, while a disk block can be unformatted, a postgres 00027 * disk page is always a slotted page of the form: 00028 * 00029 * +----------------+---------------------------------+ 00030 * | PageHeaderData | linp1 linp2 linp3 ... | 00031 * +-----------+----+---------------------------------+ 00032 * | ... linpN | | 00033 * +-----------+--------------------------------------+ 00034 * | ^ pd_lower | 00035 * | | 00036 * | v pd_upper | 00037 * +-------------+------------------------------------+ 00038 * | | tupleN ... | 00039 * +-------------+------------------+-----------------+ 00040 * | ... tuple3 tuple2 tuple1 | "special space" | 00041 * +--------------------------------+-----------------+ 00042 * ^ pd_special 00043 * 00044 * a page is full when nothing can be added between pd_lower and 00045 * pd_upper. 00046 * 00047 * all blocks written out by an access method must be disk pages. 00048 * 00049 * EXCEPTIONS: 00050 * 00051 * obviously, a page is not formatted before it is initialized by 00052 * a call to PageInit. 00053 * 00054 * NOTES: 00055 * 00056 * linp1..N form an ItemId array. ItemPointers point into this array 00057 * rather than pointing directly to a tuple. Note that OffsetNumbers 00058 * conventionally start at 1, not 0. 00059 * 00060 * tuple1..N are added "backwards" on the page. because a tuple's 00061 * ItemPointer points to its ItemId entry rather than its actual 00062 * byte-offset position, tuples can be physically shuffled on a page 00063 * whenever the need arises. 00064 * 00065 * AM-generic per-page information is kept in PageHeaderData. 00066 * 00067 * AM-specific per-page data (if any) is kept in the area marked "special 00068 * space"; each AM has an "opaque" structure defined somewhere that is 00069 * stored as the page trailer. an access method should always 00070 * initialize its pages with PageInit and then set its own opaque 00071 * fields. 00072 */ 00073 00074 typedef Pointer Page; 00075 00076 00077 /* 00078 * location (byte offset) within a page. 00079 * 00080 * note that this is actually limited to 2^15 because we have limited 00081 * ItemIdData.lp_off and ItemIdData.lp_len to 15 bits (see itemid.h). 00082 */ 00083 typedef uint16 LocationIndex; 00084 00085 00086 /* 00087 * For historical reasons, the 64-bit LSN value is stored as two 32-bit 00088 * values. 00089 */ 00090 typedef struct 00091 { 00092 uint32 xlogid; /* high bits */ 00093 uint32 xrecoff; /* low bits */ 00094 } PageXLogRecPtr; 00095 00096 #define PageXLogRecPtrGet(val) \ 00097 ((uint64) (val).xlogid << 32 | (val).xrecoff) 00098 #define PageXLogRecPtrSet(ptr, lsn) \ 00099 ((ptr).xlogid = (uint32) ((lsn) >> 32), (ptr).xrecoff = (uint32) (lsn)) 00100 00101 /* 00102 * disk page organization 00103 * 00104 * space management information generic to any page 00105 * 00106 * pd_lsn - identifies xlog record for last change to this page. 00107 * pd_checksum - page checksum, if set. 00108 * pd_flags - flag bits. 00109 * pd_lower - offset to start of free space. 00110 * pd_upper - offset to end of free space. 00111 * pd_special - offset to start of special space. 00112 * pd_pagesize_version - size in bytes and page layout version number. 00113 * pd_prune_xid - oldest XID among potentially prunable tuples on page. 00114 * 00115 * The LSN is used by the buffer manager to enforce the basic rule of WAL: 00116 * "thou shalt write xlog before data". A dirty buffer cannot be dumped 00117 * to disk until xlog has been flushed at least as far as the page's LSN. 00118 * 00119 * pd_checksum stores the page checksum, if it has been set for this page; 00120 * zero is a valid value for a checksum. If a checksum is not in use then 00121 * we leave the field unset. This will typically mean the field is zero 00122 * though non-zero values may also be present if databases have been 00123 * pg_upgraded from releases prior to 9.3, when the same byte offset was 00124 * used to store the current timelineid when the page was last updated. 00125 * Note that there is no indication on a page as to whether the checksum 00126 * is valid or not, a deliberate design choice which avoids the problem 00127 * of relying on the page contents to decide whether to verify it. Hence 00128 * there are no flag bits relating to checksums. 00129 * 00130 * pd_prune_xid is a hint field that helps determine whether pruning will be 00131 * useful. It is currently unused in index pages. 00132 * 00133 * The page version number and page size are packed together into a single 00134 * uint16 field. This is for historical reasons: before PostgreSQL 7.3, 00135 * there was no concept of a page version number, and doing it this way 00136 * lets us pretend that pre-7.3 databases have page version number zero. 00137 * We constrain page sizes to be multiples of 256, leaving the low eight 00138 * bits available for a version number. 00139 * 00140 * Minimum possible page size is perhaps 64B to fit page header, opaque space 00141 * and a minimal tuple; of course, in reality you want it much bigger, so 00142 * the constraint on pagesize mod 256 is not an important restriction. 00143 * On the high end, we can only support pages up to 32KB because lp_off/lp_len 00144 * are 15 bits. 00145 */ 00146 00147 typedef struct PageHeaderData 00148 { 00149 /* XXX LSN is member of *any* block, not only page-organized ones */ 00150 PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog 00151 * record for last change to this page */ 00152 uint16 pd_checksum; /* checksum */ 00153 uint16 pd_flags; /* flag bits, see below */ 00154 LocationIndex pd_lower; /* offset to start of free space */ 00155 LocationIndex pd_upper; /* offset to end of free space */ 00156 LocationIndex pd_special; /* offset to start of special space */ 00157 uint16 pd_pagesize_version; 00158 TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */ 00159 ItemIdData pd_linp[1]; /* beginning of line pointer array */ 00160 } PageHeaderData; 00161 00162 typedef PageHeaderData *PageHeader; 00163 00164 /* 00165 * pd_flags contains the following flag bits. Undefined bits are initialized 00166 * to zero and may be used in the future. 00167 * 00168 * PD_HAS_FREE_LINES is set if there are any LP_UNUSED line pointers before 00169 * pd_lower. This should be considered a hint rather than the truth, since 00170 * changes to it are not WAL-logged. 00171 * 00172 * PD_PAGE_FULL is set if an UPDATE doesn't find enough free space in the 00173 * page for its new tuple version; this suggests that a prune is needed. 00174 * Again, this is just a hint. 00175 */ 00176 #define PD_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */ 00177 #define PD_PAGE_FULL 0x0002 /* not enough free space for new 00178 * tuple? */ 00179 #define PD_ALL_VISIBLE 0x0004 /* all tuples on page are visible to 00180 * everyone */ 00181 00182 #define PD_VALID_FLAG_BITS 0x0007 /* OR of all valid pd_flags bits */ 00183 00184 /* 00185 * Page layout version number 0 is for pre-7.3 Postgres releases. 00186 * Releases 7.3 and 7.4 use 1, denoting a new HeapTupleHeader layout. 00187 * Release 8.0 uses 2; it changed the HeapTupleHeader layout again. 00188 * Release 8.1 uses 3; it redefined HeapTupleHeader infomask bits. 00189 * Release 8.3 uses 4; it changed the HeapTupleHeader layout again, and 00190 * added the pd_flags field (by stealing some bits from pd_tli), 00191 * as well as adding the pd_prune_xid field (which enlarges the header). 00192 * 00193 * As of Release 9.3, the checksum version must also be considered when 00194 * handling pages. 00195 */ 00196 #define PG_PAGE_LAYOUT_VERSION 4 00197 #define PG_DATA_CHECKSUM_VERSION 1 00198 00199 /* ---------------------------------------------------------------- 00200 * page support macros 00201 * ---------------------------------------------------------------- 00202 */ 00203 00204 /* 00205 * PageIsValid 00206 * True iff page is valid. 00207 */ 00208 #define PageIsValid(page) PointerIsValid(page) 00209 00210 /* 00211 * line pointer(s) do not count as part of header 00212 */ 00213 #define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp)) 00214 00215 /* 00216 * PageIsEmpty 00217 * returns true iff no itemid has been allocated on the page 00218 */ 00219 #define PageIsEmpty(page) \ 00220 (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData) 00221 00222 /* 00223 * PageIsNew 00224 * returns true iff page has not been initialized (by PageInit) 00225 */ 00226 #define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0) 00227 00228 /* 00229 * PageGetItemId 00230 * Returns an item identifier of a page. 00231 */ 00232 #define PageGetItemId(page, offsetNumber) \ 00233 ((ItemId) (&((PageHeader) (page))->pd_linp[(offsetNumber) - 1])) 00234 00235 /* 00236 * PageGetContents 00237 * To be used in case the page does not contain item pointers. 00238 * 00239 * Note: prior to 8.3 this was not guaranteed to yield a MAXALIGN'd result. 00240 * Now it is. Beware of old code that might think the offset to the contents 00241 * is just SizeOfPageHeaderData rather than MAXALIGN(SizeOfPageHeaderData). 00242 */ 00243 #define PageGetContents(page) \ 00244 ((char *) (page) + MAXALIGN(SizeOfPageHeaderData)) 00245 00246 /* ---------------- 00247 * macros to access page size info 00248 * ---------------- 00249 */ 00250 00251 /* 00252 * PageSizeIsValid 00253 * True iff the page size is valid. 00254 */ 00255 #define PageSizeIsValid(pageSize) ((pageSize) == BLCKSZ) 00256 00257 /* 00258 * PageGetPageSize 00259 * Returns the page size of a page. 00260 * 00261 * this can only be called on a formatted page (unlike 00262 * BufferGetPageSize, which can be called on an unformatted page). 00263 * however, it can be called on a page that is not stored in a buffer. 00264 */ 00265 #define PageGetPageSize(page) \ 00266 ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00)) 00267 00268 /* 00269 * PageGetPageLayoutVersion 00270 * Returns the page layout version of a page. 00271 */ 00272 #define PageGetPageLayoutVersion(page) \ 00273 (((PageHeader) (page))->pd_pagesize_version & 0x00FF) 00274 00275 /* 00276 * PageSetPageSizeAndVersion 00277 * Sets the page size and page layout version number of a page. 00278 * 00279 * We could support setting these two values separately, but there's 00280 * no real need for it at the moment. 00281 */ 00282 #define PageSetPageSizeAndVersion(page, size, version) \ 00283 ( \ 00284 AssertMacro(((size) & 0xFF00) == (size)), \ 00285 AssertMacro(((version) & 0x00FF) == (version)), \ 00286 ((PageHeader) (page))->pd_pagesize_version = (size) | (version) \ 00287 ) 00288 00289 /* ---------------- 00290 * page special data macros 00291 * ---------------- 00292 */ 00293 /* 00294 * PageGetSpecialSize 00295 * Returns size of special space on a page. 00296 */ 00297 #define PageGetSpecialSize(page) \ 00298 ((uint16) (PageGetPageSize(page) - ((PageHeader)(page))->pd_special)) 00299 00300 /* 00301 * PageGetSpecialPointer 00302 * Returns pointer to special space on a page. 00303 */ 00304 #define PageGetSpecialPointer(page) \ 00305 ( \ 00306 AssertMacro(PageIsValid(page)), \ 00307 (char *) ((char *) (page) + ((PageHeader) (page))->pd_special) \ 00308 ) 00309 00310 /* 00311 * PageGetItem 00312 * Retrieves an item on the given page. 00313 * 00314 * Note: 00315 * This does not change the status of any of the resources passed. 00316 * The semantics may change in the future. 00317 */ 00318 #define PageGetItem(page, itemId) \ 00319 ( \ 00320 AssertMacro(PageIsValid(page)), \ 00321 AssertMacro(ItemIdHasStorage(itemId)), \ 00322 (Item)(((char *)(page)) + ItemIdGetOffset(itemId)) \ 00323 ) 00324 00325 /* 00326 * PageGetMaxOffsetNumber 00327 * Returns the maximum offset number used by the given page. 00328 * Since offset numbers are 1-based, this is also the number 00329 * of items on the page. 00330 * 00331 * NOTE: if the page is not initialized (pd_lower == 0), we must 00332 * return zero to ensure sane behavior. Accept double evaluation 00333 * of the argument so that we can ensure this. 00334 */ 00335 #define PageGetMaxOffsetNumber(page) \ 00336 (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData ? 0 : \ 00337 ((((PageHeader) (page))->pd_lower - SizeOfPageHeaderData) \ 00338 / sizeof(ItemIdData))) 00339 00340 /* 00341 * Additional macros for access to page headers. (Beware multiple evaluation 00342 * of the arguments!) 00343 */ 00344 #define PageGetLSN(page) \ 00345 PageXLogRecPtrGet(((PageHeader) (page))->pd_lsn) 00346 #define PageSetLSN(page, lsn) \ 00347 PageXLogRecPtrSet(((PageHeader) (page))->pd_lsn, lsn) 00348 00349 #define PageHasFreeLinePointers(page) \ 00350 (((PageHeader) (page))->pd_flags & PD_HAS_FREE_LINES) 00351 #define PageSetHasFreeLinePointers(page) \ 00352 (((PageHeader) (page))->pd_flags |= PD_HAS_FREE_LINES) 00353 #define PageClearHasFreeLinePointers(page) \ 00354 (((PageHeader) (page))->pd_flags &= ~PD_HAS_FREE_LINES) 00355 00356 #define PageIsFull(page) \ 00357 (((PageHeader) (page))->pd_flags & PD_PAGE_FULL) 00358 #define PageSetFull(page) \ 00359 (((PageHeader) (page))->pd_flags |= PD_PAGE_FULL) 00360 #define PageClearFull(page) \ 00361 (((PageHeader) (page))->pd_flags &= ~PD_PAGE_FULL) 00362 00363 #define PageIsAllVisible(page) \ 00364 (((PageHeader) (page))->pd_flags & PD_ALL_VISIBLE) 00365 #define PageSetAllVisible(page) \ 00366 (((PageHeader) (page))->pd_flags |= PD_ALL_VISIBLE) 00367 #define PageClearAllVisible(page) \ 00368 (((PageHeader) (page))->pd_flags &= ~PD_ALL_VISIBLE) 00369 00370 #define PageIsPrunable(page, oldestxmin) \ 00371 ( \ 00372 AssertMacro(TransactionIdIsNormal(oldestxmin)), \ 00373 TransactionIdIsValid(((PageHeader) (page))->pd_prune_xid) && \ 00374 TransactionIdPrecedes(((PageHeader) (page))->pd_prune_xid, oldestxmin) \ 00375 ) 00376 #define PageSetPrunable(page, xid) \ 00377 do { \ 00378 Assert(TransactionIdIsNormal(xid)); \ 00379 if (!TransactionIdIsValid(((PageHeader) (page))->pd_prune_xid) || \ 00380 TransactionIdPrecedes(xid, ((PageHeader) (page))->pd_prune_xid)) \ 00381 ((PageHeader) (page))->pd_prune_xid = (xid); \ 00382 } while (0) 00383 #define PageClearPrunable(page) \ 00384 (((PageHeader) (page))->pd_prune_xid = InvalidTransactionId) 00385 00386 00387 /* ---------------------------------------------------------------- 00388 * extern declarations 00389 * ---------------------------------------------------------------- 00390 */ 00391 00392 extern void PageInit(Page page, Size pageSize, Size specialSize); 00393 extern bool PageIsVerified(Page page, BlockNumber blkno); 00394 extern OffsetNumber PageAddItem(Page page, Item item, Size size, 00395 OffsetNumber offsetNumber, bool overwrite, bool is_heap); 00396 extern Page PageGetTempPage(Page page); 00397 extern Page PageGetTempPageCopy(Page page); 00398 extern Page PageGetTempPageCopySpecial(Page page); 00399 extern void PageRestoreTempPage(Page tempPage, Page oldPage); 00400 extern void PageRepairFragmentation(Page page); 00401 extern Size PageGetFreeSpace(Page page); 00402 extern Size PageGetExactFreeSpace(Page page); 00403 extern Size PageGetHeapFreeSpace(Page page); 00404 extern void PageIndexTupleDelete(Page page, OffsetNumber offset); 00405 extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems); 00406 extern char *PageSetChecksumCopy(Page page, BlockNumber blkno); 00407 extern void PageSetChecksumInplace(Page page, BlockNumber blkno); 00408 00409 #endif /* BUFPAGE_H */