PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_visibility.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/visibilitymap.h"
#include "catalog/pg_type.h"
#include "catalog/storage_xlog.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/rel.h"
Include dependency graph for pg_visibility.c:

Go to the source code of this file.

Data Structures

struct  vbits
 
struct  corrupt_items
 

Typedefs

typedef struct vbits vbits
 
typedef struct corrupt_items corrupt_items
 

Functions

 PG_FUNCTION_INFO_V1 (pg_visibility_map)
 
 PG_FUNCTION_INFO_V1 (pg_visibility_map_rel)
 
 PG_FUNCTION_INFO_V1 (pg_visibility)
 
 PG_FUNCTION_INFO_V1 (pg_visibility_rel)
 
 PG_FUNCTION_INFO_V1 (pg_visibility_map_summary)
 
 PG_FUNCTION_INFO_V1 (pg_check_frozen)
 
 PG_FUNCTION_INFO_V1 (pg_check_visible)
 
 PG_FUNCTION_INFO_V1 (pg_truncate_visibility_map)
 
static TupleDesc pg_visibility_tupdesc (bool include_blkno, bool include_pd)
 
static vbitscollect_visibility_data (Oid relid, bool include_pd)
 
static corrupt_itemscollect_corrupt_items (Oid relid, bool all_visible, bool all_frozen)
 
static void record_corrupt_item (corrupt_items *items, ItemPointer tid)
 
static bool tuple_all_visible (HeapTuple tup, TransactionId OldestXmin, Buffer buffer)
 
static void check_relation_relkind (Relation rel)
 
Datum pg_visibility_map (PG_FUNCTION_ARGS)
 
Datum pg_visibility (PG_FUNCTION_ARGS)
 
Datum pg_visibility_map_rel (PG_FUNCTION_ARGS)
 
Datum pg_visibility_rel (PG_FUNCTION_ARGS)
 
Datum pg_visibility_map_summary (PG_FUNCTION_ARGS)
 
Datum pg_check_frozen (PG_FUNCTION_ARGS)
 
Datum pg_check_visible (PG_FUNCTION_ARGS)
 
Datum pg_truncate_visibility_map (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Typedef Documentation

Function Documentation

static void check_relation_relkind ( Relation  rel)
static

Definition at line 770 of file pg_visibility.c.

References ereport, errcode(), errmsg(), ERROR, RelationData::rd_rel, RelationGetRelationName, RELKIND_MATVIEW, RELKIND_RELATION, and RELKIND_TOASTVALUE.

Referenced by collect_corrupt_items(), collect_visibility_data(), pg_truncate_visibility_map(), pg_visibility(), pg_visibility_map(), and pg_visibility_map_summary().

771 {
772  if (rel->rd_rel->relkind != RELKIND_RELATION &&
773  rel->rd_rel->relkind != RELKIND_MATVIEW &&
774  rel->rd_rel->relkind != RELKIND_TOASTVALUE)
775  ereport(ERROR,
776  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
777  errmsg("\"%s\" is not a table, materialized view, or TOAST table",
778  RelationGetRelationName(rel))));
779 }
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:160
static corrupt_items * collect_corrupt_items ( Oid  relid,
bool  all_visible,
bool  all_frozen 
)
static

Definition at line 547 of file pg_visibility.c.

