PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
visibilitymap.c File Reference
#include "postgres.h"
#include "access/heapam_xlog.h"
#include "access/visibilitymap.h"
#include "access/xlog.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "utils/inval.h"
Include dependency graph for visibilitymap.c:

Go to the source code of this file.

Macros

#define MAPSIZE   (BLCKSZ - MAXALIGN(SizeOfPageHeaderData))
 
#define HEAPBLOCKS_PER_BYTE   (BITS_PER_BYTE / BITS_PER_HEAPBLOCK)
 
#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)
 

Functions

static Buffer vm_readbuf (Relation rel, BlockNumber blkno, bool extend)
 
static void vm_extend (Relation rel, BlockNumber nvmblocks)
 
bool visibilitymap_clear (Relation rel, BlockNumber heapBlk, Buffer buf, uint8 flags)
 
void visibilitymap_pin (Relation rel, BlockNumber heapBlk, Buffer *buf)
 
bool visibilitymap_pin_ok (BlockNumber heapBlk, Buffer buf)
 
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 *buf)
 
void visibilitymap_count (Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen)
 
void visibilitymap_truncate (Relation rel, BlockNumber nheapblocks)
 

Variables

static const uint8 number_of_ones_for_visible [256]
 
static const uint8 number_of_ones_for_frozen [256]
 

Macro Definition Documentation

#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 HEAPBLOCKS_PER_BYTE   (BITS_PER_BYTE / BITS_PER_HEAPBLOCK)

Definition at line 108 of file visibilitymap.c.

#define HEAPBLOCKS_PER_PAGE   (MAPSIZE * HEAPBLOCKS_PER_BYTE)

Definition at line 111 of file visibilitymap.c.

#define MAPSIZE   (BLCKSZ - MAXALIGN(SizeOfPageHeaderData))

Definition at line 105 of file visibilitymap.c.

Referenced by visibilitymap_count(), and visibilitymap_truncate().

Function Documentation

bool visibilitymap_clear ( Relation  rel,
BlockNumber  heapBlk,
Buffer  buf,
uint8  flags 
)

Definition at line 169 of file visibilitymap.c.

References Assert, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, DEBUG1, elog, ERROR, HEAPBLK_TO_MAPBLOCK, HEAPBLK_TO_MAPBYTE, HEAPBLK_TO_OFFSET, LockBuffer(), MarkBufferDirty(), PageGetContents, RelationGetRelationName, and VISIBILITYMAP_VALID_BITS.

Referenced by heap_delete(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), and lazy_scan_heap().

170 {
171  BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk);
172  int mapByte = HEAPBLK_TO_MAPBYTE(heapBlk);
173  int mapOffset = HEAPBLK_TO_OFFSET(heapBlk);
174  uint8 mask = flags << mapOffset;
175  char *map;
176  bool cleared = false;
177 
179 
180 #ifdef TRACE_VISIBILITYMAP
181  elog(DEBUG1, "vm_clear %s %d", RelationGetRelationName(rel), heapBlk);
182 #endif
183 
184  if (!BufferIsValid(buf) || BufferGetBlockNumber(buf) != mapBlock)
185  elog(ERROR, "wrong buffer passed to visibilitymap_clear");
186 
189 
190  if (map[mapByte] & mask)
191  {
192  map[mapByte] &= ~mask;
193 
195  cleared = true;
196  }
197 
199 
200  return cleared;
201 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define DEBUG1
Definition: elog.h:25
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
unsigned char uint8
Definition: c.h:256
#define HEAPBLK_TO_MAPBYTE(x)
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetContents(page)
Definition: bufpage.h:242
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define Assert(condition)
Definition: c.h:664
#define HEAPBLK_TO_OFFSET(x)
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define elog
Definition: elog.h:219
#define HEAPBLK_TO_MAPBLOCK(x)
void visibilitymap_count ( Relation  rel,
BlockNumber all_visible,
BlockNumber all_frozen 
)

