PostgreSQL Source Code  git master
hash.h File Reference
#include "access/amapi.h"
#include "access/itup.h"
#include "access/sdir.h"
#include "fmgr.h"
#include "lib/stringinfo.h"
#include "storage/bufmgr.h"
#include "storage/lockdefs.h"
#include "utils/hsearch.h"
#include "utils/relcache.h"
Include dependency graph for hash.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HashPageOpaqueData
 
struct  HashScanPosItem
 
struct  HashScanPosData
 
struct  HashScanOpaqueData
 
struct  HashMetaPageData
 

Macros

#define InvalidBucket   ((Bucket) 0xFFFFFFFF)
 
#define BUCKET_TO_BLKNO(metap, B)   ((BlockNumber) ((B) + ((B) ? (metap)->hashm_spares[_hash_spareindex((B)+1)-1] : 0)) + 1)
 
#define ROTATE_HIGH_AND_LOW_32BITS(v)
 
#define LH_UNUSED_PAGE   (0)
 
#define LH_OVERFLOW_PAGE   (1 << 0)
 
#define LH_BUCKET_PAGE   (1 << 1)
 
#define LH_BITMAP_PAGE   (1 << 2)
 
#define LH_META_PAGE   (1 << 3)
 
#define LH_BUCKET_BEING_POPULATED   (1 << 4)
 
#define LH_BUCKET_BEING_SPLIT   (1 << 5)
 
#define LH_BUCKET_NEEDS_SPLIT_CLEANUP   (1 << 6)
 
#define LH_PAGE_HAS_DEAD_TUPLES   (1 << 7)
 
#define LH_PAGE_TYPE   (LH_OVERFLOW_PAGE | LH_BUCKET_PAGE | LH_BITMAP_PAGE | LH_META_PAGE)
 
#define H_NEEDS_SPLIT_CLEANUP(opaque)   (((opaque)->hasho_flag & LH_BUCKET_NEEDS_SPLIT_CLEANUP) != 0)
 
#define H_BUCKET_BEING_SPLIT(opaque)   (((opaque)->hasho_flag & LH_BUCKET_BEING_SPLIT) != 0)
 
#define H_BUCKET_BEING_POPULATED(opaque)   (((opaque)->hasho_flag & LH_BUCKET_BEING_POPULATED) != 0)
 
#define H_HAS_DEAD_TUPLES(opaque)   (((opaque)->hasho_flag & LH_PAGE_HAS_DEAD_TUPLES) != 0)
 
#define HASHO_PAGE_ID   0xFF80
 
#define HashScanPosIsPinned(scanpos)
 
#define HashScanPosIsValid(scanpos)
 
#define HashScanPosInvalidate(scanpos)
 
#define HASH_METAPAGE   0 /* metapage is always block 0 */
 
#define HASH_MAGIC   0x6440640
 
#define HASH_VERSION   4
 
#define HASH_MAX_BITMAPS   1024
 
#define HASH_SPLITPOINT_PHASE_BITS   2
 
#define HASH_SPLITPOINT_PHASES_PER_GRP   (1 << HASH_SPLITPOINT_PHASE_BITS)
 
#define HASH_SPLITPOINT_PHASE_MASK   (HASH_SPLITPOINT_PHASES_PER_GRP - 1)
 
#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE   10
 
#define HASH_MAX_SPLITPOINT_GROUP   32
 
#define HASH_MAX_SPLITPOINTS
 
#define HashMaxItemSize(page)
 
#define INDEX_MOVED_BY_SPLIT_MASK   0x2000
 
#define HASH_MIN_FILLFACTOR   10
 
#define HASH_DEFAULT_FILLFACTOR   75
 
#define BYTE_TO_BIT   3 /* 2^3 bits/byte */
 
#define ALL_SET   ((uint32) ~0)
 
#define BMPGSZ_BYTE(metap)   ((metap)->hashm_bmsize)
 
#define BMPGSZ_BIT(metap)   ((metap)->hashm_bmsize << BYTE_TO_BIT)
 
#define BMPG_SHIFT(metap)   ((metap)->hashm_bmshift)
 
#define BMPG_MASK(metap)   (BMPGSZ_BIT(metap) - 1)
 
#define HashPageGetBitmap(page)   ((uint32 *) PageGetContents(page))
 
#define HashGetMaxBitmapSize(page)
 
#define HashPageGetMeta(page)   ((HashMetaPage) PageGetContents(page))
 
#define BITS_PER_MAP   32 /* Number of bits in uint32 */
 
#define CLRBIT(A, N)   ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
 
#define SETBIT(A, N)   ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
 
#define ISSET(A, N)   ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
 
#define HASH_READ   BUFFER_LOCK_SHARE
 
#define HASH_WRITE   BUFFER_LOCK_EXCLUSIVE
 
#define HASH_NOLOCK   (-1)
 
#define HTEqualStrategyNumber   1
 
#define HTMaxStrategyNumber   1
 
#define HASHSTANDARD_PROC   1
 
#define HASHEXTENDED_PROC   2
 
#define HASHNProcs   2
 

Typedefs

typedef uint32 Bucket
 
typedef struct HashPageOpaqueData HashPageOpaqueData
 
typedef HashPageOpaqueDataHashPageOpaque
 
typedef struct HashScanPosItem HashScanPosItem
 
typedef struct HashScanPosData HashScanPosData
 
typedef struct HashScanOpaqueData HashScanOpaqueData
 
typedef HashScanOpaqueDataHashScanOpaque
 
typedef struct HashMetaPageData HashMetaPageData
 
typedef HashMetaPageDataHashMetaPage
 
typedef struct HSpool HSpool
 

Functions

IndexBuildResulthashbuild (Relation heap, Relation index, struct IndexInfo *indexInfo)
 
void hashbuildempty (Relation index)
 
bool hashinsert (Relation rel, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, struct IndexInfo *indexInfo)
 
bool hashgettuple (IndexScanDesc scan, ScanDirection dir)
 
int64 hashgetbitmap (IndexScanDesc scan, TIDBitmap *tbm)
 
IndexScanDesc hashbeginscan (Relation rel, int nkeys, int norderbys)
 
void hashrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
void hashendscan (IndexScanDesc scan)
 
IndexBulkDeleteResulthashbulkdelete (IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
 
IndexBulkDeleteResulthashvacuumcleanup (IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 
byteahashoptions (Datum reloptions, bool validate)
 
bool hashvalidate (Oid opclassoid)
 
Datum hash_any (register const unsigned char *k, register int keylen)
 
Datum hash_any_extended (register const unsigned char *k, register int keylen, uint64 seed)
 
Datum hash_uint32 (uint32 k)
 
Datum hash_uint32_extended (uint32 k, uint64 seed)
 
void _hash_doinsert (Relation rel, IndexTuple itup, Relation heapRel)
 
OffsetNumber _hash_pgaddtup (Relation rel, Buffer buf, Size itemsize, IndexTuple itup)
 
void _hash_pgaddmultitup (Relation rel, Buffer buf, IndexTuple *itups, OffsetNumber *itup_offsets, uint16 nitups)
 
Buffer _hash_addovflpage (Relation rel, Buffer metabuf, Buffer buf, bool retain_pin)
 
BlockNumber _hash_freeovflpage (Relation rel, Buffer bucketbuf, Buffer ovflbuf, Buffer wbuf, IndexTuple *itups, OffsetNumber *itup_offsets, Size *tups_size, uint16 nitups, BufferAccessStrategy bstrategy)
 
void _hash_initbitmapbuffer (Buffer buf, uint16 bmsize, bool initpage)
 
void _hash_squeezebucket (Relation rel, Bucket bucket, BlockNumber bucket_blkno, Buffer bucket_buf, BufferAccessStrategy bstrategy)
 
uint32 _hash_ovflblkno_to_bitno (HashMetaPage metap, BlockNumber ovflblkno)
 
Buffer _hash_getbuf (Relation rel, BlockNumber blkno, int access, int flags)
 
Buffer _hash_getbuf_with_condlock_cleanup (Relation rel, BlockNumber blkno, int flags)
 
HashMetaPage _hash_getcachedmetap (Relation rel, Buffer *metabuf, bool force_refresh)
 
Buffer _hash_getbucketbuf_from_hashkey (Relation rel, uint32 hashkey, int access, HashMetaPage *cachedmetap)
 
Buffer _hash_getinitbuf (Relation rel, BlockNumber blkno)
 
void _hash_initbuf (Buffer buf, uint32 max_bucket, uint32 num_bucket, uint32 flag, bool initpage)
 
Buffer _hash_getnewbuf (Relation rel, BlockNumber blkno, ForkNumber forkNum)
 
Buffer _hash_getbuf_with_strategy (Relation rel, BlockNumber blkno, int access, int flags, BufferAccessStrategy bstrategy)
 
void _hash_relbuf (Relation rel, Buffer buf)
 
void _hash_dropbuf (Relation rel, Buffer buf)
 
void _hash_dropscanbuf (Relation rel, HashScanOpaque so)
 
uint32 _hash_init (Relation rel, double num_tuples, ForkNumber forkNum)
 
void _hash_init_metabuffer (Buffer buf, double num_tuples, RegProcedure procid, uint16 ffactor, bool initpage)
 
void _hash_pageinit (Page page, Size size)
 
void _hash_expandtable (Relation rel, Buffer metabuf)
 
void _hash_finish_split (Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, uint32 maxbucket, uint32 highmask, uint32 lowmask)
 
bool _hash_next (IndexScanDesc scan, ScanDirection dir)
 
bool _hash_first (IndexScanDesc scan, ScanDirection dir)
 
HSpool_h_spoolinit (Relation heap, Relation index, uint32 num_buckets)
 
void _h_spooldestroy (HSpool *hspool)
 
void _h_spool (HSpool *hspool, ItemPointer self, Datum *values, bool *isnull)
 
void _h_indexbuild (HSpool *hspool, Relation heapRel)
 
bool _hash_checkqual (IndexScanDesc scan, IndexTuple itup)
 
uint32 _hash_datum2hashkey (Relation rel, Datum key)
 
uint32 _hash_datum2hashkey_type (Relation rel, Datum key, Oid keytype)
 
Bucket _hash_hashkey2bucket (uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask)
 
uint32 _hash_log2 (uint32 num)
 
uint32 _hash_spareindex (uint32 num_bucket)
 
uint32 _hash_get_totalbuckets (uint32 splitpoint_phase)
 
void _hash_checkpage (Relation rel, Buffer buf, int flags)
 
uint32 _hash_get_indextuple_hashkey (IndexTuple itup)
 
bool _hash_convert_tuple (Relation index, Datum *user_values, bool *user_isnull, Datum *index_values, bool *index_isnull)
 
OffsetNumber _hash_binsearch (Page page, uint32 hash_value)
 
OffsetNumber _hash_binsearch_last (Page page, uint32 hash_value)
 
BlockNumber _hash_get_oldblock_from_newbucket (Relation rel, Bucket new_bucket)
 
BlockNumber _hash_get_newblock_from_oldbucket (Relation rel, Bucket old_bucket)
 
Bucket _hash_get_newbucket_from_oldbucket (Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket)
 
void _hash_kill_items (IndexScanDesc scan)
 
void hashbucketcleanup (Relation rel, Bucket cur_bucket, Buffer bucket_buf, BlockNumber bucket_blkno, BufferAccessStrategy bstrategy, uint32 maxbucket, uint32 highmask, uint32 lowmask, double *tuples_removed, double *num_index_tuples, bool bucket_has_garbage, IndexBulkDeleteCallback callback, void *callback_state)
 

Macro Definition Documentation

◆ ALL_SET

#define ALL_SET   ((uint32) ~0)

Definition at line 292 of file hash.h.

Referenced by _hash_addovflpage().

◆ BITS_PER_MAP

#define BITS_PER_MAP   32 /* Number of bits in uint32 */

Definition at line 319 of file hash.h.

Referenced by _hash_addovflpage(), and _hash_firstfreebit().

◆ BMPG_MASK

#define BMPG_MASK (   metap)    (BMPGSZ_BIT(metap) - 1)

◆ BMPG_SHIFT

#define BMPG_SHIFT (   metap)    ((metap)->hashm_bmshift)

◆ BMPGSZ_BIT

#define BMPGSZ_BIT (   metap)    ((metap)->hashm_bmsize << BYTE_TO_BIT)

Definition at line 302 of file hash.h.

Referenced by _hash_addovflpage().

◆ BMPGSZ_BYTE

#define BMPGSZ_BYTE (   metap)    ((metap)->hashm_bmsize)

Definition at line 301 of file hash.h.

◆ BUCKET_TO_BLKNO

#define BUCKET_TO_BLKNO (   metap,
 
)    ((BlockNumber) ((B) + ((B) ? (metap)->hashm_spares[_hash_spareindex((B)+1)-1] : 0)) + 1)

◆ BYTE_TO_BIT

#define BYTE_TO_BIT   3 /* 2^3 bits/byte */

Definition at line 291 of file hash.h.

Referenced by _hash_init_metabuffer().

◆ CLRBIT

#define CLRBIT (   A,
 
)    ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))

Definition at line 322 of file hash.h.

◆ H_BUCKET_BEING_POPULATED

#define H_BUCKET_BEING_POPULATED (   opaque)    (((opaque)->hasho_flag & LH_BUCKET_BEING_POPULATED) != 0)

Definition at line 100 of file hash.h.

Referenced by _hash_first().

◆ H_BUCKET_BEING_SPLIT

#define H_BUCKET_BEING_SPLIT (   opaque)    (((opaque)->hasho_flag & LH_BUCKET_BEING_SPLIT) != 0)

Definition at line 99 of file hash.h.

Referenced by _hash_doinsert(), _hash_expandtable(), and hashbulkdelete().

◆ H_HAS_DEAD_TUPLES

#define H_HAS_DEAD_TUPLES (   opaque)    (((opaque)->hasho_flag & LH_PAGE_HAS_DEAD_TUPLES) != 0)

Definition at line 101 of file hash.h.

Referenced by _hash_doinsert(), and hashbucketcleanup().

◆ H_NEEDS_SPLIT_CLEANUP

#define H_NEEDS_SPLIT_CLEANUP (   opaque)    (((opaque)->hasho_flag & LH_BUCKET_NEEDS_SPLIT_CLEANUP) != 0)

Definition at line 98 of file hash.h.

Referenced by _hash_expandtable(), and hashbulkdelete().

◆ HASH_DEFAULT_FILLFACTOR

#define HASH_DEFAULT_FILLFACTOR   75

Definition at line 286 of file hash.h.

Referenced by _hash_init().

◆ HASH_MAGIC

#define HASH_MAGIC   0x6440640

Definition at line 208 of file hash.h.

Referenced by _hash_checkpage(), _hash_init_metabuffer(), and verify_hash_page().

◆ HASH_MAX_BITMAPS

#define HASH_MAX_BITMAPS   1024

Definition at line 235 of file hash.h.

Referenced by _hash_addovflpage(), _hash_init(), and hash_metapage_info().

◆ HASH_MAX_SPLITPOINT_GROUP

#define HASH_MAX_SPLITPOINT_GROUP   32

Definition at line 243 of file hash.h.

◆ HASH_MAX_SPLITPOINTS

#define HASH_MAX_SPLITPOINTS
Value:
HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
#define HASH_MAX_SPLITPOINT_GROUP
Definition: hash.h:243
#define HASH_SPLITPOINT_PHASES_PER_GRP
Definition: hash.h:238
#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE
Definition: hash.h:240

Definition at line 244 of file hash.h.

Referenced by _hash_init_metabuffer(), and hash_metapage_info().

◆ HASH_METAPAGE

◆ HASH_MIN_FILLFACTOR

#define HASH_MIN_FILLFACTOR   10

Definition at line 285 of file hash.h.

◆ HASH_NOLOCK

#define HASH_NOLOCK   (-1)

Definition at line 331 of file hash.h.

Referenced by _hash_doinsert(), _hash_getbuf(), _hash_getbuf_with_strategy(), and hashbulkdelete().

◆ HASH_READ

◆ HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE

#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE   10

Definition at line 240 of file hash.h.

Referenced by _hash_get_totalbuckets(), and _hash_spareindex().

◆ HASH_SPLITPOINT_PHASE_BITS

#define HASH_SPLITPOINT_PHASE_BITS   2

Definition at line 237 of file hash.h.

Referenced by _hash_get_totalbuckets(), and _hash_spareindex().

◆ HASH_SPLITPOINT_PHASE_MASK

#define HASH_SPLITPOINT_PHASE_MASK   (HASH_SPLITPOINT_PHASES_PER_GRP - 1)

Definition at line 239 of file hash.h.

Referenced by _hash_get_totalbuckets(), and _hash_spareindex().

◆ HASH_SPLITPOINT_PHASES_PER_GRP

#define HASH_SPLITPOINT_PHASES_PER_GRP   (1 << HASH_SPLITPOINT_PHASE_BITS)

Definition at line 238 of file hash.h.

◆ HASH_VERSION

#define HASH_VERSION   4

Definition at line 209 of file hash.h.

Referenced by _hash_checkpage(), _hash_init_metabuffer(), and verify_hash_page().

◆ HASH_WRITE

◆ HASHEXTENDED_PROC

#define HASHEXTENDED_PROC   2

◆ HashGetMaxBitmapSize

#define HashGetMaxBitmapSize (   page)
Value:
(PageGetPageSize((Page) page) - \
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetPageSize(page)
Definition: bufpage.h:264
#define MAXALIGN(LEN)
Definition: c.h:633
Pointer Page
Definition: bufpage.h:74

Definition at line 309 of file hash.h.

Referenced by _hash_init_metabuffer().

◆ HashMaxItemSize

#define HashMaxItemSize (   page)
Value:
sizeof(ItemIdData) - \
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PageGetPageSize(page)
Definition: bufpage.h:264
#define MAXALIGN(LEN)
Definition: c.h:633
#define MAXALIGN_DOWN(LEN)
Definition: c.h:645

Definition at line 277 of file hash.h.

Referenced by _hash_doinsert().

◆ HASHNProcs

#define HASHNProcs   2

Definition at line 353 of file hash.h.

Referenced by hashhandler().

◆ HASHO_PAGE_ID

◆ HashPageGetBitmap

#define HashPageGetBitmap (   page)    ((uint32 *) PageGetContents(page))

◆ HashPageGetMeta

◆ HashScanPosInvalidate

#define HashScanPosInvalidate (   scanpos)
Value:
do { \
(scanpos).buf = InvalidBuffer; \
(scanpos).currPage = InvalidBlockNumber; \
(scanpos).nextPage = InvalidBlockNumber; \
(scanpos).prevPage = InvalidBlockNumber; \
(scanpos).firstItem = 0; \
(scanpos).lastItem = 0; \
(scanpos).itemIndex = 0; \
} while (0);
#define InvalidBuffer
Definition: buf.h:25
static char * buf
Definition: pg_test_fsync.c:67
#define InvalidBlockNumber
Definition: block.h:33

Definition at line 152 of file hash.h.

Referenced by _hash_next(), hashbeginscan(), and hashrescan().

◆ HashScanPosIsPinned

#define HashScanPosIsPinned (   scanpos)
Value:
( \
AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
!BufferIsValid((scanpos).buf)), \
BufferIsValid((scanpos).buf) \
)
static char * buf
Definition: pg_test_fsync.c:67
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114

Definition at line 138 of file hash.h.

Referenced by _hash_kill_items().

◆ HashScanPosIsValid

#define HashScanPosIsValid (   scanpos)
Value:
( \
AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
!BufferIsValid((scanpos).buf)), \
BlockNumberIsValid((scanpos).currPage) \
)
static char * buf
Definition: pg_test_fsync.c:67
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114

Definition at line 145 of file hash.h.

Referenced by _hash_kill_items(), hashendscan(), hashgettuple(), and hashrescan().

◆ HASHSTANDARD_PROC

◆ HTEqualStrategyNumber

#define HTEqualStrategyNumber   1

◆ HTMaxStrategyNumber

#define HTMaxStrategyNumber   1

Definition at line 337 of file hash.h.

Referenced by hashhandler(), and hashvalidate().

◆ INDEX_MOVED_BY_SPLIT_MASK

#define INDEX_MOVED_BY_SPLIT_MASK   0x2000

Definition at line 283 of file hash.h.

Referenced by _hash_load_qualified_items(), and _hash_splitbucket().

◆ InvalidBucket

#define InvalidBucket   ((Bucket) 0xFFFFFFFF)

Definition at line 36 of file hash.h.

Referenced by hashbucketcleanup().

◆ ISSET

#define ISSET (   A,
 
)    ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))

Definition at line 324 of file hash.h.

Referenced by _hash_freeovflpage(), and hash_bitmap_info().