References AccessShareLock, BAS_BULKREAD, buffer, BUFFER_LOCK_SHARE, BufferGetPage, CHECK_FOR_INTERRUPTS, check_relation_relkind(), corrupt_items::count, FirstOffsetNumber, GetAccessStrategy(), GetOldestXmin(), heap_tuple_needs_eventual_freeze(), InvalidBuffer, InvalidTransactionId, ItemIdGetLength, ItemIdIsDead, ItemIdIsRedirected, ItemIdIsUsed, ItemPointerSet, LockBuffer(), MAIN_FORKNUM, corrupt_items::next, OffsetNumberNext, OldestXmin, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, palloc(), palloc0(), PROCARRAY_FLAGS_VACUUM, RBM_NORMAL, ReadBufferExtended(), record_corrupt_item(), relation_close(), relation_open(), RelationGetNumberOfBlocks, ReleaseBuffer(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, corrupt_items::tids, TransactionIdPrecedes(), tuple_all_visible(), UnlockReleaseBuffer(), VM_ALL_FROZEN, and VM_ALL_VISIBLE.

Referenced by pg_check_frozen(), and pg_check_visible().

548 {
549  Relation rel;
550  BlockNumber nblocks;
551  corrupt_items *items;
552  BlockNumber blkno;
553  Buffer vmbuffer = InvalidBuffer;
556 
557  if (all_visible)
558  {
559  /* Don't pass rel; that will fail in recovery. */
560  OldestXmin = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM);
561  }
562 
563  rel = relation_open(relid, AccessShareLock);
564 
565  /* Only some relkinds have a visibility map */
567 
568  nblocks = RelationGetNumberOfBlocks(rel);
569 
570  /*
571  * Guess an initial array size. We don't expect many corrupted tuples, so
572  * start with a small array. This function uses the "next" field to track
573  * the next offset where we can store an item (which is the same thing as
574  * the number of items found so far) and the "count" field to track the
575  * number of entries allocated. We'll repurpose these fields before
576  * returning.
577  */
578  items = palloc0(sizeof(corrupt_items));
579  items->next = 0;
580  items->count = 64;
581  items->tids = palloc(items->count * sizeof(ItemPointerData));
582 
583  /* Loop over every block in the relation. */
584  for (blkno = 0; blkno < nblocks; ++blkno)
585  {
586  bool check_frozen = false;
587  bool check_visible = false;
588  Buffer buffer;
589  Page page;
590  OffsetNumber offnum,
591  maxoff;
592 
593  /* Make sure we are interruptible. */
595 
596  /* Use the visibility map to decide whether to check this page. */
597  if (all_frozen && VM_ALL_FROZEN(rel, blkno, &vmbuffer))
598  check_frozen = true;
599  if (all_visible && VM_ALL_VISIBLE(rel, blkno, &vmbuffer))
600  check_visible = true;
601  if (!check_visible && !check_frozen)
602  continue;
603 
604  /* Read and lock the page. */
605  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
606  bstrategy);
607  LockBuffer(buffer, BUFFER_LOCK_SHARE);
608 
609  page = BufferGetPage(buffer);
610  maxoff = PageGetMaxOffsetNumber(page);
611 
612  /*
613  * The visibility map bits might have changed while we were acquiring
614  * the page lock. Recheck to avoid returning spurious results.
615  */
616  if (check_frozen && !VM_ALL_FROZEN(rel, blkno, &vmbuffer))
617  check_frozen = false;
618  if (check_visible && !VM_ALL_VISIBLE(rel, blkno, &vmbuffer))
619  check_visible = false;
620  if (!check_visible && !check_frozen)
621  {
622  UnlockReleaseBuffer(buffer);
623  continue;
624  }
625 
626  /* Iterate over each tuple on the page. */
627  for (offnum = FirstOffsetNumber;
628  offnum <= maxoff;
629  offnum = OffsetNumberNext(offnum))
630  {
631  HeapTupleData tuple;
632  ItemId itemid;
633 
634  itemid = PageGetItemId(page, offnum);
635 
636  /* Unused or redirect line pointers are of no interest. */
637  if (!ItemIdIsUsed(itemid) || ItemIdIsRedirected(itemid))
638  continue;
639 
640  /* Dead line pointers are neither all-visible nor frozen. */
641  if (ItemIdIsDead(itemid))
642  {
643  ItemPointerSet(&(tuple.t_self), blkno, offnum);
644  record_corrupt_item(items, &tuple.t_self);
645  continue;
646  }
647 
648  /* Initialize a HeapTupleData structure for checks below. */
649  ItemPointerSet(&(tuple.t_self), blkno, offnum);
650  tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
651  tuple.t_len = ItemIdGetLength(itemid);
652  tuple.t_tableOid = relid;
653 
654  /*
655  * If we're checking whether the page is all-visible, we expect
656  * the tuple to be all-visible.
657  */
658  if (check_visible &&
659  !tuple_all_visible(&tuple, OldestXmin, buffer))
660  {
661  TransactionId RecomputedOldestXmin;
662 
663  /*
664  * Time has passed since we computed OldestXmin, so it's
665  * possible that this tuple is all-visible in reality even
666  * though it doesn't appear so based on our
667  * previously-computed value. Let's compute a new value so we
668  * can be certain whether there is a problem.
669  *
670  * From a concurrency point of view, it sort of sucks to
671  * retake ProcArrayLock here while we're holding the buffer
672  * exclusively locked, but it should be safe against
673  * deadlocks, because surely GetOldestXmin() should never take
674  * a buffer lock. And this shouldn't happen often, so it's
675  * worth being careful so as to avoid false positives.
676  */
677  RecomputedOldestXmin = GetOldestXmin(NULL, PROCARRAY_FLAGS_VACUUM);
678 
679  if (!TransactionIdPrecedes(OldestXmin, RecomputedOldestXmin))
680  record_corrupt_item(items, &tuple.t_self);
681  else
682  {
683  OldestXmin = RecomputedOldestXmin;
684  if (!tuple_all_visible(&tuple, OldestXmin, buffer))
685  record_corrupt_item(items, &tuple.t_self);
686  }
687  }
688 
689  /*
690  * If we're checking whether the page is all-frozen, we expect the
691  * tuple to be in a state where it will never need freezing.
692  */
693  if (check_frozen)
694  {
696  record_corrupt_item(items, &tuple.t_self);
697  }
698  }
699 
700  UnlockReleaseBuffer(buffer);
701  }
702 
703  /* Clean up. */
704  if (vmbuffer != InvalidBuffer)
705  ReleaseBuffer(vmbuffer);
707 
708  /*
709  * Before returning, repurpose the fields to match caller's expectations.
710  * next is now the next item that should be read (rather than written) and
711  * count is now the number of items we wrote (rather than the number we
712  * allocated).
713  */
714  items->count = items->next;
715  items->next = 0;
716 
717  return items;
718 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:542
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:105
uint32 TransactionId
Definition: c.h:391
static void record_corrupt_item(corrupt_items *items, ItemPointer tid)
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define VM_ALL_FROZEN(r, b, v)
Definition: visibilitymap.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define PROCARRAY_FLAGS_VACUUM
Definition: procarray.h:52
#define ItemIdIsDead(itemId)
Definition: itemid.h:112
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
BlockNumber count
Definition: pg_visibility.c:36
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple)
Definition: heapam.c:7199
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
#define FirstOffsetNumber
Definition: off.h:27
#define InvalidTransactionId
Definition: transam.h:31
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
static void check_relation_relkind(Relation rel)
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
static bool tuple_all_visible(HeapTuple tup, TransactionId OldestXmin, Buffer buffer)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void * palloc0(Size size)
Definition: mcxt.c:877
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
TransactionId GetOldestXmin(Relation rel, int flags)
Definition: procarray.c:1315
ItemPointer tids
Definition: pg_visibility.c:37
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define VM_ALL_VISIBLE(r, b, v)
Definition: visibilitymap.h:32
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
BlockNumber next
Definition: pg_visibility.c:35
void * palloc(Size size)
Definition: mcxt.c:848
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:105
static vbits * collect_visibility_data ( Oid  relid,
bool  include_pd 
)
static

