Add defenses to btree and hash index AMs to do simple sanity checks
on every index page they read; in particular to catch the case of an all-zero page, which PageHeaderIsValid allows to pass. It turns out hash already had this idea, but it was just Assert()ing things rather than doing a straight error check, and the Asserts were partially redundant with PageHeaderIsValid anyway. Per recent failure example from Jim Nasby. (gist still needs the same treatment.)
This commit is contained in:
parent
18691d8ee3
commit
766dc45d9f
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.81 2005/10/15 02:49:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.82 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -513,8 +513,8 @@ hashbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
* each bucket.
|
* each bucket.
|
||||||
*/
|
*/
|
||||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
orig_maxbucket = metap->hashm_maxbucket;
|
orig_maxbucket = metap->hashm_maxbucket;
|
||||||
orig_ntuples = metap->hashm_ntuples;
|
orig_ntuples = metap->hashm_ntuples;
|
||||||
memcpy(&local_metapage, metap, sizeof(local_metapage));
|
memcpy(&local_metapage, metap, sizeof(local_metapage));
|
||||||
@ -555,8 +555,8 @@ loop_top:
|
|||||||
vacuum_delay_point();
|
vacuum_delay_point();
|
||||||
|
|
||||||
buf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
buf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
Assert(opaque->hasho_bucket == cur_bucket);
|
Assert(opaque->hasho_bucket == cur_bucket);
|
||||||
|
|
||||||
@ -614,8 +614,8 @@ loop_top:
|
|||||||
|
|
||||||
/* Write-lock metapage and check for split since we started */
|
/* Write-lock metapage and check for split since we started */
|
||||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE);
|
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
if (cur_maxbucket != metap->hashm_maxbucket)
|
if (cur_maxbucket != metap->hashm_maxbucket)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.39 2005/10/18 01:06:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.40 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -73,8 +73,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
|
|
||||||
/* Read the metapage */
|
/* Read the metapage */
|
||||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether the item can fit on a hash page at all. (Eventually, we
|
* Check whether the item can fit on a hash page at all. (Eventually, we
|
||||||
@ -111,8 +111,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
|
|
||||||
/* Fetch the primary bucket page for the bucket */
|
/* Fetch the primary bucket page for the bucket */
|
||||||
buf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
buf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE);
|
|
||||||
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
Assert(pageopaque->hasho_bucket == bucket);
|
Assert(pageopaque->hasho_bucket == bucket);
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ _hash_doinsert(Relation rel, HashItem hitem)
|
|||||||
/* should fit now, given test above */
|
/* should fit now, given test above */
|
||||||
Assert(PageGetFreeSpace(page) >= itemsz);
|
Assert(PageGetFreeSpace(page) >= itemsz);
|
||||||
}
|
}
|
||||||
_hash_checkpage(rel, page, LH_OVERFLOW_PAGE);
|
_hash_checkpage(rel, buf, LH_OVERFLOW_PAGE);
|
||||||
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
Assert(pageopaque->hasho_bucket == bucket);
|
Assert(pageopaque->hasho_bucket == bucket);
|
||||||
}
|
}
|
||||||
@ -204,8 +204,8 @@ _hash_pgaddtup(Relation rel,
|
|||||||
OffsetNumber itup_off;
|
OffsetNumber itup_off;
|
||||||
Page page;
|
Page page;
|
||||||
|
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
|
|
||||||
itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
|
itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
|
||||||
if (PageAddItem(page, (Item) hitem, itemsize, itup_off, LP_USED)
|
if (PageAddItem(page, (Item) hitem, itemsize, itup_off, LP_USED)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.47 2005/10/15 02:49:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.48 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Overflow pages look like ordinary relation pages.
|
* Overflow pages look like ordinary relation pages.
|
||||||
@ -124,8 +124,8 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf)
|
|||||||
{
|
{
|
||||||
BlockNumber nextblkno;
|
BlockNumber nextblkno;
|
||||||
|
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
nextblkno = pageopaque->hasho_nextblkno;
|
nextblkno = pageopaque->hasho_nextblkno;
|
||||||
|
|
||||||
@ -183,8 +183,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
|
|||||||
/* Get exclusive lock on the meta page */
|
/* Get exclusive lock on the meta page */
|
||||||
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
||||||
|
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
/* start search at hashm_firstfree */
|
/* start search at hashm_firstfree */
|
||||||
orig_firstfree = metap->hashm_firstfree;
|
orig_firstfree = metap->hashm_firstfree;
|
||||||
@ -222,8 +222,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
|
|||||||
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
|
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
|
||||||
|
|
||||||
mapbuf = _hash_getbuf(rel, mapblkno, HASH_WRITE);
|
mapbuf = _hash_getbuf(rel, mapblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, mapbuf, LH_BITMAP_PAGE);
|
||||||
mappage = BufferGetPage(mapbuf);
|
mappage = BufferGetPage(mapbuf);
|
||||||
_hash_checkpage(rel, mappage, LH_BITMAP_PAGE);
|
|
||||||
freep = HashPageGetBitmap(mappage);
|
freep = HashPageGetBitmap(mappage);
|
||||||
|
|
||||||
for (; bit <= last_inpage; j++, bit += BITS_PER_MAP)
|
for (; bit <= last_inpage; j++, bit += BITS_PER_MAP)
|
||||||
@ -379,9 +379,9 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
Bucket bucket;
|
Bucket bucket;
|
||||||
|
|
||||||
/* Get information from the doomed page */
|
/* Get information from the doomed page */
|
||||||
|
_hash_checkpage(rel, ovflbuf, LH_OVERFLOW_PAGE);
|
||||||
ovflblkno = BufferGetBlockNumber(ovflbuf);
|
ovflblkno = BufferGetBlockNumber(ovflbuf);
|
||||||
ovflpage = BufferGetPage(ovflbuf);
|
ovflpage = BufferGetPage(ovflbuf);
|
||||||
_hash_checkpage(rel, ovflpage, LH_OVERFLOW_PAGE);
|
|
||||||
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
|
ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
|
||||||
nextblkno = ovflopaque->hasho_nextblkno;
|
nextblkno = ovflopaque->hasho_nextblkno;
|
||||||
prevblkno = ovflopaque->hasho_prevblkno;
|
prevblkno = ovflopaque->hasho_prevblkno;
|
||||||
@ -403,7 +403,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
Page prevpage = BufferGetPage(prevbuf);
|
Page prevpage = BufferGetPage(prevbuf);
|
||||||
HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
|
HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
|
||||||
|
|
||||||
_hash_checkpage(rel, prevpage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
_hash_checkpage(rel, prevbuf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
Assert(prevopaque->hasho_bucket == bucket);
|
Assert(prevopaque->hasho_bucket == bucket);
|
||||||
prevopaque->hasho_nextblkno = nextblkno;
|
prevopaque->hasho_nextblkno = nextblkno;
|
||||||
_hash_wrtbuf(rel, prevbuf);
|
_hash_wrtbuf(rel, prevbuf);
|
||||||
@ -414,7 +414,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
Page nextpage = BufferGetPage(nextbuf);
|
Page nextpage = BufferGetPage(nextbuf);
|
||||||
HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
|
HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
|
||||||
|
|
||||||
_hash_checkpage(rel, nextpage, LH_OVERFLOW_PAGE);
|
_hash_checkpage(rel, nextbuf, LH_OVERFLOW_PAGE);
|
||||||
Assert(nextopaque->hasho_bucket == bucket);
|
Assert(nextopaque->hasho_bucket == bucket);
|
||||||
nextopaque->hasho_prevblkno = prevblkno;
|
nextopaque->hasho_prevblkno = prevblkno;
|
||||||
_hash_wrtbuf(rel, nextbuf);
|
_hash_wrtbuf(rel, nextbuf);
|
||||||
@ -422,8 +422,8 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
|
|
||||||
/* Read the metapage so we can determine which bitmap page to use */
|
/* Read the metapage so we can determine which bitmap page to use */
|
||||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
/* Identify which bit to set */
|
/* Identify which bit to set */
|
||||||
ovflbitno = blkno_to_bitno(metap, ovflblkno);
|
ovflbitno = blkno_to_bitno(metap, ovflblkno);
|
||||||
@ -440,8 +440,8 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
|
|||||||
|
|
||||||
/* Clear the bitmap bit to indicate that this overflow page is free */
|
/* Clear the bitmap bit to indicate that this overflow page is free */
|
||||||
mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, mapbuf, LH_BITMAP_PAGE);
|
||||||
mappage = BufferGetPage(mapbuf);
|
mappage = BufferGetPage(mapbuf);
|
||||||
_hash_checkpage(rel, mappage, LH_BITMAP_PAGE);
|
|
||||||
freep = HashPageGetBitmap(mappage);
|
freep = HashPageGetBitmap(mappage);
|
||||||
Assert(ISSET(freep, bitmapbit));
|
Assert(ISSET(freep, bitmapbit));
|
||||||
CLRBIT(freep, bitmapbit);
|
CLRBIT(freep, bitmapbit);
|
||||||
@ -569,8 +569,8 @@ _hash_squeezebucket(Relation rel,
|
|||||||
*/
|
*/
|
||||||
wblkno = bucket_blkno;
|
wblkno = bucket_blkno;
|
||||||
wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);
|
wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, wbuf, LH_BUCKET_PAGE);
|
||||||
wpage = BufferGetPage(wbuf);
|
wpage = BufferGetPage(wbuf);
|
||||||
_hash_checkpage(rel, wpage, LH_BUCKET_PAGE);
|
|
||||||
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
|
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -593,8 +593,8 @@ _hash_squeezebucket(Relation rel,
|
|||||||
if (ropaque != wopaque)
|
if (ropaque != wopaque)
|
||||||
_hash_relbuf(rel, rbuf);
|
_hash_relbuf(rel, rbuf);
|
||||||
rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);
|
rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, rbuf, LH_OVERFLOW_PAGE);
|
||||||
rpage = BufferGetPage(rbuf);
|
rpage = BufferGetPage(rbuf);
|
||||||
_hash_checkpage(rel, rpage, LH_OVERFLOW_PAGE);
|
|
||||||
ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);
|
ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);
|
||||||
Assert(ropaque->hasho_bucket == bucket);
|
Assert(ropaque->hasho_bucket == bucket);
|
||||||
} while (BlockNumberIsValid(ropaque->hasho_nextblkno));
|
} while (BlockNumberIsValid(ropaque->hasho_nextblkno));
|
||||||
@ -635,8 +635,8 @@ _hash_squeezebucket(Relation rel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);
|
wbuf = _hash_getbuf(rel, wblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, wbuf, LH_OVERFLOW_PAGE);
|
||||||
wpage = BufferGetPage(wbuf);
|
wpage = BufferGetPage(wbuf);
|
||||||
_hash_checkpage(rel, wpage, LH_OVERFLOW_PAGE);
|
|
||||||
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
|
wopaque = (HashPageOpaque) PageGetSpecialPointer(wpage);
|
||||||
Assert(wopaque->hasho_bucket == bucket);
|
Assert(wopaque->hasho_bucket == bucket);
|
||||||
}
|
}
|
||||||
@ -688,8 +688,8 @@ _hash_squeezebucket(Relation rel,
|
|||||||
_hash_freeovflpage(rel, rbuf);
|
_hash_freeovflpage(rel, rbuf);
|
||||||
|
|
||||||
rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);
|
rbuf = _hash_getbuf(rel, rblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, rbuf, LH_OVERFLOW_PAGE);
|
||||||
rpage = BufferGetPage(rbuf);
|
rpage = BufferGetPage(rbuf);
|
||||||
_hash_checkpage(rel, rpage, LH_OVERFLOW_PAGE);
|
|
||||||
ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);
|
ropaque = (HashPageOpaque) PageGetSpecialPointer(rpage);
|
||||||
Assert(ropaque->hasho_bucket == bucket);
|
Assert(ropaque->hasho_bucket == bucket);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.52 2005/10/15 02:49:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.53 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Postgres hash pages look like ordinary relation pages. The opaque
|
* Postgres hash pages look like ordinary relation pages. The opaque
|
||||||
@ -103,9 +103,11 @@ _hash_droplock(Relation rel, BlockNumber whichlock, int access)
|
|||||||
* (ie, the buffer is "locked and pinned").
|
* (ie, the buffer is "locked and pinned").
|
||||||
*
|
*
|
||||||
* XXX P_NEW is not used because, unlike the tree structures, we
|
* XXX P_NEW is not used because, unlike the tree structures, we
|
||||||
* need the bucket blocks to be at certain block numbers. we must
|
* need the bucket blocks to be at certain block numbers.
|
||||||
* depend on the caller to call _hash_pageinit on the block if it
|
*
|
||||||
* knows that this is a new block.
|
* All call sites should call either _hash_pageinit or _hash_checkpage
|
||||||
|
* on the returned page, depending on whether the block is expected
|
||||||
|
* to be new or not.
|
||||||
*/
|
*/
|
||||||
Buffer
|
Buffer
|
||||||
_hash_getbuf(Relation rel, BlockNumber blkno, int access)
|
_hash_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||||
@ -380,8 +382,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
|
|||||||
/* Write-lock the meta page */
|
/* Write-lock the meta page */
|
||||||
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
|
||||||
|
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if split is still needed; someone else might have already
|
* Check to see if split is still needed; someone else might have already
|
||||||
@ -555,15 +557,15 @@ _hash_splitbucket(Relation rel,
|
|||||||
* either bucket.
|
* either bucket.
|
||||||
*/
|
*/
|
||||||
oblkno = start_oblkno;
|
oblkno = start_oblkno;
|
||||||
nblkno = start_nblkno;
|
|
||||||
obuf = _hash_getbuf(rel, oblkno, HASH_WRITE);
|
obuf = _hash_getbuf(rel, oblkno, HASH_WRITE);
|
||||||
nbuf = _hash_getbuf(rel, nblkno, HASH_WRITE);
|
_hash_checkpage(rel, obuf, LH_BUCKET_PAGE);
|
||||||
opage = BufferGetPage(obuf);
|
opage = BufferGetPage(obuf);
|
||||||
npage = BufferGetPage(nbuf);
|
|
||||||
|
|
||||||
_hash_checkpage(rel, opage, LH_BUCKET_PAGE);
|
|
||||||
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
|
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
|
||||||
|
|
||||||
|
nblkno = start_nblkno;
|
||||||
|
nbuf = _hash_getbuf(rel, nblkno, HASH_WRITE);
|
||||||
|
npage = BufferGetPage(nbuf);
|
||||||
|
|
||||||
/* initialize the new bucket's primary page */
|
/* initialize the new bucket's primary page */
|
||||||
_hash_pageinit(npage, BufferGetPageSize(nbuf));
|
_hash_pageinit(npage, BufferGetPageSize(nbuf));
|
||||||
nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
|
nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
|
||||||
@ -602,8 +604,8 @@ _hash_splitbucket(Relation rel,
|
|||||||
_hash_wrtbuf(rel, obuf);
|
_hash_wrtbuf(rel, obuf);
|
||||||
|
|
||||||
obuf = _hash_getbuf(rel, oblkno, HASH_WRITE);
|
obuf = _hash_getbuf(rel, oblkno, HASH_WRITE);
|
||||||
|
_hash_checkpage(rel, obuf, LH_OVERFLOW_PAGE);
|
||||||
opage = BufferGetPage(obuf);
|
opage = BufferGetPage(obuf);
|
||||||
_hash_checkpage(rel, opage, LH_OVERFLOW_PAGE);
|
|
||||||
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
|
oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
|
||||||
ooffnum = FirstOffsetNumber;
|
ooffnum = FirstOffsetNumber;
|
||||||
omaxoffnum = PageGetMaxOffsetNumber(opage);
|
omaxoffnum = PageGetMaxOffsetNumber(opage);
|
||||||
@ -642,8 +644,8 @@ _hash_splitbucket(Relation rel,
|
|||||||
_hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK);
|
_hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK);
|
||||||
/* chain to a new overflow page */
|
/* chain to a new overflow page */
|
||||||
nbuf = _hash_addovflpage(rel, metabuf, nbuf);
|
nbuf = _hash_addovflpage(rel, metabuf, nbuf);
|
||||||
|
_hash_checkpage(rel, nbuf, LH_OVERFLOW_PAGE);
|
||||||
npage = BufferGetPage(nbuf);
|
npage = BufferGetPage(nbuf);
|
||||||
_hash_checkpage(rel, npage, LH_OVERFLOW_PAGE);
|
|
||||||
/* we don't need nopaque within the loop */
|
/* we don't need nopaque within the loop */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.41 2005/10/18 01:06:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.42 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,8 +53,8 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
|
|||||||
/* if we're here, _hash_step found a valid tuple */
|
/* if we're here, _hash_step found a valid tuple */
|
||||||
current = &(scan->currentItemData);
|
current = &(scan->currentItemData);
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
|
hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
|
||||||
itup = &hitem->hash_itup;
|
itup = &hitem->hash_itup;
|
||||||
scan->xs_ctup.t_self = itup->t_tid;
|
scan->xs_ctup.t_self = itup->t_tid;
|
||||||
@ -77,8 +77,8 @@ _hash_readnext(Relation rel,
|
|||||||
if (BlockNumberIsValid(blkno))
|
if (BlockNumberIsValid(blkno))
|
||||||
{
|
{
|
||||||
*bufp = _hash_getbuf(rel, blkno, HASH_READ);
|
*bufp = _hash_getbuf(rel, blkno, HASH_READ);
|
||||||
|
_hash_checkpage(rel, *bufp, LH_OVERFLOW_PAGE);
|
||||||
*pagep = BufferGetPage(*bufp);
|
*pagep = BufferGetPage(*bufp);
|
||||||
_hash_checkpage(rel, *pagep, LH_OVERFLOW_PAGE);
|
|
||||||
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
|
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,8 +98,8 @@ _hash_readprev(Relation rel,
|
|||||||
if (BlockNumberIsValid(blkno))
|
if (BlockNumberIsValid(blkno))
|
||||||
{
|
{
|
||||||
*bufp = _hash_getbuf(rel, blkno, HASH_READ);
|
*bufp = _hash_getbuf(rel, blkno, HASH_READ);
|
||||||
|
_hash_checkpage(rel, *bufp, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
*pagep = BufferGetPage(*bufp);
|
*pagep = BufferGetPage(*bufp);
|
||||||
_hash_checkpage(rel, *pagep, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
|
*opaquep = (HashPageOpaque) PageGetSpecialPointer(*pagep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,8 +168,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/* Read the metapage */
|
/* Read the metapage */
|
||||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ);
|
||||||
|
_hash_checkpage(rel, metabuf, LH_META_PAGE);
|
||||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||||
_hash_checkpage(rel, (Page) metap, LH_META_PAGE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the target bucket number, and convert to block number.
|
* Compute the target bucket number, and convert to block number.
|
||||||
@ -198,8 +198,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/* Fetch the primary bucket page for the bucket */
|
/* Fetch the primary bucket page for the bucket */
|
||||||
buf = _hash_getbuf(rel, blkno, HASH_READ);
|
buf = _hash_getbuf(rel, blkno, HASH_READ);
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE);
|
|
||||||
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
Assert(opaque->hasho_bucket == bucket);
|
Assert(opaque->hasho_bucket == bucket);
|
||||||
|
|
||||||
@ -216,8 +216,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/* if we're here, _hash_step found a valid tuple */
|
/* if we're here, _hash_step found a valid tuple */
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
|
hitem = (HashItem) PageGetItem(page, PageGetItemId(page, offnum));
|
||||||
itup = &hitem->hash_itup;
|
itup = &hitem->hash_itup;
|
||||||
scan->xs_ctup.t_self = itup->t_tid;
|
scan->xs_ctup.t_self = itup->t_tid;
|
||||||
@ -254,8 +254,8 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
|||||||
current = &(scan->currentItemData);
|
current = &(scan->currentItemData);
|
||||||
|
|
||||||
buf = *bufP;
|
buf = *bufP;
|
||||||
|
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
_hash_checkpage(rel, page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
|
||||||
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.42 2005/05/11 01:26:01 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.43 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -110,12 +110,50 @@ _hash_log2(uint32 num)
|
|||||||
* _hash_checkpage -- sanity checks on the format of all hash pages
|
* _hash_checkpage -- sanity checks on the format of all hash pages
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_hash_checkpage(Relation rel, Page page, int flags)
|
_hash_checkpage(Relation rel, Buffer buf, int flags)
|
||||||
{
|
{
|
||||||
Assert(page);
|
Page page = BufferGetPage(buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When checking the metapage, always verify magic number and version.
|
* ReadBuffer verifies that every newly-read page passes PageHeaderIsValid,
|
||||||
|
* which means it either contains a reasonably sane page header or is
|
||||||
|
* all-zero. We have to defend against the all-zero case, however.
|
||||||
|
*/
|
||||||
|
if (PageIsNew(page))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
|
errmsg("index \"%s\" contains unexpected zero page at block %u",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
BufferGetBlockNumber(buf)),
|
||||||
|
errhint("Please REINDEX it.")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additionally check that the special area looks sane.
|
||||||
|
*/
|
||||||
|
if (((PageHeader) (page))->pd_special !=
|
||||||
|
(BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
|
errmsg("index \"%s\" contains corrupted page at block %u",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
BufferGetBlockNumber(buf)),
|
||||||
|
errhint("Please REINDEX it.")));
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
{
|
||||||
|
HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
|
if ((opaque->hasho_flag & flags) == 0)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
|
errmsg("index \"%s\" contains corrupted page at block %u",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
BufferGetBlockNumber(buf)),
|
||||||
|
errhint("Please REINDEX it.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When checking the metapage, also verify magic number and version.
|
||||||
*/
|
*/
|
||||||
if (flags == LH_META_PAGE)
|
if (flags == LH_META_PAGE)
|
||||||
{
|
{
|
||||||
@ -130,25 +168,8 @@ _hash_checkpage(Relation rel, Page page, int flags)
|
|||||||
if (metap->hashm_version != HASH_VERSION)
|
if (metap->hashm_version != HASH_VERSION)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INDEX_CORRUPTED),
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
errmsg("index \"%s\" has wrong hash version", RelationGetRelationName(rel)),
|
errmsg("index \"%s\" has wrong hash version",
|
||||||
|
RelationGetRelationName(rel)),
|
||||||
errhint("Please REINDEX it.")));
|
errhint("Please REINDEX it.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* These other checks are for debugging purposes only.
|
|
||||||
*/
|
|
||||||
#ifdef USE_ASSERT_CHECKING
|
|
||||||
Assert(((PageHeader) (page))->pd_lower >= SizeOfPageHeaderData);
|
|
||||||
Assert(((PageHeader) (page))->pd_upper <=
|
|
||||||
(BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))));
|
|
||||||
Assert(((PageHeader) (page))->pd_special ==
|
|
||||||
(BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData))));
|
|
||||||
Assert(PageGetPageSize(page) == BLCKSZ);
|
|
||||||
if (flags)
|
|
||||||
{
|
|
||||||
HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page);
|
|
||||||
|
|
||||||
Assert(opaque->hasho_flag & flags);
|
|
||||||
}
|
|
||||||
#endif /* USE_ASSERT_CHECKING */
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.127 2005/10/15 02:49:09 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.128 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -672,7 +672,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
|
|||||||
rightpage = BufferGetPage(rbuf);
|
rightpage = BufferGetPage(rbuf);
|
||||||
|
|
||||||
_bt_pageinit(leftpage, BufferGetPageSize(buf));
|
_bt_pageinit(leftpage, BufferGetPageSize(buf));
|
||||||
_bt_pageinit(rightpage, BufferGetPageSize(rbuf));
|
/* rightpage was already initialized by _bt_getbuf */
|
||||||
|
|
||||||
/* init btree private data */
|
/* init btree private data */
|
||||||
oopaque = (BTPageOpaque) PageGetSpecialPointer(origpage);
|
oopaque = (BTPageOpaque) PageGetSpecialPointer(origpage);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.88 2005/10/15 02:49:09 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.89 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||||
@ -222,8 +222,6 @@ _bt_getroot(Relation rel, int access)
|
|||||||
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
|
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
|
||||||
rootblkno = BufferGetBlockNumber(rootbuf);
|
rootblkno = BufferGetBlockNumber(rootbuf);
|
||||||
rootpage = BufferGetPage(rootbuf);
|
rootpage = BufferGetPage(rootbuf);
|
||||||
|
|
||||||
_bt_pageinit(rootpage, BufferGetPageSize(rootbuf));
|
|
||||||
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
||||||
rootopaque->btpo_prev = rootopaque->btpo_next = P_NONE;
|
rootopaque->btpo_prev = rootopaque->btpo_next = P_NONE;
|
||||||
rootopaque->btpo_flags = (BTP_LEAF | BTP_ROOT);
|
rootopaque->btpo_flags = (BTP_LEAF | BTP_ROOT);
|
||||||
@ -405,14 +403,50 @@ _bt_gettrueroot(Relation rel)
|
|||||||
return rootbuf;
|
return rootbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _bt_checkpage() -- Verify that a freshly-read page looks sane.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_bt_checkpage(Relation rel, Buffer buf)
|
||||||
|
{
|
||||||
|
Page page = BufferGetPage(buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ReadBuffer verifies that every newly-read page passes PageHeaderIsValid,
|
||||||
|
* which means it either contains a reasonably sane page header or is
|
||||||
|
* all-zero. We have to defend against the all-zero case, however.
|
||||||
|
*/
|
||||||
|
if (PageIsNew(page))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
|
errmsg("index \"%s\" contains unexpected zero page at block %u",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
BufferGetBlockNumber(buf)),
|
||||||
|
errhint("Please REINDEX it.")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additionally check that the special area looks sane.
|
||||||
|
*/
|
||||||
|
if (((PageHeader) (page))->pd_special !=
|
||||||
|
(BLCKSZ - MAXALIGN(sizeof(BTPageOpaqueData))))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||||
|
errmsg("index \"%s\" contains corrupted page at block %u",
|
||||||
|
RelationGetRelationName(rel),
|
||||||
|
BufferGetBlockNumber(buf)),
|
||||||
|
errhint("Please REINDEX it.")));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _bt_getbuf() -- Get a buffer by block number for read or write.
|
* _bt_getbuf() -- Get a buffer by block number for read or write.
|
||||||
*
|
*
|
||||||
* blkno == P_NEW means to get an unallocated index page.
|
* blkno == P_NEW means to get an unallocated index page. The page
|
||||||
|
* will be initialized before returning it.
|
||||||
*
|
*
|
||||||
* When this routine returns, the appropriate lock is set on the
|
* When this routine returns, the appropriate lock is set on the
|
||||||
* requested buffer and its reference count has been incremented
|
* requested buffer and its reference count has been incremented
|
||||||
* (ie, the buffer is "locked and pinned").
|
* (ie, the buffer is "locked and pinned"). Also, we apply
|
||||||
|
* _bt_checkpage to sanity-check the page (except in P_NEW case).
|
||||||
*/
|
*/
|
||||||
Buffer
|
Buffer
|
||||||
_bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
_bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||||
@ -424,6 +458,7 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
|||||||
/* Read an existing block of the relation */
|
/* Read an existing block of the relation */
|
||||||
buf = ReadBuffer(rel, blkno);
|
buf = ReadBuffer(rel, blkno);
|
||||||
LockBuffer(buf, access);
|
LockBuffer(buf, access);
|
||||||
|
_bt_checkpage(rel, buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -538,6 +573,7 @@ _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
|
|||||||
LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
|
||||||
buf = ReleaseAndReadBuffer(obuf, rel, blkno);
|
buf = ReleaseAndReadBuffer(obuf, rel, blkno);
|
||||||
LockBuffer(buf, access);
|
LockBuffer(buf, access);
|
||||||
|
_bt_checkpage(rel, buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.132 2005/10/15 02:49:09 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.133 2005/11/06 19:29:00 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -734,8 +734,8 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
* buffer and it will be fully initialized before we can examine it. (See
|
* buffer and it will be fully initialized before we can examine it. (See
|
||||||
* also vacuumlazy.c, which has the same issue.)
|
* also vacuumlazy.c, which has the same issue.)
|
||||||
*
|
*
|
||||||
* We can skip locking for new or temp relations, however, since no one else
|
* We can skip locking for new or temp relations, however, since no one
|
||||||
* could be accessing them.
|
* else could be accessing them.
|
||||||
*/
|
*/
|
||||||
needLock = !RELATION_IS_LOCAL(rel);
|
needLock = !RELATION_IS_LOCAL(rel);
|
||||||
|
|
||||||
@ -772,9 +772,17 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
Page page;
|
Page page;
|
||||||
BTPageOpaque opaque;
|
BTPageOpaque opaque;
|
||||||
|
|
||||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
/*
|
||||||
|
* We can't use _bt_getbuf() here because it always applies
|
||||||
|
* _bt_checkpage(), which will barf on an all-zero page.
|
||||||
|
* We want to recycle all-zero pages, not fail.
|
||||||
|
*/
|
||||||
|
buf = ReadBuffer(rel, blkno);
|
||||||
|
LockBuffer(buf, BT_READ);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
if (!PageIsNew(page))
|
||||||
|
_bt_checkpage(rel, buf);
|
||||||
if (_bt_page_recyclable(page))
|
if (_bt_page_recyclable(page))
|
||||||
{
|
{
|
||||||
/* Okay to recycle this page */
|
/* Okay to recycle this page */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.63 2005/10/15 02:49:42 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.64 2005/11/06 19:29:01 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* modeled after Margo Seltzer's hash implementation for unix.
|
* modeled after Margo Seltzer's hash implementation for unix.
|
||||||
@ -310,7 +310,7 @@ extern uint32 _hash_datum2hashkey(Relation rel, Datum key);
|
|||||||
extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
|
extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
|
||||||
uint32 highmask, uint32 lowmask);
|
uint32 highmask, uint32 lowmask);
|
||||||
extern uint32 _hash_log2(uint32 num);
|
extern uint32 _hash_log2(uint32 num);
|
||||||
extern void _hash_checkpage(Relation rel, Page page, int flags);
|
extern void _hash_checkpage(Relation rel, Buffer buf, int flags);
|
||||||
|
|
||||||
/* hash.c */
|
/* hash.c */
|
||||||
extern void hash_redo(XLogRecPtr lsn, XLogRecord *record);
|
extern void hash_redo(XLogRecPtr lsn, XLogRecord *record);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.87 2005/10/15 02:49:42 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.88 2005/11/06 19:29:01 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -429,6 +429,7 @@ extern void _bt_metapinit(Relation rel);
|
|||||||
extern void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level);
|
extern void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level);
|
||||||
extern Buffer _bt_getroot(Relation rel, int access);
|
extern Buffer _bt_getroot(Relation rel, int access);
|
||||||
extern Buffer _bt_gettrueroot(Relation rel);
|
extern Buffer _bt_gettrueroot(Relation rel);
|
||||||
|
extern void _bt_checkpage(Relation rel, Buffer buf);
|
||||||
extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
|
extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
|
||||||
extern Buffer _bt_relandgetbuf(Relation rel, Buffer obuf,
|
extern Buffer _bt_relandgetbuf(Relation rel, Buffer obuf,
|
||||||
BlockNumber blkno, int access);
|
BlockNumber blkno, int access);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user