◆ LH_BITMAP_PAGE

◆ LH_BUCKET_BEING_POPULATED

#define LH_BUCKET_BEING_POPULATED   (1 << 4)

Definition at line 68 of file hash.h.

Referenced by _hash_expandtable(), and _hash_splitbucket().

◆ LH_BUCKET_BEING_SPLIT

#define LH_BUCKET_BEING_SPLIT   (1 << 5)

Definition at line 69 of file hash.h.

Referenced by _hash_expandtable(), and _hash_splitbucket().

◆ LH_BUCKET_NEEDS_SPLIT_CLEANUP

#define LH_BUCKET_NEEDS_SPLIT_CLEANUP   (1 << 6)

Definition at line 70 of file hash.h.

Referenced by _hash_splitbucket(), hash_xlog_split_cleanup(), and hashbucketcleanup().

◆ LH_BUCKET_PAGE

◆ LH_META_PAGE

◆ LH_OVERFLOW_PAGE

◆ LH_PAGE_HAS_DEAD_TUPLES

#define LH_PAGE_HAS_DEAD_TUPLES   (1 << 7)

◆ LH_PAGE_TYPE

◆ LH_UNUSED_PAGE

#define LH_UNUSED_PAGE   (0)

◆ ROTATE_HIGH_AND_LOW_32BITS

#define ROTATE_HIGH_AND_LOW_32BITS (   v)
Value:
((((v) << 1) & UINT64CONST(0xfffffffefffffffe)) | \
(((v) >> 31) & UINT64CONST(0x100000001)))

Definition at line 48 of file hash.h.

Referenced by hash_range_extended(), and JsonbHashScalarValueExtended().

◆ SETBIT

#define SETBIT (   A,
 
)    ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))

Definition at line 323 of file hash.h.

Typedef Documentation

◆ Bucket

Definition at line 34 of file hash.h.

◆ HashMetaPage

Definition at line 272 of file hash.h.

◆ HashMetaPageData

◆ HashPageOpaque

Definition at line 96 of file hash.h.

◆ HashPageOpaqueData

◆ HashScanOpaque

Definition at line 200 of file hash.h.

◆ HashScanOpaqueData

◆ HashScanPosData

◆ HashScanPosItem

◆ HSpool

Definition at line 443 of file hash.h.

Function Documentation

◆ _h_indexbuild()

void _h_indexbuild ( HSpool hspool,
Relation  heapRel 
)

Definition at line 115 of file hashsort.c.

References _hash_doinsert(), _hash_get_indextuple_hashkey(), _hash_hashkey2bucket(), Assert, HSpool::high_mask, HSpool::index, HSpool::low_mask, HSpool::max_buckets, HSpool::sortstate, tuplesort_getindextuple(), and tuplesort_performsort().

Referenced by hashbuild().

116 {
117  IndexTuple itup;
118 #ifdef USE_ASSERT_CHECKING
119  uint32 hashkey = 0;
120 #endif
121 
123 
124  while ((itup = tuplesort_getindextuple(hspool->sortstate, true)) != NULL)
125  {
126  /*
127  * Technically, it isn't critical that hash keys be found in sorted
128  * order, since this sorting is only used to increase locality of
129  * access as a performance optimization. It still seems like a good
130  * idea to test tuplesort.c's handling of hash index tuple sorts
131  * through an assertion, though.
132  */
133 #ifdef USE_ASSERT_CHECKING
134  uint32 lasthashkey = hashkey;
135 
137  hspool->max_buckets, hspool->high_mask,
138  hspool->low_mask);
139  Assert(hashkey >= lasthashkey);
140 #endif
141 
142  _hash_doinsert(hspool->index, itup, heapRel);
143  }
144 }
IndexTuple tuplesort_getindextuple(Tuplesortstate *state, bool forward)
Definition: tuplesort.c:2052
void _hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel)
Definition: hashinsert.c:36
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1655
Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashutil.c:125
Tuplesortstate * sortstate
Definition: hashsort.c:38
uint32 low_mask
Definition: hashsort.c:47
uint32 high_mask
Definition: hashsort.c:46
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:299
unsigned int uint32
Definition: c.h:306
uint32 max_buckets
Definition: hashsort.c:48
Relation index
Definition: hashsort.c:39
#define Assert(condition)
Definition: c.h:680

◆ _h_spool()

void _h_spool ( HSpool hspool,
ItemPointer  self,
Datum values,
bool isnull 
)

Definition at line 104 of file hashsort.c.

References HSpool::index, HSpool::sortstate, and tuplesort_putindextuplevalues().

Referenced by hashbuildCallback().

105 {
107  self, values, isnull);
108 }
Tuplesortstate * sortstate
Definition: hashsort.c:38
Relation index
Definition: hashsort.c:39
void tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel, ItemPointer self, Datum *values, bool *isnull)
Definition: tuplesort.c:1344
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ _h_spooldestroy()

void _h_spooldestroy ( HSpool hspool)

Definition at line 94 of file hashsort.c.

References pfree(), HSpool::sortstate, and tuplesort_end().

Referenced by hashbuild().

95 {
96  tuplesort_end(hspool->sortstate);
97  pfree(hspool);
98 }
Tuplesortstate * sortstate
Definition: hashsort.c:38
void pfree(void *pointer)
Definition: mcxt.c:936
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1104

◆ _h_spoolinit()

HSpool* _h_spoolinit ( Relation  heap,
Relation  index,
uint32  num_buckets 
)

Definition at line 56 of file hashsort.c.

References _hash_log2(), HSpool::high_mask, HSpool::index, HSpool::low_mask, maintenance_work_mem, HSpool::max_buckets, palloc0(), HSpool::sortstate, and tuplesort_begin_index_hash().

Referenced by hashbuild().

57 {
58  HSpool *hspool = (HSpool *) palloc0(sizeof(HSpool));
59 
60  hspool->index = index;
61 
62  /*
63  * Determine the bitmask for hash code values. Since there are currently
64  * num_buckets buckets in the index, the appropriate mask can be computed
65  * as follows.
66  *
67  * NOTE : This hash mask calculation should be in sync with similar
68  * calculation in _hash_init_metabuffer.
69  */
70  hspool->high_mask = (((uint32) 1) << _hash_log2(num_buckets + 1)) - 1;
71  hspool->low_mask = (hspool->high_mask >> 1);
72  hspool->max_buckets = num_buckets - 1;
73 
74  /*
75  * We size the sort area as maintenance_work_mem rather than work_mem to
76  * speed index creation. This should be OK since a single backend can't
77  * run multiple index creations in parallel.
78  */
80  index,
81  hspool->high_mask,
82  hspool->low_mask,
83  hspool->max_buckets,
85  false);
86 
87  return hspool;
88 }
Tuplesortstate * sortstate
Definition: hashsort.c:38
uint32 low_mask
Definition: hashsort.c:47
uint32 high_mask
Definition: hashsort.c:46
Tuplesortstate * tuplesort_begin_index_hash(Relation heapRel, Relation indexRel, uint32 high_mask, uint32 low_mask, uint32 max_buckets, int workMem, bool randomAccess)
Definition: tuplesort.c:932
unsigned int uint32
Definition: c.h:306
void * palloc0(Size size)
Definition: mcxt.c:864
uint32 max_buckets
Definition: hashsort.c:48
Relation index
Definition: hashsort.c:39
int maintenance_work_mem
Definition: globals.c:114
uint32 _hash_log2(uint32 num)
Definition: hashutil.c:141

◆ _hash_addovflpage()

Buffer _hash_addovflpage ( Relation  rel,
Buffer  metabuf,
Buffer  buf,
bool  retain_pin 
)

Definition at line 111 of file hashovfl.c.

References _hash_checkpage(), _hash_firstfreebit(), _hash_getbuf(), _hash_getinitbuf(), _hash_getnewbuf(), _hash_initbitmapbuffer(), _hash_relbuf(), ALL_SET, Assert, bit(), bitno_to_blkno(), BITS_PER_MAP, BlockNumberIsValid, xl_hash_add_ovfl_page::bmpage_found, BMPG_MASK, BMPG_SHIFT, BMPGSZ_BIT, xl_hash_add_ovfl_page::bmsize, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, HASH_MAX_BITMAPS, HASH_WRITE, HashMetaPageData::hashm_bmsize, HashMetaPageData::hashm_firstfree, HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_nmaps, HashMetaPageData::hashm_ovflpoint, HashMetaPageData::hashm_spares, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, HashPageGetBitmap, HashPageGetMeta, i, InvalidBlockNumber, InvalidBuffer, LH_BITMAP_PAGE, LH_BUCKET_PAGE, LH_META_PAGE, LH_OVERFLOW_PAGE, LH_PAGE_TYPE, LockBuffer(), MAIN_FORKNUM, MarkBufferDirty(), PageGetSpecialPointer, PageSetLSN, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetRelationName, RelationNeedsWAL, SETBIT, SizeOfHashAddOvflPage, START_CRIT_SECTION, XLOG_HASH_ADD_OVFL_PAGE, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by _hash_doinsert(), and _hash_splitbucket().

112 {
113  Buffer ovflbuf;
114  Page page;
115  Page ovflpage;
116  HashPageOpaque pageopaque;
117  HashPageOpaque ovflopaque;
118  HashMetaPage metap;
119  Buffer mapbuf = InvalidBuffer;
120  Buffer newmapbuf = InvalidBuffer;
121  BlockNumber blkno;
122  uint32 orig_firstfree;
123  uint32 splitnum;
124  uint32 *freep = NULL;
125  uint32 max_ovflpg;
126  uint32 bit;
127  uint32 bitmap_page_bit;
128  uint32 first_page;
129  uint32 last_bit;
130  uint32 last_page;
131  uint32 i,
132  j;
133  bool page_found = false;
134 
135  /*
136  * Write-lock the tail page. Here, we need to maintain locking order such
137  * that, first acquire the lock on tail page of bucket, then on meta page
138  * to find and lock the bitmap page and if it is found, then lock on meta
139  * page is released, then finally acquire the lock on new overflow buffer.
140  * We need this locking order to avoid deadlock with backends that are
141  * doing inserts.
142  *
143  * Note: We could have avoided locking many buffers here if we made two
144  * WAL records for acquiring an overflow page (one to allocate an overflow
145  * page and another to add it to overflow bucket chain). However, doing
146  * so can leak an overflow page, if the system crashes after allocation.
147  * Needless to say, it is better to have a single record from a
148  * performance point of view as well.
149  */
151 
152  /* probably redundant... */
154 
155  /* loop to find current tail page, in case someone else inserted too */
156  for (;;)
157  {
158  BlockNumber nextblkno;
159 
160  page = BufferGetPage(buf);
161  pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
162  nextblkno = pageopaque->hasho_nextblkno;
163 
164  if (!BlockNumberIsValid(nextblkno))
165  break;
166 
167  /* we assume we do not need to write the unmodified page */
168  if (retain_pin)
169  {
170  /* pin will be retained only for the primary bucket page */
171  Assert((pageopaque->hasho_flag & LH_PAGE_TYPE) == LH_BUCKET_PAGE);
173  }
174  else
175  _hash_relbuf(rel, buf);
176 
177  retain_pin = false;
178 
179  buf = _hash_getbuf(rel, nextblkno, HASH_WRITE, LH_OVERFLOW_PAGE);
180  }
181 
182  /* Get exclusive lock on the meta page */
184 
185  _hash_checkpage(rel, metabuf, LH_META_PAGE);
186  metap = HashPageGetMeta(BufferGetPage(metabuf));
187 
188  /* start search at hashm_firstfree */
189  orig_firstfree = metap->hashm_firstfree;
190  first_page = orig_firstfree >> BMPG_SHIFT(metap);
191  bit = orig_firstfree & BMPG_MASK(metap);
192  i = first_page;
193  j = bit / BITS_PER_MAP;
194  bit &= ~(BITS_PER_MAP - 1);
195 
196  /* outer loop iterates once per bitmap page */
197  for (;;)
198  {
199  BlockNumber mapblkno;
200  Page mappage;
201  uint32 last_inpage;
202 
203  /* want to end search with the last existing overflow page */
204  splitnum = metap->hashm_ovflpoint;
205  max_ovflpg = metap->hashm_spares[splitnum] - 1;
206  last_page = max_ovflpg >> BMPG_SHIFT(metap);
207  last_bit = max_ovflpg & BMPG_MASK(metap);
208 
209  if (i > last_page)
210  break;
211 
212  Assert(i < metap->hashm_nmaps);
213  mapblkno = metap->hashm_mapp[i];
214 
215  if (i == last_page)
216  last_inpage = last_bit;
217  else
218  last_inpage = BMPGSZ_BIT(metap) - 1;
219 
220  /* Release exclusive lock on metapage while reading bitmap page */
221  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
222 
223  mapbuf = _hash_getbuf(rel, mapblkno, HASH_WRITE, LH_BITMAP_PAGE);
224  mappage = BufferGetPage(mapbuf);
225  freep = HashPageGetBitmap(mappage);
226 
227  for (; bit <= last_inpage; j++, bit += BITS_PER_MAP)
228  {
229  if (freep[j] != ALL_SET)
230  {
231  page_found = true;
232 
233  /* Reacquire exclusive lock on the meta page */
235 
236  /* convert bit to bit number within page */
237  bit += _hash_firstfreebit(freep[j]);
238  bitmap_page_bit = bit;
239 
240  /* convert bit to absolute bit number */
241  bit += (i << BMPG_SHIFT(metap));
242  /* Calculate address of the recycled overflow page */
243  blkno = bitno_to_blkno(metap, bit);
244 
245  /* Fetch and init the recycled page */
246  ovflbuf = _hash_getinitbuf(rel, blkno);
247 
248  goto found;
249  }
250  }
251 
252  /* No free space here, try to advance to next map page */
253  _hash_relbuf(rel, mapbuf);
254  mapbuf = InvalidBuffer;
255  i++;
256  j = 0; /* scan from start of next map page */
257  bit = 0;
258 
259  /* Reacquire exclusive lock on the meta page */
261  }
262 
263  /*
264  * No free pages --- have to extend the relation to add an overflow page.
265  * First, check to see if we have to add a new bitmap page too.
266  */
267  if (last_bit == (uint32) (BMPGSZ_BIT(metap) - 1))
268  {
269  /*
270  * We create the new bitmap page with all pages marked "in use".
271  * Actually two pages in the new bitmap's range will exist
272  * immediately: the bitmap page itself, and the following page which
273  * is the one we return to the caller. Both of these are correctly
274  * marked "in use". Subsequent pages do not exist yet, but it is
275  * convenient to pre-mark them as "in use" too.
276  */
277  bit = metap->hashm_spares[splitnum];
278 
279  /* metapage already has a write lock */
280  if (metap->hashm_nmaps >= HASH_MAX_BITMAPS)
281  ereport(ERROR,
282  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
283  errmsg("out of overflow pages in hash index \"%s\"",
284  RelationGetRelationName(rel))));
285 
286  newmapbuf = _hash_getnewbuf(rel, bitno_to_blkno(metap, bit), MAIN_FORKNUM);
287  }
288  else
289  {
290  /*
291  * Nothing to do here; since the page will be past the last used page,
292  * we know its bitmap bit was preinitialized to "in use".
293  */
294  }
295 
296  /* Calculate address of the new overflow page */
297  bit = BufferIsValid(newmapbuf) ?
298  metap->hashm_spares[splitnum] + 1 : metap->hashm_spares[splitnum];
299  blkno = bitno_to_blkno(metap, bit);
300 
301  /*
302  * Fetch the page with _hash_getnewbuf to ensure smgr's idea of the
303  * relation length stays in sync with ours. XXX It's annoying to do this
304  * with metapage write lock held; would be better to use a lock that
305  * doesn't block incoming searches.
306  *
307  * It is okay to hold two buffer locks here (one on tail page of bucket
308  * and other on new overflow page) since there cannot be anyone else
309  * contending for access to ovflbuf.
310  */
311  ovflbuf = _hash_getnewbuf(rel, blkno, MAIN_FORKNUM);
312 
313 found:
314 
315  /*
316  * Do the update. No ereport(ERROR) until changes are logged. We want to
317  * log the changes for bitmap page and overflow page together to avoid
318  * loss of pages in case the new page is added.
319  */
321 
322  if (page_found)
323  {
324  Assert(BufferIsValid(mapbuf));
325 
326  /* mark page "in use" in the bitmap */
327  SETBIT(freep, bitmap_page_bit);
328  MarkBufferDirty(mapbuf);
329  }
330  else
331  {
332  /* update the count to indicate new overflow page is added */
333  metap->hashm_spares[splitnum]++;
334 
335  if (BufferIsValid(newmapbuf))
336  {
337  _hash_initbitmapbuffer(newmapbuf, metap->hashm_bmsize, false);
338  MarkBufferDirty(newmapbuf);
339 
340  /* add the new bitmap page to the metapage's list of bitmaps */
341  metap->hashm_mapp[metap->hashm_nmaps] = BufferGetBlockNumber(newmapbuf);
342  metap->hashm_nmaps++;
343  metap->hashm_spares[splitnum]++;
344  MarkBufferDirty(metabuf);
345  }
346 
347  /*
348  * for new overflow page, we don't need to explicitly set the bit in
349  * bitmap page, as by default that will be set to "in use".
350  */
351  }
352 
353  /*
354  * Adjust hashm_firstfree to avoid redundant searches. But don't risk
355  * changing it if someone moved it while we were searching bitmap pages.
356  */
357  if (metap->hashm_firstfree == orig_firstfree)
358  {
359  metap->hashm_firstfree = bit + 1;
360  MarkBufferDirty(metabuf);
361  }
362 
363  /* initialize new overflow page */
364  ovflpage = BufferGetPage(ovflbuf);
365  ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
367  ovflopaque->hasho_nextblkno = InvalidBlockNumber;
368  ovflopaque->hasho_bucket = pageopaque->hasho_bucket;
369  ovflopaque->hasho_flag = LH_OVERFLOW_PAGE;
370  ovflopaque->hasho_page_id = HASHO_PAGE_ID;
371 
372  MarkBufferDirty(ovflbuf);
373 
374  /* logically chain overflow page to previous page */
375  pageopaque->hasho_nextblkno = BufferGetBlockNumber(ovflbuf);
376 
378 
379  /* XLOG stuff */
380  if (RelationNeedsWAL(rel))
381  {
382  XLogRecPtr recptr;
383  xl_hash_add_ovfl_page xlrec;
384 
385  xlrec.bmpage_found = page_found;
386  xlrec.bmsize = metap->hashm_bmsize;
387 
388  XLogBeginInsert();
389  XLogRegisterData((char *) &xlrec, SizeOfHashAddOvflPage);
390 
392  XLogRegisterBufData(0, (char *) &pageopaque->hasho_bucket, sizeof(Bucket));
393 
395 
396  if (BufferIsValid(mapbuf))
397  {
399  XLogRegisterBufData(2, (char *) &bitmap_page_bit, sizeof(uint32));
400  }
401 
402  if (BufferIsValid(newmapbuf))
403  XLogRegisterBuffer(3, newmapbuf, REGBUF_WILL_INIT);
404 
405  XLogRegisterBuffer(4, metabuf, REGBUF_STANDARD);
406  XLogRegisterBufData(4, (char *) &metap->hashm_firstfree, sizeof(uint32));
407 
408  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_ADD_OVFL_PAGE);
409 
410  PageSetLSN(BufferGetPage(ovflbuf), recptr);
411  PageSetLSN(BufferGetPage(buf), recptr);
412 
413  if (BufferIsValid(mapbuf))
414  PageSetLSN(BufferGetPage(mapbuf), recptr);
415 
416  if (BufferIsValid(newmapbuf))
417  PageSetLSN(BufferGetPage(newmapbuf), recptr);
418 
419  PageSetLSN(BufferGetPage(metabuf), recptr);
420  }
421 
423 
424  if (retain_pin)
426  else
427  _hash_relbuf(rel, buf);
428 
429  if (BufferIsValid(mapbuf))
430  _hash_relbuf(rel, mapbuf);
431 
432  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
433 
434  if (BufferIsValid(newmapbuf))
435  _hash_relbuf(rel, newmapbuf);
436 
437  return ovflbuf;
438 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
uint16 hasho_page_id
Definition: hash.h:93
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define SETBIT(x, i)
Definition: blutils.c:33
#define HashPageGetBitmap(page)
Definition: hash.h:306
#define LH_BITMAP_PAGE
Definition: hash.h:66
static BlockNumber bitno_to_blkno(HashMetaPage metap, uint32 ovflbitnum)
Definition: hashovfl.c:34
#define LH_META_PAGE
Definition: hash.h:67
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define InvalidBuffer
Definition: buf.h:25
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define ALL_SET
Definition: hash.h:292
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getnewbuf(Relation rel, BlockNumber blkno, ForkNumber forkNum)
Definition: hashpage.c:206
Buffer _hash_getinitbuf(Relation rel, BlockNumber blkno)
Definition: hashpage.c:143
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define LH_PAGE_TYPE
Definition: hash.h:73
static uint32 _hash_firstfreebit(uint32 map)
Definition: hashovfl.c:446
uint32 Bucket
Definition: hash.h:34
BlockNumber hasho_prevblkno
Definition: hash.h:89
#define ERROR
Definition: elog.h:43
#define XLOG_HASH_ADD_OVFL_PAGE
Definition: hash_xlog.h:30
uint32 hashm_nmaps
Definition: hash.h:265
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_WRITE
Definition: hash.h:330
#define BMPG_MASK(metap)
Definition: hash.h:304
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define RelationGetRelationName(relation)
Definition: rel.h:445
unsigned int uint32
Definition: c.h:306
#define BITS_PER_MAP
Definition: hash.h:319
#define BMPG_SHIFT(metap)
Definition: hash.h:303
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define HASH_MAX_BITMAPS
Definition: hash.h:235
uint32 hashm_ovflpoint
Definition: hash.h:262
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint32 hashm_firstfree
Definition: hash.h:264
uint32 hashm_spares[HASH_MAX_SPLITPOINTS]
Definition: hash.h:267
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
void _hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage)
Definition: hashovfl.c:739
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define LH_BUCKET_PAGE
Definition: hash.h:65
Datum bit(PG_FUNCTION_ARGS)
Definition: varbit.c:362
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define HASHO_PAGE_ID
Definition: hash.h:109
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define RelationNeedsWAL(relation)
Definition: rel.h:514
#define SizeOfHashAddOvflPage
Definition: hash_xlog.h:99
uint16 hasho_flag
Definition: hash.h:92
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define HashPageGetMeta(page)
Definition: hash.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
BlockNumber hasho_nextblkno
Definition: hash.h:90
uint16 hashm_bmsize
Definition: hash.h:256
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition: hash.h:269
int Buffer
Definition: buf.h:23
#define BMPGSZ_BIT(metap)
Definition: hash.h:302
Pointer Page
Definition: bufpage.h:74