Definition at line 408 of file visibilitymap.c.

References Assert, BufferGetPage, BufferIsValid, i, MAPSIZE, number_of_ones_for_frozen, number_of_ones_for_visible, PageGetContents, ReleaseBuffer(), and vm_readbuf().

Referenced by do_analyze_rel(), index_update_stats(), and lazy_vacuum_rel().

409 {
410  BlockNumber mapBlock;
411 
412  /* all_visible must be specified */
413  Assert(all_visible);
414 
415  *all_visible = 0;
416  if (all_frozen)
417  *all_frozen = 0;
418 
419  for (mapBlock = 0;; mapBlock++)
420  {
421  Buffer mapBuffer;
422  unsigned char *map;
423  int i;
424 
425  /*
426  * Read till we fall off the end of the map. We assume that any extra
427  * bytes in the last page are zeroed, so we don't bother excluding
428  * them from the count.
429  */
430  mapBuffer = vm_readbuf(rel, mapBlock, false);
431  if (!BufferIsValid(mapBuffer))
432  break;
433 
434  /*
435  * We choose not to lock the page, since the result is going to be
436  * immediately stale anyway if anyone is concurrently setting or
437  * clearing bits, and we only really need an approximate value.
438  */
439  map = (unsigned char *) PageGetContents(BufferGetPage(mapBuffer));
440 
441  for (i = 0; i < MAPSIZE; i++)
442  {
443  *all_visible += number_of_ones_for_visible[map[i]];
444  if (all_frozen)
445  *all_frozen += number_of_ones_for_frozen[map[i]];
446  }
447 
448  ReleaseBuffer(mapBuffer);
449  }
450 }
static const uint8 number_of_ones_for_frozen[256]
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define MAPSIZE
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetContents(page)
Definition: bufpage.h:242
#define Assert(condition)
Definition: c.h:664
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
int i
static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
static const uint8 number_of_ones_for_visible[256]
int Buffer
Definition: buf.h:23
uint8 visibilitymap_get_status ( Relation  rel,
BlockNumber  heapBlk,
Buffer buf 
)

Definition at line 360 of file visibilitymap.c.

References BufferGetBlockNumber(), BufferGetPage, BufferIsValid, DEBUG1, elog, HEAPBLK_TO_MAPBLOCK, HEAPBLK_TO_MAPBYTE, HEAPBLK_TO_OFFSET, InvalidBuffer, PageGetContents, RelationGetRelationName, ReleaseBuffer(), VISIBILITYMAP_VALID_BITS, and vm_readbuf().

Referenced by collect_visibility_data(), lazy_scan_heap(), lazy_vacuum_page(), pg_visibility(), pg_visibility_map(), and pg_visibility_map_summary().

361 {
362  BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk);
363  uint32 mapByte = HEAPBLK_TO_MAPBYTE(heapBlk);
364  uint8 mapOffset = HEAPBLK_TO_OFFSET(heapBlk);
365  char *map;
366  uint8 result;
367 
368 #ifdef TRACE_VISIBILITYMAP
369  elog(DEBUG1, "vm_get_status %s %d", RelationGetRelationName(rel), heapBlk);
370 #endif
371 
372  /* Reuse the old pinned buffer if possible */
373  if (BufferIsValid(*buf))
374  {
375  if (BufferGetBlockNumber(*buf) != mapBlock)
376  {
377  ReleaseBuffer(*buf);
378  *buf = InvalidBuffer;
379  }
380  }
381 
382  if (!BufferIsValid(*buf))
383  {
384  *buf = vm_readbuf(rel, mapBlock, false);
385  if (!BufferIsValid(*buf))
386  return false;
387  }
388 
390 
391  /*
392  * A single byte read is atomic. There could be memory-ordering effects
393  * here, but for performance reasons we make it the caller's job to worry
394  * about that.
395  */
396  result = ((map[mapByte] >> mapOffset) & VISIBILITYMAP_VALID_BITS);
397  return result;
398 }
#define DEBUG1
Definition: elog.h:25
unsigned char uint8
Definition: c.h:256
#define HEAPBLK_TO_MAPBYTE(x)
#define InvalidBuffer
Definition: buf.h:25
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
static char * buf
Definition: pg_test_fsync.c:67
#define RelationGetRelationName(relation)
Definition: rel.h:436
unsigned int uint32
Definition: c.h:258
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetContents(page)
Definition: bufpage.h:242
#define HEAPBLK_TO_OFFSET(x)
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define elog
Definition: elog.h:219
static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
#define HEAPBLK_TO_MAPBLOCK(x)
void visibilitymap_pin ( Relation  rel,
BlockNumber  heapBlk,
Buffer buf 
)

