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)
 
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 corrupt_items * collect_corrupt_items ( Oid  relid,
bool  all_visible,
bool  all_frozen 
)
static

Definition at line 528 of file pg_visibility.c.

References AccessShareLock, BAS_BULKREAD, BUFFER_LOCK_SHARE, BufferGetPage, CHECK_FOR_INTERRUPTS, corrupt_items::count, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, GetAccessStrategy(), GetOldestXmin(), heap_tuple_needs_eventual_freeze(), InvalidBuffer, InvalidTransactionId, ItemIdGetLength, ItemIdIsDead, ItemIdIsRedirected, ItemIdIsUsed, ItemPointerSet, LockBuffer(), MAIN_FORKNUM, corrupt_items::next, NULL, OffsetNumberNext, OldestXmin, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, palloc(), palloc0(), RBM_NORMAL, RelationData::rd_rel, ReadBufferExtended(), record_corrupt_item(), relation_close(), relation_open(), RelationGetNumberOfBlocks, RelationGetRelationName, ReleaseBuffer(), RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_TOASTVALUE, 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().

529 {
530  Relation rel;
531  BlockNumber nblocks;
532  corrupt_items *items;
533  BlockNumber blkno;
534  Buffer vmbuffer = InvalidBuffer;
537 
538  if (all_visible)
539  {
540  /* Don't pass rel; that will fail in recovery. */
541  OldestXmin = GetOldestXmin(NULL, true);
542  }
543 
544  rel = relation_open(relid, AccessShareLock);
545 
546  if (rel->rd_rel->relkind != RELKIND_RELATION &&
547  rel->rd_rel->relkind != RELKIND_MATVIEW &&
548  rel->rd_rel->relkind != RELKIND_TOASTVALUE)
549  ereport(ERROR,
550  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
551  errmsg("\"%s\" is not a table, materialized view, or TOAST table",
552  RelationGetRelationName(rel))));
553 
554  nblocks = RelationGetNumberOfBlocks(rel);
555 
556  /*
557  * Guess an initial array size. We don't expect many corrupted tuples, so
558  * start with a small array. This function uses the "next" field to track
559  * the next offset where we can store an item (which is the same thing as
560  * the number of items found so far) and the "count" field to track the
561  * number of entries allocated. We'll repurpose these fields before
562  * returning.
563  */
564  items = palloc0(sizeof(corrupt_items));
565  items->next = 0;
566  items->count = 64;
567  items->tids = palloc(items->count * sizeof(ItemPointerData));
568 
569  /* Loop over every block in the relation. */
570  for (blkno = 0; blkno < nblocks; ++blkno)
571  {
572  bool check_frozen = false;
573  bool check_visible = false;
574  Buffer buffer;
575  Page page;
576  OffsetNumber offnum,
577  maxoff;
578 
579  /* Make sure we are interruptible. */
581 
582  /* Use the visibility map to decide whether to check this page. */
583  if (all_frozen && VM_ALL_FROZEN(rel, blkno, &vmbuffer))
584  check_frozen = true;
585  if (all_visible && VM_ALL_VISIBLE(rel, blkno, &vmbuffer))
586  check_visible = true;
587  if (!check_visible && !check_frozen)
588  continue;
589 
590  /* Read and lock the page. */
591  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
592  bstrategy);
593  LockBuffer(buffer, BUFFER_LOCK_SHARE);
594 
595  page = BufferGetPage(buffer);
596  maxoff = PageGetMaxOffsetNumber(page);
597 
598  /*
599  * The visibility map bits might have changed while we were acquiring
600  * the page lock. Recheck to avoid returning spurious results.
601  */
602  if (check_frozen && !VM_ALL_FROZEN(rel, blkno, &vmbuffer))
603  check_frozen = false;
604  if (check_visible && !VM_ALL_VISIBLE(rel, blkno, &vmbuffer))
605  check_visible = false;
606  if (!check_visible && !check_frozen)
607  {
608  UnlockReleaseBuffer(buffer);
609  continue;
610  }
611 
612  /* Iterate over each tuple on the page. */
613  for (offnum = FirstOffsetNumber;
614  offnum <= maxoff;
615  offnum = OffsetNumberNext(offnum))
616  {
617  HeapTupleData tuple;
618  ItemId itemid;
619 
620  itemid = PageGetItemId(page, offnum);
621 
622  /* Unused or redirect line pointers are of no interest. */
623  if (!ItemIdIsUsed(itemid) || ItemIdIsRedirected(itemid))
624  continue;
625 
626  /* Dead line pointers are neither all-visible nor frozen. */
627  if (ItemIdIsDead(itemid))
628  {
629  ItemPointerSet(&(tuple.t_self), blkno, offnum);
630  record_corrupt_item(items, &tuple.t_self);
631  continue;
632  }
633 
634  /* Initialize a HeapTupleData structure for checks below. */
635  ItemPointerSet(&(tuple.t_self), blkno, offnum);
636  tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
637  tuple.t_len = ItemIdGetLength(itemid);
638  tuple.t_tableOid = relid;
639 
640  /*
641  * If we're checking whether the page is all-visible, we expect
642  * the tuple to be all-visible.
643  */
644  if (check_visible &&
645  !tuple_all_visible(&tuple, OldestXmin, buffer))
646  {
647  TransactionId RecomputedOldestXmin;
648 
649  /*
650  * Time has passed since we computed OldestXmin, so it's
651  * possible that this tuple is all-visible in reality even
652  * though it doesn't appear so based on our
653  * previously-computed value. Let's compute a new value so we
654  * can be certain whether there is a problem.
655  *
656  * From a concurrency point of view, it sort of sucks to
657  * retake ProcArrayLock here while we're holding the buffer
658  * exclusively locked, but it should be safe against
659  * deadlocks, because surely GetOldestXmin() should never take
660  * a buffer lock. And this shouldn't happen often, so it's
661  * worth being careful so as to avoid false positives.
662  */
663  RecomputedOldestXmin = GetOldestXmin(NULL, true);
664 
665  if (!TransactionIdPrecedes(OldestXmin, RecomputedOldestXmin))
666  record_corrupt_item(items, &tuple.t_self);
667  else
668  {
669  OldestXmin = RecomputedOldestXmin;
670  if (!tuple_all_visible(&tuple, OldestXmin, buffer))
671  record_corrupt_item(items, &tuple.t_self);
672  }
673  }
674 
675  /*
676  * If we're checking whether the page is all-frozen, we expect the
677  * tuple to be in a state where it will never need freezing.
678  */
679  if (check_frozen)
680  {
682  record_corrupt_item(items, &tuple.t_self);
683  }
684  }
685 
686  UnlockReleaseBuffer(buffer);
687  }
688 
689  /* Clean up. */
690  if (vmbuffer != InvalidBuffer)
691  ReleaseBuffer(vmbuffer);
693 
694  /*
695  * Before returning, repurpose the fields to match caller's expectations.
696  * next is now the next item that should be read (rather than written) and
697  * count is now the number of items we wrote (rather than the number we
698  * allocated).
699  */
700  items->count = items->next;
701  items->next = 0;
702 
703  return items;
704 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:525
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:105
uint32 TransactionId
Definition: c.h:394
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 RELKIND_MATVIEW
Definition: pg_class.h:167
#define VM_ALL_FROZEN(r, b, v)
Definition: visibilitymap.h:34
#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:1263
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
Form_pg_class rd_rel
Definition: rel.h:113
#define ItemIdIsDead(itemId)
Definition: itemid.h:112
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
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:7186
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ERROR
Definition: elog.h:43
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
#define RelationGetRelationName(relation)
Definition: rel.h:433
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
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)
#define ereport(elevel, rest)
Definition: elog.h:122
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
void * palloc0(Size size)
Definition: mcxt.c:920
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
TransactionId GetOldestXmin(Relation rel, bool ignoreVacuum)
Definition: procarray.c:1305
ItemPointer tids
Definition: pg_visibility.c:37
#define NULL
Definition: c.h:226
#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:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define RELKIND_RELATION
Definition: pg_class.h:160
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:86
static vbits * collect_visibility_data ( Oid  relid,
bool  include_pd 
)
static