◆ _hash_binsearch()

OffsetNumber _hash_binsearch ( Page  page,
uint32  hash_value 
)

Definition at line 358 of file hashutil.c.

References _hash_get_indextuple_hashkey(), Assert, FirstOffsetNumber, lower(), OffsetNumberIsValid, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, and upper().

Referenced by _hash_pgaddmultitup(), _hash_pgaddtup(), and _hash_readpage().

359 {
362 
363  /* Loop invariant: lower <= desired place <= upper */
364  upper = PageGetMaxOffsetNumber(page) + 1;
365  lower = FirstOffsetNumber;
366 
367  while (upper > lower)
368  {
369  OffsetNumber off;
370  IndexTuple itup;
371  uint32 hashkey;
372 
373  off = (upper + lower) / 2;
375 
376  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
377  hashkey = _hash_get_indextuple_hashkey(itup);
378  if (hashkey < hash_value)
379  lower = off + 1;
380  else
381  upper = off;
382  }
383 
384  return lower;
385 }
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:44
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:75
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:299
#define FirstOffsetNumber
Definition: off.h:27
IndexTupleData * IndexTuple
Definition: itup.h:53
unsigned int uint32
Definition: c.h:306
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define Assert(condition)
Definition: c.h:680
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define PageGetItem(page, itemId)
Definition: bufpage.h:336

◆ _hash_binsearch_last()

OffsetNumber _hash_binsearch_last ( Page  page,
uint32  hash_value 
)

Definition at line 396 of file hashutil.c.

References _hash_get_indextuple_hashkey(), Assert, FirstOffsetNumber, lower(), OffsetNumberIsValid, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, and upper().

Referenced by _hash_readpage().

397 {
400 
401  /* Loop invariant: lower <= desired place <= upper */
402  upper = PageGetMaxOffsetNumber(page);
403  lower = FirstOffsetNumber - 1;
404 
405  while (upper > lower)
406  {
407  IndexTuple itup;
408  OffsetNumber off;
409  uint32 hashkey;
410 
411  off = (upper + lower + 1) / 2;
413 
414  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
415  hashkey = _hash_get_indextuple_hashkey(itup);
416  if (hashkey > hash_value)
417  upper = off - 1;
418  else
419  lower = off;
420  }
421 
422  return lower;
423 }
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:44
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:75
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:299
#define FirstOffsetNumber
Definition: off.h:27
IndexTupleData * IndexTuple
Definition: itup.h:53
unsigned int uint32
Definition: c.h:306
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define Assert(condition)
Definition: c.h:680
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define PageGetItem(page, itemId)
Definition: bufpage.h:336

◆ _hash_checkpage()

void _hash_checkpage ( Relation  rel,
Buffer  buf,
int  flags 
)

Definition at line 225 of file hashutil.c.

References BufferGetBlockNumber(), BufferGetPage, ereport, errcode(), errhint(), errmsg(), ERROR, HASH_MAGIC, HASH_VERSION, HashMetaPageData::hashm_magic, HashMetaPageData::hashm_version, HashPageOpaqueData::hasho_flag, HashPageGetMeta, LH_META_PAGE, MAXALIGN, PageGetSpecialPointer, PageGetSpecialSize, PageIsNew, and RelationGetRelationName.

Referenced by _hash_addovflpage(), _hash_expandtable(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), _hash_getbuf_with_strategy(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readpage(), and hashbulkdelete().

226 {
227  Page page = BufferGetPage(buf);
228 
229  /*
230  * ReadBuffer verifies that every newly-read page passes
231  * PageHeaderIsValid, which means it either contains a reasonably sane
232  * page header or is all-zero. We have to defend against the all-zero
233  * case, however.
234  */
235  if (PageIsNew(page))
236  ereport(ERROR,
237  (errcode(ERRCODE_INDEX_CORRUPTED),
238  errmsg("index \"%s\" contains unexpected zero page at block %u",
241  errhint("Please REINDEX it.")));
242 
243  /*
244  * Additionally check that the special area looks sane.
245  */
246  if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData)))
247  ereport(ERROR,
248  (errcode(ERRCODE_INDEX_CORRUPTED),
249  errmsg("index \"%s\" contains corrupted page at block %u",
252  errhint("Please REINDEX it.")));
253 
254  if (flags)
255  {
257 
258  if ((opaque->hasho_flag & flags) == 0)
259  ereport(ERROR,
260  (errcode(ERRCODE_INDEX_CORRUPTED),
261  errmsg("index \"%s\" contains corrupted page at block %u",
264  errhint("Please REINDEX it.")));
265  }
266 
267  /*
268  * When checking the metapage, also verify magic number and version.
269  */
270  if (flags == LH_META_PAGE)
271  {
272  HashMetaPage metap = HashPageGetMeta(page);
273 
274  if (metap->hashm_magic != HASH_MAGIC)
275  ereport(ERROR,
276  (errcode(ERRCODE_INDEX_CORRUPTED),
277  errmsg("index \"%s\" is not a hash index",
278  RelationGetRelationName(rel))));
279 
280  if (metap->hashm_version != HASH_VERSION)
281  ereport(ERROR,
282  (errcode(ERRCODE_INDEX_CORRUPTED),
283  errmsg("index \"%s\" has wrong hash version",
285  errhint("Please REINDEX it.")));
286  }
287 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define LH_META_PAGE
Definition: hash.h:67
uint32 hashm_magic
Definition: hash.h:251
int errcode(int sqlerrcode)
Definition: elog.c:575
#define HASH_VERSION
Definition: hash.h:209
#define HASH_MAGIC
Definition: hash.h:208
#define ERROR
Definition: elog.h:43
uint32 hashm_version
Definition: hash.h:252
static char * buf
Definition: pg_test_fsync.c:67
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define MAXALIGN(LEN)
Definition: c.h:633
#define PageGetSpecialSize(page)
Definition: bufpage.h:296
uint16 hasho_flag
Definition: hash.h:92
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define PageIsNew(page)
Definition: bufpage.h:225
#define HashPageGetMeta(page)
Definition: hash.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:797
Pointer Page
Definition: bufpage.h:74

◆ _hash_checkqual()

bool _hash_checkqual ( IndexScanDesc  scan,
IndexTuple  itup 
)

Definition at line 31 of file hashutil.c.

References DatumGetBool, FunctionCall2Coll(), index_getattr, IndexScanDescData::indexRelation, IndexScanDescData::keyData, IndexScanDescData::numberOfKeys, RelationGetDescr, ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_flags, ScanKeyData::sk_func, SK_ISNULL, and test().

Referenced by _hash_load_qualified_items().

32 {
33  /*
34  * Currently, we can't check any of the scan conditions since we do not
35  * have the original index entry value to supply to the sk_func. Always
36  * return true; we expect that hashgettuple already set the recheck flag
37  * to make the main indexscan code do it.
38  */
39 #ifdef NOT_USED
40  TupleDesc tupdesc = RelationGetDescr(scan->indexRelation);
41  ScanKey key = scan->keyData;
42  int scanKeySize = scan->numberOfKeys;
43 
44  while (scanKeySize > 0)
45  {
46  Datum datum;
47  bool isNull;
48  Datum test;
49 
50  datum = index_getattr(itup,
51  key->sk_attno,
52  tupdesc,
53  &isNull);
54 
55  /* assume sk_func is strict */
56  if (isNull)
57  return false;
58  if (key->sk_flags & SK_ISNULL)
59  return false;
60 
61  test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
62  datum, key->sk_argument);
63 
64  if (!DatumGetBool(test))
65  return false;
66 
67  key++;
68  scanKeySize--;
69  }
70 #endif
71 
72  return true;
73 }
static void test(void)
#define RelationGetDescr(relation)
Definition: rel.h:437
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1042
Relation indexRelation
Definition: relscan.h:90
FmgrInfo sk_func
Definition: skey.h:71
#define DatumGetBool(X)
Definition: postgres.h:399
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:372
int sk_flags
Definition: skey.h:66
#define index_getattr(tup, attnum, tupleDesc, isnull)
Definition: itup.h:100
ScanKey keyData
Definition: relscan.h:94
Oid sk_collation
Definition: skey.h:70
Datum sk_argument
Definition: skey.h:72
AttrNumber sk_attno
Definition: skey.h:67

◆ _hash_convert_tuple()

bool _hash_convert_tuple ( Relation  index,
Datum user_values,
bool user_isnull,
Datum index_values,
bool index_isnull 
)

Definition at line 326 of file hashutil.c.

References _hash_datum2hashkey(), and UInt32GetDatum.

Referenced by hashbuildCallback(), and hashinsert().

329 {
330  uint32 hashkey;
331 
332  /*
333  * We do not insert null values into hash indexes. This is okay because
334  * the only supported search operator is '=', and we assume it is strict.
335  */
336  if (user_isnull[0])
337  return false;
338 
339  hashkey = _hash_datum2hashkey(index, user_values[0]);
340  index_values[0] = UInt32GetDatum(hashkey);
341  index_isnull[0] = false;
342  return true;
343 }
uint32 _hash_datum2hashkey(Relation rel, Datum key)
Definition: hashutil.c:82
unsigned int uint32
Definition: c.h:306
#define UInt32GetDatum(X)
Definition: postgres.h:499

◆ _hash_datum2hashkey()

uint32 _hash_datum2hashkey ( Relation  rel,
Datum  key 
)

Definition at line 82 of file hashutil.c.

References DatumGetUInt32, FunctionCall1Coll(), HASHSTANDARD_PROC, index_getprocinfo(), and RelationData::rd_indcollation.

Referenced by _hash_convert_tuple(), and _hash_first().

83 {
84  FmgrInfo *procinfo;
85  Oid collation;
86 
87  /* XXX assumes index has only one attribute */
88  procinfo = index_getprocinfo(rel, 1, HASHSTANDARD_PROC);
89  collation = rel->rd_indcollation[0];
90 
91  return DatumGetUInt32(FunctionCall1Coll(procinfo, collation, key));
92 }
#define DatumGetUInt32(X)
Definition: postgres.h:492
Definition: fmgr.h:56
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:855
unsigned int Oid
Definition: postgres_ext.h:31
Oid * rd_indcollation
Definition: rel.h:193
#define HASHSTANDARD_PROC
Definition: hash.h:351
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1022

◆ _hash_datum2hashkey_type()

uint32 _hash_datum2hashkey_type ( Relation  rel,
Datum  key,
Oid  keytype 
)

Definition at line 102 of file hashutil.c.

References DatumGetUInt32, elog, ERROR, get_opfamily_proc(), HASHSTANDARD_PROC, OidFunctionCall1Coll(), RelationData::rd_indcollation, RelationData::rd_opfamily, RegProcedureIsValid, and RelationGetRelationName.

Referenced by _hash_first().

103 {
104  RegProcedure hash_proc;
105  Oid collation;
106 
107  /* XXX assumes index has only one attribute */
108  hash_proc = get_opfamily_proc(rel->rd_opfamily[0],
109  keytype,
110  keytype,
112  if (!RegProcedureIsValid(hash_proc))
113  elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"",
114  HASHSTANDARD_PROC, keytype, keytype,
116  collation = rel->rd_indcollation[0];
117 
118  return DatumGetUInt32(OidFunctionCall1Coll(hash_proc, collation, key));
119 }
#define DatumGetUInt32(X)
Definition: postgres.h:492
regproc RegProcedure
Definition: c.h:453
unsigned int Oid
Definition: postgres_ext.h:31
Oid * rd_indcollation
Definition: rel.h:193
#define ERROR
Definition: elog.h:43
#define RegProcedureIsValid(p)
Definition: c.h:588
#define RelationGetRelationName(relation)
Definition: rel.h:445
Oid * rd_opfamily
Definition: rel.h:182
#define HASHSTANDARD_PROC
Definition: hash.h:351
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition: fmgr.c:1314
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
#define elog
Definition: elog.h:219

◆ _hash_doinsert()

void _hash_doinsert ( Relation  rel,
IndexTuple  itup,
Relation  heapRel 
)

Definition at line 36 of file hashinsert.c.

References _hash_addovflpage(), _hash_dropbuf(), _hash_expandtable(), _hash_finish_split(), _hash_get_indextuple_hashkey(), _hash_getbucketbuf_from_hashkey(), _hash_getbuf(), _hash_pgaddtup(), _hash_relbuf(), _hash_vacuum_one_page(), Assert, BlockNumberIsValid, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage, END_CRIT_SECTION, ereport, errcode(), errhint(), errmsg(), ERROR, H_BUCKET_BEING_SPLIT, H_HAS_DEAD_TUPLES, HASH_METAPAGE, HASH_NOLOCK, HASH_WRITE, HashMetaPageData::hashm_ffactor, HashMetaPageData::hashm_highmask, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_ntuples, HashMaxItemSize, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageGetMeta, IndexTupleDSize, InvalidBuffer, IsBufferCleanupOK(), LH_META_PAGE, LH_OVERFLOW_PAGE, LH_PAGE_TYPE, LockBuffer(), MarkBufferDirty(), MAXALIGN, xl_hash_insert::offnum, PageGetFreeSpace(), PageGetSpecialPointer, PageSetLSN, RelationData::rd_node, REGBUF_STANDARD, RelationNeedsWAL, SizeOfHashInsert, START_CRIT_SECTION, XLOG_HASH_INSERT, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by _h_indexbuild(), hashbuildCallback(), and hashinsert().

37 {
39  Buffer bucket_buf;
40  Buffer metabuf;
41  HashMetaPage metap;
42  HashMetaPage usedmetap = NULL;
43  Page metapage;
44  Page page;
45  HashPageOpaque pageopaque;
46  Size itemsz;
47  bool do_expand;
48  uint32 hashkey;
49  Bucket bucket;
50  OffsetNumber itup_off;
51 
52  /*
53  * Get the hash key for the item (it's stored in the index tuple itself).
54  */
55  hashkey = _hash_get_indextuple_hashkey(itup);
56 
57  /* compute item size too */
58  itemsz = IndexTupleDSize(*itup);
59  itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we
60  * need to be consistent */
61 
62 restart_insert:
63 
64  /*
65  * Read the metapage. We don't lock it yet; HashMaxItemSize() will
66  * examine pd_pagesize_version, but that can't change so we can examine it
67  * without a lock.
68  */
70  metapage = BufferGetPage(metabuf);
71 
72  /*
73  * Check whether the item can fit on a hash page at all. (Eventually, we
74  * ought to try to apply TOAST methods if not.) Note that at this point,
75  * itemsz doesn't include the ItemId.
76  *
77  * XXX this is useless code if we are only storing hash keys.
78  */
79  if (itemsz > HashMaxItemSize(metapage))
80  ereport(ERROR,
81  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
82  errmsg("index row size %zu exceeds hash maximum %zu",
83  itemsz, HashMaxItemSize(metapage)),
84  errhint("Values larger than a buffer page cannot be indexed.")));
85 
86  /* Lock the primary bucket page for the target bucket. */
87  buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_WRITE,
88  &usedmetap);
89  Assert(usedmetap != NULL);
90 
91  /* remember the primary bucket buffer to release the pin on it at end. */
92  bucket_buf = buf;
93 
94  page = BufferGetPage(buf);
95  pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
96  bucket = pageopaque->hasho_bucket;
97 
98  /*
99  * If this bucket is in the process of being split, try to finish the
100  * split before inserting, because that might create room for the
101  * insertion to proceed without allocating an additional overflow page.
102  * It's only interesting to finish the split if we're trying to insert
103  * into the bucket from which we're removing tuples (the "old" bucket),
104  * not if we're trying to insert into the bucket into which tuples are
105  * being moved (the "new" bucket).
106  */
107  if (H_BUCKET_BEING_SPLIT(pageopaque) && IsBufferCleanupOK(buf))
108  {
109  /* release the lock on bucket buffer, before completing the split. */
111 
112  _hash_finish_split(rel, metabuf, buf, bucket,
113  usedmetap->hashm_maxbucket,
114  usedmetap->hashm_highmask,
115  usedmetap->hashm_lowmask);
116 
117  /* release the pin on old and meta buffer. retry for insert. */
118  _hash_dropbuf(rel, buf);
119  _hash_dropbuf(rel, metabuf);
120  goto restart_insert;
121  }
122 
123  /* Do the insertion */
124  while (PageGetFreeSpace(page) < itemsz)
125  {
126  BlockNumber nextblkno;
127 
128  /*
129  * Check if current page has any DEAD tuples. If yes, delete these
130  * tuples and see if we can get a space for the new item to be
131  * inserted before moving to the next page in the bucket chain.
132  */
133  if (H_HAS_DEAD_TUPLES(pageopaque))
134  {
135 
136  if (IsBufferCleanupOK(buf))
137  {
138  _hash_vacuum_one_page(rel, metabuf, buf, heapRel->rd_node);
139 
140  if (PageGetFreeSpace(page) >= itemsz)
141  break; /* OK, now we have enough space */
142  }
143  }
144 
145  /*
146  * no space on this page; check for an overflow page
147  */
148  nextblkno = pageopaque->hasho_nextblkno;
149 
150  if (BlockNumberIsValid(nextblkno))
151  {
152  /*
153  * ovfl page exists; go get it. if it doesn't have room, we'll
154  * find out next pass through the loop test above. we always
155  * release both the lock and pin if this is an overflow page, but
156  * only the lock if this is the primary bucket page, since the pin
157  * on the primary bucket must be retained throughout the scan.
158  */
159  if (buf != bucket_buf)
160  _hash_relbuf(rel, buf);
161  else
163  buf = _hash_getbuf(rel, nextblkno, HASH_WRITE, LH_OVERFLOW_PAGE);
164  page = BufferGetPage(buf);
165  }
166  else
167  {
168  /*
169  * we're at the end of the bucket chain and we haven't found a
170  * page with enough room. allocate a new overflow page.
171  */
172 
173  /* release our write lock without modifying buffer */
175 
176  /* chain to a new overflow page */
177  buf = _hash_addovflpage(rel, metabuf, buf, (buf == bucket_buf) ? true : false);
178  page = BufferGetPage(buf);
179 
180  /* should fit now, given test above */
181  Assert(PageGetFreeSpace(page) >= itemsz);
182  }
183  pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
184  Assert((pageopaque->hasho_flag & LH_PAGE_TYPE) == LH_OVERFLOW_PAGE);
185  Assert(pageopaque->hasho_bucket == bucket);
186  }
187 
188  /*
189  * Write-lock the metapage so we can increment the tuple count. After
190  * incrementing it, check to see if it's time for a split.
191  */
193 
194  /* Do the update. No ereport(ERROR) until changes are logged */
196 
197  /* found page with enough space, so add the item here */
198  itup_off = _hash_pgaddtup(rel, buf, itemsz, itup);
199  MarkBufferDirty(buf);
200 
201  /* metapage operations */
202  metap = HashPageGetMeta(metapage);
203  metap->hashm_ntuples += 1;
204 
205  /* Make sure this stays in sync with _hash_expandtable() */
206  do_expand = metap->hashm_ntuples >
207  (double) metap->hashm_ffactor * (metap->hashm_maxbucket + 1);
208 
209  MarkBufferDirty(metabuf);
210 
211  /* XLOG stuff */
212  if (RelationNeedsWAL(rel))
213  {
214  xl_hash_insert xlrec;
215  XLogRecPtr recptr;
216 
217  xlrec.offnum = itup_off;
218 
219  XLogBeginInsert();
220  XLogRegisterData((char *) &xlrec, SizeOfHashInsert);
221 
222  XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD);
223 
225  XLogRegisterBufData(0, (char *) itup, IndexTupleDSize(*itup));
226 
227  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INSERT);
228 
229  PageSetLSN(BufferGetPage(buf), recptr);
230  PageSetLSN(BufferGetPage(metabuf), recptr);
231  }
232 
234 
235  /* drop lock on metapage, but keep pin */
236  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
237 
238  /*
239  * Release the modified page and ensure to release the pin on primary
240  * page.
241  */
242  _hash_relbuf(rel, buf);
243  if (buf != bucket_buf)
244  _hash_dropbuf(rel, bucket_buf);
245 
246  /* Attempt to split if a split is needed */
247  if (do_expand)
248  _hash_expandtable(rel, metabuf);
249 
250  /* Finally drop our pin on the metapage */
251  _hash_dropbuf(rel, metabuf);
252 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
#define HashMaxItemSize(page)
Definition: hash.h:277
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define XLOG_HASH_INSERT
Definition: hash_xlog.h:29
int errhint(const char *fmt,...)
Definition: elog.c:987
#define LH_META_PAGE
Definition: hash.h:67
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
uint16 hashm_ffactor
Definition: hash.h:254
uint32 hashm_highmask
Definition: hash.h:260
#define InvalidBuffer
Definition: buf.h:25
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
Buffer _hash_getbucketbuf_from_hashkey(Relation rel, uint32 hashkey, int access, HashMetaPage *cachedmetap)
Definition: hashpage.c:1561
uint32 BlockNumber
Definition: block.h:31
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
uint32 hashm_lowmask
Definition: hash.h:261
Size PageGetFreeSpace(Page page)
Definition: bufpage.c:578
uint16 OffsetNumber
Definition: off.h:24
#define LH_PAGE_TYPE
Definition: hash.h:73
uint32 Bucket
Definition: hash.h:34
#define SizeOfHashInsert
Definition: hash_xlog.h:80
#define ERROR
Definition: elog.h:43
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:299
void _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashpage.c:1357
#define IndexTupleDSize(itup)
Definition: itup.h:71
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_WRITE
Definition: hash.h:330
#define HASH_NOLOCK
Definition: hash.h:331
#define REGBUF_STANDARD
Definition: xloginsert.h:34
unsigned int uint32
Definition: c.h:306
void _hash_expandtable(Relation rel, Buffer metabuf)
Definition: hashpage.c:625
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsBufferCleanupOK(Buffer buffer)
Definition: bufmgr.c:3774
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define HASH_METAPAGE
Definition: hash.h:206
double hashm_ntuples
Definition: hash.h:253
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define H_BUCKET_BEING_SPLIT(opaque)
Definition: hash.h:99
RelFileNode rd_node
Definition: rel.h:85
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
size_t Size
Definition: c.h:414
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
OffsetNumber offnum
Definition: hash_xlog.h:77
Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin)
Definition: hashovfl.c:111
#define MAXALIGN(LEN)
Definition: c.h:633
#define RelationNeedsWAL(relation)
Definition: rel.h:514
uint32 hashm_maxbucket
Definition: hash.h:259
OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, Size itemsize, IndexTuple itup)
Definition: hashinsert.c:266
static void _hash_vacuum_one_page(Relation rel, Buffer metabuf, Buffer buf, RelFileNode hnode)
Definition: hashinsert.c:336
uint16 hasho_flag
Definition: hash.h:92
#define HashPageGetMeta(page)
Definition: hash.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:797
BlockNumber hasho_nextblkno
Definition: hash.h:90
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define H_HAS_DEAD_TUPLES(opaque)
Definition: hash.h:101
Pointer Page
Definition: bufpage.h:74