Definition at line 469 of file pg_visibility.c.

References AccessShareLock, BAS_BULKREAD, vbits::bits, buffer, BUFFER_LOCK_SHARE, BufferGetPage, CHECK_FOR_INTERRUPTS, check_relation_relkind(), vbits::count, GetAccessStrategy(), InvalidBuffer, LockBuffer(), MAIN_FORKNUM, vbits::next, offsetof, PageIsAllVisible, palloc0(), RBM_NORMAL, ReadBufferExtended(), relation_close(), relation_open(), RelationGetNumberOfBlocks, ReleaseBuffer(), UnlockReleaseBuffer(), VISIBILITYMAP_ALL_FROZEN, VISIBILITYMAP_ALL_VISIBLE, and visibilitymap_get_status().

Referenced by pg_visibility_map_rel(), and pg_visibility_rel().

470 {
471  Relation rel;
472  BlockNumber nblocks;
473  vbits *info;
474  BlockNumber blkno;
475  Buffer vmbuffer = InvalidBuffer;
477 
478  rel = relation_open(relid, AccessShareLock);
479 
480  /* Only some relkinds have a visibility map */
482 
483  nblocks = RelationGetNumberOfBlocks(rel);
484  info = palloc0(offsetof(vbits, bits) + nblocks);
485  info->next = 0;
486  info->count = nblocks;
487 
488  for (blkno = 0; blkno < nblocks; ++blkno)
489  {
490  int32 mapbits;
491 
492  /* Make sure we are interruptible. */
494 
495  /* Get map info. */
496  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
497  if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
498  info->bits[blkno] |= (1 << 0);
499  if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
500  info->bits[blkno] |= (1 << 1);
501 
502  /*
503  * Page-level data requires reading every block, so only get it if the
504  * caller needs it. Use a buffer access strategy, too, to prevent
505  * cache-trashing.
506  */
507  if (include_pd)
508  {
509  Buffer buffer;
510  Page page;
511 
512  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
513  bstrategy);
514  LockBuffer(buffer, BUFFER_LOCK_SHARE);
515 
516  page = BufferGetPage(buffer);
517  if (PageIsAllVisible(page))
518  info->bits[blkno] |= (1 << 2);
519 
520  UnlockReleaseBuffer(buffer);
521  }
522  }
523 
524  /* Clean up. */
525  if (vmbuffer != InvalidBuffer)
526  ReleaseBuffer(vmbuffer);
528 
529  return info;
530 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:542
#define PageIsAllVisible(page)
Definition: bufpage.h:381
#define VISIBILITYMAP_ALL_FROZEN
Definition: visibilitymap.h:27
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:640
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
signed int int32
Definition: c.h:246
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
static void check_relation_relkind(Relation rel)
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void * palloc0(Size size)
Definition: mcxt.c:877
BlockNumber count
Definition: pg_visibility.c:29
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
int Buffer
Definition: buf.h:23
BlockNumber next
Definition: pg_visibility.c:28
#define offsetof(type, field)
Definition: c.h:549
Pointer Page
Definition: bufpage.h:74
Datum pg_check_frozen ( PG_FUNCTION_ARGS  )