Definition at line 456 of file pg_visibility.c.

References AccessShareLock, BAS_BULKREAD, vbits::bits, BUFFER_LOCK_SHARE, BufferGetPage, CHECK_FOR_INTERRUPTS, 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().

457 {
458  Relation rel;
459  BlockNumber nblocks;
460  vbits *info;
461  BlockNumber blkno;
462  Buffer vmbuffer = InvalidBuffer;
464 
465  rel = relation_open(relid, AccessShareLock);
466 
467  nblocks = RelationGetNumberOfBlocks(rel);
468  info = palloc0(offsetof(vbits, bits) +nblocks);
469  info->next = 0;
470  info->count = nblocks;
471 
472  for (blkno = 0; blkno < nblocks; ++blkno)
473  {
474  int32 mapbits;
475 
476  /* Make sure we are interruptible. */
478 
479  /* Get map info. */
480  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
481  if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
482  info->bits[blkno] |= (1 << 0);
483  if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
484  info->bits[blkno] |= (1 << 1);
485 
486  /*
487  * Page-level data requires reading every block, so only get it if the
488  * caller needs it. Use a buffer access strategy, too, to prevent
489  * cache-trashing.
490  */
491  if (include_pd)
492  {
493  Buffer buffer;
494  Page page;
495 
496  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL,
497  bstrategy);
498  LockBuffer(buffer, BUFFER_LOCK_SHARE);
499 
500  page = BufferGetPage(buffer);
501  if (PageIsAllVisible(page))
502  info->bits[blkno] |= (1 << 2);
503 
504  UnlockReleaseBuffer(buffer);
505  }
506  }
507 
508  /* Clean up. */
509  if (vmbuffer != InvalidBuffer)
510  ReleaseBuffer(vmbuffer);
512 
513  return info;
514 }
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:525
#define PageIsAllVisible(page)
Definition: bufpage.h:382
#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:1263
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
signed int int32
Definition: c.h:253
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void * palloc0(Size size)
Definition: mcxt.c:920
BlockNumber count
Definition: pg_visibility.c:29
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#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:1117
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
int Buffer
Definition: buf.h:23
BlockNumber next
Definition: pg_visibility.c:28
#define offsetof(type, field)
Definition: c.h:551
Pointer Page
Definition: bufpage.h:74
Datum pg_check_frozen ( PG_FUNCTION_ARGS  )