◆ _hash_dropbuf()

void _hash_dropbuf ( Relation  rel,
Buffer  buf 
)

Definition at line 285 of file hashpage.c.

References ReleaseBuffer().

Referenced by _hash_doinsert(), _hash_dropscanbuf(), _hash_expandtable(), _hash_finish_split(), _hash_first(), _hash_getbucketbuf_from_hashkey(), _hash_next(), _hash_readprev(), and hashbulkdelete().

286 {
288 }
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
static char * buf
Definition: pg_test_fsync.c:67

◆ _hash_dropscanbuf()

void _hash_dropscanbuf ( Relation  rel,
HashScanOpaque  so 
)

Definition at line 297 of file hashpage.c.

References _hash_dropbuf(), HashScanPosData::buf, BufferIsValid, HashScanOpaqueData::currPos, HashScanOpaqueData::hashso_buc_populated, HashScanOpaqueData::hashso_buc_split, HashScanOpaqueData::hashso_bucket_buf, HashScanOpaqueData::hashso_split_bucket_buf, and InvalidBuffer.

Referenced by _hash_next(), hashendscan(), and hashrescan().

298 {
299  /* release pin we hold on primary bucket page */
300  if (BufferIsValid(so->hashso_bucket_buf) &&
301  so->hashso_bucket_buf != so->currPos.buf)
304 
305  /* release pin we hold on primary bucket page of bucket being split */
310 
311  /* release any pin we still hold */
312  if (BufferIsValid(so->currPos.buf))
313  _hash_dropbuf(rel, so->currPos.buf);
314  so->currPos.buf = InvalidBuffer;
315 
316  /* reset split scan */
317  so->hashso_buc_populated = false;
318  so->hashso_buc_split = false;
319 }
#define InvalidBuffer
Definition: buf.h:25
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
Buffer hashso_bucket_buf
Definition: hash.h:172
bool hashso_buc_populated
Definition: hash.h:182
Buffer buf
Definition: hash.h:119
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
HashScanPosData currPos
Definition: hash.h:197
bool hashso_buc_split
Definition: hash.h:188
Buffer hashso_split_bucket_buf
Definition: hash.h:179

◆ _hash_expandtable()

void _hash_expandtable ( Relation  rel,
Buffer  metabuf 
)

Definition at line 625 of file hashpage.c.

References _hash_alloc_buckets(), _hash_checkpage(), _hash_dropbuf(), _hash_finish_split(), _hash_get_totalbuckets(), _hash_getbuf_with_condlock_cleanup(), _hash_getnewbuf(), _hash_relbuf(), _hash_spareindex(), _hash_splitbucket(), Assert, BUCKET_TO_BLKNO, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage, END_CRIT_SECTION, xl_hash_split_allocate_page::flags, H_BUCKET_BEING_SPLIT, H_NEEDS_SPLIT_CLEANUP, hashbucketcleanup(), HashMetaPageData::hashm_ffactor, HashMetaPageData::hashm_highmask, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_ntuples, HashMetaPageData::hashm_ovflpoint, HashMetaPageData::hashm_spares, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, HashPageGetMeta, InvalidBlockNumber, IsBufferCleanupOK(), LH_BUCKET_BEING_POPULATED, LH_BUCKET_BEING_SPLIT, LH_BUCKET_PAGE, LH_META_PAGE, LockBuffer(), MAIN_FORKNUM, MarkBufferDirty(), xl_hash_split_allocate_page::new_bucket, xl_hash_split_allocate_page::new_bucket_flag, xl_hash_split_allocate_page::old_bucket_flag, PageGetSpecialPointer, PageSetLSN, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationNeedsWAL, SizeOfHashSplitAllocPage, START_CRIT_SECTION, XLH_SPLIT_META_UPDATE_MASKS, XLH_SPLIT_META_UPDATE_SPLITPOINT, XLOG_HASH_SPLIT_ALLOCATE_PAGE, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by _hash_doinsert().

