Skip to content

Commit 2040bb4

Browse files
committed
Clean up manipulations of hash indexes' hasho_flag field.
Standardize on testing a hash index page's type by doing (opaque->hasho_flag & LH_PAGE_TYPE) == LH_xxx_PAGE Various places were taking shortcuts like opaque->hasho_flag & LH_BUCKET_PAGE which while not actually wrong, is still bad practice because it encourages use of opaque->hasho_flag & LH_UNUSED_PAGE which *is* wrong (LH_UNUSED_PAGE == 0, so the above is constant false). hash_xlog.c's hash_mask() contained such an incorrect test. This also ensures that we mask out the additional flag bits that hasho_flag has accreted since 9.6. pgstattuple's pgstat_hash_page(), for one, was failing to do that and was thus actively broken. Also fix assorted comments that hadn't been updated to reflect the extended usage of hasho_flag, and fix some macros that were testing just "(hasho_flag & bit)" to use the less dangerous, project-approved form "((hasho_flag & bit) != 0)". Coverity found the bug in hash_mask(); I noted the one in pgstat_hash_page() through code reading.
1 parent 1dffabe commit 2040bb4

File tree

6 files changed

+29
-25
lines changed

6 files changed

+29
-25
lines changed

contrib/pageinspect/hashfuncs.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ hash_page_type(PG_FUNCTION_ARGS)
184184
bytea *raw_page = PG_GETARG_BYTEA_P(0);
185185
Page page;
186186
HashPageOpaque opaque;
187-
char *type;
187+
int pagetype;
188+
const char *type;
188189