Definition at line 313 of file pg_visibility.c.

References collect_corrupt_items(), corrupt_items::count, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, corrupt_items::next, PG_GETARG_OID, PointerGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, corrupt_items::tids, and FuncCallContext::user_fctx.

314 {
315  FuncCallContext *funcctx;
316  corrupt_items *items;
317 
318  if (SRF_IS_FIRSTCALL())
319  {
320  Oid relid = PG_GETARG_OID(0);
321  MemoryContext oldcontext;
322 
323  funcctx = SRF_FIRSTCALL_INIT();
324  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
325  /* collect_corrupt_items will verify the relkind */
326  funcctx->user_fctx = collect_corrupt_items(relid, false, true);
327  MemoryContextSwitchTo(oldcontext);
328  }
329 
330  funcctx = SRF_PERCALL_SETUP();
331  items = (corrupt_items *) funcctx->user_fctx;
332 
333  if (items->next < items->count)
334  SRF_RETURN_NEXT(funcctx, PointerGetDatum(&items->tids[items->next++]));
335 
336  SRF_RETURN_DONE(funcctx);
337 }
static corrupt_items * collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
BlockNumber count
Definition: pg_visibility.c:36
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
ItemPointer tids
Definition: pg_visibility.c:37
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
BlockNumber next
Definition: pg_visibility.c:35
void * user_fctx
Definition: funcapi.h:90
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum pg_check_visible ( PG_FUNCTION_ARGS  )

Definition at line 345 of file pg_visibility.c.

References collect_corrupt_items(), corrupt_items::count, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, corrupt_items::next, PG_GETARG_OID, PointerGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, corrupt_items::tids, and FuncCallContext::user_fctx.

346 {
347  FuncCallContext *funcctx;
348  corrupt_items *items;
349 
350  if (SRF_IS_FIRSTCALL())
351  {
352  Oid relid = PG_GETARG_OID(0);
353  MemoryContext oldcontext;
354 
355  funcctx = SRF_FIRSTCALL_INIT();
356  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
357  /* collect_corrupt_items will verify the relkind */
358  funcctx->user_fctx = collect_corrupt_items(relid, true, false);
359  MemoryContextSwitchTo(oldcontext);
360  }
361 
362  funcctx = SRF_PERCALL_SETUP();
363  items = (corrupt_items *) funcctx->user_fctx;
364 
365  if (items->next < items->count)
366  SRF_RETURN_NEXT(funcctx, PointerGetDatum(&items->tids[items->next++]));
367 
368  SRF_RETURN_DONE(funcctx);
369 }
static corrupt_items * collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
BlockNumber count
Definition: pg_visibility.c:36
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
ItemPointer tids
Definition: pg_visibility.c:37
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
BlockNumber next
Definition: pg_visibility.c:35
void * user_fctx
Definition: funcapi.h:90
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
PG_FUNCTION_INFO_V1 ( pg_visibility_map  )
PG_FUNCTION_INFO_V1 ( pg_visibility_map_rel  )
PG_FUNCTION_INFO_V1 ( pg_visibility  )
PG_FUNCTION_INFO_V1 ( pg_visibility_rel  )
PG_FUNCTION_INFO_V1 ( pg_visibility_map_summary  )
PG_FUNCTION_INFO_V1 ( pg_check_frozen  )
PG_FUNCTION_INFO_V1 ( pg_check_visible  )
PG_FUNCTION_INFO_V1 ( pg_truncate_visibility_map  )
Datum pg_truncate_visibility_map ( PG_FUNCTION_ARGS  )

Definition at line 380 of file pg_visibility.c.

References AccessExclusiveLock, xl_smgr_truncate::blkno, check_relation_relkind(), xl_smgr_truncate::flags, InvalidBlockNumber, PG_GETARG_OID, PG_RETURN_VOID, RelationData::rd_node, RelationData::rd_smgr, relation_close(), relation_open(), RelationNeedsWAL, RelationOpenSmgr, xl_smgr_truncate::rnode, SMGR_TRUNCATE_VM, SMgrRelationData::smgr_vm_nblocks, visibilitymap_truncate(), XLOG_SMGR_TRUNCATE, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