626 {
627  HashMetaPage metap;
628  Bucket old_bucket;
629  Bucket new_bucket;
630  uint32 spare_ndx;
631  BlockNumber start_oblkno;
632  BlockNumber start_nblkno;
633  Buffer buf_nblkno;
634  Buffer buf_oblkno;
635  Page opage;
636  Page npage;
637  HashPageOpaque oopaque;
638  HashPageOpaque nopaque;
639  uint32 maxbucket;
640  uint32 highmask;
641  uint32 lowmask;
642  bool metap_update_masks = false;
643  bool metap_update_splitpoint = false;
644 
645 restart_expand:
646 
647  /*
648  * Write-lock the meta page. It used to be necessary to acquire a
649  * heavyweight lock to begin a split, but that is no longer required.
650  */
652 
653  _hash_checkpage(rel, metabuf, LH_META_PAGE);
654  metap = HashPageGetMeta(BufferGetPage(metabuf));
655 
656  /*
657  * Check to see if split is still needed; someone else might have already
658  * done one while we waited for the lock.
659  *
660  * Make sure this stays in sync with _hash_doinsert()
661  */
662  if (metap->hashm_ntuples <=
663  (double) metap->hashm_ffactor * (metap->hashm_maxbucket + 1))
664  goto fail;
665 
666  /*
667  * Can't split anymore if maxbucket has reached its maximum possible
668  * value.
669  *
670  * Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because
671  * the calculation maxbucket+1 mustn't overflow). Currently we restrict
672  * to half that because of overflow looping in _hash_log2() and
673  * insufficient space in hashm_spares[]. It's moot anyway because an
674  * index with 2^32 buckets would certainly overflow BlockNumber and hence
675  * _hash_alloc_buckets() would fail, but if we supported buckets smaller
676  * than a disk block then this would be an independent constraint.
677  *
678  * If you change this, see also the maximum initial number of buckets in
679  * _hash_init().
680  */
681  if (metap->hashm_maxbucket >= (uint32) 0x7FFFFFFE)
682  goto fail;
683 
684  /*
685  * Determine which bucket is to be split, and attempt to take cleanup lock
686  * on the old bucket. If we can't get the lock, give up.
687  *
688  * The cleanup lock protects us not only against other backends, but
689  * against our own backend as well.
690  *
691  * The cleanup lock is mainly to protect the split from concurrent
692  * inserts. See src/backend/access/hash/README, Lock Definitions for
693  * further details. Due to this locking restriction, if there is any
694  * pending scan, the split will give up which is not good, but harmless.
695  */
696  new_bucket = metap->hashm_maxbucket + 1;
697 
698  old_bucket = (new_bucket & metap->hashm_lowmask);
699 
700  start_oblkno = BUCKET_TO_BLKNO(metap, old_bucket);
701 
702  buf_oblkno = _hash_getbuf_with_condlock_cleanup(rel, start_oblkno, LH_BUCKET_PAGE);
703  if (!buf_oblkno)
704  goto fail;
705 
706  opage = BufferGetPage(buf_oblkno);
707  oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
708 
709  /*
710  * We want to finish the split from a bucket as there is no apparent
711  * benefit by not doing so and it will make the code complicated to finish
712  * the split that involves multiple buckets considering the case where new
713  * split also fails. We don't need to consider the new bucket for
714  * completing the split here as it is not possible that a re-split of new
715  * bucket starts when there is still a pending split from old bucket.
716  */
717  if (H_BUCKET_BEING_SPLIT(oopaque))
718  {
719  /*
720  * Copy bucket mapping info now; refer the comment in code below where
721  * we copy this information before calling _hash_splitbucket to see
722  * why this is okay.
723  */
724  maxbucket = metap->hashm_maxbucket;
725  highmask = metap->hashm_highmask;
726  lowmask = metap->hashm_lowmask;
727 
728  /*
729  * Release the lock on metapage and old_bucket, before completing the
730  * split.
731  */
732  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
733  LockBuffer(buf_oblkno, BUFFER_LOCK_UNLOCK);
734 
735  _hash_finish_split(rel, metabuf, buf_oblkno, old_bucket, maxbucket,
736  highmask, lowmask);
737 
738  /* release the pin on old buffer and retry for expand. */
739  _hash_dropbuf(rel, buf_oblkno);
740 
741  goto restart_expand;
742  }
743 
744  /*
745  * Clean the tuples remained from the previous split. This operation
746  * requires cleanup lock and we already have one on the old bucket, so
747  * let's do it. We also don't want to allow further splits from the bucket
748  * till the garbage of previous split is cleaned. This has two
749  * advantages; first, it helps in avoiding the bloat due to garbage and
750  * second is, during cleanup of bucket, we are always sure that the
751  * garbage tuples belong to most recently split bucket. On the contrary,
752  * if we allow cleanup of bucket after meta page is updated to indicate
753  * the new split and before the actual split, the cleanup operation won't
754  * be able to decide whether the tuple has been moved to the newly created
755  * bucket and ended up deleting such tuples.
756  */
757  if (H_NEEDS_SPLIT_CLEANUP(oopaque))
758  {
759  /*
760  * Copy bucket mapping info now; refer to the comment in code below
761  * where we copy this information before calling _hash_splitbucket to
762  * see why this is okay.
763  */
764  maxbucket = metap->hashm_maxbucket;
765  highmask = metap->hashm_highmask;
766  lowmask = metap->hashm_lowmask;
767 
768  /* Release the metapage lock. */
769  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
770 
771  hashbucketcleanup(rel, old_bucket, buf_oblkno, start_oblkno, NULL,
772  maxbucket, highmask, lowmask, NULL, NULL, true,
773  NULL, NULL);
774 
775  _hash_dropbuf(rel, buf_oblkno);
776 
777  goto restart_expand;
778  }
779 
780  /*
781  * There shouldn't be any active scan on new bucket.
782  *
783  * Note: it is safe to compute the new bucket's blkno here, even though we
784  * may still need to update the BUCKET_TO_BLKNO mapping. This is because
785  * the current value of hashm_spares[hashm_ovflpoint] correctly shows
786  * where we are going to put a new splitpoint's worth of buckets.
787  */
788  start_nblkno = BUCKET_TO_BLKNO(metap, new_bucket);
789 
790  /*
791  * If the split point is increasing we need to allocate a new batch of
792  * bucket pages.
793  */
794  spare_ndx = _hash_spareindex(new_bucket + 1);
795  if (spare_ndx > metap->hashm_ovflpoint)
796  {
797  uint32 buckets_to_add;
798 
799  Assert(spare_ndx == metap->hashm_ovflpoint + 1);
800 
801  /*
802  * We treat allocation of buckets as a separate WAL-logged action.
803  * Even if we fail after this operation, won't leak bucket pages;
804  * rather, the next split will consume this space. In any case, even
805  * without failure we don't use all the space in one split operation.
806  */
807  buckets_to_add = _hash_get_totalbuckets(spare_ndx) - new_bucket;
808  if (!_hash_alloc_buckets(rel, start_nblkno, buckets_to_add))
809  {
810  /* can't split due to BlockNumber overflow */
811  _hash_relbuf(rel, buf_oblkno);
812  goto fail;
813  }
814  }
815 
816  /*
817  * Physically allocate the new bucket's primary page. We want to do this
818  * before changing the metapage's mapping info, in case we can't get the
819  * disk space. Ideally, we don't need to check for cleanup lock on new
820  * bucket as no other backend could find this bucket unless meta page is
821  * updated. However, it is good to be consistent with old bucket locking.
822  */
823  buf_nblkno = _hash_getnewbuf(rel, start_nblkno, MAIN_FORKNUM);
824  if (!IsBufferCleanupOK(buf_nblkno))
825  {
826  _hash_relbuf(rel, buf_oblkno);
827  _hash_relbuf(rel, buf_nblkno);
828  goto fail;
829  }
830 
831  /*
832  * Since we are scribbling on the pages in the shared buffers, establish a
833  * critical section. Any failure in this next code leaves us with a big
834  * problem: the metapage is effectively corrupt but could get written back
835  * to disk.
836  */
838 
839  /*
840  * Okay to proceed with split. Update the metapage bucket mapping info.
841  */
842  metap->hashm_maxbucket = new_bucket;
843 
844  if (new_bucket > metap->hashm_highmask)
845  {
846  /* Starting a new doubling */
847  metap->hashm_lowmask = metap->hashm_highmask;
848  metap->hashm_highmask = new_bucket | metap->hashm_lowmask;
849  metap_update_masks = true;
850  }
851 
852  /*
853  * If the split point is increasing we need to adjust the hashm_spares[]
854  * array and hashm_ovflpoint so that future overflow pages will be created
855  * beyond this new batch of bucket pages.
856  */
857  if (spare_ndx > metap->hashm_ovflpoint)
858  {
859  metap->hashm_spares[spare_ndx] = metap->hashm_spares[metap->hashm_ovflpoint];
860  metap->hashm_ovflpoint = spare_ndx;
861  metap_update_splitpoint = true;
862  }
863 
864  MarkBufferDirty(metabuf);
865 
866  /*
867  * Copy bucket mapping info now; this saves re-accessing the meta page
868  * inside _hash_splitbucket's inner loop. Note that once we drop the
869  * split lock, other splits could begin, so these values might be out of
870  * date before _hash_splitbucket finishes. That's okay, since all it
871  * needs is to tell which of these two buckets to map hashkeys into.
872  */
873  maxbucket = metap->hashm_maxbucket;
874  highmask = metap->hashm_highmask;
875  lowmask = metap->hashm_lowmask;
876 
877  opage = BufferGetPage(buf_oblkno);
878  oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
879 
880  /*
881  * Mark the old bucket to indicate that split is in progress. (At
882  * operation end, we will clear the split-in-progress flag.) Also, for a
883  * primary bucket page, hasho_prevblkno stores the number of buckets that
884  * existed as of the last split, so we must update that value here.
885  */
886  oopaque->hasho_flag |= LH_BUCKET_BEING_SPLIT;
887  oopaque->hasho_prevblkno = maxbucket;
888 
889  MarkBufferDirty(buf_oblkno);
890 
891  npage = BufferGetPage(buf_nblkno);
892 
893  /*
894  * initialize the new bucket's primary page and mark it to indicate that
895  * split is in progress.
896  */
897  nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
898  nopaque->hasho_prevblkno = maxbucket;
900  nopaque->hasho_bucket = new_bucket;
902  nopaque->hasho_page_id = HASHO_PAGE_ID;
903 
904  MarkBufferDirty(buf_nblkno);
905 
906  /* XLOG stuff */
907  if (RelationNeedsWAL(rel))
908  {
910  XLogRecPtr recptr;
911 
912  xlrec.new_bucket = maxbucket;
913  xlrec.old_bucket_flag = oopaque->hasho_flag;
914  xlrec.new_bucket_flag = nopaque->hasho_flag;
915  xlrec.flags = 0;
916 
917  XLogBeginInsert();
918 
919  XLogRegisterBuffer(0, buf_oblkno, REGBUF_STANDARD);
920  XLogRegisterBuffer(1, buf_nblkno, REGBUF_WILL_INIT);
921  XLogRegisterBuffer(2, metabuf, REGBUF_STANDARD);
922 
923  if (metap_update_masks)
924  {
926  XLogRegisterBufData(2, (char *) &metap->hashm_lowmask, sizeof(uint32));
927  XLogRegisterBufData(2, (char *) &metap->hashm_highmask, sizeof(uint32));
928  }
929 
930  if (metap_update_splitpoint)
931  {
933  XLogRegisterBufData(2, (char *) &metap->hashm_ovflpoint,
934  sizeof(uint32));
936  (char *) &metap->hashm_spares[metap->hashm_ovflpoint],
937  sizeof(uint32));
938  }
939 
940  XLogRegisterData((char *) &xlrec, SizeOfHashSplitAllocPage);
941 
942  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_ALLOCATE_PAGE);
943 
944  PageSetLSN(BufferGetPage(buf_oblkno), recptr);
945  PageSetLSN(BufferGetPage(buf_nblkno), recptr);
946  PageSetLSN(BufferGetPage(metabuf), recptr);
947  }
948 
950 
951  /* drop lock, but keep pin */
952  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
953 
954  /* Relocate records to the new bucket */
955  _hash_splitbucket(rel, metabuf,
956  old_bucket, new_bucket,
957  buf_oblkno, buf_nblkno, NULL,
958  maxbucket, highmask, lowmask);
959 
960  /* all done, now release the pins on primary buckets. */
961  _hash_dropbuf(rel, buf_oblkno);
962  _hash_dropbuf(rel, buf_nblkno);
963 
964  return;
965 
966  /* Here if decide not to split or fail to acquire old bucket lock */
967 fail:
968 
969  /* We didn't write the metapage, so just drop lock */
970  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
971 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
uint16 hasho_page_id
Definition: hash.h:93
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define XLH_SPLIT_META_UPDATE_SPLITPOINT
Definition: hash_xlog.h:52
#define LH_META_PAGE
Definition: hash.h:67
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
uint16 hashm_ffactor
Definition: hash.h:254
uint32 hashm_highmask
Definition: hash.h:260
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
void hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, BlockNumber bucket_blkno, BufferAccessStrategy bstrategy, uint32 maxbucket, uint32 highmask, uint32 lowmask, double *tuples_removed, double *num_index_tuples, bool split_cleanup, IndexBulkDeleteCallback callback, void *callback_state)
Definition: hash.c:672
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getnewbuf(Relation rel, BlockNumber blkno, ForkNumber forkNum)
Definition: hashpage.c:206
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
uint32 hashm_lowmask
Definition: hash.h:261
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
static bool _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nblocks)
Definition: hashpage.c:999
uint32 Bucket
Definition: hash.h:34
#define H_NEEDS_SPLIT_CLEANUP(opaque)
Definition: hash.h:98
BlockNumber hasho_prevblkno
Definition: hash.h:89
#define SizeOfHashSplitAllocPage
Definition: hash_xlog.h:119
uint32 _hash_spareindex(uint32 num_bucket)
Definition: hashutil.c:157
uint32 _hash_get_totalbuckets(uint32 splitpoint_phase)
Definition: hashutil.c:189
void _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashpage.c:1357
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define LH_BUCKET_BEING_SPLIT
Definition: hash.h:69
unsigned int uint32
Definition: c.h:306
Buffer _hash_getbuf_with_condlock_cleanup(Relation rel, BlockNumber blkno, int flags)
Definition: hashpage.c:104
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
bool IsBufferCleanupOK(Buffer buffer)
Definition: bufmgr.c:3774
uint32 hashm_ovflpoint
Definition: hash.h:262
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
#define LH_BUCKET_BEING_POPULATED
Definition: hash.h:68
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
double hashm_ntuples
Definition: hash.h:253
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint32 hashm_spares[HASH_MAX_SPLITPOINTS]
Definition: hash.h:267
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define LH_BUCKET_PAGE
Definition: hash.h:65
#define H_BUCKET_BEING_SPLIT(opaque)
Definition: hash.h:99
static void _hash_splitbucket(Relation rel, Buffer metabuf, Bucket obucket, Bucket nbucket, Buffer obuf, Buffer nbuf, HTAB *htab, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashpage.c:1079
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define HASHO_PAGE_ID
Definition: hash.h:109
#define RelationNeedsWAL(relation)
Definition: rel.h:514
uint32 hashm_maxbucket
Definition: hash.h:259
uint16 hasho_flag
Definition: hash.h:92
#define XLOG_HASH_SPLIT_ALLOCATE_PAGE
Definition: hash_xlog.h:31
#define HashPageGetMeta(page)
Definition: hash.h:313
BlockNumber hasho_nextblkno
Definition: hash.h:90
#define XLH_SPLIT_META_UPDATE_MASKS
Definition: hash_xlog.h:51
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74

◆ _hash_finish_split()

void _hash_finish_split ( Relation  rel,
Buffer  metabuf,
Buffer  obuf,
Bucket  obucket,
uint32  maxbucket,
uint32  highmask,
uint32  lowmask 
)

Definition at line 1357 of file hashpage.c.

References _hash_dropbuf(), _hash_get_newblock_from_oldbucket(), _hash_getbuf(), _hash_relbuf(), _hash_splitbucket(), Assert, BlockNumberIsValid, BUFFER_LOCK_UNLOCK, BufferGetPage, ConditionalLockBufferForCleanup(), CurrentMemoryContext, HASHCTL::entrysize, FirstOffsetNumber, HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, HASH_ENTER, HASH_READ, hash_search(), HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_nextblkno, HASHCTL::hcxt, InvalidBuffer, HASHCTL::keysize, LH_BUCKET_PAGE, LH_OVERFLOW_PAGE, LockBuffer(), OffsetNumberNext, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageGetSpecialPointer, and IndexTupleData::t_tid.

Referenced by _hash_doinsert(), and _hash_expandtable().

1359 {
1360  HASHCTL hash_ctl;
1361  HTAB *tidhtab;
1362  Buffer bucket_nbuf = InvalidBuffer;
1363  Buffer nbuf;
1364  Page npage;
1365  BlockNumber nblkno;
1366  BlockNumber bucket_nblkno;
1367  HashPageOpaque npageopaque;
1368  Bucket nbucket;
1369  bool found;
1370 
1371  /* Initialize hash tables used to track TIDs */
1372  memset(&hash_ctl, 0, sizeof(hash_ctl));
1373  hash_ctl.keysize = sizeof(ItemPointerData);
1374  hash_ctl.entrysize = sizeof(ItemPointerData);
1375  hash_ctl.hcxt = CurrentMemoryContext;
1376 
1377  tidhtab =
1378  hash_create("bucket ctids",
1379  256, /* arbitrary initial size */
1380  &hash_ctl,
1382 
1383  bucket_nblkno = nblkno = _hash_get_newblock_from_oldbucket(rel, obucket);
1384 
1385  /*
1386  * Scan the new bucket and build hash table of TIDs
1387  */
1388  for (;;)
1389  {
1390  OffsetNumber noffnum;
1391  OffsetNumber nmaxoffnum;
1392 
1393  nbuf = _hash_getbuf(rel, nblkno, HASH_READ,
1395 
1396  /* remember the primary bucket buffer to acquire cleanup lock on it. */
1397  if (nblkno == bucket_nblkno)
1398  bucket_nbuf = nbuf;
1399 
1400  npage = BufferGetPage(nbuf);
1401  npageopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
1402 
1403  /* Scan each tuple in new page */
1404  nmaxoffnum = PageGetMaxOffsetNumber(npage);
1405  for (noffnum = FirstOffsetNumber;
1406  noffnum <= nmaxoffnum;
1407  noffnum = OffsetNumberNext(noffnum))
1408  {
1409  IndexTuple itup;
1410 
1411  /* Fetch the item's TID and insert it in hash table. */
1412  itup = (IndexTuple) PageGetItem(npage,
1413  PageGetItemId(npage, noffnum));
1414 
1415  (void) hash_search(tidhtab, &itup->t_tid, HASH_ENTER, &found);
1416 
1417  Assert(!found);
1418  }
1419 
1420  nblkno = npageopaque->hasho_nextblkno;
1421 
1422  /*
1423  * release our write lock without modifying buffer and ensure to
1424  * retain the pin on primary bucket.
1425  */
1426  if (nbuf == bucket_nbuf)
1428  else
1429  _hash_relbuf(rel, nbuf);
1430 
1431  /* Exit loop if no more overflow pages in new bucket */
1432  if (!BlockNumberIsValid(nblkno))
1433  break;
1434  }
1435 
1436  /*
1437  * Conditionally get the cleanup lock on old and new buckets to perform
1438  * the split operation. If we don't get the cleanup locks, silently give
1439  * up and next insertion on old bucket will try again to complete the
1440  * split.
1441  */
1443  {
1444  hash_destroy(tidhtab);
1445  return;
1446  }
1447  if (!ConditionalLockBufferForCleanup(bucket_nbuf))
1448  {
1450  hash_destroy(tidhtab);
1451  return;
1452  }
1453 
1454  npage = BufferGetPage(bucket_nbuf);
1455  npageopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
1456  nbucket = npageopaque->hasho_bucket;
1457 
1458  _hash_splitbucket(rel, metabuf, obucket,
1459  nbucket, obuf, bucket_nbuf, tidhtab,
1460  maxbucket, highmask, lowmask);
1461 
1462  _hash_dropbuf(rel, bucket_nbuf);
1463  hash_destroy(tidhtab);
1464 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:812
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
ItemPointerData t_tid
Definition: itup.h:37
#define InvalidBuffer
Definition: buf.h:25
Size entrysize
Definition: hsearch.h:73
uint32 BlockNumber
Definition: block.h:31
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
Definition: dynahash.c:208
bool ConditionalLockBufferForCleanup(Buffer buffer)
Definition: bufmgr.c:3718
#define FirstOffsetNumber
Definition: off.h:27
IndexTupleData * IndexTuple
Definition: itup.h:53
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Size keysize
Definition: hsearch.h:72
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
BlockNumber _hash_get_newblock_from_oldbucket(Relation rel, Bucket old_bucket)
Definition: hashutil.c:469
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define LH_BUCKET_PAGE
Definition: hash.h:65
static void _hash_splitbucket(Relation rel, Buffer metabuf, Bucket obucket, Bucket nbucket, Buffer obuf, Buffer nbuf, HTAB *htab, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashpage.c:1079
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
struct ItemPointerData ItemPointerData
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
BlockNumber hasho_nextblkno
Definition: hash.h:90
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74

◆ _hash_first()

bool _hash_first ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 290 of file hashsearch.c.

References _hash_datum2hashkey(), _hash_datum2hashkey_type(), _hash_dropbuf(), _hash_get_oldblock_from_newbucket(), _hash_getbucketbuf_from_hashkey(), _hash_getbuf(), _hash_readnext(), _hash_readpage(), Assert, BlockNumberIsValid, buf, HashScanPosData::buf, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, BufferIsInvalid, cur, HashScanOpaqueData::currPos, ereport, errcode(), errmsg(), ERROR, H_BUCKET_BEING_POPULATED, HASH_READ, HashScanOpaqueData::hashso_buc_populated, HashScanOpaqueData::hashso_buc_split, HashScanOpaqueData::hashso_bucket_buf, HashScanOpaqueData::hashso_sk_hash, HashScanOpaqueData::hashso_split_bucket_buf, HTEqualStrategyNumber, IndexScanDescData::indexRelation, InvalidBuffer, InvalidOid, HashScanPosData::itemIndex, HashScanPosData::items, IndexScanDescData::keyData, LH_BUCKET_PAGE, LockBuffer(), IndexScanDescData::numberOfKeys, IndexScanDescData::opaque, PageGetSpecialPointer, pgstat_count_index_scan, RelationData::rd_opcintype, ScanDirectionIsBackward, SK_ISNULL, HeapTupleData::t_self, TestForOldSnapshot(), IndexScanDescData::xs_ctup, and IndexScanDescData::xs_snapshot.

Referenced by hashgetbitmap(), and hashgettuple().

291 {
292  Relation rel = scan->indexRelation;
293  HashScanOpaque so = (HashScanOpaque) scan->opaque;
294  ScanKey cur;
295  uint32 hashkey;
296  Bucket bucket;
297  Buffer buf;
298  Page page;
299  HashPageOpaque opaque;
300  HashScanPosItem *currItem;
301 
303 
304  /*
305  * We do not support hash scans with no index qualification, because we
306  * would have to read the whole index rather than just one bucket. That
307  * creates a whole raft of problems, since we haven't got a practical way
308  * to lock all the buckets against splits or compactions.
309  */
310  if (scan->numberOfKeys < 1)
311  ereport(ERROR,
312  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
313  errmsg("hash indexes do not support whole-index scans")));
314 
315  /* There may be more than one index qual, but we hash only the first */
316  cur = &scan->keyData[0];
317 
318  /* We support only single-column hash indexes */
319  Assert(cur->sk_attno == 1);
320  /* And there's only one operator strategy, too */
321  Assert(cur->sk_strategy == HTEqualStrategyNumber);
322 
323  /*
324  * If the constant in the index qual is NULL, assume it cannot match any
325  * items in the index.
326  */
327  if (cur->sk_flags & SK_ISNULL)
328  return false;
329 
330  /*
331  * Okay to compute the hash key. We want to do this before acquiring any
332  * locks, in case a user-defined hash function happens to be slow.
333  *
334  * If scankey operator is not a cross-type comparison, we can use the
335  * cached hash function; otherwise gotta look it up in the catalogs.
336  *
337  * We support the convention that sk_subtype == InvalidOid means the
338  * opclass input type; this is a hack to simplify life for ScanKeyInit().
339  */
340  if (cur->sk_subtype == rel->rd_opcintype[0] ||
341  cur->sk_subtype == InvalidOid)
342  hashkey = _hash_datum2hashkey(rel, cur->sk_argument);
343  else
344  hashkey = _hash_datum2hashkey_type(rel, cur->sk_argument,
345  cur->sk_subtype);
346 
347  so->hashso_sk_hash = hashkey;
348 
349  buf = _hash_getbucketbuf_from_hashkey(rel, hashkey, HASH_READ, NULL);
350  page = BufferGetPage(buf);
351  TestForOldSnapshot(scan->xs_snapshot, rel, page);
352  opaque = (HashPageOpaque) PageGetSpecialPointer(page);
353  bucket = opaque->hasho_bucket;
354 
355  so->hashso_bucket_buf = buf;
356 
357  /*
358  * If a bucket split is in progress, then while scanning the bucket being
359  * populated, we need to skip tuples that were copied from bucket being
360  * split. We also need to maintain a pin on the bucket being split to
361  * ensure that split-cleanup work done by vacuum doesn't remove tuples
362  * from it till this scan is done. We need to maintain a pin on the
363  * bucket being populated to ensure that vacuum doesn't squeeze that
364  * bucket till this scan is complete; otherwise, the ordering of tuples
365  * can't be maintained during forward and backward scans. Here, we have
366  * to be cautious about locking order: first, acquire the lock on bucket
367  * being split; then, release the lock on it but not the pin; then,
368  * acquire a lock on bucket being populated and again re-verify whether
369  * the bucket split is still in progress. Acquiring the lock on bucket
370  * being split first ensures that the vacuum waits for this scan to
371  * finish.
372  */
373  if (H_BUCKET_BEING_POPULATED(opaque))
374  {
375  BlockNumber old_blkno;
376  Buffer old_buf;
377 
378  old_blkno = _hash_get_oldblock_from_newbucket(rel, bucket);
379 
380  /*
381  * release the lock on new bucket and re-acquire it after acquiring
382  * the lock on old bucket.
383  */
385 
386  old_buf = _hash_getbuf(rel, old_blkno, HASH_READ, LH_BUCKET_PAGE);
387  TestForOldSnapshot(scan->xs_snapshot, rel, BufferGetPage(old_buf));
388 
389  /*
390  * remember the split bucket buffer so as to use it later for
391  * scanning.
392  */
393  so->hashso_split_bucket_buf = old_buf;
394  LockBuffer(old_buf, BUFFER_LOCK_UNLOCK);
395 
397  page = BufferGetPage(buf);
398  opaque = (HashPageOpaque) PageGetSpecialPointer(page);
399  Assert(opaque->hasho_bucket == bucket);
400 
401  if (H_BUCKET_BEING_POPULATED(opaque))
402  so->hashso_buc_populated = true;
403  else
404  {
407  }
408  }
409 
410  /* If a backwards scan is requested, move to the end of the chain */
411  if (ScanDirectionIsBackward(dir))
412  {
413  /*
414  * Backward scans that start during split needs to start from end of
415  * bucket being split.
416  */
417  while (BlockNumberIsValid(opaque->hasho_nextblkno) ||
419  _hash_readnext(scan, &buf, &page, &opaque);
420  }
421 
422  /* remember which buffer we have pinned, if any */
424  so->currPos.buf = buf;
425 
426  /* Now find all the tuples satisfying the qualification from a page */
427  if (!_hash_readpage(scan, &buf, dir))
428  return false;
429 
430  /* OK, itemIndex says what to return */
431  currItem = &so->currPos.items[so->currPos.itemIndex];
432  scan->xs_ctup.t_self = currItem->heapTid;
433 
434  /* if we're here, _hash_readpage found a valid tuples */
435  return true;
436 }
HashScanOpaqueData * HashScanOpaque
Definition: hash.h:200
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
static void TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
Definition: bufmgr.h:265
static void _hash_readnext(IndexScanDesc scan, Buffer *bufp, Page *pagep, HashPageOpaque *opaquep)
Definition: hashsearch.c:132
static bool _hash_readpage(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
Definition: hashsearch.c:449
#define HTEqualStrategyNumber
Definition: hash.h:336
Snapshot xs_snapshot
Definition: relscan.h:91
#define InvalidBuffer
Definition: buf.h:25
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:575
Buffer _hash_getbucketbuf_from_hashkey(Relation rel, uint32 hashkey, int access, HashMetaPage *cachedmetap)
Definition: hashpage.c:1561
uint32 BlockNumber
Definition: block.h:31
uint32 _hash_datum2hashkey(Relation rel, Datum key)
Definition: hashutil.c:82
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
Relation indexRelation
Definition: relscan.h:90
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
#define ScanDirectionIsBackward(direction)
Definition: sdir.h:41
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define BufferIsInvalid(buffer)
Definition: buf.h:31
static char * buf
Definition: pg_test_fsync.c:67
#define pgstat_count_index_scan(rel)
Definition: pgstat.h:1275
unsigned int uint32
Definition: c.h:306
#define SK_ISNULL
Definition: skey.h:115
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
Buffer hashso_bucket_buf
Definition: hash.h:172
#define H_BUCKET_BEING_POPULATED(opaque)
Definition: hash.h:100
bool hashso_buc_populated
Definition: hash.h:182
Buffer buf
Definition: hash.h:119
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint32 hashso_sk_hash
Definition: hash.h:169
#define InvalidOid
Definition: postgres_ext.h:36
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define LH_BUCKET_PAGE
Definition: hash.h:65
#define Assert(condition)
Definition: c.h:680
HeapTupleData xs_ctup
Definition: relscan.h:120
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
ScanKey keyData
Definition: relscan.h:94
BlockNumber _hash_get_oldblock_from_newbucket(Relation rel, Bucket new_bucket)
Definition: hashutil.c:430
HashScanPosData currPos
Definition: hash.h:197
bool hashso_buc_split
Definition: hash.h:188
int errmsg(const char *fmt,...)
Definition: elog.c:797
Buffer hashso_split_bucket_buf
Definition: hash.h:179
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype)
Definition: hashutil.c:102
int itemIndex
Definition: hash.h:133
Oid * rd_opcintype
Definition: rel.h:183
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
HashScanPosItem items[MaxIndexTuplesPerPage]
Definition: hash.h:135

◆ _hash_freeovflpage()

BlockNumber _hash_freeovflpage ( Relation  rel,
Buffer  bucketbuf,
Buffer  ovflbuf,
Buffer  wbuf,
IndexTuple itups,
OffsetNumber itup_offsets,
Size tups_size,
uint16  nitups,
BufferAccessStrategy  bstrategy 
)

Definition at line 488 of file hashovfl.c.

References _hash_checkpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_ovflblkno_to_bitno(), _hash_pageinit(), _hash_pgaddmultitup(), _hash_relbuf(), Assert, BlockNumberIsValid, BMPG_MASK, BMPG_SHIFT, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferGetPageSize, BufferIsValid, CLRBIT, elog, END_CRIT_SECTION, ERROR, HASH_METAPAGE, HASH_READ, HASH_WRITE, HASH_XLOG_FREE_OVFL_BUFS, HashMetaPageData::hashm_firstfree, HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_nmaps, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, HashPageGetBitmap, HashPageGetMeta, i, InvalidBlockNumber, InvalidBuffer, xl_hash_squeeze_page::is_prev_bucket_same_wrt, xl_hash_squeeze_page::is_prim_bucket_same_wrt, ISSET, LH_BITMAP_PAGE, LH_BUCKET_PAGE, LH_META_PAGE, LH_OVERFLOW_PAGE, LH_UNUSED_PAGE, LockBuffer(), MarkBufferDirty(), xl_hash_squeeze_page::nextblkno, xl_hash_squeeze_page::ntups, PageGetSpecialPointer, PageSetLSN, PG_USED_FOR_ASSERTS_ONLY, xl_hash_squeeze_page::prevblkno, REGBUF_NO_IMAGE, REGBUF_STANDARD, RelationNeedsWAL, SizeOfHashSqueezePage, START_CRIT_SECTION, XLOG_HASH_SQUEEZE_PAGE, XLogBeginInsert(), XLogEnsureRecordSpace(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by _hash_squeezebucket().

492 {
493  HashMetaPage metap;
494  Buffer metabuf;
495  Buffer mapbuf;
496  BlockNumber ovflblkno;
497  BlockNumber prevblkno;
498  BlockNumber blkno;
499  BlockNumber nextblkno;
500  BlockNumber writeblkno;
501  HashPageOpaque ovflopaque;
502  Page ovflpage;
503  Page mappage;
504  uint32 *freep;
505  uint32 ovflbitno;
506  int32 bitmappage,
507  bitmapbit;
509  Buffer prevbuf = InvalidBuffer;
510  Buffer nextbuf = InvalidBuffer;
511  bool update_metap = false;
512 
513  /* Get information from the doomed page */
514  _hash_checkpage(rel, ovflbuf, LH_OVERFLOW_PAGE);
515  ovflblkno = BufferGetBlockNumber(ovflbuf);
516  ovflpage = BufferGetPage(ovflbuf);
517  ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
518  nextblkno = ovflopaque->hasho_nextblkno;
519  prevblkno = ovflopaque->hasho_prevblkno;
520  writeblkno = BufferGetBlockNumber(wbuf);
521  bucket = ovflopaque->hasho_bucket;
522 
523  /*
524  * Fix up the bucket chain. this is a doubly-linked list, so we must fix
525  * up the bucket chain members behind and ahead of the overflow page being
526  * deleted. Concurrency issues are avoided by using lock chaining as
527  * described atop hashbucketcleanup.
528  */
529  if (BlockNumberIsValid(prevblkno))
530  {
531  if (prevblkno == writeblkno)
532  prevbuf = wbuf;
533  else
534  prevbuf = _hash_getbuf_with_strategy(rel,
535  prevblkno,
536  HASH_WRITE,
538  bstrategy);
539  }
540  if (BlockNumberIsValid(nextblkno))
541  nextbuf = _hash_getbuf_with_strategy(rel,
542  nextblkno,
543  HASH_WRITE,
545  bstrategy);
546 
547  /* Note: bstrategy is intentionally not used for metapage and bitmap */
548 
549  /* Read the metapage so we can determine which bitmap page to use */
551  metap = HashPageGetMeta(BufferGetPage(metabuf));
552 
553  /* Identify which bit to set */
554  ovflbitno = _hash_ovflblkno_to_bitno(metap, ovflblkno);
555 
556  bitmappage = ovflbitno >> BMPG_SHIFT(metap);
557  bitmapbit = ovflbitno & BMPG_MASK(metap);
558 
559  if (bitmappage >= metap->hashm_nmaps)
560  elog(ERROR, "invalid overflow bit number %u", ovflbitno);
561  blkno = metap->hashm_mapp[bitmappage];
562 
563  /* Release metapage lock while we access the bitmap page */
564  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
565 
566  /* read the bitmap page to clear the bitmap bit */
567  mapbuf = _hash_getbuf(rel, blkno, HASH_WRITE, LH_BITMAP_PAGE);
568  mappage = BufferGetPage(mapbuf);
569  freep = HashPageGetBitmap(mappage);
570  Assert(ISSET(freep, bitmapbit));
571 
572  /* Get write-lock on metapage to update firstfree */
574 
575  /* This operation needs to log multiple tuples, prepare WAL for that */
576  if (RelationNeedsWAL(rel))
578 
580 
581  /*
582  * we have to insert tuples on the "write" page, being careful to preserve
583  * hashkey ordering. (If we insert many tuples into the same "write" page
584  * it would be worth qsort'ing them).
585  */
586  if (nitups > 0)
587  {
588  _hash_pgaddmultitup(rel, wbuf, itups, itup_offsets, nitups);
589  MarkBufferDirty(wbuf);
590  }
591 
592  /*
593  * Reinitialize the freed overflow page. Just zeroing the page won't
594  * work, because WAL replay routines expect pages to be initialized. See
595  * explanation of RBM_NORMAL mode atop XLogReadBufferExtended. We are
596  * careful to make the special space valid here so that tools like
597  * pageinspect won't get confused.
598  */
599  _hash_pageinit(ovflpage, BufferGetPageSize(ovflbuf));
600 
601  ovflopaque = (HashPageOpaque) PageGetSpecialPointer(ovflpage);
602 
603  ovflopaque->hasho_prevblkno = InvalidBlockNumber;
604  ovflopaque->hasho_nextblkno = InvalidBlockNumber;
605  ovflopaque->hasho_bucket = -1;
606  ovflopaque->hasho_flag = LH_UNUSED_PAGE;
607  ovflopaque->hasho_page_id = HASHO_PAGE_ID;
608 
609  MarkBufferDirty(ovflbuf);
610 
611  if (BufferIsValid(prevbuf))
612  {
613  Page prevpage = BufferGetPage(prevbuf);
614  HashPageOpaque prevopaque = (HashPageOpaque) PageGetSpecialPointer(prevpage);
615 
616  Assert(prevopaque->hasho_bucket == bucket);
617  prevopaque->hasho_nextblkno = nextblkno;
618  MarkBufferDirty(prevbuf);
619  }
620  if (BufferIsValid(nextbuf))
621  {
622  Page nextpage = BufferGetPage(nextbuf);
623  HashPageOpaque nextopaque = (HashPageOpaque) PageGetSpecialPointer(nextpage);
624 
625  Assert(nextopaque->hasho_bucket == bucket);
626  nextopaque->hasho_prevblkno = prevblkno;
627  MarkBufferDirty(nextbuf);
628  }
629 
630  /* Clear the bitmap bit to indicate that this overflow page is free */
631  CLRBIT(freep, bitmapbit);
632  MarkBufferDirty(mapbuf);
633 
634  /* if this is now the first free page, update hashm_firstfree */
635  if (ovflbitno < metap->hashm_firstfree)
636  {
637  metap->hashm_firstfree = ovflbitno;
638  update_metap = true;
639  MarkBufferDirty(metabuf);
640  }
641 
642  /* XLOG stuff */
643  if (RelationNeedsWAL(rel))
644  {
645  xl_hash_squeeze_page xlrec;
646  XLogRecPtr recptr;
647  int i;
648 
649  xlrec.prevblkno = prevblkno;
650  xlrec.nextblkno = nextblkno;
651  xlrec.ntups = nitups;
652  xlrec.is_prim_bucket_same_wrt = (wbuf == bucketbuf);
653  xlrec.is_prev_bucket_same_wrt = (wbuf == prevbuf);
654 
655  XLogBeginInsert();
656  XLogRegisterData((char *) &xlrec, SizeOfHashSqueezePage);
657 
658  /*
659  * bucket buffer needs to be registered to ensure that we can acquire
660  * a cleanup lock on it during replay.
661  */
662  if (!xlrec.is_prim_bucket_same_wrt)
664 
666  if (xlrec.ntups > 0)
667  {
668  XLogRegisterBufData(1, (char *) itup_offsets,
669  nitups * sizeof(OffsetNumber));
670  for (i = 0; i < nitups; i++)
671  XLogRegisterBufData(1, (char *) itups[i], tups_size[i]);
672  }
673 
674  XLogRegisterBuffer(2, ovflbuf, REGBUF_STANDARD);
675 
676  /*
677  * If prevpage and the writepage (block in which we are moving tuples
678  * from overflow) are same, then no need to separately register
679  * prevpage. During replay, we can directly update the nextblock in
680  * writepage.
681  */
682  if (BufferIsValid(prevbuf) && !xlrec.is_prev_bucket_same_wrt)
683  XLogRegisterBuffer(3, prevbuf, REGBUF_STANDARD);
684 
685  if (BufferIsValid(nextbuf))
686  XLogRegisterBuffer(4, nextbuf, REGBUF_STANDARD);
687 
689  XLogRegisterBufData(5, (char *) &bitmapbit, sizeof(uint32));
690 
691  if (update_metap)
692  {
693  XLogRegisterBuffer(6, metabuf, REGBUF_STANDARD);
694  XLogRegisterBufData(6, (char *) &metap->hashm_firstfree, sizeof(uint32));
695  }
696 
697  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SQUEEZE_PAGE);
698 
699  PageSetLSN(BufferGetPage(wbuf), recptr);
700  PageSetLSN(BufferGetPage(ovflbuf), recptr);
701 
702  if (BufferIsValid(prevbuf) && !xlrec.is_prev_bucket_same_wrt)
703  PageSetLSN(BufferGetPage(prevbuf), recptr);
704  if (BufferIsValid(nextbuf))
705  PageSetLSN(BufferGetPage(nextbuf), recptr);
706 
707  PageSetLSN(BufferGetPage(mapbuf), recptr);
708 
709  if (update_metap)
710  PageSetLSN(BufferGetPage(metabuf), recptr);
711  }
712 
714 
715  /* release previous bucket if it is not same as write bucket */
716  if (BufferIsValid(prevbuf) && prevblkno != writeblkno)
717  _hash_relbuf(rel, prevbuf);
718 
719  if (BufferIsValid(ovflbuf))
720  _hash_relbuf(rel, ovflbuf);
721 
722  if (BufferIsValid(nextbuf))
723  _hash_relbuf(rel, nextbuf);
724 
725  _hash_relbuf(rel, mapbuf);
726  _hash_relbuf(rel, metabuf);
727 
728  return nextblkno;
729 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
uint16 hasho_page_id
Definition: hash.h:93
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void _hash_pgaddmultitup(Relation rel, Buffer buf, IndexTuple *itups, OffsetNumber *itup_offsets, uint16 nitups)
Definition: hashinsert.c:297
#define HashPageGetBitmap(page)
Definition: hash.h:306
#define LH_BITMAP_PAGE
Definition: hash.h:66
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
#define LH_META_PAGE
Definition: hash.h:67
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
Buffer _hash_getbuf_with_strategy(Relation rel, BlockNumber blkno, int access, int flags, BufferAccessStrategy bstrategy)
Definition: hashpage.c:247
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define InvalidBuffer
Definition: buf.h:25
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
signed int int32
Definition: c.h:294
BlockNumber prevblkno
Definition: hash_xlog.h:174
#define LH_UNUSED_PAGE
Definition: hash.h:63
bool is_prim_bucket_same_wrt
Definition: hash_xlog.h:177
uint16 OffsetNumber
Definition: off.h:24
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
#define SizeOfHashSqueezePage
Definition: hash_xlog.h:186
BlockNumber hasho_prevblkno
Definition: hash.h:89
#define ERROR
Definition: elog.h:43
BlockNumber nextblkno
Definition: hash_xlog.h:175
uint32 hashm_nmaps
Definition: hash.h:265
#define HASH_WRITE
Definition: hash.h:330
#define BMPG_MASK(metap)
Definition: hash.h:304
#define REGBUF_STANDARD
Definition: xloginsert.h:34
unsigned int uint32
Definition: c.h:306
#define BMPG_SHIFT(metap)
Definition: hash.h:303
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define HASH_XLOG_FREE_OVFL_BUFS
Definition: hash_xlog.h:22
#define ISSET(A, N)
Definition: hash.h:324
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
#define CLRBIT(x, i)
Definition: blutils.c:32
#define HASH_METAPAGE
Definition: hash.h:206
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
uint32 hashm_firstfree
Definition: hash.h:264
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define LH_BUCKET_PAGE
Definition: hash.h:65
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
bool is_prev_bucket_same_wrt
Definition: hash_xlog.h:180
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:31
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:146
#define HASHO_PAGE_ID
Definition: hash.h:109
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define RelationNeedsWAL(relation)
Definition: rel.h:514
uint32 _hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno)
Definition: hashovfl.c:61
uint16 hasho_flag
Definition: hash.h:92
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define HashPageGetMeta(page)
Definition: hash.h:313
int i
#define XLOG_HASH_SQUEEZE_PAGE
Definition: hash_xlog.h:36
BlockNumber hasho_nextblkno
Definition: hash.h:90
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:122
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition: hash.h:269
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74

◆ _hash_get_indextuple_hashkey()

uint32 _hash_get_indextuple_hashkey ( IndexTuple  itup)

Definition at line 299 of file hashutil.c.

References IndexInfoFindDataOffset, and IndexTupleData::t_info.

Referenced by _h_indexbuild(), _hash_binsearch(), _hash_binsearch_last(), _hash_doinsert(), _hash_load_qualified_items(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_splitbucket(), hash_page_items(), and hashbucketcleanup().

300 {
301  char *attp;
302 
303  /*
304  * We assume the hash key is the first attribute and can't be null, so
305  * this can be done crudely but very very cheaply ...
306  */
307  attp = (char *) itup + IndexInfoFindDataOffset(itup->t_info);
308  return *((uint32 *) attp);
309 }
#define IndexInfoFindDataOffset(t_info)
Definition: itup.h:80
unsigned int uint32
Definition: c.h:306
unsigned short t_info
Definition: itup.h:49

◆ _hash_get_newblock_from_oldbucket()

BlockNumber _hash_get_newblock_from_oldbucket ( Relation  rel,
Bucket  old_bucket 
)

Definition at line 469 of file hashutil.c.

References _hash_get_newbucket_from_oldbucket(), _hash_getbuf(), _hash_relbuf(), BUCKET_TO_BLKNO, BufferGetPage, HASH_METAPAGE, HASH_READ, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashPageGetMeta, and LH_META_PAGE.

Referenced by _hash_finish_split().

470 {
471  Bucket new_bucket;
472  Buffer metabuf;
473  HashMetaPage metap;
474  BlockNumber blkno;
475 
477  metap = HashPageGetMeta(BufferGetPage(metabuf));
478 
479  new_bucket = _hash_get_newbucket_from_oldbucket(rel, old_bucket,
480  metap->hashm_lowmask,
481  metap->hashm_maxbucket);
482  blkno = BUCKET_TO_BLKNO(metap, new_bucket);
483 
484  _hash_relbuf(rel, metabuf);
485 
486  return blkno;
487 }
#define LH_META_PAGE
Definition: hash.h:67
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
uint32 hashm_lowmask
Definition: hash.h:261
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
Bucket _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket)
Definition: hashutil.c:502
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define HASH_METAPAGE
Definition: hash.h:206
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
uint32 hashm_maxbucket
Definition: hash.h:259
#define HashPageGetMeta(page)
Definition: hash.h:313
int Buffer
Definition: buf.h:23

◆ _hash_get_newbucket_from_oldbucket()

Bucket _hash_get_newbucket_from_oldbucket ( Relation  rel,
Bucket  old_bucket,
uint32  lowmask,
uint32  maxbucket 
)

Definition at line 502 of file hashutil.c.

References CALC_NEW_BUCKET.

Referenced by _hash_get_newblock_from_oldbucket(), and hashbucketcleanup().

504 {
505  Bucket new_bucket;
506 
507  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
508  if (new_bucket > maxbucket)
509  {
510  lowmask = lowmask >> 1;
511  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
512  }
513 
514  return new_bucket;
515 }
#define CALC_NEW_BUCKET(old_bucket, lowmask)
Definition: hashutil.c:24
uint32 Bucket
Definition: hash.h:34

◆ _hash_get_oldblock_from_newbucket()

BlockNumber _hash_get_oldblock_from_newbucket ( Relation  rel,
Bucket  new_bucket 
)

Definition at line 430 of file hashutil.c.

References _hash_getbuf(), _hash_relbuf(), BUCKET_TO_BLKNO, BufferGetPage, fls(), HASH_METAPAGE, HASH_READ, HashPageGetMeta, and LH_META_PAGE.

Referenced by _hash_first().

431 {
432  Bucket old_bucket;
433  uint32 mask;
434  Buffer metabuf;
435  HashMetaPage metap;
436  BlockNumber blkno;
437 
438  /*
439  * To get the old bucket from the current bucket, we need a mask to modulo
440  * into lower half of table. This mask is stored in meta page as
441  * hashm_lowmask, but here we can't rely on the same, because we need a
442  * value of lowmask that was prevalent at the time when bucket split was
443  * started. Masking the most significant bit of new bucket would give us
444  * old bucket.
445  */
446  mask = (((uint32) 1) << (fls(new_bucket) - 1)) - 1;
447  old_bucket = new_bucket & mask;
448 
450  metap = HashPageGetMeta(BufferGetPage(metabuf));
451 
452  blkno = BUCKET_TO_BLKNO(metap, old_bucket);
453 
454  _hash_relbuf(rel, metabuf);
455 
456  return blkno;
457 }
#define LH_META_PAGE
Definition: hash.h:67
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
int fls(int mask)
Definition: fls.c:55
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
unsigned int uint32
Definition: c.h:306
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define HASH_METAPAGE
Definition: hash.h:206
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define HashPageGetMeta(page)
Definition: hash.h:313
int Buffer
Definition: buf.h:23

◆ _hash_get_totalbuckets()

uint32 _hash_get_totalbuckets ( uint32  splitpoint_phase)

Definition at line 189 of file hashutil.c.

References HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE, HASH_SPLITPOINT_PHASE_BITS, and HASH_SPLITPOINT_PHASE_MASK.

Referenced by _hash_expandtable(), _hash_init_metabuffer(), _hash_ovflblkno_to_bitno(), and bitno_to_blkno().

190 {
191  uint32 splitpoint_group;
192  uint32 total_buckets;
193  uint32 phases_within_splitpoint_group;
194 
195  if (splitpoint_phase < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
196  return (1 << splitpoint_phase);
197 
198  /* get splitpoint's group */
199  splitpoint_group = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
200  splitpoint_group +=
201  ((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) >>
203 
204  /* account for buckets before splitpoint_group */
205  total_buckets = (1 << (splitpoint_group - 1));
206 
207  /* account for buckets within splitpoint_group */
208  phases_within_splitpoint_group =
209  (((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) &
210  HASH_SPLITPOINT_PHASE_MASK) + 1); /* from 0-based to 1-based */
211  total_buckets +=
212  (((1 << (splitpoint_group - 1)) >> HASH_SPLITPOINT_PHASE_BITS) *
213  phases_within_splitpoint_group);
214 
215  return total_buckets;
216 }
#define HASH_SPLITPOINT_PHASE_MASK
Definition: hash.h:239
#define HASH_SPLITPOINT_PHASE_BITS
Definition: hash.h:237
unsigned int uint32
Definition: c.h:306
#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE
Definition: hash.h:240

◆ _hash_getbucketbuf_from_hashkey()

Buffer _hash_getbucketbuf_from_hashkey ( Relation  rel,
uint32  hashkey,
int  access,
HashMetaPage cachedmetap 
)

Definition at line 1561 of file hashpage.c.

References _hash_dropbuf(), _hash_getbuf(), _hash_getcachedmetap(), _hash_hashkey2bucket(), _hash_relbuf(), Assert, BUCKET_TO_BLKNO, buf, BufferGetPage, BufferIsValid, HASH_READ, HASH_WRITE, HashMetaPageData::hashm_highmask, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_prevblkno, InvalidBlockNumber, InvalidBuffer, LH_BUCKET_PAGE, and PageGetSpecialPointer.

Referenced by _hash_doinsert(), and _hash_first().

1563 {
1564  HashMetaPage metap;
1565  Buffer buf;
1566  Buffer metabuf = InvalidBuffer;
1567  Page page;
1568  Bucket bucket;
1569  BlockNumber blkno;
1570  HashPageOpaque opaque;
1571 
1572  /* We read from target bucket buffer, hence locking is must. */
1573  Assert(access == HASH_READ || access == HASH_WRITE);
1574 
1575  metap = _hash_getcachedmetap(rel, &metabuf, false);
1576  Assert(metap != NULL);
1577 
1578  /*
1579  * Loop until we get a lock on the correct target bucket.
1580  */
1581  for (;;)
1582  {
1583  /*
1584  * Compute the target bucket number, and convert to block number.
1585  */
1586  bucket = _hash_hashkey2bucket(hashkey,
1587  metap->hashm_maxbucket,
1588  metap->hashm_highmask,
1589  metap->hashm_lowmask);
1590 
1591  blkno = BUCKET_TO_BLKNO(metap, bucket);
1592 
1593  /* Fetch the primary bucket page for the bucket */
1594  buf = _hash_getbuf(rel, blkno, access, LH_BUCKET_PAGE);
1595  page = BufferGetPage(buf);
1596  opaque = (HashPageOpaque) PageGetSpecialPointer(page);
1597  Assert(opaque->hasho_bucket == bucket);
1599 
1600  /*
1601  * If this bucket hasn't been split, we're done.
1602  */
1603  if (opaque->hasho_prevblkno <= metap->hashm_maxbucket)
1604  break;
1605 
1606  /* Drop lock on this buffer, update cached metapage, and retry. */
1607  _hash_relbuf(rel, buf);
1608  metap = _hash_getcachedmetap(rel, &metabuf, true);
1609  Assert(metap != NULL);
1610  }
1611 
1612  if (BufferIsValid(metabuf))
1613  _hash_dropbuf(rel, metabuf);
1614 
1615  if (cachedmetap)
1616  *cachedmetap = metap;
1617 
1618  return buf;
1619 }
Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashutil.c:125
uint32 hashm_highmask
Definition: hash.h:260
#define InvalidBuffer
Definition: buf.h:25
uint32 BlockNumber
Definition: block.h:31
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
uint32 hashm_lowmask
Definition: hash.h:261
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
BlockNumber hasho_prevblkno
Definition: hash.h:89
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_WRITE
Definition: hash.h:330
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
HashMetaPage _hash_getcachedmetap(Relation rel, Buffer *metabuf, bool force_refresh)
Definition: hashpage.c:1503
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define LH_BUCKET_PAGE
Definition: hash.h:65
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
uint32 hashm_maxbucket
Definition: hash.h:259
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74

◆ _hash_getbuf()

Buffer _hash_getbuf ( Relation  rel,
BlockNumber  blkno,
int  access,
int  flags 
)

Definition at line 78 of file hashpage.c.

References _hash_checkpage(), buf, elog, ERROR, HASH_NOLOCK, LockBuffer(), P_NEW, and ReadBuffer().

Referenced by _hash_addovflpage(), _hash_doinsert(), _hash_finish_split(), _hash_first(), _hash_freeovflpage(), _hash_get_newblock_from_oldbucket(), _hash_get_oldblock_from_newbucket(), _hash_getbucketbuf_from_hashkey(), _hash_getcachedmetap(), _hash_kill_items(), _hash_next(), _hash_readnext(), _hash_readprev(), _hash_splitbucket(), hash_bitmap_info(), hashbulkdelete(), and pgstathashindex().

79 {
80  Buffer buf;
81 
82  if (blkno == P_NEW)
83  elog(ERROR, "hash AM does not use P_NEW");
84 
85  buf = ReadBuffer(rel, blkno);
86 
87  if (access != HASH_NOLOCK)
88  LockBuffer(buf, access);
89 
90  /* ref count and lock type are correct */
91 
92  _hash_checkpage(rel, buf, flags);
93 
94  return buf;
95 }
#define P_NEW
Definition: bufmgr.h:82
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_NOLOCK
Definition: hash.h:331
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23

◆ _hash_getbuf_with_condlock_cleanup()

Buffer _hash_getbuf_with_condlock_cleanup ( Relation  rel,
BlockNumber  blkno,
int  flags 
)

Definition at line 104 of file hashpage.c.

References _hash_checkpage(), buf, ConditionalLockBufferForCleanup(), elog, ERROR, InvalidBuffer, P_NEW, ReadBuffer(), and ReleaseBuffer().

Referenced by _hash_expandtable().

105 {
106  Buffer buf;
107 
108  if (blkno == P_NEW)
109  elog(ERROR, "hash AM does not use P_NEW");
110 
111  buf = ReadBuffer(rel, blkno);
112 
114  {
115  ReleaseBuffer(buf);
116  return InvalidBuffer;
117  }
118 
119  /* ref count and lock type are correct */
120 
121  _hash_checkpage(rel, buf, flags);
122 
123  return buf;
124 }
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define P_NEW
Definition: bufmgr.h:82
bool ConditionalLockBufferForCleanup(Buffer buffer)
Definition: bufmgr.c:3718
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23

◆ _hash_getbuf_with_strategy()

Buffer _hash_getbuf_with_strategy ( Relation  rel,
BlockNumber  blkno,
int  access,
int  flags,
BufferAccessStrategy  bstrategy 
)

Definition at line 247 of file hashpage.c.

References _hash_checkpage(), buf, elog, ERROR, HASH_NOLOCK, LockBuffer(), MAIN_FORKNUM, P_NEW, RBM_NORMAL, and ReadBufferExtended().

Referenced by _hash_freeovflpage(), _hash_squeezebucket(), hashbucketcleanup(), and pgstat_hash_page().

250 {
251  Buffer buf;
252 
253  if (blkno == P_NEW)
254  elog(ERROR, "hash AM does not use P_NEW");
255 
256  buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
257 
258  if (access != HASH_NOLOCK)
259  LockBuffer(buf, access);
260 
261  /* ref count and lock type are correct */
262 
263  _hash_checkpage(rel, buf, flags);
264 
265  return buf;
266 }
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define P_NEW
Definition: bufmgr.h:82
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_NOLOCK
Definition: hash.h:331
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23

◆ _hash_getcachedmetap()

HashMetaPage _hash_getcachedmetap ( Relation  rel,
Buffer metabuf,
bool  force_refresh 
)

Definition at line 1503 of file hashpage.c.

References _hash_getbuf(), Assert, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, BufferIsValid, HASH_METAPAGE, HASH_READ, HashPageGetMeta, LH_META_PAGE, LockBuffer(), MemoryContextAlloc(), RelationData::rd_amcache, and RelationData::rd_indexcxt.

Referenced by _hash_getbucketbuf_from_hashkey(), and hashbulkdelete().

1504 {
1505  Page page;
1506 
1507  Assert(metabuf);
1508  if (force_refresh || rel->rd_amcache == NULL)
1509  {
1510  char *cache = NULL;
1511 
1512  /*
1513  * It's important that we don't set rd_amcache to an invalid value.
1514  * Either MemoryContextAlloc or _hash_getbuf could fail, so don't
1515  * install a pointer to the newly-allocated storage in the actual
1516  * relcache entry until both have succeeeded.
1517  */
1518  if (rel->rd_amcache == NULL)
1519  cache = MemoryContextAlloc(rel->rd_indexcxt,
1520  sizeof(HashMetaPageData));
1521 
1522  /* Read the metapage. */
1523  if (BufferIsValid(*metabuf))
1524  LockBuffer(*metabuf, BUFFER_LOCK_SHARE);
1525  else
1526  *metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ,
1527  LH_META_PAGE);
1528  page = BufferGetPage(*metabuf);
1529 
1530  /* Populate the cache. */
1531  if (rel->rd_amcache == NULL)
1532  rel->rd_amcache = cache;
1533  memcpy(rel->rd_amcache, HashPageGetMeta(page),
1534  sizeof(HashMetaPageData));
1535 
1536  /* Release metapage lock, but keep the pin. */
1537  LockBuffer(*metabuf, BUFFER_LOCK_UNLOCK);
1538  }
1539 
1540  return (HashMetaPage) rel->rd_amcache;
1541 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define LH_META_PAGE
Definition: hash.h:67
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define HASH_READ
Definition: hash.h:329
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define HASH_METAPAGE
Definition: hash.h:206
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define Assert(condition)
Definition: c.h:680
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define HashPageGetMeta(page)
Definition: hash.h:313
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
MemoryContext rd_indexcxt
Definition: rel.h:179
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
void * rd_amcache
Definition: rel.h:192
Pointer Page
Definition: bufpage.h:74

◆ _hash_getinitbuf()

Buffer _hash_getinitbuf ( Relation  rel,
BlockNumber  blkno 
)

Definition at line 143 of file hashpage.c.

References _hash_pageinit(), buf, BufferGetPage, BufferGetPageSize, elog, ERROR, MAIN_FORKNUM, P_NEW, RBM_ZERO_AND_LOCK, and ReadBufferExtended().

Referenced by _hash_addovflpage().

144 {
145  Buffer buf;
146 
147  if (blkno == P_NEW)
148  elog(ERROR, "hash AM does not use P_NEW");
149 
151  NULL);
152 
153  /* ref count and lock type are correct */
154 
155  /* initialize the page */
157 
158  return buf;
159 }
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define P_NEW
Definition: bufmgr.h:82
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23

◆ _hash_getnewbuf()

Buffer _hash_getnewbuf ( Relation  rel,
BlockNumber  blkno,
ForkNumber  forkNum 
)

Definition at line 206 of file hashpage.c.

References _hash_pageinit(), buf, BufferGetBlockNumber(), BufferGetPage, BufferGetPageSize, elog, ERROR, HASH_WRITE, LockBuffer(), P_NEW, RBM_NORMAL, RBM_ZERO_AND_LOCK, ReadBufferExtended(), RelationGetNumberOfBlocksInFork(), and RelationGetRelationName.

Referenced by _hash_addovflpage(), _hash_expandtable(), and _hash_init().

207 {
208  BlockNumber nblocks = RelationGetNumberOfBlocksInFork(rel, forkNum);
209  Buffer buf;
210 
211  if (blkno == P_NEW)
212  elog(ERROR, "hash AM does not use P_NEW");
213  if (blkno > nblocks)
214  elog(ERROR, "access to noncontiguous page in hash index \"%s\"",
216 
217  /* smgr insists we use P_NEW to extend the relation */
218  if (blkno == nblocks)
219  {
220  buf = ReadBufferExtended(rel, forkNum, P_NEW, RBM_NORMAL, NULL);
221  if (BufferGetBlockNumber(buf) != blkno)
222  elog(ERROR, "unexpected hash relation size: %u, should be %u",
223  BufferGetBlockNumber(buf), blkno);
224  LockBuffer(buf, HASH_WRITE);
225  }
226  else
227  {
228  buf = ReadBufferExtended(rel, forkNum, blkno, RBM_ZERO_AND_LOCK,
229  NULL);
230  }
231 
232  /* ref count and lock type are correct */
233 
234  /* initialize the page */
236 
237  return buf;
238 }
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
uint32 BlockNumber
Definition: block.h:31
#define P_NEW
Definition: bufmgr.h:82
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define HASH_WRITE
Definition: hash.h:330
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
Definition: bufmgr.c:2788
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23

◆ _hash_hashkey2bucket()

Bucket _hash_hashkey2bucket ( uint32  hashkey,
uint32  maxbucket,
uint32  highmask,
uint32  lowmask 
)

Definition at line 125 of file hashutil.c.

Referenced by _h_indexbuild(), _hash_getbucketbuf_from_hashkey(), _hash_splitbucket(), comparetup_index_hash(), and hashbucketcleanup().

127 {
128  Bucket bucket;
129 
130  bucket = hashkey & highmask;
131  if (bucket > maxbucket)
132  bucket = bucket & lowmask;
133 
134  return bucket;
135 }
uint32 Bucket
Definition: hash.h:34

◆ _hash_init()

uint32 _hash_init ( Relation  rel,
double  num_tuples,
ForkNumber  forkNum 
)

Definition at line 335 of file hashpage.c.

References _hash_getnewbuf(), _hash_init_metabuffer(), _hash_initbitmapbuffer(), _hash_initbuf(), _hash_relbuf(), xl_hash_init_bitmap_page::bmsize, BUCKET_TO_BLKNO, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetPage, CHECK_FOR_INTERRUPTS, elog, ereport, errcode(), errmsg(), ERROR, xl_hash_init_meta_page::ffactor, HASH_DEFAULT_FILLFACTOR, HASH_MAX_BITMAPS, HASH_METAPAGE, HashMetaPageData::hashm_bmsize, HashMetaPageData::hashm_ffactor, HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_nmaps, HashMetaPageData::hashm_procid, HashPageGetMeta, HASHSTANDARD_PROC, i, index_getprocid(), INIT_FORKNUM, LH_BUCKET_PAGE, LockBuffer(), log_newpage(), MarkBufferDirty(), MAXALIGN, xl_hash_init_meta_page::num_tuples, PageSetLSN, xl_hash_init_meta_page::procid, RelationData::rd_node, REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetNumberOfBlocksInFork(), RelationGetRelationName, RelationGetTargetPageUsage, RelationNeedsWAL, SizeOfHashInitBitmapPage, SizeOfHashInitMetaPage, XLOG_HASH_INIT_BITMAP_PAGE, XLOG_HASH_INIT_META_PAGE, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by hashbuild(), and hashbuildempty().

336 {
337  Buffer metabuf;
338  Buffer buf;
339  Buffer bitmapbuf;
340  Page pg;
341  HashMetaPage metap;
342  RegProcedure procid;
343  int32 data_width;
344  int32 item_width;
345  int32 ffactor;
346  uint32 num_buckets;
347  uint32 i;
348  bool use_wal;
349 
350  /* safety check */
351  if (RelationGetNumberOfBlocksInFork(rel, forkNum) != 0)
352  elog(ERROR, "cannot initialize non-empty hash index \"%s\"",
354 
355  /*
356  * WAL log creation of pages if the relation is persistent, or this is the
357  * init fork. Init forks for unlogged relations always need to be WAL
358  * logged.
359  */
360  use_wal = RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM;
361 
362  /*
363  * Determine the target fill factor (in tuples per bucket) for this index.
364  * The idea is to make the fill factor correspond to pages about as full
365  * as the user-settable fillfactor parameter says. We can compute it
366  * exactly since the index datatype (i.e. uint32 hash key) is fixed-width.
367  */
368  data_width = sizeof(uint32);
369  item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
370  sizeof(ItemIdData); /* include the line pointer */
371  ffactor = RelationGetTargetPageUsage(rel, HASH_DEFAULT_FILLFACTOR) / item_width;
372  /* keep to a sane range */
373  if (ffactor < 10)
374  ffactor = 10;
375 
376  procid = index_getprocid(rel, 1, HASHSTANDARD_PROC);
377 
378  /*
379  * We initialize the metapage, the first N bucket pages, and the first
380  * bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
381  * calls to occur. This ensures that the smgr level has the right idea of
382  * the physical index length.
383  *
384  * Critical section not required, because on error the creation of the
385  * whole relation will be rolled back.
386  */
387  metabuf = _hash_getnewbuf(rel, HASH_METAPAGE, forkNum);
388  _hash_init_metabuffer(metabuf, num_tuples, procid, ffactor, false);
389  MarkBufferDirty(metabuf);
390 
391  pg = BufferGetPage(metabuf);
392  metap = HashPageGetMeta(pg);
393 
394  /* XLOG stuff */
395  if (use_wal)
396  {
398  XLogRecPtr recptr;
399 
400  xlrec.num_tuples = num_tuples;
401  xlrec.procid = metap->hashm_procid;
402  xlrec.ffactor = metap->hashm_ffactor;
403 
404  XLogBeginInsert();
405  XLogRegisterData((char *) &xlrec, SizeOfHashInitMetaPage);
407 
408  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INIT_META_PAGE);
409 
410  PageSetLSN(BufferGetPage(metabuf), recptr);
411  }
412 
413  num_buckets = metap->hashm_maxbucket + 1;
414 
415  /*
416  * Release buffer lock on the metapage while we initialize buckets.
417  * Otherwise, we'll be in interrupt holdoff and the CHECK_FOR_INTERRUPTS
418  * won't accomplish anything. It's a bad idea to hold buffer locks for
419  * long intervals in any case, since that can block the bgwriter.
420  */
421  LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
422 
423  /*
424  * Initialize and WAL Log the first N buckets
425  */
426  for (i = 0; i < num_buckets; i++)
427  {
428  BlockNumber blkno;
429 
430  /* Allow interrupts, in case N is huge */
432 
433  blkno = BUCKET_TO_BLKNO(metap, i);
434  buf = _hash_getnewbuf(rel, blkno, forkNum);
435  _hash_initbuf(buf, metap->hashm_maxbucket, i, LH_BUCKET_PAGE, false);
436  MarkBufferDirty(buf);
437 
438  if (use_wal)
439  log_newpage(&rel->rd_node,
440  forkNum,
441  blkno,
442  BufferGetPage(buf),
443  true);
444  _hash_relbuf(rel, buf);
445  }
446 
447  /* Now reacquire buffer lock on metapage */
449 
450  /*
451  * Initialize bitmap page
452  */
453  bitmapbuf = _hash_getnewbuf(rel, num_buckets + 1, forkNum);
454  _hash_initbitmapbuffer(bitmapbuf, metap->hashm_bmsize, false);
455  MarkBufferDirty(bitmapbuf);
456 
457  /* add the new bitmap page to the metapage's list of bitmaps */
458  /* metapage already has a write lock */
459  if (metap->hashm_nmaps >= HASH_MAX_BITMAPS)
460  ereport(ERROR,
461  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
462  errmsg("out of overflow pages in hash index \"%s\"",
463  RelationGetRelationName(rel))));
464 
465  metap->hashm_mapp[metap->hashm_nmaps] = num_buckets + 1;
466 
467  metap->hashm_nmaps++;
468  MarkBufferDirty(metabuf);
469 
470  /* XLOG stuff */
471  if (use_wal)
472  {
474  XLogRecPtr recptr;
475 
476  xlrec.bmsize = metap->hashm_bmsize;
477 
478  XLogBeginInsert();
479  XLogRegisterData((char *) &xlrec, SizeOfHashInitBitmapPage);
480  XLogRegisterBuffer(0, bitmapbuf, REGBUF_WILL_INIT);
481 
482  /*
483  * This is safe only because nobody else can be modifying the index at
484  * this stage; it's only visible to the transaction that is creating
485  * it.
486  */
487  XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD);
488 
489  recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INIT_BITMAP_PAGE);
490 
491  PageSetLSN(BufferGetPage(bitmapbuf), recptr);
492  PageSetLSN(BufferGetPage(metabuf), recptr);
493  }
494 
495  /* all done */
496  _hash_relbuf(rel, bitmapbuf);
497  _hash_relbuf(rel, metabuf);
498 
499  return num_buckets;
500 }
#define HASH_DEFAULT_FILLFACTOR
Definition: hash.h:286
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
RegProcedure hashm_procid
Definition: hash.h:266
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
regproc RegProcedure
Definition: c.h:453
#define XLOG_HASH_INIT_BITMAP_PAGE
Definition: hash_xlog.h:28
uint16 hashm_ffactor
Definition: hash.h:254
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
int errcode(int sqlerrcode)
Definition: elog.c:575
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getnewbuf(Relation rel, BlockNumber blkno, ForkNumber forkNum)
Definition: hashpage.c:206
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
signed int int32
Definition: c.h:294
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
#define ERROR
Definition: elog.h:43
#define SizeOfHashInitMetaPage
Definition: hash_xlog.h:236
void _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, uint16 ffactor, bool initpage)
Definition: hashpage.c:506
#define SizeOfHashInitBitmapPage
Definition: hash_xlog.h:252
uint32 hashm_nmaps
Definition: hash.h:265
static char * buf
Definition: pg_test_fsync.c:67
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define RelationGetRelationName(relation)
Definition: rel.h:445
unsigned int uint32
Definition: c.h:306
struct ItemIdData ItemIdData
#define XLOG_HASH_INIT_META_PAGE
Definition: hash_xlog.h:27
#define HASHSTANDARD_PROC
Definition: hash.h:351
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define HASH_MAX_BITMAPS
Definition: hash.h:235
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define HASH_METAPAGE
Definition: hash.h:206
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
void _hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage)
Definition: hashovfl.c:739
#define LH_BUCKET_PAGE
Definition: hash.h:65
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
Definition: bufmgr.c:2788
RelFileNode rd_node
Definition: rel.h:85
#define RelationGetTargetPageUsage(relation, defaultff)
Definition: rel.h:309
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void _hash_initbuf(Buffer buf, uint32 max_bucket, uint32 num_bucket, uint32 flag, bool initpage)
Definition: hashpage.c:165
#define MAXALIGN(LEN)
Definition: c.h:633
#define RelationNeedsWAL(relation)
Definition: rel.h:514
uint32 hashm_maxbucket
Definition: hash.h:259
RegProcedure procid
Definition: hash_xlog.h:232
#define HashPageGetMeta(page)
Definition: hash.h:313
int errmsg(const char *fmt,...)
Definition: elog.c:797
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:972
int i
uint16 hashm_bmsize
Definition: hash.h:256
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition: hash.h:269
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:821

◆ _hash_init_metabuffer()

void _hash_init_metabuffer ( Buffer  buf,
double  num_tuples,
RegProcedure  procid,
uint16  ffactor,
bool  initpage 
)

Definition at line 506 of file hashpage.c.

References _hash_get_totalbuckets(), _hash_log2(), _hash_pageinit(), _hash_spareindex(), Assert, BMPG_MASK, BMPG_SHIFT, BufferGetPage, BufferGetPageSize, BYTE_TO_BIT, HASH_MAGIC, HASH_MAX_SPLITPOINTS, HASH_VERSION, HashGetMaxBitmapSize, HashMetaPageData::hashm_bmshift, HashMetaPageData::hashm_bmsize, HashMetaPageData::hashm_bsize, HashMetaPageData::hashm_ffactor, HashMetaPageData::hashm_firstfree, HashMetaPageData::hashm_highmask, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_magic, HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_nmaps, HashMetaPageData::hashm_ntuples, HashMetaPageData::hashm_ovflpoint, HashMetaPageData::hashm_procid, HashMetaPageData::hashm_spares, HashMetaPageData::hashm_version, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, HashPageGetMeta, i, InvalidBlockNumber, LH_META_PAGE, MemSet, and PageGetSpecialPointer.

Referenced by _hash_init(), and hash_xlog_init_meta_page().

508 {
509  HashMetaPage metap;
510  HashPageOpaque pageopaque;
511  Page page;
512  double dnumbuckets;
513  uint32 num_buckets;
514  uint32 spare_index;
515  uint32 i;
516 
517  /*
518  * Choose the number of initial bucket pages to match the fill factor
519  * given the estimated number of tuples. We round up the result to the
520  * total number of buckets which has to be allocated before using its
521  * _hashm_spare element. However always force at least 2 bucket pages. The
522  * upper limit is determined by considerations explained in
523  * _hash_expandtable().
524  */
525  dnumbuckets = num_tuples / ffactor;
526  if (dnumbuckets <= 2.0)
527  num_buckets = 2;
528  else if (dnumbuckets >= (double) 0x40000000)
529  num_buckets = 0x40000000;
530  else
531  num_buckets = _hash_get_totalbuckets(_hash_spareindex(dnumbuckets));
532 
533  spare_index = _hash_spareindex(num_buckets);
534  Assert(spare_index < HASH_MAX_SPLITPOINTS);
535 
536  page = BufferGetPage(buf);
537  if (initpage)
539 
540  pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
541  pageopaque->hasho_prevblkno = InvalidBlockNumber;
542  pageopaque->hasho_nextblkno = InvalidBlockNumber;
543  pageopaque->hasho_bucket = -1;
544  pageopaque->hasho_flag = LH_META_PAGE;
545  pageopaque->hasho_page_id = HASHO_PAGE_ID;
546 
547  metap = HashPageGetMeta(page);
548 
549  metap->hashm_magic = HASH_MAGIC;
550  metap->hashm_version = HASH_VERSION;
551  metap->hashm_ntuples = 0;
552  metap->hashm_nmaps = 0;
553  metap->hashm_ffactor = ffactor;
554  metap->hashm_bsize = HashGetMaxBitmapSize(page);
555  /* find largest bitmap array size that will fit in page size */
556  for (i = _hash_log2(metap->hashm_bsize); i > 0; --i)
557  {
558  if ((1 << i) <= metap->hashm_bsize)
559  break;
560  }
561  Assert(i > 0);
562  metap->hashm_bmsize = 1 << i;
563  metap->hashm_bmshift = i + BYTE_TO_BIT;
564  Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1));
565 
566  /*
567  * Label the index with its primary hash support function's OID. This is
568  * pretty useless for normal operation (in fact, hashm_procid is not used
569  * anywhere), but it might be handy for forensic purposes so we keep it.
570  */
571  metap->hashm_procid = procid;
572 
573  /*
574  * We initialize the index with N buckets, 0 .. N-1, occupying physical
575  * blocks 1 to N. The first freespace bitmap page is in block N+1.
576  */
577  metap->hashm_maxbucket = num_buckets - 1;
578 
579  /*
580  * Set highmask as next immediate ((2 ^ x) - 1), which should be
581  * sufficient to cover num_buckets.
582  */
583  metap->hashm_highmask = (1 << (_hash_log2(num_buckets + 1))) - 1;
584  metap->hashm_lowmask = (metap->hashm_highmask >> 1);
585 
586  MemSet(metap->hashm_spares, 0, sizeof(metap->hashm_spares));
587  MemSet(metap->hashm_mapp, 0, sizeof(metap->hashm_mapp));
588 
589  /* Set up mapping for one spare page after the initial splitpoints */
590  metap->hashm_spares[spare_index] = 1;
591  metap->hashm_ovflpoint = spare_index;
592  metap->hashm_firstfree = 0;
593 
594  /*
595  * Set pd_lower just past the end of the metadata. This is essential,
596  * because without doing so, metadata will be lost if xlog.c compresses
597  * the page.
598  */
599  ((PageHeader) page)->pd_lower =
600  ((char *) metap + sizeof(HashMetaPageData)) - (char *) page;
601 }
uint16 hashm_bmshift
Definition: hash.h:258
uint16 hasho_page_id
Definition: hash.h:93
RegProcedure hashm_procid
Definition: hash.h:266
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
#define LH_META_PAGE
Definition: hash.h:67
#define BYTE_TO_BIT
Definition: hash.h:291
uint32 hashm_magic
Definition: hash.h:251
uint16 hashm_ffactor
Definition: hash.h:254
uint32 hashm_highmask
Definition: hash.h:260
#define MemSet(start, val, len)
Definition: c.h:863
#define HASH_VERSION
Definition: hash.h:209
uint32 hashm_lowmask
Definition: hash.h:261
#define HASH_MAX_SPLITPOINTS
Definition: hash.h:244
#define HASH_MAGIC
Definition: hash.h:208
#define HashGetMaxBitmapSize(page)
Definition: hash.h:309
BlockNumber hasho_prevblkno
Definition: hash.h:89
uint32 _hash_spareindex(uint32 num_bucket)
Definition: hashutil.c:157
uint32 _hash_get_totalbuckets(uint32 splitpoint_phase)
Definition: hashutil.c:189
uint32 hashm_version
Definition: hash.h:252
uint32 hashm_nmaps
Definition: hash.h:265
static char * buf
Definition: pg_test_fsync.c:67
#define BMPG_MASK(metap)
Definition: hash.h:304
unsigned int uint32
Definition: c.h:306
#define BMPG_SHIFT(metap)
Definition: hash.h:303
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
uint32 hashm_ovflpoint
Definition: hash.h:262
uint16 hashm_bsize
Definition: hash.h:255
double hashm_ntuples
Definition: hash.h:253
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
uint32 hashm_firstfree
Definition: hash.h:264
uint32 hashm_spares[HASH_MAX_SPLITPOINTS]
Definition: hash.h:267
PageHeaderData * PageHeader
Definition: bufpage.h:162
#define Assert(condition)
Definition: c.h:680
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define HASHO_PAGE_ID
Definition: hash.h:109
uint32 hashm_maxbucket
Definition: hash.h:259
uint16 hasho_flag
Definition: hash.h:92
#define HashPageGetMeta(page)
Definition: hash.h:313
uint32 _hash_log2(uint32 num)
Definition: hashutil.c:141
int i
BlockNumber hasho_nextblkno
Definition: hash.h:90
uint16 hashm_bmsize
Definition: hash.h:256
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition: hash.h:269
Pointer Page
Definition: bufpage.h:74

