* Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *         $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.29 2008/06/19 00:46:03 alvherre Exp $
+ *         $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.30 2008/07/13 20:45:46 tgl Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
    /*
     * Additionally check that the special area looks sane.
     */
-   if (((PageHeader) (page))->pd_special !=
-       (BLCKSZ - MAXALIGN(sizeof(GISTPageOpaqueData))))
+   if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
        ereport(ERROR,
                (errcode(ERRCODE_INDEX_CORRUPTED),
                 errmsg("index \"%s\" contains corrupted page at block %u",
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.55 2008/06/19 00:46:03 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.56 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    /*
     * Additionally check that the special area looks sane.
     */
-   if (((PageHeader) (page))->pd_special !=
-       (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))))
+   if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData)))
        ereport(ERROR,
                (errcode(ERRCODE_INDEX_CORRUPTED),
                 errmsg("index \"%s\" contains corrupted page at block %u",
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.260 2008/06/19 00:46:03 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.261 2008/07/13 20:45:47 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
    ItemPointer tid = &(tuple->t_self);
    ItemId      lp;
    Buffer      buffer;
-   PageHeader  dp;
+   Page        page;
    OffsetNumber offnum;
    bool        valid;
 
     * Need share lock on buffer to examine tuple commit status.
     */
    LockBuffer(buffer, BUFFER_LOCK_SHARE);
-   dp = (PageHeader) BufferGetPage(buffer);
+   page = BufferGetPage(buffer);
 
    /*
     * We'd better check for out-of-range offnum in case of VACUUM since the
     * TID was obtained.
     */
    offnum = ItemPointerGetOffsetNumber(tid);
-   if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
+   if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
    {
        LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
        if (keep_buf)
    /*
     * get the item line pointer corresponding to the requested tid
     */
-   lp = PageGetItemId(dp, offnum);
+   lp = PageGetItemId(page, offnum);
 
    /*
     * Must check for deleted tuple.
    /*
     * fill in *tuple fields
     */
-   tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+   tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
    tuple->t_len = ItemIdGetLength(lp);
    tuple->t_tableOid = RelationGetRelid(relation);
 
    for (;;)
    {
        Buffer      buffer;
-       PageHeader  dp;
+       Page        page;
        OffsetNumber offnum;
        ItemId      lp;
        HeapTupleData tp;
         */
        buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&ctid));
        LockBuffer(buffer, BUFFER_LOCK_SHARE);
-       dp = (PageHeader) BufferGetPage(buffer);
+       page = BufferGetPage(buffer);
 
        /*
         * Check for bogus item number.  This is not treated as an error
         * just assume that the prior tid is OK and return it unchanged.
         */
        offnum = ItemPointerGetOffsetNumber(&ctid);
-       if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(dp))
+       if (offnum < FirstOffsetNumber || offnum > PageGetMaxOffsetNumber(page))
        {
            UnlockReleaseBuffer(buffer);
            break;
        }
-       lp = PageGetItemId(dp, offnum);
+       lp = PageGetItemId(page, offnum);
        if (!ItemIdIsNormal(lp))
        {
            UnlockReleaseBuffer(buffer);
 
        /* OK to access the tuple */
        tp.t_self = ctid;
-       tp.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
+       tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
        tp.t_len = ItemIdGetLength(lp);
 
        /*
    TransactionId xid = GetCurrentTransactionId();
    ItemId      lp;
    HeapTupleData tp;
-   PageHeader  dp;
+   Page        page;
    Buffer      buffer;
    bool        have_tuple_lock = false;
    bool        iscombo;
    buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
    LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 
-   dp = (PageHeader) BufferGetPage(buffer);
-   lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+   page = BufferGetPage(buffer);
+   lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
    Assert(ItemIdIsNormal(lp));
 
-   tp.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
+   tp.t_data = (HeapTupleHeader) PageGetItem(page, lp);
    tp.t_len = ItemIdGetLength(lp);
    tp.t_self = *tid;
 
     * the subsequent page pruning will be a no-op and the hint will be
     * cleared.
     */
-   PageSetPrunable(dp, xid);
+   PageSetPrunable(page, xid);
 
    /* store transaction information of xact deleting the tuple */
    tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
 
        recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE, rdata);
 
-       PageSetLSN(dp, recptr);
-       PageSetTLI(dp, ThisTimeLineID);
+       PageSetLSN(page, recptr);
+       PageSetTLI(page, ThisTimeLineID);
    }
 
    END_CRIT_SECTION();
    ItemId      lp;
    HeapTupleData oldtup;
    HeapTuple   heaptup;
-   PageHeader  dp;
+   Page        page;
    Buffer      buffer,
                newbuf;
    bool        need_toast,
    buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
    LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 
-   dp = (PageHeader) BufferGetPage(buffer);
-   lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(otid));
+   page = BufferGetPage(buffer);
+   lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid));
    Assert(ItemIdIsNormal(lp));
 
