src/backend/access/hash/hashpage.c
static void
_hash_splitbucket(Relation rel,
				  Buffer metabuf,
				  Bucket obucket,
				  Bucket nbucket,
				  Buffer obuf,
				  Buffer nbuf,
				  uint32 maxbucket,
				  uint32 highmask,
				  uint32 lowmask)
{
	Page		opage;
	Page		npage;
	HashPageOpaque oopaque;
	HashPageOpaque nopaque;

	opage = BufferGetPage(obuf);
	oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);

	/*
	 * Mark the old bucket to indicate that split is in progress.  At
	 * operation end, we clear split-in-progress flag.
	 */
	oopaque->hasho_flag |= LH_BUCKET_BEING_SPLIT;

	npage = BufferGetPage(nbuf);

	/*
	 * initialize the new bucket's primary page and mark it to indicate that
	 * split is in progress.
	 */
	nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
	nopaque->hasho_prevblkno = InvalidBlockNumber;
	nopaque->hasho_nextblkno = InvalidBlockNumber;
	nopaque->hasho_bucket = nbucket;
	nopaque->hasho_flag = LH_BUCKET_PAGE | LH_BUCKET_BEING_POPULATED;
	nopaque->hasho_page_id = HASHO_PAGE_ID;

	_hash_splitbucket_guts(rel, metabuf, obucket,
						   nbucket, obuf, nbuf, NULL,
						   maxbucket, highmask, lowmask);

	/* all done, now release the locks and pins on primary buckets. */
	_hash_relbuf(rel, obuf);
	_hash_relbuf(rel, nbuf);
}
/*
 * _hash_splitbucket -- split 'obucket' into 'obucket' and 'nbucket'
 *
 * We are splitting a bucket that consists of a base bucket page and zero
 * or more overflow (bucket chain) pages.  We must relocate tuples that
 * belong in the new bucket, and compress out any free space in the old
 * bucket.
 *
 * The caller must hold cleanup locks on both buckets to ensure that
 * no one else is trying to access them (see README).
 *
 * The caller must hold a pin, but no lock, on the metapage buffer.
 * The buffer is returned in the same state.  (The metapage is only
 * touched if it becomes necessary to add or remove overflow pages.)
 *
 * Split needs to retain pin on primary bucket pages of both old and new
 * buckets till end of operation.  This is to prevent vacuum from starting
 * while a split is in progress.
 *
 * In addition, the caller must have created the new bucket's base page,
 * which is passed in buffer nbuf, pinned and write-locked.  That lock and
 * pin are released here.  (The API is set up this way because we must do
 * _hash_getnewbuf() before releasing the metapage write lock.  So instead of
 * passing the new bucket's start block number, we pass an actual buffer.)
 */


The caller must hold cleanup locks on both buckets to ensure that
no one else is trying to access them .

The caller must hold a pin, but no lock, on the metapage buffer.
The buffer is returned in the same state.  (The metapage is only
touched if it becomes necessary to add or remove overflow pages.)

Split needs to retain pin on primary bucket pages of both old and new
buckets till end of operation.  This is to prevent vacuum from starting
while a split is in progress.

In addition, the caller must have created the new bucket's base page,
which is passed in buffer nbuf, pinned and write-locked.  That lock and
pin are released here.  (The API is set up this way because we must do
_hash_getnewbuf() before releasing the metapage write lock.  So instead of
passing the new bucket's start block number, we pass an actual buffer.)
The caller must hold cleanup locks on both buckets to ensure that no one else is trying to access them . The caller must hold a pin but no lock on the metapage buffer . The buffer is returned in the same state . ( The metapage is only touched if it becomes necessary to add or remove overflow pages . ) Split needs to retain pin on primary bucket pages of both old and new buckets till end of operation . This is to prevent vacuum from starting while a split is in progress . In addition the caller must have created the new bucket ' s base page which is passed in buffer nbuf pinned and write - locked . That lock and pin are released here . ( The API is set up this way because we must do _hash_getnewbuf () before releasing the metapage write lock . So instead of passing the new bucket ' s start block number we pass an actual buffer . )
static void
_hash_splitbucket(Relation rel,
				  Buffer metabuf,
				  Bucket obucket,
				  Bucket nbucket,
				  Buffer obuf,
				  Buffer nbuf,
				  uint32 maxbucket,
				  uint32 highmask,
				  uint32 lowmask)
{
	Page		opage;
	Page		npage;
	HashPageOpaque oopaque;
	HashPageOpaque nopaque;
	opage = BufferGetPage(obuf);
	oopaque = (HashPageOpaque) PageGetSpecialPointer(opage);
	oopaque->hasho_flag |= LH_BUCKET_BEING_SPLIT;
	npage = BufferGetPage(nbuf);
	nopaque = (HashPageOpaque) PageGetSpecialPointer(npage);
	nopaque->hasho_prevblkno = InvalidBlockNumber;
	nopaque->hasho_nextblkno = InvalidBlockNumber;
	nopaque->hasho_bucket = nbucket;
	nopaque->hasho_flag = LH_BUCKET_PAGE | LH_BUCKET_BEING_POPULATED;
	nopaque->hasho_page_id = HASHO_PAGE_ID;
	_hash_splitbucket_guts(rel, metabuf, obucket,
						   nbucket, obuf, nbuf, NULL,
						   maxbucket, highmask, lowmask);
	_hash_relbuf(rel, obuf);
	_hash_relbuf(rel, nbuf);
}
static void _hash_splitbucket ( Relation rel , Buffer metabuf , Bucket obucket , Bucket nbucket , Buffer obuf , Buffer nbuf , uint32 maxbucket , uint32 highmask , uint32 lowmask ) { Page opage ; Page npage ; HashPageOpaque oopaque ; HashPageOpaque nopaque ; opage = BufferGetPage ( obuf ) ; oopaque = ( HashPageOpaque ) PageGetSpecialPointer ( opage ) ; oopaque -> hasho_flag |= LH_BUCKET_BEING_SPLIT ; npage = BufferGetPage ( nbuf ) ; nopaque = ( HashPageOpaque ) PageGetSpecialPointer ( npage ) ; nopaque -> hasho_prevblkno = InvalidBlockNumber ; nopaque -> hasho_nextblkno = InvalidBlockNumber ; nopaque -> hasho_bucket = nbucket ; nopaque -> hasho_flag = LH_BUCKET_PAGE | LH_BUCKET_BEING_POPULATED ; nopaque -> hasho_page_id = HASHO_PAGE_ID ; _hash_splitbucket_guts ( rel , metabuf , obucket , nbucket , obuf , nbuf , NULL , maxbucket , highmask , lowmask ) ; _hash_relbuf ( rel , obuf ) ; _hash_relbuf ( rel , nbuf ) ; }
_hash_splitbucket -- split 'obucket' into 'obucket' and 'nbucket'
 We are splitting a bucket that consists of a base bucket page and zero
 or more overflow (bucket chain) pages.
_hash_splitbucket -- split ' obucket ' into ' obucket ' and ' nbucket ' We are splitting a bucket that consists of a base bucket page and zero or more overflow ( bucket chain ) pages .
/*
	 * Mark the old bucket to indicate that split is in progress.  At
	 * operation end, we clear split-in-progress flag.
	 */ /*
	 * initialize the new bucket's primary page and mark it to indicate that
	 * split is in progress.
	 */ /* all done, now release the locks and pins on primary buckets. */