simplify_hash_bitmap_info_v2.patch
application/x-download
Filename: simplify_hash_bitmap_info_v2.patch
Type: application/x-download
Part: 0
Message:
Re: pageinspect: Hash index support
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| contrib/pageinspect/expected/hash.out | 10 | 12 |
| contrib/pageinspect/hashfuncs.c | 51 | 23 |
| src/backend/access/hash/hashovfl.c | 3 | 5 |
| src/include/access/hash.h | 0 | 1 |
diff --git a/contrib/pageinspect/expected/hash.out b/contrib/pageinspect/expected/hash.out
index 7eb1537..fb0caee 100644
--- a/contrib/pageinspect/expected/hash.out
+++ b/contrib/pageinspect/expected/hash.out
@@ -30,23 +30,21 @@ hash_page_type | bitmap
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 6));
ERROR: block number 6 is out of range for relation "test_hash_a_idx"
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 0);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000008.
+ERROR: invalid overflow block number 0
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 1);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000002.
+ERROR: invalid overflow block number 1
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 2);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000002.
+ERROR: invalid overflow block number 2
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 3);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000002.
+ERROR: invalid overflow block number 3
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 4);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000002.
+ERROR: invalid overflow block number 4
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 5);
-ERROR: page is not an overflow page
-DETAIL: Expected 00000001, got 00000004.
+-[ RECORD 1 ]--
+bitmapblkno | 5
+bitmapbit | 0
+bitstatus | t
+
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
hash_metapage_info(get_raw_page('test_hash_a_idx', 0));
diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c
index 08663c1..af25506 100644
--- a/contrib/pageinspect/hashfuncs.c
+++ b/contrib/pageinspect/hashfuncs.c
@@ -170,6 +170,45 @@ GetHashPageStatistics(Page page, HashPageStat * stat)
stat->free_size = PageGetFreeSpace(page);
}
+/*
+ * _hash_ovflblkno_to_bitno
+ *
+ * Convert overflow page block number to bit number for free-page bitmap.
+ * We already have similar function defined in hashovfl.c but which does
+ * return value for some of the bucket pages along with overflow and bit-
+ * map pages and it is seems to be buggy to me. This function has been
+ * designed such that it only returns the value for overflow and bitmap
+ * pages.
+ */
+static uint32
+_hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
+{
+ uint32 splitnum = metap->hashm_ovflpoint;
+ uint32 i;
+ uint32 bitnum;
+
+ /* Determine the split number containing this page */
+ for (i = 1; i <= splitnum; i++)
+ {
+ if (ovflblkno <= (BlockNumber) (1 << i))
+ break; /* oops */
+ bitnum = ovflblkno - (1 << i);
+ /*
+ * bitnum has to be greater than number of overflow
+ * page added in previous split point. The overflow
+ * page at this splitnum (i) if any should start from
+ * ((2 ^ i) + metap->hashm_spares[i -1] + 1).
+ */
+ if (bitnum > metap->hashm_spares[i -1] &&
+ bitnum <= metap->hashm_spares[i])
+ return bitnum - 1; /* -1 to convert 1-based to 0-based */
+ }
+
+ elog(ERROR, "invalid overflow block number %u", ovflblkno);
+ return 0; /* keep compiler quiet */
+}
+
+
/* ---------------------------------------------------
* hash_page_type()
*
@@ -380,12 +419,11 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
Oid indexRelid = PG_GETARG_OID(0);
uint64 ovflblkno = PG_GETARG_INT64(1);
HashMetaPage metap;
- Buffer buf,
- metabuf;
+ Buffer metabuf,
+ mapbuf;
BlockNumber bitmapblkno;
- Page page;
+ Page mappage;
bool bit = false;
- HashPageOpaque opaque;
TupleDesc tupleDesc;
Relation indexRel;
uint32 ovflbitno;
@@ -395,6 +433,7 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
int j;
Datum values[3];
bool nulls[3];
+ uint32 *freep = NULL;
if (!superuser())
ereport(ERROR,
@@ -418,25 +457,6 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
errmsg("block number " UINT64_FORMAT " is out of range for relation \"%s\"",
ovflblkno, RelationGetRelationName(indexRel))));
- buf = ReadBufferExtended(indexRel, MAIN_FORKNUM, (BlockNumber) ovflblkno,
- RBM_NORMAL, NULL);
- LockBuffer(buf, BUFFER_LOCK_SHARE);
- _hash_checkpage(indexRel, buf, LH_PAGE_TYPE);
- page = BufferGetPage(buf);
- opaque = (HashPageOpaque) PageGetSpecialPointer(page);
-
- if (opaque->hasho_flag != LH_OVERFLOW_PAGE)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("page is not an overflow page"),
- errdetail("Expected %08x, got %08x.",
- LH_OVERFLOW_PAGE, opaque->hasho_flag)));
-
- if (BlockNumberIsValid(opaque->hasho_prevblkno))
- bit = true;
-
- UnlockReleaseBuffer(buf);
-
/* Read the metapage so we can determine which bitmap page to use */
metabuf = _hash_getbuf(indexRel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
metap = HashPageGetMeta(BufferGetPage(metabuf));
@@ -456,6 +476,14 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
_hash_relbuf(indexRel, metabuf);
+ /* Check the status of bitmap bit for overflow page */
+ mapbuf = _hash_getbuf(indexRel, bitmapblkno, HASH_READ, LH_BITMAP_PAGE);
+ mappage = BufferGetPage(mapbuf);
+ freep = HashPageGetBitmap(mappage);
+
+ bit = ISSET(freep, bitmapbit) != 0;
+
+ _hash_relbuf(indexRel, mapbuf);
index_close(indexRel, AccessShareLock);
/* Build a tuple descriptor for our result type */
diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c
index 753c8a6..e8928ef 100644
--- a/src/backend/access/hash/hashovfl.c
+++ b/src/backend/access/hash/hashovfl.c
@@ -52,12 +52,10 @@ bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
}
/*
- * _hash_ovflblkno_to_bitno
- *
* Convert overflow page block number to bit number for free-page bitmap.
*/
-uint32
-_hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
+static uint32
+blkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
{
uint32 splitnum = metap->hashm_ovflpoint;
uint32 i;
@@ -487,7 +485,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf, Buffer wbuf,
metap = HashPageGetMeta(BufferGetPage(metabuf));
/* Identify which bit to set */
- ovflbitno = _hash_ovflblkno_to_bitno(metap, ovflblkno);
+ ovflbitno = blkno_to_bitno(metap, ovflblkno);
bitmappage = ovflbitno >> BMPG_SHIFT(metap);
bitmapbit = ovflbitno & BMPG_MASK(metap);
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index c045585..acbe0ea 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -313,7 +313,6 @@ extern void _hash_squeezebucket(Relation rel,
Bucket bucket, BlockNumber bucket_blkno,
Buffer bucket_buf,
BufferAccessStrategy bstrategy);
-extern uint32 _hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno);
/* hashpage.c */
extern Buffer _hash_getbuf(Relation rel, BlockNumber blkno,