-   oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
+   oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
    oldtup.t_len = ItemIdGetLength(lp);
    oldtup.t_self = *otid;
 
                      HeapTupleHasExternal(newtup) ||
                      newtup->t_len > TOAST_TUPLE_THRESHOLD);
 
-   pagefree = PageGetHeapFreeSpace((Page) dp);
+   pagefree = PageGetHeapFreeSpace(page);
 
    newtupsize = MAXALIGN(newtup->t_len);
 
            /* Re-acquire the lock on the old tuple's page. */
            LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
            /* Re-check using the up-to-date free space */
-           pagefree = PageGetHeapFreeSpace((Page) dp);
+           pagefree = PageGetHeapFreeSpace(page);
            if (newtupsize > pagefree)
            {
                /*
    else
    {
        /* Set a hint that the old page could use prune/defrag */
-       PageSetFull(dp);
+       PageSetFull(page);
    }
 
    /* NO EREPORT(ERROR) from here till changes are logged */
     * not to optimize for aborts.  Note that heap_xlog_update must be kept in
     * sync if this decision changes.
     */
-   PageSetPrunable(dp, xid);
+   PageSetPrunable(page, xid);
 
    if (use_hot_update)
    {
    HTSU_Result result;
    ItemPointer tid = &(tuple->t_self);
    ItemId      lp;
-   PageHeader  dp;
+   Page        page;
    TransactionId xid;
    TransactionId xmax;
    uint16      old_infomask;
    *buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
    LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
 
-   dp = (PageHeader) BufferGetPage(*buffer);
-   lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+   page = BufferGetPage(*buffer);
+   lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
    Assert(ItemIdIsNormal(lp));
 
-   tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+   tuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
    tuple->t_len = ItemIdGetLength(lp);
    tuple->t_tableOid = RelationGetRelid(relation);
 
 
        recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_LOCK, rdata);
 