381 {
382  Oid relid = PG_GETARG_OID(0);
383  Relation rel;
384 
385  rel = relation_open(relid, AccessExclusiveLock);
386 
387  /* Only some relkinds have a visibility map */
389 
390  RelationOpenSmgr(rel);
392 
393  visibilitymap_truncate(rel, 0);
394 
395  if (RelationNeedsWAL(rel))
396  {
397  xl_smgr_truncate xlrec;
398 
399  xlrec.blkno = 0;
400  xlrec.rnode = rel->rd_node;
401  xlrec.flags = SMGR_TRUNCATE_VM;
402 
403  XLogBeginInsert();
404  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
405 
407  }
408 
409  /*
410  * Release the lock right away, not at commit time.
411  *
412  * It would be a problem to release the lock prior to commit if this
413  * truncate operation sends any transactional invalidation messages. Other
414  * backends would potentially be able to lock the relation without
415  * processing them in the window of time between when we release the lock
416  * here and when we sent the messages at our eventual commit. However,
417  * we're currently only sending a non-transactional smgr invalidation,
418  * which will have been posted to shared memory immediately from within
419  * visibilitymap_truncate. Therefore, there should be no race here.
420  *
421  * The reason why it's desirable to release the lock early here is because
422  * of the possibility that someone will need to use this to blow away many
423  * visibility map forks at once. If we can't release the lock until
424  * commit time, the transaction doing this will accumulate
425  * AccessExclusiveLocks on all of those relations at the same time, which
426  * is undesirable. However, if this turns out to be unsafe we may have no
427  * choice...
428  */
430 
431  /* Nothing to return. */
432  PG_RETURN_VOID();
433 }
BlockNumber smgr_vm_nblocks
Definition: smgr.h:57
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
RelFileNode rnode
Definition: storage_xlog.h:49
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationOpenSmgr(relation)
Definition: rel.h:460
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void check_relation_relkind(Relation rel)
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define PG_RETURN_VOID()
Definition: fmgr.h:309
RelFileNode rd_node
Definition: rel.h:85
void visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
#define InvalidBlockNumber
Definition: block.h:33
#define SMGR_TRUNCATE_VM
Definition: storage_xlog.h:41
#define RelationNeedsWAL(relation)
Definition: rel.h:505
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
BlockNumber blkno
Definition: storage_xlog.h:48
void XLogBeginInsert(void)
Definition: xloginsert.c:120
Datum pg_visibility ( PG_FUNCTION_ARGS  )

Definition at line 106 of file pg_visibility.c.

References AccessShareLock, BoolGetDatum, buffer, BUFFER_LOCK_SHARE, BufferGetPage, check_relation_relkind(), ereport, errcode(), errmsg(), ERROR, heap_form_tuple(), HeapTupleGetDatum, InvalidBuffer, LockBuffer(), MaxBlockNumber, MemSet, PageIsAllVisible, PG_GETARG_INT64, PG_GETARG_OID, PG_RETURN_DATUM, pg_visibility_tupdesc(), ReadBuffer(), relation_close(), relation_open(), RelationGetNumberOfBlocks, ReleaseBuffer(), UnlockReleaseBuffer(), values, VISIBILITYMAP_ALL_FROZEN, VISIBILITYMAP_ALL_VISIBLE, and visibilitymap_get_status().

107 {
108  Oid relid = PG_GETARG_OID(0);
109  int64 blkno = PG_GETARG_INT64(1);
110  int32 mapbits;
111  Relation rel;
112  Buffer vmbuffer = InvalidBuffer;
113  Buffer buffer;
114  Page page;
115  TupleDesc tupdesc;
116  Datum values[3];
117  bool nulls[3];
118 
119  rel = relation_open(relid, AccessShareLock);
120 
121  /* Only some relkinds have a visibility map */
123 
124  if (blkno < 0 || blkno > MaxBlockNumber)
125  ereport(ERROR,
126  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
127  errmsg("invalid block number")));
128 
129  tupdesc = pg_visibility_tupdesc(false, true);
130  MemSet(nulls, 0, sizeof(nulls));
131 
132  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
133  if (vmbuffer != InvalidBuffer)
134  ReleaseBuffer(vmbuffer);
135  values[0] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0);
136  values[1] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0);
137 
138  /* Here we have to explicitly check rel size ... */
139  if (blkno < RelationGetNumberOfBlocks(rel))
140  {
141  buffer = ReadBuffer(rel, blkno);
142  LockBuffer(buffer, BUFFER_LOCK_SHARE);
143 
144  page = BufferGetPage(buffer);
145  values[2] = BoolGetDatum(PageIsAllVisible(page));
146 
147  UnlockReleaseBuffer(buffer);
148  }
149  else
150  {
151  /* As with the vismap, silently return 0 for pages past EOF */
152  values[2] = BoolGetDatum(false);
153  }
154 
156 
157  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
158 }
#define PageIsAllVisible(page)
Definition: bufpage.h:381
#define VISIBILITYMAP_ALL_FROZEN
Definition: visibilitymap.h:27
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define MemSet(start, val, len)
Definition: c.h:846
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd)
signed int int32
Definition: c.h:246
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define MaxBlockNumber
Definition: block.h:35
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void check_relation_relkind(Relation rel)
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define BoolGetDatum(X)
Definition: postgres.h:408
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
Datum pg_visibility_map ( PG_FUNCTION_ARGS  )