Definition at line 220 of file visibilitymap.c.

References BufferGetBlockNumber(), BufferIsValid, HEAPBLK_TO_MAPBLOCK, ReleaseBuffer(), and vm_readbuf().

Referenced by GetVisibilityMapPins(), heap_delete(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_update(), heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), lazy_scan_heap(), and RelationGetBufferForTuple().

221 {
222  BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk);
223 
224  /* Reuse the old pinned buffer if possible */
225  if (BufferIsValid(*buf))
226  {
227  if (BufferGetBlockNumber(*buf) == mapBlock)
228  return;
229 
230  ReleaseBuffer(*buf);
231  }
232  *buf = vm_readbuf(rel, mapBlock, true);
233 }
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
static char * buf
Definition: pg_test_fsync.c:67
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
#define HEAPBLK_TO_MAPBLOCK(x)
bool visibilitymap_pin_ok ( BlockNumber  heapBlk,
Buffer  buf 
)

Definition at line 244 of file visibilitymap.c.

References BufferGetBlockNumber(), BufferIsValid, and HEAPBLK_TO_MAPBLOCK.

Referenced by GetVisibilityMapPins().

245 {
246  BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk);
247 
248  return BufferIsValid(buf) && BufferGetBlockNumber(buf) == mapBlock;
249 }
uint32 BlockNumber
Definition: block.h:31
static char * buf
Definition: pg_test_fsync.c:67
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define HEAPBLK_TO_MAPBLOCK(x)
void visibilitymap_set ( Relation  rel,
BlockNumber  heapBlk,
Buffer  heapBuf,
XLogRecPtr  recptr,
Buffer  vmBuf,
TransactionId  cutoff_xid,
uint8  flags 
)

Definition at line 273 of file visibilitymap.c.

References Assert, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, DEBUG1, elog, END_CRIT_SECTION, ERROR, HEAPBLK_TO_MAPBLOCK, HEAPBLK_TO_MAPBYTE, HEAPBLK_TO_OFFSET, InRecovery, LockBuffer(), log_heap_visible(), MarkBufferDirty(), PageGetContents, PageIsAllVisible, PageSetLSN, RelationData::rd_node, RelationGetRelationName, RelationNeedsWAL, START_CRIT_SECTION, VISIBILITYMAP_VALID_BITS, XLogHintBitIsNeeded, and XLogRecPtrIsInvalid.

Referenced by heap_xlog_visible(), lazy_scan_heap(), and lazy_vacuum_page().