◆ _hash_initbitmapbuffer()

void _hash_initbitmapbuffer ( Buffer  buf,
uint16  bmsize,
bool  initpage 
)

Definition at line 739 of file hashovfl.c.

References _hash_pageinit(), BufferGetPage, BufferGetPageSize, HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, HashPageGetBitmap, InvalidBlockNumber, LH_BITMAP_PAGE, MemSet, and PageGetSpecialPointer.

Referenced by _hash_addovflpage(), _hash_init(), hash_xlog_add_ovfl_page(), and hash_xlog_init_bitmap_page().

740 {
741  Page pg;
742  HashPageOpaque op;
743  uint32 *freep;
744 
745  pg = BufferGetPage(buf);
746 
747  /* initialize the page */
748  if (initpage)
750 
751  /* initialize the page's special space */
755  op->hasho_bucket = -1;
758 
759  /* set all of the bits to 1 */
760  freep = HashPageGetBitmap(pg);
761  MemSet(freep, 0xFF, bmsize);
762 
763  /*
764  * Set pd_lower just past the end of the bitmap page data. We could even
765  * set pd_lower equal to pd_upper, but this is more precise and makes the
766  * page look compressible to xlog.c.
767  */
768  ((PageHeader) pg)->pd_lower = ((char *) freep + bmsize) - (char *) pg;
769 }
uint16 hasho_page_id
Definition: hash.h:93
#define HashPageGetBitmap(page)
Definition: hash.h:306
#define LH_BITMAP_PAGE
Definition: hash.h:66
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
#define MemSet(start, val, len)
Definition: c.h:863
BlockNumber hasho_prevblkno
Definition: hash.h:89
static char * buf
Definition: pg_test_fsync.c:67
unsigned int uint32
Definition: c.h:306
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
PageHeaderData * PageHeader
Definition: bufpage.h:162
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define HASHO_PAGE_ID
Definition: hash.h:109
uint16 hasho_flag
Definition: hash.h:92
BlockNumber hasho_nextblkno
Definition: hash.h:90
Pointer Page
Definition: bufpage.h:74