Definition at line 66 of file pg_visibility.c.

References AccessShareLock, BoolGetDatum, check_relation_relkind(), ereport, errcode(), errmsg(), ERROR, heap_form_tuple(), HeapTupleGetDatum, InvalidBuffer, MaxBlockNumber, MemSet, PG_GETARG_INT64, PG_GETARG_OID, PG_RETURN_DATUM, pg_visibility_tupdesc(), relation_close(), relation_open(), ReleaseBuffer(), values, VISIBILITYMAP_ALL_FROZEN, VISIBILITYMAP_ALL_VISIBLE, and visibilitymap_get_status().

67 {
68  Oid relid = PG_GETARG_OID(0);
69  int64 blkno = PG_GETARG_INT64(1);
70  int32 mapbits;
71  Relation rel;
72  Buffer vmbuffer = InvalidBuffer;
73  TupleDesc tupdesc;
74  Datum values[2];
75  bool nulls[2];
76 
77  rel = relation_open(relid, AccessShareLock);
78 
79  /* Only some relkinds have a visibility map */
81 
82  if (blkno < 0 || blkno > MaxBlockNumber)
83  ereport(ERROR,
84  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
85  errmsg("invalid block number")));
86 
87  tupdesc = pg_visibility_tupdesc(false, false);
88  MemSet(nulls, 0, sizeof(nulls));
89 
90  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
91  if (vmbuffer != InvalidBuffer)
92  ReleaseBuffer(vmbuffer);
93  values[0] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0);
94  values[1] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0);
95 
97 
98  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
99 }
#define VISIBILITYMAP_ALL_FROZEN
Definition: visibilitymap.h:27
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define MemSet(start, val, len)
Definition: c.h:846
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd)
signed int int32
Definition: c.h:246
#define ERROR
Definition: elog.h:43
#define MaxBlockNumber
Definition: block.h:35
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void check_relation_relkind(Relation rel)
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define BoolGetDatum(X)
Definition: postgres.h:408
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
int Buffer
Definition: buf.h:23
Datum pg_visibility_map_rel ( PG_FUNCTION_ARGS  )

Definition at line 164 of file pg_visibility.c.