Definition at line 300 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.

301 {
302  FuncCallContext *funcctx;
303  corrupt_items *items;
304 
305  if (SRF_IS_FIRSTCALL())
306  {
307  Oid relid = PG_GETARG_OID(0);
308  MemoryContext oldcontext;
309 
310  funcctx = SRF_FIRSTCALL_INIT();
311  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
312  funcctx->user_fctx = collect_corrupt_items(relid, false, true);
313  MemoryContextSwitchTo(oldcontext);
314  }
315 
316  funcctx = SRF_PERCALL_SETUP();
317  items = (corrupt_items *) funcctx->user_fctx;
318 
319  if (items->next < items->count)
320  SRF_RETURN_NEXT(funcctx, PointerGetDatum(&items->tids[items->next++]));
321 
322  SRF_RETURN_DONE(funcctx);
323 }
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:564
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:231
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 331 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.

332 {
333  FuncCallContext *funcctx;
334  corrupt_items *items;
335 
336  if (SRF_IS_FIRSTCALL())
337  {
338  Oid relid = PG_GETARG_OID(0);
339  MemoryContext oldcontext;
340 
341  funcctx = SRF_FIRSTCALL_INIT();
342  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
343  funcctx->user_fctx = collect_corrupt_items(relid, true, false);
344  MemoryContextSwitchTo(oldcontext);
345  }
346 
347  funcctx = SRF_PERCALL_SETUP();
348  items = (corrupt_items *) funcctx->user_fctx;
349 
350  if (items->next < items->count)
351  SRF_RETURN_NEXT(funcctx, PointerGetDatum(&items->tids[items->next++]));
352 
353  SRF_RETURN_DONE(funcctx);
354 }
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:564
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:231
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 365 of file pg_visibility.c.