◆ _hash_initbuf()

void _hash_initbuf ( Buffer  buf,
uint32  max_bucket,
uint32  num_bucket,
uint32  flag,
bool  initpage 
)

Definition at line 165 of file hashpage.c.

References _hash_pageinit(), BufferGetPage, BufferGetPageSize, flag(), HashPageOpaqueData::hasho_bucket, HashPageOpaqueData::hasho_flag, HashPageOpaqueData::hasho_nextblkno, HashPageOpaqueData::hasho_page_id, HASHO_PAGE_ID, HashPageOpaqueData::hasho_prevblkno, InvalidBlockNumber, and PageGetSpecialPointer.

Referenced by _hash_init(), hash_xlog_add_ovfl_page(), and hash_xlog_split_allocate_page().

167 {
168  HashPageOpaque pageopaque;
169  Page page;
170 
171  page = BufferGetPage(buf);
172 
173  /* initialize the page */
174  if (initpage)
176 
177  pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
178 
179  /*
180  * Set hasho_prevblkno with current hashm_maxbucket. This value will be
181  * used to validate cached HashMetaPageData. See
182  * _hash_getbucketbuf_from_hashkey().
183  */
184  pageopaque->hasho_prevblkno = max_bucket;
185  pageopaque->hasho_nextblkno = InvalidBlockNumber;
186  pageopaque->hasho_bucket = num_bucket;
187  pageopaque->hasho_flag = flag;
188  pageopaque->hasho_page_id = HASHO_PAGE_ID;
189 }
uint16 hasho_page_id
Definition: hash.h:93
void _hash_pageinit(Page page, Size size)
Definition: hashpage.c:607
BlockNumber hasho_prevblkno
Definition: hash.h:89
static char * buf
Definition: pg_test_fsync.c:67
char * flag(int b)
Definition: test-ctype.c:33
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
Bucket hasho_bucket
Definition: hash.h:91
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
#define InvalidBlockNumber
Definition: block.h:33
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
#define HASHO_PAGE_ID
Definition: hash.h:109
uint16 hasho_flag
Definition: hash.h:92
BlockNumber hasho_nextblkno
Definition: hash.h:90
Pointer Page
Definition: bufpage.h:74

