1 概述#
1.1 vm接口调用点#
heap_insert()
buffer = RelationGetBufferForTuple()
RelationPutHeapTuple(buffer, heaptup)
if PageIsAllVisible(buffer):
PageClearAllVisible(buffer)
visibilitymap_clear(ItemPointerGetBlockNumber(heaptup), vmbuffer)
MarkBufferDirty(buffer)
#define PageIsAllVisible(page) ((page)->pd_flags & PD_ALL_VISIBLE)
1.2 vm模块对外接口#
visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
int mapByte = HEAPBLK_TO_MAPBYTE(heapBlk)
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE)
char *map = PageGetContents(buf)
if map[mapByte]
1.3 vmmap结构与定位#
/* 8192 - 24 = 8168 */
#define MAPSIZE (BLCKSZ - MAXALIGN(SizeOfPageHeaderData))
/* 1字节 2bit表示1页 : | 00 00 00 00 | */
#define BITS_PER_BYTE 8
#define BITS_PER_HEAPBLOCK 2
/* 1字节 可映射4个heapblock */
#define HEAPBLOCKS_PER_BYTE (BITS_PER_BYTE / BITS_PER_HEAPBLOCK)
/* 计算heapblock对应的vmblock, vmbyte, vmoffset的位置 */
/* 1vmblock可映射4 * 8168个datablock */
#define HEAPBLOCKS_PER_PAGE (MAPSIZE * HEAPBLOCKS_PER_BYTE)
#define HEAPBLK_TO_MAPBLOCK(x) ((x) / HEAPBLOCKS_PER_PAGE)
#define HEAPBLK_TO_MAPBYTE(x) (((x) % HEAPBLOCKS_PER_PAGE) / HEAPBLOCKS_PER_BYTE)
#define HEAPBLK_TO_OFFSET(x) (((x) % HEAPBLOCKS_PER_BYTE) * BITS_PER_HEAPBLOCK)
#define VISIBILITYMAP_ALL_VISIBLE 0x01
#define VISIBILITYMAP_ALL_FROZEN 0x02
#define VISIBILITYMAP_VALID_BITS 0x03
1.4 vmblock读写#
vm_extend(Relation rel, BlockNumber vm_nblocks)
PGAlignedBlock pg
PageInit((Page) pg.data, BLCKSZ, 0)
LockRelationForExtension(rel, ExclusiveLock)
BlockNumber vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM)
while vm_nblocks_now < vm_nblocks:
PageSetChecksumInplace((Page) pg.data, vm_nblocks_now)
smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now,
pg.data, false)
vm_nblocks_now++
/* 让其他postgres进程smgrclose(rel) */
CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode) {
SharedInvalidationMessage msg
msg.sm.id = SHAREDINVALSMGR_ID;
msg.sm.backend_hi = rnode.backend >> 16;
msg.sm.backend_lo = rnode.backend & 0xffff;
msg.sm.rnode = rnode.node;
VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg))
SendSharedInvalidMessages(&msg, 1)
}
rel->rd_smgr->smgr_vm_nblocks = vm_nblocks_now
UnlockRelationForExtension(rel, ExclusiveLock)
Buffer
vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
RelationOpenSmgr(rel)
if blkno >= rel->rd_smgr->smgr_vm_nblocks:
if extend:
vm_extend(rel, blkno + 1)
buf = ReadBufferExtended(rel , VISIBILITYMAP_FORKNUM, blkno,RBM_ZERO_ON_ERROR)
if PageIsNew(buf):
PageInit(buf, BLKSZ, 0)
return buf
1.5 vm模块对外接口#
void visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, XLogRecPtr recptr, Buffer vmBuf, TransactionId cutoff_xid, uint8 flags)
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *vmbuf)
bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, Buffer vmbuf, uint8 flags)
/* 每个heapblock有3种状态 */
uint8
visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk)
uint32 mapByte = HEAPBLK_TO_MAPBYTE(heapBlk)
uint8 mapOffset = HEAPBLK_TO_OFFSET(heapBlk)
/* 比较传入的buf和计算的mapblock是否为同一个 */
if BufferIsValid(*buf):
if BufferGetBlockNumber(*buf) != mapBlock:
*buf = InvalidBuffer
if !BufferIsValid(*buf):
*buf = vm_readbuf(rel, mapBlock, false)
map = PageGetContents(BufferGetPage(*buf))
/* 每个heapbuf有01 10 11共3种状态 */
unit8 result = ((map[mapByte] >> mapOffset) & VISIBILITYMAP_VALID_BITS)
return uint8
void visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, XLogRecPtr recptr, Buffer vmBuf, TransactionId cutoff_xid, uint8 flags)
...