References AccessExclusiveLock, xl_smgr_truncate::blkno, ereport, errcode(), errmsg(), ERROR, xl_smgr_truncate::flags, InvalidBlockNumber, PG_GETARG_OID, PG_RETURN_VOID, RelationData::rd_node, RelationData::rd_rel, RelationData::rd_smgr, relation_close(), relation_open(), RelationGetRelationName, RelationNeedsWAL, RelationOpenSmgr, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_TOASTVALUE, xl_smgr_truncate::rnode, SMGR_TRUNCATE_VM, SMgrRelationData::smgr_vm_nblocks, visibilitymap_truncate(), XLOG_SMGR_TRUNCATE, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

366 {
367  Oid relid = PG_GETARG_OID(0);
368  Relation rel;
369 
370  rel = relation_open(relid, AccessExclusiveLock);
371 
372  if (rel->rd_rel->relkind != RELKIND_RELATION &&
373  rel->rd_rel->relkind != RELKIND_MATVIEW &&
374  rel->rd_rel->relkind != RELKIND_TOASTVALUE)
375  ereport(ERROR,
376  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
377  errmsg("\"%s\" is not a table, materialized view, or TOAST table",
378  RelationGetRelationName(rel))));
379 
380  RelationOpenSmgr(rel);
382 
383  visibilitymap_truncate(rel, 0);
384 
385  if (RelationNeedsWAL(rel))
386  {
387  xl_smgr_truncate xlrec;
388 
389  xlrec.blkno = 0;
390  xlrec.rnode = rel->rd_node;
391  xlrec.flags = SMGR_TRUNCATE_VM;
392 
393  XLogBeginInsert();
394  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
395 
397  }
398 
399  /*
400  * Release the lock right away, not at commit time.
401  *
402  * It would be a problem to release the lock prior to commit if this
403  * truncate operation sends any transactional invalidation messages. Other
404  * backends would potentially be able to lock the relation without
405  * processing them in the window of time between when we release the lock
406  * here and when we sent the messages at our eventual commit. However,
407  * we're currently only sending a non-transactional smgr invalidation,
408  * which will have been posted to shared memory immediately from within
409  * visibilitymap_truncate. Therefore, there should be no race here.
410  *
411  * The reason why it's desirable to release the lock early here is because
412  * of the possibility that someone will need to use this to blow away many
413  * visibility map forks at once. If we can't release the lock until
414  * commit time, the transaction doing this will accumulate
415  * AccessExclusiveLocks on all of those relations at the same time, which
416  * is undesirable. However, if this turns out to be unsafe we may have no
417  * choice...
418  */
420 
421  /* Nothing to return. */
422  PG_RETURN_VOID();
423 }
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
#define RELKIND_MATVIEW
Definition: pg_class.h:167
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
RelFileNode rnode
Definition: storage_xlog.h:49
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationOpenSmgr(relation)
Definition: rel.h:457
#define ERROR
Definition: elog.h:43
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ereport(elevel, rest)
Definition: elog.h:122
#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 RELKIND_TOASTVALUE
Definition: pg_class.h:163
#define PG_RETURN_VOID()
Definition: fmgr.h:293
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:502
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
BlockNumber blkno
Definition: storage_xlog.h:48
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define RELKIND_RELATION
Definition: pg_class.h:160
Datum pg_visibility ( PG_FUNCTION_ARGS  )

Definition at line 102 of file pg_visibility.c.