◆ _hash_kill_items()

void _hash_kill_items ( IndexScanDesc  scan)

Definition at line 544 of file hashutil.c.

References _hash_getbuf(), _hash_relbuf(), Assert, buf, HashScanPosData::buf, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, HashScanPosData::currPage, HashScanOpaqueData::currPos, HashScanPosData::firstItem, HASH_READ, HashScanPosIsPinned, HashScanPosIsValid, HashScanOpaqueData::hashso_bucket_buf, HashScanPosItem::heapTid, i, HashScanPosItem::indexOffset, IndexScanDescData::indexRelation, ItemIdMarkDead, ItemPointerEquals(), HashScanPosData::items, HashScanOpaqueData::killedItems, LH_OVERFLOW_PAGE, LH_PAGE_HAS_DEAD_TUPLES, LockBuffer(), MarkBufferDirtyHint(), HashScanOpaqueData::numKilled, OffsetNumberNext, IndexScanDescData::opaque, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageGetSpecialPointer, and IndexTupleData::t_tid.

Referenced by _hash_next(), _hash_readpage(), hashendscan(), and hashrescan().

545 {
546  HashScanOpaque so = (HashScanOpaque) scan->opaque;
547  Relation rel = scan->indexRelation;
548  BlockNumber blkno;
549  Buffer buf;
550  Page page;
551  HashPageOpaque opaque;
552  OffsetNumber offnum,
553  maxoff;
554  int numKilled = so->numKilled;
555  int i;
556  bool killedsomething = false;
557  bool havePin = false;
558 
559  Assert(so->numKilled > 0);
560  Assert(so->killedItems != NULL);
562 
563  /*
564  * Always reset the scan state, so we don't look for same items on other
565  * pages.
566  */
567  so->numKilled = 0;
568 
569  blkno = so->currPos.currPage;
570  if (HashScanPosIsPinned(so->currPos))
571  {
572  /*
573  * We already have pin on this buffer, so, all we need to do is
574  * acquire lock on it.
575  */
576  havePin = true;
577  buf = so->currPos.buf;
579  }
580  else
581  buf = _hash_getbuf(rel, blkno, HASH_READ, LH_OVERFLOW_PAGE);
582 
583  page = BufferGetPage(buf);
584  opaque = (HashPageOpaque) PageGetSpecialPointer(page);
585  maxoff = PageGetMaxOffsetNumber(page);
586 
587  for (i = 0; i < numKilled; i++)
588  {
589  int itemIndex = so->killedItems[i];
590  HashScanPosItem *currItem = &so->currPos.items[itemIndex];
591 
592  offnum = currItem->indexOffset;
593 
594  Assert(itemIndex >= so->currPos.firstItem &&
595  itemIndex <= so->currPos.lastItem);
596 
597  while (offnum <= maxoff)
598  {
599  ItemId iid = PageGetItemId(page, offnum);
600  IndexTuple ituple = (IndexTuple) PageGetItem(page, iid);
601 
602  if (ItemPointerEquals(&ituple->t_tid, &currItem->heapTid))
603  {
604  /* found the item */
605  ItemIdMarkDead(iid);
606  killedsomething = true;
607  break; /* out of inner search loop */
608  }
609  offnum = OffsetNumberNext(offnum);
610  }
611  }
612 
613  /*
614  * Since this can be redone later if needed, mark as dirty hint. Whenever
615  * we mark anything LP_DEAD, we also set the page's
616  * LH_PAGE_HAS_DEAD_TUPLES flag, which is likewise just a hint.
617  */
618  if (killedsomething)
619  {
620  opaque->hasho_flag |= LH_PAGE_HAS_DEAD_TUPLES;
621  MarkBufferDirtyHint(buf, true);
622  }
623 
624  if (so->hashso_bucket_buf == so->currPos.buf ||
625  havePin)
627  else
628  _hash_relbuf(rel, buf);
629 }
HashScanOpaqueData * HashScanOpaque
Definition: hash.h:200
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
#define ItemIdMarkDead(itemId)
Definition: itemid.h:178
#define HashScanPosIsPinned(scanpos)
Definition: hash.h:138
#define HashScanPosIsValid(scanpos)
Definition: hash.h:145
ItemPointerData t_tid
Definition: itup.h:37
uint32 BlockNumber
Definition: block.h:31
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
Relation indexRelation
Definition: relscan.h:90
uint16 OffsetNumber
Definition: off.h:24
#define HASH_READ
Definition: hash.h:329
int * killedItems
Definition: hash.h:190
static char * buf
Definition: pg_test_fsync.c:67
IndexTupleData * IndexTuple
Definition: itup.h:53
BlockNumber currPage
Definition: hash.h:120
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
Buffer hashso_bucket_buf
Definition: hash.h:172
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
Buffer buf
Definition: hash.h:119
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
#define Assert(condition)
Definition: c.h:680
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
HashScanPosData currPos
Definition: hash.h:197
OffsetNumber indexOffset
Definition: hash.h:114
int i
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
ItemPointerData heapTid
Definition: hash.h:113
int firstItem
Definition: hash.h:131
int Buffer
Definition: buf.h:23
#define LH_PAGE_HAS_DEAD_TUPLES
Definition: hash.h:71
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
HashScanPosItem items[MaxIndexTuplesPerPage]
Definition: hash.h:135

◆ _hash_log2()

uint32 _hash_log2 ( uint32  num)

Definition at line 141 of file hashutil.c.

References i.

Referenced by _h_spoolinit(), _hash_init_metabuffer(), and _hash_spareindex().

142 {
143  uint32 i,
144  limit;
145 
146  limit = 1;
147  for (i = 0; limit < num; limit <<= 1, i++)
148  ;
149  return i;
150 }
unsigned int uint32
Definition: c.h:306
int i

◆ _hash_next()

bool _hash_next ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 47 of file hashsearch.c.

References _hash_dropbuf(), _hash_dropscanbuf(), _hash_getbuf(), _hash_kill_items(), _hash_readpage(), BlockNumberIsValid, buf, BufferGetPage, HashScanOpaqueData::currPos, HashScanPosData::firstItem, HASH_READ, HashScanPosInvalidate, HashScanOpaqueData::hashso_bucket_buf, HashScanOpaqueData::hashso_split_bucket_buf, IndexScanDescData::indexRelation, HashScanPosData::itemIndex, HashScanPosData::items, HashScanPosData::lastItem, LH_BUCKET_PAGE, LH_OVERFLOW_PAGE, HashScanPosData::nextPage, HashScanOpaqueData::numKilled, IndexScanDescData::opaque, HashScanPosData::prevPage, ScanDirectionIsForward, HeapTupleData::t_self, TestForOldSnapshot(), IndexScanDescData::xs_ctup, and IndexScanDescData::xs_snapshot.

Referenced by hashgetbitmap(), and hashgettuple().

48 {
49  Relation rel = scan->indexRelation;
51  HashScanPosItem *currItem;
52  BlockNumber blkno;
53  Buffer buf;
54  bool end_of_scan = false;
55 
56  /*
57  * Advance to the next tuple on the current page; or if done, try to read
58  * data from the next or previous page based on the scan direction. Before
59  * moving to the next or previous page make sure that we deal with all the
60  * killed items.
61  */
62  if (ScanDirectionIsForward(dir))
63  {
64  if (++so->currPos.itemIndex > so->currPos.lastItem)
65  {
66  if (so->numKilled > 0)
67  _hash_kill_items(scan);
68 
69  blkno = so->currPos.nextPage;
70  if (BlockNumberIsValid(blkno))
71  {
74  if (!_hash_readpage(scan, &buf, dir))
75  end_of_scan = true;
76  }
77  else
78  end_of_scan = true;
79  }
80  }
81  else
82  {
83  if (--so->currPos.itemIndex < so->currPos.firstItem)
84  {
85  if (so->numKilled > 0)
86  _hash_kill_items(scan);
87 
88  blkno = so->currPos.prevPage;
89  if (BlockNumberIsValid(blkno))
90  {
91  buf = _hash_getbuf(rel, blkno, HASH_READ,
94 
95  /*
96  * We always maintain the pin on bucket page for whole scan
97  * operation, so releasing the additional pin we have acquired
98  * here.
99  */
100  if (buf == so->hashso_bucket_buf ||
102  _hash_dropbuf(rel, buf);
103 
104  if (!_hash_readpage(scan, &buf, dir))
105  end_of_scan = true;
106  }
107  else
108  end_of_scan = true;
109  }
110  }
111 
112  if (end_of_scan)
113  {
114  _hash_dropscanbuf(rel, so);
116  return false;
117  }
118 
119  /* OK, itemIndex says what to return */
120  currItem = &so->currPos.items[so->currPos.itemIndex];
121  scan->xs_ctup.t_self = currItem->heapTid;
122 
123  return true;
124 }
HashScanOpaqueData * HashScanOpaque
Definition: hash.h:200
static void TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
Definition: bufmgr.h:265
void _hash_dropscanbuf(Relation rel, HashScanOpaque so)
Definition: hashpage.c:297
static bool _hash_readpage(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
Definition: hashsearch.c:449
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
Snapshot xs_snapshot
Definition: relscan.h:91
uint32 BlockNumber
Definition: block.h:31
void _hash_dropbuf(Relation rel, Buffer buf)
Definition: hashpage.c:285
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
Relation indexRelation
Definition: relscan.h:90
#define HASH_READ
Definition: hash.h:329
ItemPointerData t_self
Definition: htup.h:65
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
Buffer hashso_bucket_buf
Definition: hash.h:172
#define HashScanPosInvalidate(scanpos)
Definition: hash.h:152
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
#define LH_BUCKET_PAGE
Definition: hash.h:65
int lastItem
Definition: hash.h:132
HeapTupleData xs_ctup
Definition: relscan.h:120
void _hash_kill_items(IndexScanDesc scan)
Definition: hashutil.c:544
HashScanPosData currPos
Definition: hash.h:197
Buffer hashso_split_bucket_buf
Definition: hash.h:179
BlockNumber nextPage
Definition: hash.h:121
int itemIndex
Definition: hash.h:133
int firstItem
Definition: hash.h:131
BlockNumber prevPage
Definition: hash.h:122
int Buffer
Definition: buf.h:23
HashScanPosItem items[MaxIndexTuplesPerPage]
Definition: hash.h:135

◆ _hash_ovflblkno_to_bitno()

uint32 _hash_ovflblkno_to_bitno ( HashMetaPage  metap,
BlockNumber  ovflblkno 
)