References vbits::bits, BoolGetDatum, collect_visibility_data(), vbits::count, heap_form_tuple(), HeapTupleGetDatum, Int64GetDatum(), MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, vbits::next, PG_GETARG_OID, pg_visibility_tupdesc(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::tuple_desc, FuncCallContext::user_fctx, and values.

165 {
166  FuncCallContext *funcctx;
167  vbits *info;
168 
169  if (SRF_IS_FIRSTCALL())
170  {
171  Oid relid = PG_GETARG_OID(0);
172  MemoryContext oldcontext;
173 
174  funcctx = SRF_FIRSTCALL_INIT();
175  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
176  funcctx->tuple_desc = pg_visibility_tupdesc(true, false);
177  /* collect_visibility_data will verify the relkind */
178  funcctx->user_fctx = collect_visibility_data(relid, false);
179  MemoryContextSwitchTo(oldcontext);
180  }
181 
182  funcctx = SRF_PERCALL_SETUP();
183  info = (vbits *) funcctx->user_fctx;
184 
185  if (info->next < info->count)
186  {
187  Datum values[3];
188  bool nulls[3];
189  HeapTuple tuple;
190 
191  MemSet(nulls, 0, sizeof(nulls));
192  values[0] = Int64GetDatum(info->next);
193  values[1] = BoolGetDatum((info->bits[info->next] & (1 << 0)) != 0);
194  values[2] = BoolGetDatum((info->bits[info->next] & (1 << 1)) != 0);
195  info->next++;
196 
197  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
198  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
199  }
200 
201  SRF_RETURN_DONE(funcctx);
202 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define MemSet(start, val, len)
Definition: c.h:846
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd)
TupleDesc tuple_desc
Definition: funcapi.h:120
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
BlockNumber count
Definition: pg_visibility.c:29
uintptr_t Datum
Definition: postgres.h:372
#define BoolGetDatum(X)
Definition: postgres.h:408
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
static Datum values[MAXATTR]
Definition: bootstrap.c:163
void * user_fctx
Definition: funcapi.h:90
BlockNumber next
Definition: pg_visibility.c:28
static vbits * collect_visibility_data(Oid relid, bool include_pd)
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum pg_visibility_map_summary ( PG_FUNCTION_ARGS  )

Definition at line 255 of file pg_visibility.c.

References AccessShareLock, BlessTupleDesc(), CHECK_FOR_INTERRUPTS, check_relation_relkind(), CreateTemplateTupleDesc(), heap_form_tuple(), HeapTupleGetDatum, Int64GetDatum(), INT8OID, InvalidBuffer, MemSet, PG_GETARG_OID, PG_RETURN_DATUM, relation_close(), relation_open(), RelationGetNumberOfBlocks, ReleaseBuffer(), TupleDescInitEntry(), values, VISIBILITYMAP_ALL_FROZEN, VISIBILITYMAP_ALL_VISIBLE, and visibilitymap_get_status().

256 {
257  Oid relid = PG_GETARG_OID(0);
258  Relation rel;
259  BlockNumber nblocks;
260  BlockNumber blkno;
261  Buffer vmbuffer = InvalidBuffer;
262  int64 all_visible = 0;
263  int64 all_frozen = 0;
264  TupleDesc tupdesc;
265  Datum values[2];
266  bool nulls[2];
267 
268  rel = relation_open(relid, AccessShareLock);
269 
270  /* Only some relkinds have a visibility map */
272 
273  nblocks = RelationGetNumberOfBlocks(rel);
274 
275  for (blkno = 0; blkno < nblocks; ++blkno)
276  {
277  int32 mapbits;
278 
279  /* Make sure we are interruptible. */
281 
282  /* Get map info. */
283  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
284  if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
285  ++all_visible;
286  if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
287  ++all_frozen;
288  }
289 
290  /* Clean up. */
291  if (vmbuffer != InvalidBuffer)
292  ReleaseBuffer(vmbuffer);
294 
295  tupdesc = CreateTemplateTupleDesc(2, false);
296  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "all_visible", INT8OID, -1, 0);
297  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "all_frozen", INT8OID, -1, 0);
298  tupdesc = BlessTupleDesc(tupdesc);
299 
300  MemSet(nulls, 0, sizeof(nulls));
301  values[0] = Int64GetDatum(all_visible);
302  values[1] = Int64GetDatum(all_frozen);
303 
304  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
305 }
#define VISIBILITYMAP_ALL_FROZEN
Definition: visibilitymap.h:27
#define AccessShareLock
Definition: lockdefs.h:36
#define InvalidBuffer
Definition: buf.h:25
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define MemSet(start, val, len)
Definition: c.h:846
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static void check_relation_relkind(Relation rel)
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:505
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define INT8OID
Definition: pg_type.h:304
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
static Datum values[MAXATTR]
Definition: bootstrap.c:163
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
int Buffer
Definition: buf.h:23
int16 AttrNumber
Definition: attnum.h:21
Datum pg_visibility_rel ( PG_FUNCTION_ARGS  )

Definition at line 209 of file pg_visibility.c.