References AccessShareLock, BoolGetDatum, BUFFER_LOCK_SHARE, BufferGetPage, 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().

103 {
104  Oid relid = PG_GETARG_OID(0);
105  int64 blkno = PG_GETARG_INT64(1);
106  int32 mapbits;
107  Relation rel;
108  Buffer vmbuffer = InvalidBuffer;
109  Buffer buffer;
110  Page page;
111  TupleDesc tupdesc;
112  Datum values[3];
113  bool nulls[3];
114 
115  rel = relation_open(relid, AccessShareLock);
116 
117  if (blkno < 0 || blkno > MaxBlockNumber)
118  ereport(ERROR,
119  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
120  errmsg("invalid block number")));
121 
122  tupdesc = pg_visibility_tupdesc(false, true);
123  MemSet(nulls, 0, sizeof(nulls));
124 
125  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
126  if (vmbuffer != InvalidBuffer)
127  ReleaseBuffer(vmbuffer);
128  values[0] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0);
129  values[1] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0);
130 
131  /* Here we have to explicitly check rel size ... */
132  if (blkno < RelationGetNumberOfBlocks(rel))
133  {
134  buffer = ReadBuffer(rel, blkno);
135  LockBuffer(buffer, BUFFER_LOCK_SHARE);
136 
137  page = BufferGetPage(buffer);
138  values[2] = BoolGetDatum(PageIsAllVisible(page));
139 
140  UnlockReleaseBuffer(buffer);
141  }
142  else
143  {
144  /* As with the vismap, silently return 0 for pages past EOF */
145  values[2] = BoolGetDatum(false);
146  }
147 
149 
150  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
151 }
#define PageIsAllVisible(page)
Definition: bufpage.h:382
#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:1263
#define MemSet(start, val, len)
Definition: c.h:853
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
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:253
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3315
#define ERROR
Definition: elog.h:43
#define MaxBlockNumber
Definition: block.h:35
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define BoolGetDatum(X)
Definition: postgres.h:410
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:162
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:1117
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
Datum pg_visibility_map ( PG_FUNCTION_ARGS  )

Definition at line 65 of file pg_visibility.c.

References AccessShareLock, BoolGetDatum, 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().

66 {
67  Oid relid = PG_GETARG_OID(0);
68  int64 blkno = PG_GETARG_INT64(1);
69  int32 mapbits;
70  Relation rel;
71  Buffer vmbuffer = InvalidBuffer;
72  TupleDesc tupdesc;
73  Datum values[2];
74  bool nulls[2];
75 
76  rel = relation_open(relid, AccessShareLock);
77 
78  if (blkno < 0 || blkno > MaxBlockNumber)
79  ereport(ERROR,
80  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
81  errmsg("invalid block number")));
82 
83  tupdesc = pg_visibility_tupdesc(false, false);
84  MemSet(nulls, 0, sizeof(nulls));
85 
86  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
87  if (vmbuffer != InvalidBuffer)
88  ReleaseBuffer(vmbuffer);
89  values[0] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0);
90  values[1] = BoolGetDatum((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0);
91 
93 
94  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
95 }
#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:1263
#define MemSet(start, val, len)
Definition: c.h:853
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
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:253
#define ERROR
Definition: elog.h:43
#define MaxBlockNumber
Definition: block.h:35
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define BoolGetDatum(X)
Definition: postgres.h:410
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
static Datum values[MAXATTR]
Definition: bootstrap.c:162
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:1117
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
int Buffer
Definition: buf.h:23
Datum pg_visibility_map_rel ( PG_FUNCTION_ARGS  )

Definition at line 157 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.