276 {
277  BlockNumber mapBlock = HEAPBLK_TO_MAPBLOCK(heapBlk);
278  uint32 mapByte = HEAPBLK_TO_MAPBYTE(heapBlk);
279  uint8 mapOffset = HEAPBLK_TO_OFFSET(heapBlk);
280  Page page;
281  uint8 *map;
282 
283 #ifdef TRACE_VISIBILITYMAP
284  elog(DEBUG1, "vm_set %s %d", RelationGetRelationName(rel), heapBlk);
285 #endif
286 
288  Assert(InRecovery || BufferIsValid(heapBuf));
290 
291  /* Check that we have the right heap page pinned, if present */
292  if (BufferIsValid(heapBuf) && BufferGetBlockNumber(heapBuf) != heapBlk)
293  elog(ERROR, "wrong heap buffer passed to visibilitymap_set");
294 
295  /* Check that we have the right VM page pinned */
296  if (!BufferIsValid(vmBuf) || BufferGetBlockNumber(vmBuf) != mapBlock)
297  elog(ERROR, "wrong VM buffer passed to visibilitymap_set");
298 
299  page = BufferGetPage(vmBuf);
300  map = (uint8 *) PageGetContents(page);
302 
303  if (flags != (map[mapByte] >> mapOffset & VISIBILITYMAP_VALID_BITS))
304  {
306 
307  map[mapByte] |= (flags << mapOffset);
308  MarkBufferDirty(vmBuf);
309 
310  if (RelationNeedsWAL(rel))
311  {
312  if (XLogRecPtrIsInvalid(recptr))
313  {
314  Assert(!InRecovery);
315  recptr = log_heap_visible(rel->rd_node, heapBuf, vmBuf,
316  cutoff_xid, flags);
317 
318  /*
319  * If data checksums are enabled (or wal_log_hints=on), we
320  * need to protect the heap page from being torn.
321  */
322  if (XLogHintBitIsNeeded())
323  {
324  Page heapPage = BufferGetPage(heapBuf);
325 
326  /* caller is expected to set PD_ALL_VISIBLE first */
327  Assert(PageIsAllVisible(heapPage));
328  PageSetLSN(heapPage, recptr);
329  }
330  }
331  PageSetLSN(page, recptr);
332  }
333 
335  }
336 
338 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define DEBUG1
Definition: elog.h:25
#define PageIsAllVisible(page)
Definition: bufpage.h:381
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
bool InRecovery
Definition: xlog.c:194
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
unsigned char uint8
Definition: c.h:256
#define HEAPBLK_TO_MAPBYTE(x)
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define VISIBILITYMAP_VALID_BITS
Definition: visibilitymap.h:28
#define ERROR
Definition: elog.h:43
XLogRecPtr log_heap_visible(RelFileNode rnode, Buffer heap_buffer, Buffer vm_buffer, TransactionId cutoff_xid, uint8 vmflags)
Definition: heapam.c:7491
#define RelationGetRelationName(relation)
Definition: rel.h:436
unsigned int uint32
Definition: c.h:258
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define PageGetContents(page)
Definition: bufpage.h:242
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:664
#define HEAPBLK_TO_OFFSET(x)
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define RelationNeedsWAL(relation)
Definition: rel.h:505
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define elog
Definition: elog.h:219
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
#define XLogHintBitIsNeeded()
Definition: xlog.h:157
Pointer Page
Definition: bufpage.h:74
#define HEAPBLK_TO_MAPBLOCK(x)
void visibilitymap_truncate ( Relation  rel,
BlockNumber  nheapblocks 
)

Definition at line 462 of file visibilitymap.c.

References BUFFER_LOCK_EXCLUSIVE, BufferGetPage, BufferIsValid, DEBUG1, elog, END_CRIT_SECTION, HEAPBLK_TO_MAPBLOCK, HEAPBLK_TO_MAPBYTE, HEAPBLK_TO_OFFSET, InRecovery, LockBuffer(), log_newpage_buffer(), MAPSIZE, MarkBufferDirty(), MemSet, PageGetContents, RelationData::rd_smgr, RelationGetRelationName, RelationNeedsWAL, RelationOpenSmgr, SMgrRelationData::smgr_vm_nblocks, smgrexists(), smgrnblocks(), smgrtruncate(), START_CRIT_SECTION, UnlockReleaseBuffer(), VISIBILITYMAP_FORKNUM, vm_readbuf(), and XLogHintBitIsNeeded.

Referenced by pg_truncate_visibility_map(), RelationTruncate(), and smgr_redo().

463 {
464  BlockNumber newnblocks;
465 
466  /* last remaining block, byte, and bit */
467  BlockNumber truncBlock = HEAPBLK_TO_MAPBLOCK(nheapblocks);
468  uint32 truncByte = HEAPBLK_TO_MAPBYTE(nheapblocks);
469  uint8 truncOffset = HEAPBLK_TO_OFFSET(nheapblocks);
470 
471 #ifdef TRACE_VISIBILITYMAP
472  elog(DEBUG1, "vm_truncate %s %d", RelationGetRelationName(rel), nheapblocks);
473 #endif
474 
475  RelationOpenSmgr(rel);
476 
477  /*
478  * If no visibility map has been created yet for this relation, there's
479  * nothing to truncate.
480  */
482  return;
483 
484  /*
485  * Unless the new size is exactly at a visibility map page boundary, the
486  * tail bits in the last remaining map page, representing truncated heap
487  * blocks, need to be cleared. This is not only tidy, but also necessary
488  * because we don't get a chance to clear the bits if the heap is extended
489  * again.
490  */
491  if (truncByte != 0 || truncOffset != 0)
492  {
493  Buffer mapBuffer;
494  Page page;
495  char *map;
496 
497  newnblocks = truncBlock + 1;
498 
499  mapBuffer = vm_readbuf(rel, truncBlock, false);
500  if (!BufferIsValid(mapBuffer))
501  {
502  /* nothing to do, the file was already smaller */
503  return;
504  }
505 
506  page = BufferGetPage(mapBuffer);
507  map = PageGetContents(page);
508 
509  LockBuffer(mapBuffer, BUFFER_LOCK_EXCLUSIVE);
510 
511  /* NO EREPORT(ERROR) from here till changes are logged */
513 
514  /* Clear out the unwanted bytes. */
515  MemSet(&map[truncByte + 1], 0, MAPSIZE - (truncByte + 1));
516 
517  /*----
518  * Mask out the unwanted bits of the last remaining byte.
519  *
520  * ((1 << 0) - 1) = 00000000
521  * ((1 << 1) - 1) = 00000001
522  * ...
523  * ((1 << 6) - 1) = 00111111
524  * ((1 << 7) - 1) = 01111111
525  *----
526  */
527  map[truncByte] &= (1 << truncOffset) - 1;
528 
529  /*
530  * Truncation of a relation is WAL-logged at a higher-level, and we
531  * will be called at WAL replay. But if checksums are enabled, we need
532  * to still write a WAL record to protect against a torn page, if the
533  * page is flushed to disk before the truncation WAL record. We cannot
534  * use MarkBufferDirtyHint here, because that will not dirty the page
535  * during recovery.
536  */
537  MarkBufferDirty(mapBuffer);
539  log_newpage_buffer(mapBuffer, false);
540 
542 
543  UnlockReleaseBuffer(mapBuffer);
544  }
545  else
546  newnblocks = truncBlock;
547 
548  if (smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM) <= newnblocks)
549  {
550  /* nothing to do, the file was already smaller than requested size */
551  return;
552  }
553 
554  /* Truncate the unused VM pages, and send smgr inval message */
555  smgrtruncate(rel->rd_smgr, VISIBILITYMAP_FORKNUM, newnblocks);
556 
557  /*
558  * We might as well update the local smgr_vm_nblocks setting. smgrtruncate
559  * sent an smgr cache inval message, which will cause other backends to
560  * invalidate their copy of smgr_vm_nblocks, and this one too at the next
561  * command boundary. But this ensures it isn't outright wrong until then.
562  */
563  if (rel->rd_smgr)
564  rel->rd_smgr->smgr_vm_nblocks = newnblocks;
565 }
BlockNumber smgr_vm_nblocks
Definition: smgr.h:57
#define DEBUG1
Definition: elog.h:25
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1009
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
bool InRecovery
Definition: xlog.c:194
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
unsigned char uint8
Definition: c.h:256
#define HEAPBLK_TO_MAPBYTE(x)
void smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: smgr.c:684
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
#define MemSet(start, val, len)
Definition: c.h:846
uint32 BlockNumber
Definition: block.h:31
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:287
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define RelationOpenSmgr(relation)
Definition: rel.h:460
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define RelationGetRelationName(relation)
Definition: rel.h:436
unsigned int uint32
Definition: c.h:258
#define MAPSIZE
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetContents(page)
Definition: bufpage.h:242
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:672
#define HEAPBLK_TO_OFFSET(x)
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define RelationNeedsWAL(relation)
Definition: rel.h:505
#define elog
Definition: elog.h:219
static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
int Buffer
Definition: buf.h:23
#define XLogHintBitIsNeeded()
Definition: xlog.h:157
Pointer Page
Definition: bufpage.h:74
#define HEAPBLK_TO_MAPBLOCK(x)
static void vm_extend ( Relation  rel,
BlockNumber  nvmblocks 
)
static

