aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/gist/gist.c4
-rw-r--r--src/backend/access/hash/hashpage.c14
-rw-r--r--src/backend/access/heap/heapam.c8
-rw-r--r--src/backend/access/nbtree/nbtpage.c10
-rw-r--r--src/backend/access/rtree/rtree.c4
-rw-r--r--src/backend/storage/page/bufpage.c194
-rw-r--r--src/include/storage/bufpage.h4
7 files changed, 94 insertions, 144 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 38fe008e8ea..db57a5f3ffa 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.86 2001/11/05 17:46:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.87 2002/01/15 22:14:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1437,7 +1437,7 @@ GISTInitBuffer(Buffer b, uint32 f)
pageSize = BufferGetPageSize(b);
page = BufferGetPage(b);
- MemSet(page, 0, (int) pageSize);
+
PageInit(page, pageSize, sizeof(GISTPageOpaqueData));
opaque = (GISTPageOpaque) PageGetSpecialPointer(page);
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 0fff5a11e6f..668f0b16d09 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.33 2001/10/25 05:49:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.34 2002/01/15 22:14:16 tgl Exp $
*
* NOTES
* Postgres hash pages look like ordinary relation pages. The opaque
@@ -301,17 +301,7 @@ _hash_chgbufaccess(Relation rel,
void
_hash_pageinit(Page page, Size size)
{
- Assert(((PageHeader) page)->pd_lower == 0);
- Assert(((PageHeader) page)->pd_upper == 0);
- Assert(((PageHeader) page)->pd_special == 0);
-
- /*
- * Cargo-cult programming -- don't really need this to be zero, but
- * creating new pages is an infrequent occurrence and it makes me feel
- * good when I know they're empty.
- */
- MemSet(page, 0, size);
-
+ Assert(PageIsNew(page));
PageInit(page, size, sizeof(HashPageOpaqueData));
}
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 5073a2e1900..878896d5e27 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.128 2001/11/05 17:46:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.129 2002/01/15 22:14:17 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -2094,10 +2094,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
- {
PageInit(page, BufferGetPageSize(buffer), 0);
- PageZero(page);
- }
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
{
@@ -2262,10 +2259,7 @@ newsame:;
uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
- {
PageInit(page, BufferGetPageSize(buffer), 0);
- PageZero(page);
- }
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
{
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 2e6eb20cd4c..17006ed06ce 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.54 2001/10/25 05:49:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.55 2002/01/15 22:14:17 tgl Exp $
*
* NOTES
* Postgres btree pages look like ordinary relation pages. The opaque
@@ -399,14 +399,6 @@ _bt_wrtnorelbuf(Relation rel, Buffer buf)
void
_bt_pageinit(Page page, Size size)
{
- /*
- * Cargo_cult programming -- don't really need this to be zero, but
- * creating new pages is an infrequent occurrence and it makes me feel
- * good when I know they're empty.
- */
-
- MemSet(page, 0, size);
-
PageInit(page, size, sizeof(BTPageOpaqueData));
((BTPageOpaque) PageGetSpecialPointer(page))->btpo_parent =
InvalidBlockNumber;
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index 1e74678831f..2526ea4b812 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.68 2001/11/05 17:46:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.69 2002/01/15 22:14:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1107,7 +1107,7 @@ RTInitBuffer(Buffer b, uint32 f)
pageSize = BufferGetPageSize(b);
page = BufferGetPage(b);
- MemSet(page, 0, (int) pageSize);
+
PageInit(page, pageSize, sizeof(RTreePageOpaqueData));
opaque = (RTreePageOpaque) PageGetSpecialPointer(page);
diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c
index 916071aa098..d6c0339e142 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.41 2001/11/08 04:05:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.42 2002/01/15 22:14:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,10 +20,6 @@
#include "storage/bufpage.h"
-static void PageIndexTupleDeleteAdjustLinePointers(PageHeader phdr,
- char *location, Size size);
-
-
/* ----------------------------------------------------------------
* Page support functions
* ----------------------------------------------------------------
@@ -44,24 +40,15 @@ PageInit(Page page, Size pageSize, Size specialSize)
Assert(pageSize >
specialSize + sizeof(PageHeaderData) - sizeof(ItemIdData));
+ /* 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_upper = pageSize - specialSize;
p->pd_special = pageSize - specialSize;
PageSetPageSize(page, pageSize);
-
- p->pd_lsn.xlogid = p->pd_lsn.xrecoff = 0;
- p->pd_sui = 0;
}
-/*
- * WAL needs in zero-ed page data content
- */
-void
-PageZero(Page page)
-{
- MemSet((char *) page + ((PageHeader) page)->pd_lower, 0,
- ((PageHeader) page)->pd_special - ((PageHeader) page)->pd_lower);
-}
/* ----------------
* PageAddItem
@@ -86,10 +73,11 @@ PageAddItem(Page page,
OffsetNumber offsetNumber,
ItemIdFlags flags)
{
+ PageHeader phdr = (PageHeader) page;
int i;
Size alignedSize;
- Offset lower;
- Offset upper;
+ int lower;
+ int upper;
ItemId itemId;
OffsetNumber limit;
bool needshuffle = false;
@@ -98,6 +86,16 @@ PageAddItem(Page page,
flags &= ~OverwritePageMode;
/*
+ * Be wary about corrupted page pointers
+ */
+ if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) ||
+ phdr->pd_lower > phdr->pd_upper ||
+ phdr->pd_upper > phdr->pd_special ||
+ phdr->pd_special > BLCKSZ)
+ elog(ERROR, "PageAddItem: corrupted page pointers: lower = %u, upper = %u, special = %u",
+ phdr->pd_lower, phdr->pd_upper, phdr->pd_special);
+
+ /*
* Find first unallocated offsetNumber
*/
limit = OffsetNumberNext(PageGetMaxOffsetNumber(page));
@@ -114,7 +112,7 @@ PageAddItem(Page page,
}
if (offsetNumber < limit)
{
- itemId = &((PageHeader) page)->pd_linp[offsetNumber - 1];
+ itemId = &phdr->pd_linp[offsetNumber - 1];
if (((*itemId).lp_flags & LP_USED) ||
((*itemId).lp_len != 0))
{
@@ -138,7 +136,7 @@ PageAddItem(Page page,
/* look for "recyclable" (unused & deallocated) ItemId */
for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
{
- itemId = &((PageHeader) page)->pd_linp[offsetNumber - 1];
+ itemId = &phdr->pd_linp[offsetNumber - 1];
if ((((*itemId).lp_flags & LP_USED) == 0) &&
((*itemId).lp_len == 0))
break;
@@ -146,18 +144,21 @@ PageAddItem(Page page,
}
/*
- * Compute new lower and upper pointers for page, see if it'll fit
+ * Compute new lower and upper pointers for page, see if it'll fit.
+ *
+ * Note: do arithmetic as signed ints, to avoid mistakes if, say,
+ * alignedSize > pd_upper.
*/
if (offsetNumber > limit)
- lower = (Offset) (((char *) (&((PageHeader) page)->pd_linp[offsetNumber])) - ((char *) page));
+ lower = (char *) (&phdr->pd_linp[offsetNumber]) - (char *) page;
else if (offsetNumber == limit || needshuffle)
- lower = ((PageHeader) page)->pd_lower + sizeof(ItemIdData);
+ lower = phdr->pd_lower + sizeof(ItemIdData);
else
- lower = ((PageHeader) page)->pd_lower;
+ lower = phdr->pd_lower;
alignedSize = MAXALIGN(size);
- upper = ((PageHeader) page)->pd_upper - alignedSize;
+ upper = (int) phdr->pd_upper - (int) alignedSize;
if (lower > upper)
return InvalidOffsetNumber;
@@ -169,24 +170,26 @@ PageAddItem(Page page,
if (needshuffle)
{
/* shuffle ItemId's (Do the PageManager Shuffle...) */
- for (i = (limit - 1); i >= offsetNumber; i--)
+ for (i = (int) limit - 1; i >= (int) offsetNumber; i--)
{
ItemId fromitemId,
toitemId;
- fromitemId = &((PageHeader) page)->pd_linp[i - 1];
- toitemId = &((PageHeader) page)->pd_linp[i];
+ fromitemId = &phdr->pd_linp[i - 1];
+ toitemId = &phdr->pd_linp[i];
*toitemId = *fromitemId;
}
}
- itemId = &((PageHeader) page)->pd_linp[offsetNumber - 1];
+ itemId = &phdr->pd_linp[offsetNumber - 1];
(*itemId).lp_off = upper;
(*itemId).lp_len = size;
(*itemId).lp_flags = flags;
+
memmove((char *) page + upper, item, size);
- ((PageHeader) page)->pd_lower = lower;
- ((PageHeader) page)->pd_upper = upper;
+
+ phdr->pd_lower = (LocationIndex) lower;
+ phdr->pd_upper = (LocationIndex) upper;
return offsetNumber;
}
@@ -383,79 +386,76 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
Size
PageGetFreeSpace(Page page)
{
- Size space;
+ int space;
- space = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
+ /*
+ * Use signed arithmetic here so that we behave sensibly if
+ * pd_lower > pd_upper.
+ */
+ space = (int) ((PageHeader) page)->pd_upper -
+ (int) ((PageHeader) page)->pd_lower;
- if (space < sizeof(ItemIdData))
+ if (space < (int) sizeof(ItemIdData))
return 0;
space -= sizeof(ItemIdData); /* XXX not always appropriate */
- return space;
+ return (Size) space;
}
-/*
- * PageRepairFragmentation un-useful for index page cleanup because
- * of it doesn't remove line pointers. This routine could be more
- * effective but ... no time -:)
- */
-void
-IndexPageCleanup(Buffer buffer)
-{
- Page page = (Page) BufferGetPage(buffer);
- ItemId lp;
- OffsetNumber maxoff;
- OffsetNumber i;
-
- maxoff = PageGetMaxOffsetNumber(page);
- for (i = 0; i < maxoff; i++)
- {
- lp = ((PageHeader) page)->pd_linp + i;
- if ((*lp).lp_flags & LP_DELETE) /* marked for deletion */
- {
- PageIndexTupleDelete(page, i + 1);
- maxoff--;
- }
- }
-}
/*
- *----------------------------------------------------------------
* PageIndexTupleDelete
- *----------------------------------------------------------------
*
- * This routine does the work of removing a tuple from an index page.
+ * This routine does the work of removing a tuple from an index page.
+ *
+ * Unlike heap pages, we compact out the line pointer for the removed tuple.
*/
void
PageIndexTupleDelete(Page page, OffsetNumber offnum)
{
- PageHeader phdr;
+ PageHeader phdr = (PageHeader) page;
char *addr;
ItemId tup;
Size size;
- char *locn;
+ unsigned offset;
int nbytes;
int offidx;
+ int nline,
+ i;
+
+ /*
+ * As with PageRepairFragmentation, paranoia seems justified.
+ */
+ if (phdr->pd_lower < (sizeof(PageHeaderData) - sizeof(ItemIdData)) ||
+ phdr->pd_lower > phdr->pd_upper ||
+ phdr->pd_upper > phdr->pd_special ||
+ phdr->pd_special > BLCKSZ)
+ elog(ERROR, "PageIndexTupleDelete: corrupted page pointers: lower = %u, upper = %u, special = %u",
+ phdr->pd_lower, phdr->pd_upper, phdr->pd_special);
- phdr = (PageHeader) page;
+ nline = PageGetMaxOffsetNumber(page);
+ if ((int) offnum <= 0 || (int) offnum > nline)
+ elog(ERROR, "PageIndexTupleDelete: bad offnum %u", offnum);
/* change offset number to offset index */
offidx = offnum - 1;
tup = PageGetItemId(page, offnum);
size = ItemIdGetLength(tup);
- size = MAXALIGN(size);
+ offset = ItemIdGetOffset(tup);
- /* location of deleted tuple data */
- locn = (char *) (page + ItemIdGetOffset(tup));
+ if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
+ offset != MAXALIGN(offset) || size != MAXALIGN(size))
+ elog(ERROR, "PageIndexTupleDelete: corrupted item pointer: offset = %u size = %u",
+ offset, size);
/*
* 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.
*/
-
nbytes = phdr->pd_lower -
((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr);
+
memmove((char *) &(phdr->pd_linp[offidx]),
(char *) &(phdr->pd_linp[offidx + 1]),
nbytes);
@@ -470,52 +470,28 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
*/
/* beginning of tuple space */
- addr = (char *) (page + phdr->pd_upper);
+ addr = (char *) page + phdr->pd_upper;
- if (locn != addr)
- memmove(addr + size, addr, (int) (locn - addr));
+ if (offset > phdr->pd_upper)
+ memmove(addr + size, addr, (int) (offset - phdr->pd_upper));
/* adjust free space boundary pointers */
phdr->pd_upper += size;
phdr->pd_lower -= sizeof(ItemIdData);
- /* finally, we need to adjust the linp entries that remain */
+ /*
+ * Finally, we need to adjust the linp entries that remain.
+ *
+ * Anything that used to be before the deleted tuple's data was moved
+ * forward by the size of the deleted tuple.
+ */
if (!PageIsEmpty(page))
- PageIndexTupleDeleteAdjustLinePointers(phdr, locn, size);
-}
-
-/*
- *----------------------------------------------------------------
- * PageIndexTupleDeleteAdjustLinePointers
- *----------------------------------------------------------------
- *
- * Once the line pointers and tuple data have been shifted around
- * on the page, we need to go down the line pointer vector and
- * adjust pointers to reflect new locations. Anything that used
- * to be before the deleted tuple's data was moved forward by the
- * size of the deleted tuple.
- *
- * This routine does the work of adjusting the line pointers.
- * Location is where the tuple data used to lie; size is how
- * much space it occupied. We assume that size has been aligned
- * as required by the time we get here.
- *
- * This routine should never be called on an empty page.
- */
-static void
-PageIndexTupleDeleteAdjustLinePointers(PageHeader phdr,
- char *location,
- Size size)
-{
- int i;
- unsigned offset;
-
- /* location is an index into the page... */
- offset = (unsigned) (location - (char *) phdr);
-
- for (i = PageGetMaxOffsetNumber((Page) phdr) - 1; i >= 0; i--)
{
- if (phdr->pd_linp[i].lp_off <= offset)
- phdr->pd_linp[i].lp_off += size;
+ 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;
+ }
}
}
diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h
index 6e75f12b3c8..3537d8f9e2d 100644
--- a/src/include/storage/bufpage.h
+++ b/src/include/storage/bufpage.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: bufpage.h,v 1.46 2001/11/05 17:46:35 momjian Exp $
+ * $Id: bufpage.h,v 1.47 2002/01/15 22:14:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -310,7 +310,6 @@ typedef enum
*/
extern void PageInit(Page page, Size pageSize, Size specialSize);
-extern void PageZero(Page page);
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
OffsetNumber offsetNumber, ItemIdFlags flags);
extern Page PageGetTempPage(Page page, Size specialSize);
@@ -318,6 +317,5 @@ extern void PageRestoreTempPage(Page tempPage, Page oldPage);
extern int PageRepairFragmentation(Page page, OffsetNumber *unused);
extern Size PageGetFreeSpace(Page page);
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
-extern void IndexPageCleanup(Buffer buffer);
#endif /* BUFPAGE_H */