158 {
159  FuncCallContext *funcctx;
160  vbits *info;
161 
162  if (SRF_IS_FIRSTCALL())
163  {
164  Oid relid = PG_GETARG_OID(0);
165  MemoryContext oldcontext;
166 
167  funcctx = SRF_FIRSTCALL_INIT();
168  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
169  funcctx->tuple_desc = pg_visibility_tupdesc(true, false);
170  funcctx->user_fctx = collect_visibility_data(relid, false);
171  MemoryContextSwitchTo(oldcontext);
172  }
173 
174  funcctx = SRF_PERCALL_SETUP();
175  info = (vbits *) funcctx->user_fctx;
176 
177  if (info->next < info->count)
178  {
179  Datum values[3];
180  bool nulls[3];
181  HeapTuple tuple;
182 
183  MemSet(nulls, 0, sizeof(nulls));
184  values[0] = Int64GetDatum(info->next);
185  values[1] = BoolGetDatum((info->bits[info->next] & (1 << 0)) != 0);
186  values[2] = BoolGetDatum((info->bits[info->next] & (1 << 1)) != 0);
187  info->next++;
188 
189  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
190  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
191  }
192 
193  SRF_RETURN_DONE(funcctx);
194 }
#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:853
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
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:231
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
BlockNumber count
Definition: pg_visibility.c:29
uintptr_t Datum
Definition: postgres.h:374
#define BoolGetDatum(X)
Definition: postgres.h:410
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
static Datum values[MAXATTR]
Definition: bootstrap.c:162
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 246 of file pg_visibility.c.

References AccessShareLock, BlessTupleDesc(), CHECK_FOR_INTERRUPTS, 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().

247 {
248  Oid relid = PG_GETARG_OID(0);
249  Relation rel;
250  BlockNumber nblocks;
251  BlockNumber blkno;
252  Buffer vmbuffer = InvalidBuffer;
253  int64 all_visible = 0;
254  int64 all_frozen = 0;
255  TupleDesc tupdesc;
256  Datum values[2];
257  bool nulls[2];
258 
259  rel = relation_open(relid, AccessShareLock);
260  nblocks = RelationGetNumberOfBlocks(rel);
261 
262  for (blkno = 0; blkno < nblocks; ++blkno)
263  {
264  int32 mapbits;
265 
266  /* Make sure we are interruptible. */
268 
269  /* Get map info. */
270  mapbits = (int32) visibilitymap_get_status(rel, blkno, &vmbuffer);
271  if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0)
272  ++all_visible;
273  if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0)
274  ++all_frozen;
275  }
276 
277  /* Clean up. */
278  if (vmbuffer != InvalidBuffer)
279  ReleaseBuffer(vmbuffer);
281 
282  tupdesc = CreateTemplateTupleDesc(2, false);
283  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "all_visible", INT8OID, -1, 0);
284  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "all_frozen", INT8OID, -1, 0);
285  tupdesc = BlessTupleDesc(tupdesc);
286 
287  MemSet(nulls, 0, sizeof(nulls));
288  values[0] = Int64GetDatum(all_visible);
289  values[1] = Int64GetDatum(all_frozen);
290 
291  PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
292 }
#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:1263
#define MemSet(start, val, len)
Definition: c.h:853
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:253
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:493
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#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:41
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
static Datum values[MAXATTR]
Definition: bootstrap.c:162
uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *buf)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
int Buffer
Definition: buf.h:23
int16 AttrNumber
Definition: attnum.h:21
Datum pg_visibility_rel ( PG_FUNCTION_ARGS  )

Definition at line 201 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.