189190
if (!superuser())
190191
ereport(ERROR,
@@ -200,13 +201,14 @@ hash_page_type(PG_FUNCTION_ARGS)
200201
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
201202

202203
/* page type (flags) */
203-
if (opaque->hasho_flag & LH_META_PAGE)
204+
pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
205+
if (pagetype == LH_META_PAGE)
204206
type = "metapage";
205-
else if (opaque->hasho_flag & LH_OVERFLOW_PAGE)
207+
else if (pagetype == LH_OVERFLOW_PAGE)
206208
type = "overflow";
207-
else if (opaque->hasho_flag & LH_BUCKET_PAGE)
209+
else if (pagetype == LH_BUCKET_PAGE)
208210
type = "bucket";
209-
else if (opaque->hasho_flag & LH_BITMAP_PAGE)
211+
else if (pagetype == LH_BITMAP_PAGE)
210212
type = "bitmap";
211213
else
212214
type = "unused";

contrib/pgstattuple/pgstattuple.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ pgstat_hash_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno,
453453
HashPageOpaque opaque;
454454

455455
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
456-
switch (opaque->hasho_flag)
456+
switch (opaque->hasho_flag & LH_PAGE_TYPE)
457457
{
458458
case LH_UNUSED_PAGE:
459459
stat->free_space += BLCKSZ;

src/backend/access/hash/hash_xlog.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,7 @@ hash_mask(char *pagedata, BlockNumber blkno)
12341234
{
12351235
Page page = (Page) pagedata;
12361236
HashPageOpaque opaque;
1237+
int pagetype;
12371238

12381239
mask_page_lsn(page);
12391240

@@ -1242,15 +1243,16 @@ hash_mask(char *pagedata, BlockNumber blkno)
12421243

12431244
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
12441245

1245-
if (opaque->hasho_flag & LH_UNUSED_PAGE)
1246+
pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
1247+
if (pagetype == LH_UNUSED_PAGE)
12461248
{
12471249
/*
12481250
* Mask everything on a UNUSED page.
12491251
*/
12501252
mask_page_content(page);
12511253
}
1252-
else if ((opaque->hasho_flag & LH_BUCKET_PAGE) ||
1253-
(opaque->hasho_flag & LH_OVERFLOW_PAGE))
1254+
else if (pagetype == LH_BUCKET_PAGE ||
1255+
pagetype == LH_OVERFLOW_PAGE)
12541256
{
12551257
/*
12561258
* In hash bucket and overflow pages, it is possible to modify the

src/backend/access/hash/hashovfl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin)
168168
if (retain_pin)
169169
{
170170
/* pin will be retained only for the primary bucket page */
171-
Assert(pageopaque->hasho_flag & LH_BUCKET_PAGE);
171+
Assert((pageopaque->hasho_flag & LH_PAGE_TYPE) == LH_BUCKET_PAGE);
172172
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
173173
}
174174
else

src/backend/access/hash/hashutil.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ _hash_get_totalbuckets(uint32 splitpoint_phase)
218218
/*
219219
* _hash_checkpage -- sanity checks on the format of all hash pages
220220
*
221-
* If flags is not zero, it is a bitwise OR of the acceptable values of
222-
* hasho_flag.
221+
* If flags is not zero, it is a bitwise OR of the acceptable page types
222+
* (values of hasho_flag & LH_PAGE_TYPE).
223223
*/
224224
void
225225
_hash_checkpage(Relation rel, Buffer buf, int flags)

src/include/access/hash.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ typedef uint32 Bucket;
4141
/*
4242
* Special space for hash index pages.
4343
*
44-
* hasho_flag tells us which type of page we're looking at. For
45-
* example, knowing overflow pages from bucket pages is necessary
46-
* information when you're deleting tuples from a page. If all the
47-
* tuples are deleted from an overflow page, the overflow is made
48-
* available to other buckets by calling _hash_freeovflpage(). If all
49-
* the tuples are deleted from a bucket page, no additional action is
50-
* necessary.
44+
* hasho_flag's LH_PAGE_TYPE bits tell us which type of page we're looking at.
45+
* Additional bits in the flag word are used for more transient purposes.
46+
*
47+
* To test a page's type, do (hasho_flag & LH_PAGE_TYPE) == LH_xxx_PAGE.
48+
* However, we ensure that each used page type has a distinct bit so that
49+
* we can OR together page types for uses such as the allowable-page-types
50+
* argument of _hash_checkpage().
5151
*/
5252
#define LH_UNUSED_PAGE (0)
5353
#define LH_OVERFLOW_PAGE (1 << 0)
@@ -60,7 +60,7 @@ typedef uint32 Bucket;
6060
#define LH_PAGE_HAS_DEAD_TUPLES (1 << 7)
6161

6262
#define LH_PAGE_TYPE \
63-
(LH_OVERFLOW_PAGE|LH_BUCKET_PAGE|LH_BITMAP_PAGE|LH_META_PAGE)
63+
(LH_OVERFLOW_PAGE | LH_BUCKET_PAGE | LH_BITMAP_PAGE | LH_META_PAGE)
6464

6565
/*
6666
* In an overflow page, hasho_prevblkno stores the block number of the previous
@@ -78,16 +78,16 @@ typedef struct HashPageOpaqueData
7878
BlockNumber hasho_prevblkno; /* see above */
7979
BlockNumber hasho_nextblkno; /* see above */
8080
Bucket hasho_bucket; /* bucket number this pg belongs to */
81-
uint16 hasho_flag; /* page type code, see above */
81+
uint16 hasho_flag; /* page type code + flag bits, see above */
8282
uint16 hasho_page_id; /* for identification of hash indexes */
8383
} HashPageOpaqueData;
8484

8585
typedef HashPageOpaqueData *HashPageOpaque;
8686

87-
#define H_NEEDS_SPLIT_CLEANUP(opaque) ((opaque)->hasho_flag & LH_BUCKET_NEEDS_SPLIT_CLEANUP)
88-
#define H_BUCKET_BEING_SPLIT(opaque) ((opaque)->hasho_flag & LH_BUCKET_BEING_SPLIT)
89-
#define H_BUCKET_BEING_POPULATED(opaque) ((opaque)->hasho_flag & LH_BUCKET_BEING_POPULATED)
90-
#define H_HAS_DEAD_TUPLES(opaque) ((opaque)->hasho_flag & LH_PAGE_HAS_DEAD_TUPLES)
87+
#define H_NEEDS_SPLIT_CLEANUP(opaque) (((opaque)->hasho_flag & LH_BUCKET_NEEDS_SPLIT_CLEANUP) != 0)
88+
#define H_BUCKET_BEING_SPLIT(opaque) (((opaque)->hasho_flag & LH_BUCKET_BEING_SPLIT) != 0)
89+
#define H_BUCKET_BEING_POPULATED(opaque) (((opaque)->hasho_flag & LH_BUCKET_BEING_POPULATED) != 0)
90+
#define H_HAS_DEAD_TUPLES(opaque) (((opaque)->hasho_flag & LH_PAGE_HAS_DEAD_TUPLES) != 0)
9191

9292
/*
9393
* The page ID is for the convenience of pg_filedump and similar utilities,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy