Header And Logo

PostgreSQL
| The world's most advanced open source database.

bufpage.h

Go to the documentation of this file.
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 */