202 {
203  FuncCallContext *funcctx;
204  vbits *info;
205 
206  if (SRF_IS_FIRSTCALL())
207  {
208  Oid relid = PG_GETARG_OID(0);
209  MemoryContext oldcontext;
210 
211  funcctx = SRF_FIRSTCALL_INIT();
212  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
213  funcctx->tuple_desc = pg_visibility_tupdesc(true, true);
214  funcctx->user_fctx = collect_visibility_data(relid, true);
215  MemoryContextSwitchTo(oldcontext);
216  }
217 
218  funcctx = SRF_PERCALL_SETUP();
219  info = (vbits *) funcctx->user_fctx;
220 
221  if (info->next < info->count)
222  {
223  Datum values[4];
224  bool nulls[4];
225  HeapTuple tuple;
226 
227  MemSet(nulls, 0, sizeof(nulls));
228  values[0] = Int64GetDatum(info->next);
229  values[1] = BoolGetDatum((info->bits[info->next] & (1 << 0)) != 0);
230  values[2] = BoolGetDatum((info->bits[info->next] & (1 << 1)) != 0);
231  values[3] = BoolGetDatum((info->bits[info->next] & (1 << 2)) != 0);
232  info->next++;
233 
234  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
235  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
236  }
237 
238  SRF_RETURN_DONE(funcctx);
239 }
#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:853
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
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:231
uint8 bits[FLEXIBLE_ARRAY_MEMBER]
Definition: pg_visibility.c:30
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:2102
BlockNumber count
Definition: pg_visibility.c:29
uintptr_t Datum
Definition: postgres.h:374
#define BoolGetDatum(X)
Definition: postgres.h:410
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
static Datum values[MAXATTR]
Definition: bootstrap.c:162
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 430 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().

431 {
432  TupleDesc tupdesc;
433  AttrNumber maxattr = 2;
434  AttrNumber a = 0;
435 
436  if (include_blkno)
437  ++maxattr;
438  if (include_pd)
439  ++maxattr;
440  tupdesc = CreateTemplateTupleDesc(maxattr, false);
441  if (include_blkno)
442  TupleDescInitEntry(tupdesc, ++a, "blkno", INT8OID, -1, 0);
443  TupleDescInitEntry(tupdesc, ++a, "all_visible", BOOLOID, -1, 0);
444  TupleDescInitEntry(tupdesc, ++a, "all_frozen", BOOLOID, -1, 0);
445  if (include_pd)
446  TupleDescInitEntry(tupdesc, ++a, "pd_all_visible", BOOLOID, -1, 0);
447  Assert(a == maxattr);
448 
449  return BlessTupleDesc(tupdesc);
450 }
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:493
#define INT8OID
Definition: pg_type.h:304
#define Assert(condition)
Definition: c.h:671
#define BOOLOID
Definition: pg_type.h:288
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
int16 AttrNumber
Definition: attnum.h:21
static void record_corrupt_item ( corrupt_items items,
ItemPointer  tid 
)
static

Definition at line 710 of file pg_visibility.c.

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

Referenced by collect_corrupt_items().

711 {
712  /* enlarge output array if needed. */
713  if (items->next >= items->count)
714  {
715  items->count *= 2;
716  items->tids = repalloc(items->tids,
717  items->count * sizeof(ItemPointerData));
718  }
719  /* and add the new item */
720  items->tids[items->next++] = *tid;
721 }
BlockNumber count
Definition: pg_visibility.c:36
ItemPointer tids
Definition: pg_visibility.c:37
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
BlockNumber next
Definition: pg_visibility.c:35
static bool tuple_all_visible ( HeapTuple  tup,
TransactionId  OldestXmin,
Buffer  buffer 
)
static

Definition at line 728 of file pg_visibility.c.

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

Referenced by collect_corrupt_items().

729 {
731  TransactionId xmin;
732 
733  state = HeapTupleSatisfiesVacuum(tup, OldestXmin, buffer);
734  if (state != HEAPTUPLE_LIVE)
735  return false; /* all-visible implies live */
736 
737  /*
738  * Neither lazy_scan_heap nor heap_page_is_all_visible will mark a page
739  * all-visible unless every tuple is hinted committed. However, those hint
740  * bits could be lost after a crash, so we can't be certain that they'll
741  * be set here. So just check the xmin.
742  */
743 
744  xmin = HeapTupleHeaderGetXmin(tup->t_data);
745  if (!TransactionIdPrecedes(xmin, OldestXmin))
746  return false; /* xmin not old enough for all to see */
747 
748  return true;
749 }
uint32 TransactionId
Definition: c.h:394
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
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
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307

Variable Documentation

PG_MODULE_MAGIC

Definition at line 24 of file pg_visibility.c.