-       PageSetLSN(dp, recptr);
-       PageSetTLI(dp, ThisTimeLineID);
+       PageSetLSN(page, recptr);
+       PageSetTLI(page, ThisTimeLineID);
    }
 
    END_CRIT_SECTION();
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.71 2008/06/08 22:00:47 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.72 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                          Buffer otherBuffer, bool use_fsm)
 {
    Buffer      buffer = InvalidBuffer;
-   Page        pageHeader;
+   Page        page;
    Size        pageFreeSpace,
                saveFreeSpace;
    BlockNumber targetBlock,
         * Now we can check to see if there's enough free space here. If so,
         * we're done.
         */
-       pageHeader = (Page) BufferGetPage(buffer);
-       pageFreeSpace = PageGetHeapFreeSpace(pageHeader);
+       page = BufferGetPage(buffer);
+       pageFreeSpace = PageGetHeapFreeSpace(page);
        if (len + saveFreeSpace <= pageFreeSpace)
        {
            /* use this page as future insert target, too */
     * is empty (this should never happen, but if it does we don't want to
     * risk wiping out valid data).
     */
-   pageHeader = (Page) BufferGetPage(buffer);
+   page = BufferGetPage(buffer);
 
-   if (!PageIsNew((PageHeader) pageHeader))
+   if (!PageIsNew(page))
        elog(ERROR, "page %u of relation \"%s\" should be empty but is not",
             BufferGetBlockNumber(buffer),
             RelationGetRelationName(relation));
 
-   PageInit(pageHeader, BufferGetPageSize(buffer), 0);
+   PageInit(page, BufferGetPageSize(buffer), 0);
 
-   if (len > PageGetHeapFreeSpace(pageHeader))
+   if (len > PageGetHeapFreeSpace(page))
    {
        /* We should not get here given the test at the top */
        elog(PANIC, "tuple is too big: size %lu", (unsigned long) len);
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.15 2008/06/19 00:46:03 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.16 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 void
 heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
 {
-   PageHeader  dp = (PageHeader) BufferGetPage(buffer);
+   Page        page = BufferGetPage(buffer);
    Size        minfree;
 
    /*
     * Forget it if page is not hinted to contain something prunable that's
     * older than OldestXmin.
     */
-   if (!PageIsPrunable(dp, OldestXmin))
+   if (!PageIsPrunable(page, OldestXmin))
        return;
 
    /*
                                             HEAP_DEFAULT_FILLFACTOR);
    minfree = Max(minfree, BLCKSZ / 10);
 
-   if (PageIsFull(dp) || PageGetHeapFreeSpace((Page) dp) < minfree)
+   if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
    {
        /* OK, try to get exclusive buffer lock */
        if (!ConditionalLockBufferForCleanup(buffer))
         * prune. (We needn't recheck PageIsPrunable, since no one else could
         * have pruned while we hold pin.)
         */
-       if (PageIsFull(dp) || PageGetHeapFreeSpace((Page) dp) < minfree)
+       if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
        {
            /* OK to prune (though not to remove redirects) */
            (void) heap_page_prune(relation, buffer, OldestXmin, false, true);
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.109 2008/05/12 00:00:45 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.110 2008/07/13 20:45:47 tgl Exp $
  *
  * NOTES
  *    Postgres btree pages look like ordinary relation pages.  The opaque
    /*
     * Additionally check that the special area looks sane.
     */
-   if (((PageHeader) (page))->pd_special !=
-       (BLCKSZ - MAXALIGN(sizeof(BTPageOpaqueData))))
+   if (PageGetSpecialSize(page) != MAXALIGN(sizeof(BTPageOpaqueData)))
        ereport(ERROR,
                (errcode(ERRCODE_INDEX_CORRUPTED),
                 errmsg("index \"%s\" contains corrupted page at block %u",
 
        /* Initialize the new page before returning it */
        page = BufferGetPage(buf);
-       Assert(PageIsNew((PageHeader) page));
+       Assert(PageIsNew(page));
        _bt_pageinit(page, BufferGetPageSize(buf));
    }
 
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.315 2008/06/30 22:10:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.316 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
                XLogRecPtr *lsn, BkpBlock *bkpb)
 {
-   PageHeader  page;
+   Page        page;
 
-   page = (PageHeader) BufferGetBlock(rdata->buffer);
+   page = BufferGetPage(rdata->buffer);
 
    /*
     * XXX We assume page LSN is first data on *every* page that can be passed
     * to XLogInsert, whether it otherwise has the standard page layout or
     * not.
     */
-   *lsn = page->pd_lsn;
+   *lsn = PageGetLSN(page);
 
    if (doPageWrites &&
-       XLByteLE(page->pd_lsn, RedoRecPtr))
+       XLByteLE(PageGetLSN(page), RedoRecPtr))
    {
        /*
         * The page needs to be backed up, so set up *bkpb
        if (rdata->buffer_std)
        {
            /* Assume we can omit data between pd_lower and pd_upper */
-           uint16      lower = page->pd_lower;
-           uint16      upper = page->pd_upper;
+           uint16      lower = ((PageHeader) page)->pd_lower;
+           uint16      upper = ((PageHeader) page)->pd_upper;
 
            if (lower >= SizeOfPageHeaderData &&
                upper > lower &&
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.56 2008/06/19 00:46:03 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.57 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
        /* check that page has been initialized */
        Page        page = (Page) BufferGetPage(buffer);
 
-       if (PageIsNew((PageHeader) page))
+       if (PageIsNew(page))
        {
            UnlockReleaseBuffer(buffer);
            log_invalid_page(rnode, blkno, true);
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.153 2008/06/12 09:12:30 heikki Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.154 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    Oid         seqoid;
    Relation    rel;
    Buffer      buf;
-   PageHeader  page;
+   Page        page;
    sequence_magic *sm;
    HeapTuple   tuple;
    TupleDesc   tupDesc;
    buf = ReadBuffer(rel, P_NEW);
    Assert(BufferGetBlockNumber(buf) == 0);
 
-   page = (PageHeader) BufferGetPage(buf);
+   page = BufferGetPage(buf);
 
-   PageInit((Page) page, BufferGetPageSize(buf), sizeof(sequence_magic));
+   PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
    sm = (sequence_magic *) PageGetSpecialPointer(page);
    sm->magic = SEQ_MAGIC;
 
 static Form_pg_sequence
 read_info(SeqTable elm, Relation rel, Buffer *buf)
 {
-   PageHeader  page;
+   Page        page;
    ItemId      lp;
    HeapTupleData tuple;
    sequence_magic *sm;
    *buf = ReadBuffer(rel, 0);
    LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
 
-   page = (PageHeader) BufferGetPage(*buf);
+   page = BufferGetPage(*buf);
    sm = (sequence_magic *) PageGetSpecialPointer(page);
 
    if (sm->magic != SEQ_MAGIC)
 
    lp = PageGetItemId(page, FirstOffsetNumber);
    Assert(ItemIdIsNormal(lp));
-   tuple.t_data = (HeapTupleHeader) PageGetItem((Page) page, lp);
+   tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
 
    seq = (Form_pg_sequence) GETSTRUCT(&tuple);
 
 
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.234 2008/05/15 00:17:39 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.235 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    }
    else
    {
-       PageHeader  dp;
+       Page        page;
        ItemId      lp;
 
        buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
 
-       dp = (PageHeader) BufferGetPage(buffer);
-       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+       page = BufferGetPage(buffer);
+       lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
 
        Assert(ItemIdIsNormal(lp));
 
-       tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+       tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
        tuple.t_len = ItemIdGetLength(lp);
        tuple.t_self = *tid;
        tuple.t_tableOid = RelationGetRelid(relation);
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.147 2008/06/19 00:46:04 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.148 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                tuple_width += sizeof(HeapTupleHeaderData);
                tuple_width += sizeof(ItemPointerData);
                /* note: integer division is intentional here */
-               density = (BLCKSZ - sizeof(PageHeaderData)) / tuple_width;
+               density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;
            }
            *tuples = rint(density * (double) curpages);
            break;
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.233 2008/06/19 00:46:05 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.234 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
         * always have left a zero-filled buffer, complain if not PageIsNew.
         */
        bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr);
-       if (!PageIsNew((PageHeader) bufBlock))
+       if (!PageIsNew((Page) bufBlock))
            ereport(ERROR,
                    (errmsg("unexpected data beyond EOF in block %u of relation %u/%u/%u",
                            blockNum, smgr->smgr_rnode.spcNode, smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode),
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.88 2008/06/19 00:46:05 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.89 2008/07/13 20:45:47 tgl Exp $
  *
  * NOTES
  *     modeled after Margo Seltzer's hash implementation for unix.
  * Maximum size of a hash index item (it's okay to have only one per page)
  */
 #define HashMaxItemSize(page) \
-   (PageGetPageSize(page) - \
-    sizeof(PageHeaderData) - \
-    MAXALIGN(sizeof(HashPageOpaqueData)) - \
-    sizeof(ItemIdData))
+   MAXALIGN_DOWN(PageGetPageSize(page) - \
+                 SizeOfPageHeaderData - \
+                 sizeof(ItemIdData) - \
+                 MAXALIGN(sizeof(HashPageOpaqueData)))
 
 #define HASH_MIN_FILLFACTOR            10
 #define HASH_DEFAULT_FILLFACTOR        75
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.99 2008/05/12 00:00:53 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.100 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * other stuff that has to be on a disk page.  Since heap pages use no
  * "special space", there's no deduction for that.
  *
- * NOTE: we do not need to count an ItemId for the tuple because
- * sizeof(PageHeaderData) includes the first ItemId on the page.  But beware
- * of assuming that, say, you can fit 2 tuples of size MaxHeapTupleSize/2
- * on the same page.
+ * NOTE: we allow for the ItemId that must point to the tuple, ensuring that
+ * an otherwise-empty page can indeed hold a tuple of this size.  Because
+ * ItemIds and tuples have different alignment requirements, don't assume that
+ * you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page.
  */
-#define MaxHeapTupleSize  (BLCKSZ - MAXALIGN(sizeof(PageHeaderData)))
+#define MaxHeapTupleSize  (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData)))
 
 /*
  * MaxHeapTuplesPerPage is an upper bound on the number of tuples that can
  * require increases in the size of work arrays.
  */
 #define MaxHeapTuplesPerPage   \
-   ((int) ((BLCKSZ - offsetof(PageHeaderData, pd_linp)) / \
+   ((int) ((BLCKSZ - SizeOfPageHeaderData) / \
            (MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + sizeof(ItemIdData))))
 
 /*
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.49 2008/01/01 19:45:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/itup.h,v 1.50 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * must be maxaligned, and it must have an associated item pointer.
  */
 #define MaxIndexTuplesPerPage  \
-   ((int) ((BLCKSZ - offsetof(PageHeaderData, pd_linp)) / \
+   ((int) ((BLCKSZ - SizeOfPageHeaderData) / \
            (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData))))
 
 
 
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.120 2008/06/19 00:46:06 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.121 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  *
  * We actually need to be able to fit three items on every page,
  * so restrict any one item to 1/3 the per-page available space.
- *
- * Note: sizeof(PageHeaderData) includes the first ItemId, but we have
- * to allow for 2 more, as well as the end-of-page special space.
  */
 #define BTMaxItemSize(page) \
    MAXALIGN_DOWN((PageGetPageSize(page) - \
-                  MAXALIGN(sizeof(PageHeaderData) + 2*sizeof(ItemIdData)) - \
+                  MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \
                   MAXALIGN(sizeof(BTPageOpaqueData))) / 3)
 
 /*
 
  *
  * Copyright (c) 2000-2008, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.40 2008/06/19 00:46:06 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.41 2008/07/13 20:45:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 #define TOAST_TUPLES_PER_PAGE  4
 
-/* Note: sizeof(PageHeaderData) includes the first ItemId on the page */
 #define TOAST_TUPLE_THRESHOLD  \
    MAXALIGN_DOWN((BLCKSZ - \
-                  MAXALIGN(sizeof(PageHeaderData) + (TOAST_TUPLES_PER_PAGE-1) * sizeof(ItemIdData))) \
+                  MAXALIGN(SizeOfPageHeaderData + TOAST_TUPLES_PER_PAGE * sizeof(ItemIdData))) \
                  / TOAST_TUPLES_PER_PAGE)
 
 #define TOAST_TUPLE_TARGET     TOAST_TUPLE_THRESHOLD
  */
 #define EXTERN_TUPLES_PER_PAGE 4       /* tweak only this */
 
-/* Note: sizeof(PageHeaderData) includes the first ItemId on the page */
 #define EXTERN_TUPLE_MAX_SIZE  \
    MAXALIGN_DOWN((BLCKSZ - \
-                  MAXALIGN(sizeof(PageHeaderData) + (EXTERN_TUPLES_PER_PAGE-1) * sizeof(ItemIdData))) \
+                  MAXALIGN(SizeOfPageHeaderData + EXTERN_TUPLES_PER_PAGE * sizeof(ItemIdData))) \
                  / EXTERN_TUPLES_PER_PAGE)
 
 #define TOAST_MAX_CHUNK_SIZE   \