diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index ebafcffd28..9a6a0b0740 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.140 2002/07/02 05:46:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.141 2002/07/02 05:48:44 momjian Exp $ * * * INTERFACE ROUTINES @@ -2067,7 +2067,7 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record) while ((char *) unused < unend) { - lp = ((PageHeader) page)->pd_linp + *unused; + lp = PageGetItemId(page, *unused + 1); lp->lp_flags &= ~LP_USED; unused++; } diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 4929d1d058..c0190859b7 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.93 2002/06/20 20:29:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.94 2002/07/02 05:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -383,10 +383,9 @@ _bt_insertonpg(Relation rel, * to 1/3 the per-page available space. Note that at this point, * itemsz doesn't include the ItemId. */ - if (itemsz > (PageGetPageSize(page) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)) + if (itemsz > BTMaxItemSize(page)) elog(ERROR, "btree: index item size %lu exceeds maximum %lu", - (unsigned long) itemsz, - (PageGetPageSize(page) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)); + (unsigned long) itemsz, BTMaxItemSize(page)); /* * Determine exactly where new item will go. @@ -1020,9 +1019,8 @@ _bt_findsplitloc(Relation rel, /* Total free space available on a btree page, after fixed overhead */ leftspace = rightspace = - PageGetPageSize(page) - sizeof(PageHeaderData) - - MAXALIGN(sizeof(BTPageOpaqueData)) - +sizeof(ItemIdData); + PageGetPageSize(page) - SizeOfPageHeaderData - + MAXALIGN(sizeof(BTPageOpaqueData)); /* * Finding the best possible split would require checking all the diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index dff1c0dee1..80d56f0451 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -35,7 +35,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.64 2002/06/20 20:29:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.65 2002/07/02 05:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -346,10 +346,9 @@ _bt_buildadd(Relation index, BTPageState *state, BTItem bti) * oversize items being inserted into an already-existing index. But * during creation of an index, we don't go through there. */ - if (btisz > (PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)) + if (btisz > BTMaxItemSize(npage)) elog(ERROR, "btree: index item size %lu exceeds maximum %ld", - (unsigned long) btisz, - (PageGetPageSize(npage) - sizeof(PageHeaderData) - MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)); + (unsigned long) btisz, BTMaxItemSize(npage)); if (pgspc < btisz || pgspc < state->btps_full) { diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index bffd403af2..e6abf3b41e 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.45 2002/06/20 20:29:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.46 2002/07/02 05:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -37,13 +37,12 @@ PageInit(Page page, Size pageSize, Size specialSize) specialSize = MAXALIGN(specialSize); Assert(pageSize == BLCKSZ); - Assert(pageSize > - specialSize + sizeof(PageHeaderData) - sizeof(ItemIdData)); + Assert(pageSize > specialSize + SizeOfPageHeaderData); /* Make sure all fields of page are zero, as well as unused space */ MemSet(p, 0, pageSize); - p->pd_lower = sizeof(PageHeaderData) - sizeof(ItemIdData); + p->pd_lower = SizeOfPageHeaderData; p->pd_upper = pageSize - specialSize; p->pd_special = pageSize - specialSize; PageSetPageSize(page, pageSize); @@ -88,7 +87,7 @@ PageAddItem(Page page, /* * Be wary about corrupted page pointers */ - if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) || + if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || phdr->pd_special > BLCKSZ) @@ -112,7 +111,7 @@ PageAddItem(Page page, } if (offsetNumber < limit) { - itemId = &phdr->pd_linp[offsetNumber - 1]; + itemId = PageGetItemId(phdr, offsetNumber); if (((*itemId).lp_flags & LP_USED) || ((*itemId).lp_len != 0)) { @@ -136,7 +135,7 @@ PageAddItem(Page page, /* look for "recyclable" (unused & deallocated) ItemId */ for (offsetNumber = 1; offsetNumber < limit; offsetNumber++) { - itemId = &phdr->pd_linp[offsetNumber - 1]; + itemId = PageGetItemId(phdr, offsetNumber); if ((((*itemId).lp_flags & LP_USED) == 0) && ((*itemId).lp_len == 0)) break; @@ -150,7 +149,7 @@ PageAddItem(Page page, * alignedSize > pd_upper. */ if (offsetNumber > limit) - lower = (char *) (&phdr->pd_linp[offsetNumber]) - (char *) page; + lower = (char *) PageGetItemId(phdr, offsetNumber + 1) - (char *) page; else if (offsetNumber == limit || needshuffle) lower = phdr->pd_lower + sizeof(ItemIdData); else @@ -175,13 +174,13 @@ PageAddItem(Page page, ItemId fromitemId, toitemId; - fromitemId = &phdr->pd_linp[i - 1]; - toitemId = &phdr->pd_linp[i]; + fromitemId = PageGetItemId(phdr, i); + toitemId = PageGetItemId(phdr, i + 1); *toitemId = *fromitemId; } } - itemId = &phdr->pd_linp[offsetNumber - 1]; + itemId = PageGetItemId(phdr, offsetNumber); (*itemId).lp_off = upper; (*itemId).lp_len = size; (*itemId).lp_flags = flags; @@ -214,12 +213,12 @@ PageGetTempPage(Page page, Size specialSize) memcpy(temp, page, pageSize); /* clear out the middle */ - size = (pageSize - sizeof(PageHeaderData)) + sizeof(ItemIdData); + size = pageSize - SizeOfPageHeaderData; size -= MAXALIGN(specialSize); - MemSet((char *) &(thdr->pd_linp[0]), 0, size); + MemSet(PageGetContents(thdr), 0, size); /* set high, low water marks */ - thdr->pd_lower = sizeof(PageHeaderData) - sizeof(ItemIdData); + thdr->pd_lower = SizeOfPageHeaderData; thdr->pd_upper = pageSize - MAXALIGN(specialSize); return temp; @@ -291,7 +290,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused) * pointers, lengths, etc could cause us to clobber adjacent disk * buffers, spreading the data loss further. So, check everything. */ - if (pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) || + if (pd_lower < SizeOfPageHeaderData || pd_lower > pd_upper || pd_upper > pd_special || pd_special > BLCKSZ || @@ -303,7 +302,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused) nused = 0; for (i = 0; i < nline; i++) { - lp = ((PageHeader) page)->pd_linp + i; + lp = PageGetItemId(page, i + 1); if ((*lp).lp_flags & LP_DELETE) /* marked for deletion */ (*lp).lp_flags &= ~(LP_USED | LP_DELETE); if ((*lp).lp_flags & LP_USED) @@ -317,7 +316,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused) /* Page is completely empty, so just reset it quickly */ for (i = 0; i < nline; i++) { - lp = ((PageHeader) page)->pd_linp + i; + lp = PageGetItemId(page, i + 1); (*lp).lp_len = 0; /* indicate unused & deallocated */ } ((PageHeader) page)->pd_upper = pd_special; @@ -331,7 +330,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused) totallen = 0; for (i = 0; i < nline; i++) { - lp = ((PageHeader) page)->pd_linp + i; + lp = PageGetItemId(page, i + 1); if ((*lp).lp_flags & LP_USED) { itemidptr->offsetindex = i; @@ -363,7 +362,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused) for (i = 0, itemidptr = itemidbase; i < nused; i++, itemidptr++) { - lp = ((PageHeader) page)->pd_linp + itemidptr->offsetindex; + lp = PageGetItemId(page, itemidptr->offsetindex + 1); upper -= itemidptr->alignedlen; memmove((char *) page + upper, (char *) page + itemidptr->itemoff, @@ -426,7 +425,7 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum) /* * As with PageRepairFragmentation, paranoia seems justified. */ - if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) || + if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || phdr->pd_special > BLCKSZ) @@ -452,6 +451,8 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum) /* * First, we want to get rid of the pd_linp entry for the index tuple. * We copy all subsequent linp's back one slot in the array. + * We don't use PageGetItemId, because we are manipulating the _array_, + * not individual linp's. */ nbytes = phdr->pd_lower - ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr); @@ -490,8 +491,8 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum) nline--; /* there's one less than when we started */ for (i = nline; --i >= 0; ) { - if (phdr->pd_linp[i].lp_off <= offset) - phdr->pd_linp[i].lp_off += size; + if (PageGetItemId(phdr, i + 1)->lp_off <= offset) + PageGetItemId(phdr, i + 1)->lp_off += size; } } } diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 9bc86a01a8..7d279ef94d 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nbtree.h,v 1.62 2002/06/20 20:29:43 momjian Exp $ + * $Id: nbtree.h,v 1.63 2002/07/02 05:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -65,7 +65,7 @@ typedef struct BTMetaPageData } BTMetaPageData; #define BTPageGetMeta(p) \ - ((BTMetaPageData *) &((PageHeader) p)->pd_linp[0]) + ((BTMetaPageData *) PageGetContents(p)) #define BTREE_METAPAGE 0 /* first page is meta */ #define BTREE_MAGIC 0x053162 /* magic number of btree pages */ @@ -76,6 +76,14 @@ typedef struct BTMetaPageData #define BTREE_VERSION 1 +/* + * 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. + */ +#define BTMaxItemSize(page) \ + ((PageGetPageSize(page) - \ + sizeof(PageHeaderData) - \ + MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)) /* * BTScanOpaqueData is used to remember which buffers we're currently * examining in the scan. We keep these buffers pinned (but not locked, diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index 5c9c4a6c06..31a858ec4f 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: bufpage.h,v 1.48 2002/06/20 20:29:52 momjian Exp $ + * $Id: bufpage.h,v 1.49 2002/07/02 05:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -157,13 +157,17 @@ typedef enum ((bool) (((PageHeader) (page))->pd_lower != 0)) \ ) +/* + * line pointer does not count as part of header + */ +#define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp[0])) + /* * PageIsEmpty * returns true iff no itemid has been allocated on the page */ #define PageIsEmpty(page) \ - (((PageHeader) (page))->pd_lower <= \ - (sizeof(PageHeaderData) - sizeof(ItemIdData))) + (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData) /* * PageIsNew @@ -179,6 +183,13 @@ typedef enum #define PageGetItemId(page, offsetNumber) \ ((ItemId) (&((PageHeader) (page))->pd_linp[(offsetNumber) - 1])) +/* + * PageGetContents + * To be used in case the page does not contain item pointers. + */ +#define PageGetContents(page) \ + ((char *) (&((PageHeader) (page))->pd_linp[0])) + /* ---------------- * macros to access opaque space * ---------------- @@ -290,8 +301,7 @@ typedef enum * That way we get -1 or so, not a huge positive number... */ #define PageGetMaxOffsetNumber(page) \ - (((int) (((PageHeader) (page))->pd_lower - \ - (sizeof(PageHeaderData) - sizeof(ItemIdData)))) \ + (((int) (((PageHeader) (page))->pd_lower - SizeOfPageHeaderData)) \ / ((int) sizeof(ItemIdData))) #define PageGetLSN(page) \