Definition at line 626 of file visibilitymap.c.

References CacheInvalidateSmgr(), ExclusiveLock, InvalidBlockNumber, LockRelationForExtension(), PageInit(), PageSetChecksumInplace(), palloc(), pfree(), RelationData::rd_smgr, RelationOpenSmgr, SMgrRelationData::smgr_rnode, SMgrRelationData::smgr_vm_nblocks, smgrcreate(), smgrexists(), smgrextend(), smgrnblocks(), UnlockRelationForExtension(), and VISIBILITYMAP_FORKNUM.

Referenced by vm_readbuf().

627 {
628  BlockNumber vm_nblocks_now;
629  Page pg;
630 
631  pg = (Page) palloc(BLCKSZ);
632  PageInit(pg, BLCKSZ, 0);
633 
634  /*
635  * We use the relation extension lock to lock out other backends trying to
636  * extend the visibility map at the same time. It also locks out extension
637  * of the main fork, unnecessarily, but extending the visibility map
638  * happens seldom enough that it doesn't seem worthwhile to have a
639  * separate lock tag type for it.
640  *
641  * Note that another backend might have extended or created the relation
642  * by the time we get the lock.
643  */
645 
646  /* Might have to re-open if a cache flush happened */
647  RelationOpenSmgr(rel);
648 
649  /*
650  * Create the file first if it doesn't exist. If smgr_vm_nblocks is
651  * positive then it must exist, no need for an smgrexists call.
652  */
653  if ((rel->rd_smgr->smgr_vm_nblocks == 0 ||
657 
658  vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
659 
660  /* Now extend the file */
661  while (vm_nblocks_now < vm_nblocks)
662  {
663  PageSetChecksumInplace(pg, vm_nblocks_now);
664 
665  smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now,
666  (char *) pg, false);
667  vm_nblocks_now++;
668  }
669 
670  /*
671  * Send a shared-inval message to force other backends to close any smgr
672  * references they may have for this rel, which we are about to change.
673  * This is a useful optimization because it means that backends don't have
674  * to keep checking for creation or extension of the file, which happens
675  * infrequently.
676  */
678 
679  /* Update local cache with the up-to-date size */
680  rel->rd_smgr->smgr_vm_nblocks = vm_nblocks_now;
681 
683 
684  pfree(pg);
685 }
void CacheInvalidateSmgr(RelFileNodeBackend rnode)
Definition: inval.c:1332
BlockNumber smgr_vm_nblocks
Definition: smgr.h:57
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
#define ExclusiveLock
Definition: lockdefs.h:44
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
uint32 BlockNumber
Definition: block.h:31
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:287
#define RelationOpenSmgr(relation)
Definition: rel.h:460
void pfree(void *pointer)
Definition: mcxt.c:949
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:332
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:382
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:672
#define InvalidBlockNumber
Definition: block.h:33
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1199
void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:600
void * palloc(Size size)
Definition: mcxt.c:848
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
static Buffer vm_readbuf ( Relation  rel,
BlockNumber  blkno,
bool  extend 
)
static

Definition at line 574 of file visibilitymap.c.

References buf, BufferGetPage, InvalidBlockNumber, InvalidBuffer, PageInit(), PageIsNew, RBM_ZERO_ON_ERROR, RelationData::rd_smgr, ReadBufferExtended(), RelationOpenSmgr, SMgrRelationData::smgr_vm_nblocks, smgrexists(), smgrnblocks(), VISIBILITYMAP_FORKNUM, and vm_extend().

Referenced by visibilitymap_count(), visibilitymap_get_status(), visibilitymap_pin(), and visibilitymap_truncate().

575 {
576  Buffer buf;
577 
578  /*
579  * We might not have opened the relation at the smgr level yet, or we
580  * might have been forced to close it by a sinval message. The code below
581  * won't necessarily notice relation extension immediately when extend =
582  * false, so we rely on sinval messages to ensure that our ideas about the
583  * size of the map aren't too far out of date.
584  */
585  RelationOpenSmgr(rel);
586 
587  /*
588  * If we haven't cached the size of the visibility map fork yet, check it
589  * first.
590  */
592  {
596  else
597  rel->rd_smgr->smgr_vm_nblocks = 0;
598  }
599 
600  /* Handle requests beyond EOF */
601  if (blkno >= rel->rd_smgr->smgr_vm_nblocks)
602  {
603  if (extend)
604  vm_extend(rel, blkno + 1);
605  else
606  return InvalidBuffer;
607  }
608 
609  /*
610  * Use ZERO_ON_ERROR mode, and initialize the page if necessary. It's
611  * always safe to clear bits, so it's better to clear corrupt pages than
612  * error out.
613  */
614  buf = ReadBufferExtended(rel, VISIBILITYMAP_FORKNUM, blkno,
615  RBM_ZERO_ON_ERROR, NULL);
616  if (PageIsNew(BufferGetPage(buf)))
617  PageInit(BufferGetPage(buf), BLCKSZ, 0);
618  return buf;
619 }
static void vm_extend(Relation rel, BlockNumber nvmblocks)
BlockNumber smgr_vm_nblocks
Definition: smgr.h:57
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define InvalidBuffer
Definition: buf.h:25
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:287
#define RelationOpenSmgr(relation)
Definition: rel.h:460
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:672
#define InvalidBlockNumber
Definition: block.h:33
#define PageIsNew(page)
Definition: bufpage.h:225
int Buffer
Definition: buf.h:23
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41

Variable Documentation

const uint8 number_of_ones_for_frozen[256]
static
Initial value:
= {
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2,
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2,
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 3, 3,
2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4
}

Definition at line 137 of file visibilitymap.c.

Referenced by visibilitymap_count().

const uint8 number_of_ones_for_visible[256]
static
Initial value:
= {
0, 1, 0, 1, 1, 2, 1, 2, 0, 1, 0, 1, 1, 2, 1, 2,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
0, 1, 0, 1, 1, 2, 1, 2, 0, 1, 0, 1, 1, 2, 1, 2,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
2, 3, 2, 3, 3, 4, 3, 4, 2, 3, 2, 3, 3, 4, 3, 4,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
2, 3, 2, 3, 3, 4, 3, 4, 2, 3, 2, 3, 3, 4, 3, 4,
0, 1, 0, 1, 1, 2, 1, 2, 0, 1, 0, 1, 1, 2, 1, 2,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
0, 1, 0, 1, 1, 2, 1, 2, 0, 1, 0, 1, 1, 2, 1, 2,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
2, 3, 2, 3, 3, 4, 3, 4, 2, 3, 2, 3, 3, 4, 3, 4,
1, 2, 1, 2, 2, 3, 2, 3, 1, 2, 1, 2, 2, 3, 2, 3,
2, 3, 2, 3, 3, 4, 3, 4, 2, 3, 2, 3, 3, 4, 3, 4
}

Definition at line 119 of file visibilitymap.c.

Referenced by visibilitymap_count().