References vbits::bits, BoolGetDatum, collect_visibility_data(), vbits::count, heap_form_tuple(), HeapTupleGetDatum, Int64GetDatum(), MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, vbits::next, PG_GETARG_OID, pg_visibility_tupdesc(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::tuple_desc, FuncCallContext::user_fctx, and values.

210 {
211  FuncCallContext *funcctx;
212  vbits *info;
213 
214  if (SRF_IS_FIRSTCALL())
215  {
216  Oid relid = PG_GETARG_OID(0);
217  MemoryContext oldcontext;
218 
219  funcctx = SRF_FIRSTCALL_INIT();
220  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
221  funcctx->tuple_desc = pg_visibility_tupdesc(true, true);
222  /* collect_visibility_data will verify the relkind */
223  funcctx->user_fctx = collect_visibility_data(relid, true);
224  MemoryContextSwitchTo(oldcontext);
225  }
226 
227  funcctx = SRF_PERCALL_SETUP();
228  info = (vbits *) funcctx->user_fctx;
229 
230  if (info->next < info->count)
231  {
232  Datum values[4];
233  bool nulls[4];
234  HeapTuple tuple;
235 
236  MemSet(nulls, 0, sizeof(nulls));
237  values[0] = Int64GetDatum(info->next);
238  values[1] = BoolGetDatum((info->bits[info->next] & (1 << 0)) != 0);
239  values[2] = BoolGetDatum((info->bits[info->next] & (1 << 1)) != 0);
240  values[3] = BoolGetDatum((info->bits[info->next] & (1 << 2)) != 0);
241  info->next++;
242 
243  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
244  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
245  }
246 
247  SRF_RETURN_DONE(funcctx);
248 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define MemSet(start, val, len)
Definition: c.h:846
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
unsigned int Oid
Definition: postgres_ext.h:31
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd)
TupleDesc tuple_desc
Definition: funcapi.h:120
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
BlockNumber count
Definition: pg_visibility.c:29
uintptr_t Datum
Definition: postgres.h:372
#define BoolGetDatum(X)
Definition: postgres.h:408
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
static Datum values[MAXATTR]
Definition: bootstrap.c:163
void * user_fctx
Definition: funcapi.h:90
BlockNumber next
Definition: pg_visibility.c:28
static vbits * collect_visibility_data(Oid relid, bool include_pd)
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
static TupleDesc pg_visibility_tupdesc ( bool  include_blkno,
bool  include_pd 
)
static

Definition at line 440 of file pg_visibility.c.

References Assert, BlessTupleDesc(), BOOLOID, CreateTemplateTupleDesc(), INT8OID, and TupleDescInitEntry().

Referenced by pg_visibility(), pg_visibility_map(), pg_visibility_map_rel(), and pg_visibility_rel().

441 {
442  TupleDesc tupdesc;
443  AttrNumber maxattr = 2;
444  AttrNumber a = 0;
445 
446  if (include_blkno)
447  ++maxattr;
448  if (include_pd)
449  ++maxattr;
450  tupdesc = CreateTemplateTupleDesc(maxattr, false);
451  if (include_blkno)
452  TupleDescInitEntry(tupdesc, ++a, "blkno", INT8OID, -1, 0);
453  TupleDescInitEntry(tupdesc, ++a, "all_visible", BOOLOID, -1, 0);
454  TupleDescInitEntry(tupdesc, ++a, "all_frozen", BOOLOID, -1, 0);
455  if (include_pd)
456  TupleDescInitEntry(tupdesc, ++a, "pd_all_visible", BOOLOID, -1, 0);
457  Assert(a == maxattr);
458 
459  return BlessTupleDesc(tupdesc);
460 }
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:505
#define INT8OID
Definition: pg_type.h:304
#define Assert(condition)
Definition: c.h:664
#define BOOLOID
Definition: pg_type.h:288
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
int16 AttrNumber
Definition: attnum.h:21
static void record_corrupt_item ( corrupt_items items,
ItemPointer  tid 
)
static

Definition at line 724 of file pg_visibility.c.

References corrupt_items::count, corrupt_items::next, repalloc(), and corrupt_items::tids.

Referenced by collect_corrupt_items().

725 {
726  /* enlarge output array if needed. */
727  if (items->next >= items->count)
728  {
729  items->count *= 2;
730  items->tids = repalloc(items->tids,
731  items->count * sizeof(ItemPointerData));
732  }
733  /* and add the new item */
734  items->tids[items->next++] = *tid;
735 }
BlockNumber count
Definition: pg_visibility.c:36
ItemPointer tids
Definition: pg_visibility.c:37
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
BlockNumber next
Definition: pg_visibility.c:35
static bool tuple_all_visible ( HeapTuple  tup,
TransactionId  OldestXmin,
Buffer  buffer 
)
static

Definition at line 742 of file pg_visibility.c.

References HEAPTUPLE_LIVE, HeapTupleHeaderGetXmin, HeapTupleSatisfiesVacuum(), HeapTupleData::t_data, and TransactionIdPrecedes().

Referenced by collect_corrupt_items().

743 {
745  TransactionId xmin;
746 
748  if (state != HEAPTUPLE_LIVE)
749  return false; /* all-visible implies live */
750 
751  /*
752  * Neither lazy_scan_heap nor heap_page_is_all_visible will mark a page
753  * all-visible unless every tuple is hinted committed. However, those hint
754  * bits could be lost after a crash, so we can't be certain that they'll
755  * be set here. So just check the xmin.
756  */
757 
758  xmin = HeapTupleHeaderGetXmin(tup->t_data);
759  if (!TransactionIdPrecedes(xmin, OldestXmin))
760  return false; /* xmin not old enough for all to see */
761 
762  return true;
763 }
uint32 TransactionId
Definition: c.h:391
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1166
HTSV_Result
Definition: tqual.h:49
HeapTupleHeader t_data
Definition: htup.h:67
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
Definition: regguts.h:298
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307

Variable Documentation

PG_MODULE_MAGIC

Definition at line 24 of file pg_visibility.c.