PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
nbtree.c File Reference
#include "postgres.h"
#include "access/nbtree.h"
#include "access/relscan.h"
#include "access/stratnum.h"
#include "commands/progress.h"
#include "commands/vacuum.h"
#include "nodes/execnodes.h"
#include "pgstat.h"
#include "storage/bulk_write.h"
#include "storage/condition_variable.h"
#include "storage/indexfsm.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/read_stream.h"
#include "utils/datum.h"
#include "utils/fmgrprotos.h"
#include "utils/index_selfuncs.h"
#include "utils/memutils.h"
Include dependency graph for nbtree.c:

Go to the source code of this file.

Data Structures

struct  BTParallelScanDescData
 

Typedefs

typedef struct BTParallelScanDescData BTParallelScanDescData
 
typedef struct BTParallelScanDescDataBTParallelScanDesc
 

Enumerations

enum  BTPS_State {
  BTPARALLEL_NOT_INITIALIZED , BTPARALLEL_NEED_PRIMSCAN , BTPARALLEL_ADVANCING , BTPARALLEL_IDLE ,
  BTPARALLEL_DONE
}
 

Functions

static void _bt_parallel_serialize_arrays (Relation rel, BTParallelScanDesc btscan, BTScanOpaque so)
 
static void _bt_parallel_restore_arrays (Relation rel, BTParallelScanDesc btscan, BTScanOpaque so)
 
static void btvacuumscan (IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state, BTCycleId cycleid)
 
static BlockNumber btvacuumpage (BTVacState *vstate, Buffer buf)
 
static BTVacuumPosting btreevacuumposting (BTVacState *vstate, IndexTuple posting, OffsetNumber updatedoffset, int *nremaining)
 
Datum bthandler (PG_FUNCTION_ARGS)
 
void btbuildempty (Relation index)
 
bool btinsert (Relation rel, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
 
bool btgettuple (IndexScanDesc scan, ScanDirection dir)
 
int64 btgetbitmap (IndexScanDesc scan, TIDBitmap *tbm)
 
IndexScanDesc btbeginscan (Relation rel, int nkeys, int norderbys)
 
void btrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
void btendscan (IndexScanDesc scan)
 
void btmarkpos (IndexScanDesc scan)
 
void btrestrpos (IndexScanDesc scan)
 
Size btestimateparallelscan (Relation rel, int nkeys, int norderbys)
 
void btinitparallelscan (void *target)
 
void btparallelrescan (IndexScanDesc scan)
 
bool _bt_parallel_seize (IndexScanDesc scan, BlockNumber *next_scan_page, BlockNumber *last_curr_page, bool first)
 
void _bt_parallel_release (IndexScanDesc scan, BlockNumber next_scan_page, BlockNumber curr_page)
 
void _bt_parallel_done (IndexScanDesc scan)
 
void _bt_parallel_primscan_schedule (IndexScanDesc scan, BlockNumber curr_page)
 
IndexBulkDeleteResultbtbulkdelete (IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
 
IndexBulkDeleteResultbtvacuumcleanup (IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 
bool btcanreturn (Relation index, int attno)
 
int btgettreeheight (Relation rel)
 
CompareType bttranslatestrategy (StrategyNumber strategy, Oid opfamily)
 
StrategyNumber bttranslatecmptype (CompareType cmptype, Oid opfamily)
 

Typedef Documentation

◆ BTParallelScanDesc

Definition at line 93 of file nbtree.c.

◆ BTParallelScanDescData

Enumeration Type Documentation

◆ BTPS_State

enum BTPS_State
Enumerator
BTPARALLEL_NOT_INITIALIZED 
BTPARALLEL_NEED_PRIMSCAN 
BTPARALLEL_ADVANCING 
BTPARALLEL_IDLE 
BTPARALLEL_DONE 

Definition at line 54 of file nbtree.c.

55{
BTPS_State
Definition: nbtree.c:55
@ BTPARALLEL_ADVANCING
Definition: nbtree.c:58
@ BTPARALLEL_NEED_PRIMSCAN
Definition: nbtree.c:57
@ BTPARALLEL_NOT_INITIALIZED
Definition: nbtree.c:56
@ BTPARALLEL_IDLE
Definition: nbtree.c:59
@ BTPARALLEL_DONE
Definition: nbtree.c:60

Function Documentation

◆ _bt_parallel_done()

void _bt_parallel_done ( IndexScanDesc  scan)

Definition at line 981 of file nbtree.c.

982{
983 BTScanOpaque so = (BTScanOpaque) scan->opaque;
984 ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
985 BTParallelScanDesc btscan;
986 bool status_changed = false;
987
989
990 /* Do nothing, for non-parallel scans */
991 if (parallel_scan == NULL)
992 return;
993
994 /*
995 * Should not mark parallel scan done when there's still a pending
996 * primitive index scan
997 */
998 if (so->needPrimScan)
999 return;
1000
1001 btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan,
1002 parallel_scan->ps_offset_am);
1003
1004 /*
1005 * Mark the parallel scan as done, unless some other process did so
1006 * already
1007 */
1008 LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE);
1009 Assert(btscan->btps_pageStatus != BTPARALLEL_NEED_PRIMSCAN);
1010 if (btscan->btps_pageStatus != BTPARALLEL_DONE)
1011 {
1012 btscan->btps_pageStatus = BTPARALLEL_DONE;
1013 status_changed = true;
1014 }
1015 LWLockRelease(&btscan->btps_lock);
1016
1017 /* wake up all the workers associated with this parallel scan */
1018 if (status_changed)
1019 ConditionVariableBroadcast(&btscan->btps_cv);
1020}
#define OffsetToPointer(base, offset)
Definition: c.h:771
void ConditionVariableBroadcast(ConditionVariable *cv)
Assert(PointerIsAligned(start, uint64))
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_EXCLUSIVE
Definition: lwlock.h:112
struct BTParallelScanDescData * BTParallelScanDesc
Definition: nbtree.c:93
#define BTScanPosIsValid(scanpos)
Definition: nbtree.h:1021
BTScanOpaqueData * BTScanOpaque
Definition: nbtree.h:1097
bool needPrimScan
Definition: nbtree.h:1063
BTScanPosData currPos
Definition: nbtree.h:1093
struct ParallelIndexScanDescData * parallel_scan
Definition: relscan.h:191

References Assert(), BTPARALLEL_DONE, BTPARALLEL_NEED_PRIMSCAN, BTScanPosIsValid, ConditionVariableBroadcast(), BTScanOpaqueData::currPos, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), BTScanOpaqueData::needPrimScan, OffsetToPointer, IndexScanDescData::opaque, and IndexScanDescData::parallel_scan.

Referenced by _bt_endpoint(), _bt_first(), _bt_parallel_seize(), _bt_readnextpage(), and _bt_start_prim_scan().

◆ _bt_parallel_primscan_schedule()

void _bt_parallel_primscan_schedule ( IndexScanDesc  scan,
BlockNumber  curr_page 
)

Definition at line 1031 of file nbtree.c.

1032{
1033 Relation rel = scan->indexRelation;
1034 BTScanOpaque so = (BTScanOpaque) scan->opaque;
1035 ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
1036 BTParallelScanDesc btscan;
1037
1038 Assert(so->numArrayKeys);
1039
1040 btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan,
1041 parallel_scan->ps_offset_am);
1042
1043 LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE);
1044 if (btscan->btps_lastCurrPage == curr_page &&
1045 btscan->btps_pageStatus == BTPARALLEL_IDLE)
1046 {
1047 btscan->btps_nextScanPage = InvalidBlockNumber;
1048 btscan->btps_lastCurrPage = InvalidBlockNumber;
1049 btscan->btps_pageStatus = BTPARALLEL_NEED_PRIMSCAN;
1050
1051 /* Serialize scan's current array keys */
1052 _bt_parallel_serialize_arrays(rel, btscan, so);
1053 }
1054 LWLockRelease(&btscan->btps_lock);
1055}
#define InvalidBlockNumber
Definition: block.h:33
static void _bt_parallel_serialize_arrays(Relation rel, BTParallelScanDesc btscan, BTScanOpaque so)
Definition: nbtree.c:663
Relation indexRelation
Definition: relscan.h:137

References _bt_parallel_serialize_arrays(), Assert(), BTPARALLEL_IDLE, BTPARALLEL_NEED_PRIMSCAN, IndexScanDescData::indexRelation, InvalidBlockNumber, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), BTScanOpaqueData::numArrayKeys, OffsetToPointer, IndexScanDescData::opaque, and IndexScanDescData::parallel_scan.

Referenced by _bt_advance_array_keys(), and _bt_readpage().

◆ _bt_parallel_release()

void _bt_parallel_release ( IndexScanDesc  scan,
BlockNumber  next_scan_page,
BlockNumber  curr_page 
)

Definition at line 954 of file nbtree.c.

956{
957 ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
958 BTParallelScanDesc btscan;
959
960 Assert(BlockNumberIsValid(next_scan_page));
961
962 btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan,
963 parallel_scan->ps_offset_am);
964
966 btscan->btps_nextScanPage = next_scan_page;
967 btscan->btps_lastCurrPage = curr_page;
969 LWLockRelease(&btscan->btps_lock);
971}
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
void ConditionVariableSignal(ConditionVariable *cv)
BTPS_State btps_pageStatus
Definition: nbtree.c:72
BlockNumber btps_lastCurrPage
Definition: nbtree.c:70
ConditionVariable btps_cv
Definition: nbtree.c:76
BlockNumber btps_nextScanPage
Definition: nbtree.c:69

References Assert(), BlockNumberIsValid(), BTPARALLEL_IDLE, BTParallelScanDescData::btps_cv, BTParallelScanDescData::btps_lastCurrPage, BTParallelScanDescData::btps_lock, BTParallelScanDescData::btps_nextScanPage, BTParallelScanDescData::btps_pageStatus, ConditionVariableSignal(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OffsetToPointer, IndexScanDescData::parallel_scan, and ParallelIndexScanDescData::ps_offset_am.

Referenced by _bt_readnextpage(), and _bt_readpage().

◆ _bt_parallel_restore_arrays()

static void _bt_parallel_restore_arrays ( Relation  rel,
BTParallelScanDesc  btscan,
BTScanOpaque  so 
)
static

Definition at line 706 of file nbtree.c.

708{
709 char *datumshared;
710
711 /* Space for serialized datums begins immediately after btps_arrElems[] */
712 datumshared = ((char *) &btscan->btps_arrElems[so->numArrayKeys]);
713 for (int i = 0; i < so->numArrayKeys; i++)
714 {
715 BTArrayKeyInfo *array = &so->arrayKeys[i];
716 ScanKey skey = &so->keyData[array->scan_key];
717 bool isnull;
718
719 if (array->num_elems != -1)
720 {
721 /* Restore SAOP array using its saved cur_elem */
722 Assert(!(skey->sk_flags & SK_BT_SKIP));
723 array->cur_elem = btscan->btps_arrElems[i];
724 skey->sk_argument = array->elem_values[array->cur_elem];
725 continue;
726 }
727
728 /* Restore skip array by restoring its key directly */
729 if (!array->attbyval && skey->sk_argument)
731 skey->sk_argument = (Datum) 0;
732 memcpy(&skey->sk_flags, datumshared, sizeof(int));
733 datumshared += sizeof(int);
734
735 Assert(skey->sk_flags & SK_BT_SKIP);
736
737 if (skey->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL))
738 {
739 /* No sk_argument datum to restore */
740 continue;
741 }
742
743 skey->sk_argument = datumRestore(&datumshared, &isnull);
744 if (isnull)
745 {
746 Assert(skey->sk_argument == 0);
748 Assert(skey->sk_flags & SK_ISNULL);
749 }
750 }
751}
Datum datumRestore(char **start_address, bool *isnull)
Definition: datum.c:521
int i
Definition: isn.c:77
void pfree(void *pointer)
Definition: mcxt.c:1594
#define SK_BT_SKIP
Definition: nbtree.h:1137
#define SK_BT_MAXVAL
Definition: nbtree.h:1141
#define SK_BT_MINVAL
Definition: nbtree.h:1140
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
#define SK_SEARCHNULL
Definition: skey.h:121
#define SK_ISNULL
Definition: skey.h:115
bool attbyval
Definition: nbtree.h:1046
Datum * elem_values
Definition: nbtree.h:1041
int btps_arrElems[FLEXIBLE_ARRAY_MEMBER]
Definition: nbtree.c:83
BTArrayKeyInfo * arrayKeys
Definition: nbtree.h:1066
ScanKey keyData
Definition: nbtree.h:1058
int sk_flags
Definition: skey.h:66
Datum sk_argument
Definition: skey.h:72

References BTScanOpaqueData::arrayKeys, Assert(), BTArrayKeyInfo::attbyval, BTParallelScanDescData::btps_arrElems, BTArrayKeyInfo::cur_elem, DatumGetPointer(), datumRestore(), BTArrayKeyInfo::elem_values, i, BTScanOpaqueData::keyData, BTArrayKeyInfo::num_elems, BTScanOpaqueData::numArrayKeys, pfree(), BTArrayKeyInfo::scan_key, ScanKeyData::sk_argument, SK_BT_MAXVAL, SK_BT_MINVAL, SK_BT_SKIP, ScanKeyData::sk_flags, SK_ISNULL, and SK_SEARCHNULL.

Referenced by _bt_parallel_seize().

◆ _bt_parallel_seize()

bool _bt_parallel_seize ( IndexScanDesc  scan,
BlockNumber next_scan_page,
BlockNumber last_curr_page,
bool  first 
)

Definition at line 816 of file nbtree.c.

818{
819 Relation rel = scan->indexRelation;
820 BTScanOpaque so = (BTScanOpaque) scan->opaque;
821 bool exit_loop = false,
822 status = true,
823 endscan = false;
824 ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
825 BTParallelScanDesc btscan;
826
827 *next_scan_page = InvalidBlockNumber;
828 *last_curr_page = InvalidBlockNumber;
829
830 /*
831 * Reset so->currPos, and initialize moreLeft/moreRight such that the next
832 * call to _bt_readnextpage treats this backend similarly to a serial
833 * backend that steps from *last_curr_page to *next_scan_page (unless this
834 * backend's so->currPos is initialized by _bt_readfirstpage before then).
835 */
837 so->currPos.moreLeft = so->currPos.moreRight = true;
838
839 if (first)
840 {
841 /*
842 * Initialize array related state when called from _bt_first, assuming
843 * that this will be the first primitive index scan for the scan
844 */
845 so->needPrimScan = false;
846 so->scanBehind = false;
847 so->oppositeDirCheck = false;
848 }
849 else
850 {
851 /*
852 * Don't attempt to seize the scan when it requires another primitive
853 * index scan, since caller's backend cannot start it right now
854 */
855 if (so->needPrimScan)
856 return false;
857 }
858
859 btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan,
860 parallel_scan->ps_offset_am);
861
862 while (1)
863 {
864 LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE);
865
866 if (btscan->btps_pageStatus == BTPARALLEL_DONE)
867 {
868 /* We're done with this parallel index scan */
869 status = false;
870 }
871 else if (btscan->btps_pageStatus == BTPARALLEL_IDLE &&
872 btscan->btps_nextScanPage == P_NONE)
873 {
874 /* End this parallel index scan */
875 status = false;
876 endscan = true;
877 }
878 else if (btscan->btps_pageStatus == BTPARALLEL_NEED_PRIMSCAN)
879 {
880 Assert(so->numArrayKeys);
881
882 if (first)
883 {
884 /* Can start scheduled primitive scan right away, so do so */
885 btscan->btps_pageStatus = BTPARALLEL_ADVANCING;
886
887 /* Restore scan's array keys from serialized values */
888 _bt_parallel_restore_arrays(rel, btscan, so);
889 exit_loop = true;
890 }
891 else
892 {
893 /*
894 * Don't attempt to seize the scan when it requires another
895 * primitive index scan, since caller's backend cannot start
896 * it right now
897 */
898 status = false;
899 }
900
901 /*
902 * Either way, update backend local state to indicate that a
903 * pending primitive scan is required
904 */
905 so->needPrimScan = true;
906 so->scanBehind = false;
907 so->oppositeDirCheck = false;
908 }
909 else if (btscan->btps_pageStatus != BTPARALLEL_ADVANCING)
910 {
911 /*
912 * We have successfully seized control of the scan for the purpose
913 * of advancing it to a new page!
914 */
915 btscan->btps_pageStatus = BTPARALLEL_ADVANCING;
916 Assert(btscan->btps_nextScanPage != P_NONE);
917 *next_scan_page = btscan->btps_nextScanPage;
918 *last_curr_page = btscan->btps_lastCurrPage;
919 exit_loop = true;
920 }
921 LWLockRelease(&btscan->btps_lock);
922 if (exit_loop || !status)
923 break;
924 ConditionVariableSleep(&btscan->btps_cv, WAIT_EVENT_BTREE_PAGE);
925 }
927
928 /* When the scan has reached the rightmost (or leftmost) page, end it */
929 if (endscan)
930 _bt_parallel_done(scan);
931
932 return status;
933}
bool ConditionVariableCancelSleep(void)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
void _bt_parallel_done(IndexScanDesc scan)
Definition: nbtree.c:981
static void _bt_parallel_restore_arrays(Relation rel, BTParallelScanDesc btscan, BTScanOpaque so)
Definition: nbtree.c:706
#define P_NONE
Definition: nbtree.h:213
#define BTScanPosInvalidate(scanpos)
Definition: nbtree.h:1027
bool oppositeDirCheck
Definition: nbtree.h:1065
bool moreRight
Definition: nbtree.h:986
bool moreLeft
Definition: nbtree.h:985

References _bt_parallel_done(), _bt_parallel_restore_arrays(), Assert(), BTPARALLEL_ADVANCING, BTPARALLEL_DONE, BTPARALLEL_IDLE, BTPARALLEL_NEED_PRIMSCAN, BTScanPosInvalidate, ConditionVariableCancelSleep(), ConditionVariableSleep(), BTScanOpaqueData::currPos, IndexScanDescData::indexRelation, InvalidBlockNumber, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), BTScanPosData::moreLeft, BTScanPosData::moreRight, BTScanOpaqueData::needPrimScan, BTScanOpaqueData::numArrayKeys, OffsetToPointer, IndexScanDescData::opaque, BTScanOpaqueData::oppositeDirCheck, P_NONE, IndexScanDescData::parallel_scan, and BTScanOpaqueData::scanBehind.

Referenced by _bt_first(), and _bt_readnextpage().

◆ _bt_parallel_serialize_arrays()

static void _bt_parallel_serialize_arrays ( Relation  rel,
BTParallelScanDesc  btscan,
BTScanOpaque  so 
)
static

Definition at line 663 of file nbtree.c.

665{
666 char *datumshared;
667
668 /* Space for serialized datums begins immediately after btps_arrElems[] */
669 datumshared = ((char *) &btscan->btps_arrElems[so->numArrayKeys]);
670 for (int i = 0; i < so->numArrayKeys; i++)
671 {
672 BTArrayKeyInfo *array = &so->arrayKeys[i];
673 ScanKey skey = &so->keyData[array->scan_key];
674
675 if (array->num_elems != -1)
676 {
677 /* Save SAOP array's cur_elem (no need to copy key/datum) */
678 Assert(!(skey->sk_flags & SK_BT_SKIP));
679 btscan->btps_arrElems[i] = array->cur_elem;
680 continue;
681 }
682
683 /* Save all mutable state associated with skip array's key */
684 Assert(skey->sk_flags & SK_BT_SKIP);
685 memcpy(datumshared, &skey->sk_flags, sizeof(int));
686 datumshared += sizeof(int);
687
688 if (skey->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL))
689 {
690 /* No sk_argument datum to serialize */
691 Assert(skey->sk_argument == 0);
692 continue;
693 }
694
695 datumSerialize(skey->sk_argument, (skey->sk_flags & SK_ISNULL) != 0,
696 array->attbyval, array->attlen, &datumshared);
697 }
698}
void datumSerialize(Datum value, bool isnull, bool typByVal, int typLen, char **start_address)
Definition: datum.c:459
int16 attlen
Definition: nbtree.h:1045

References BTScanOpaqueData::arrayKeys, Assert(), BTArrayKeyInfo::attbyval, BTArrayKeyInfo::attlen, BTParallelScanDescData::btps_arrElems, BTArrayKeyInfo::cur_elem, datumSerialize(), i, BTScanOpaqueData::keyData, BTArrayKeyInfo::num_elems, BTScanOpaqueData::numArrayKeys, BTArrayKeyInfo::scan_key, ScanKeyData::sk_argument, SK_BT_MAXVAL, SK_BT_MINVAL, SK_BT_SKIP, ScanKeyData::sk_flags, and SK_ISNULL.

Referenced by _bt_parallel_primscan_schedule().

◆ btbeginscan()

IndexScanDesc btbeginscan ( Relation  rel,
int  nkeys,
int  norderbys 
)

Definition at line 336 of file nbtree.c.

337{
338 IndexScanDesc scan;
339 BTScanOpaque so;
340
341 /* no order by operators allowed */
342 Assert(norderbys == 0);
343
344 /* get the scan */
345 scan = RelationGetIndexScan(rel, nkeys, norderbys);
346
347 /* allocate private workspace */
348 so = (BTScanOpaque) palloc(sizeof(BTScanOpaqueData));
351 if (scan->numberOfKeys > 0)
352 so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData));
353 else
354 so->keyData = NULL;
355
356 so->skipScan = false;
357 so->needPrimScan = false;
358 so->scanBehind = false;
359 so->oppositeDirCheck = false;
360 so->arrayKeys = NULL;
361 so->orderProcs = NULL;
362 so->arrayContext = NULL;
363
364 so->killedItems = NULL; /* until needed */
365 so->numKilled = 0;
366
367 /*
368 * We don't know yet whether the scan will be index-only, so we do not
369 * allocate the tuple workspace arrays until btrescan. However, we set up
370 * scan->xs_itupdesc whether we'll need it or not, since that's so cheap.
371 */
372 so->currTuples = so->markTuples = NULL;
373
374 scan->xs_itupdesc = RelationGetDescr(rel);
375
376 scan->opaque = so;
377
378 return scan;
379}
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
void * palloc(Size size)
Definition: mcxt.c:1365
#define RelationGetDescr(relation)
Definition: rel.h:540
ScanKeyData * ScanKey
Definition: skey.h:75
char * markTuples
Definition: nbtree.h:1081
FmgrInfo * orderProcs
Definition: nbtree.h:1067
int * killedItems
Definition: nbtree.h:1071
char * currTuples
Definition: nbtree.h:1080
BTScanPosData markPos
Definition: nbtree.h:1094
MemoryContext arrayContext
Definition: nbtree.h:1068
struct TupleDescData * xs_itupdesc
Definition: relscan.h:168

References BTScanOpaqueData::arrayContext, BTScanOpaqueData::arrayKeys, Assert(), BTScanPosInvalidate, BTScanOpaqueData::currPos, BTScanOpaqueData::currTuples, BTScanOpaqueData::keyData, BTScanOpaqueData::killedItems, BTScanOpaqueData::markPos, BTScanOpaqueData::markTuples, BTScanOpaqueData::needPrimScan, IndexScanDescData::numberOfKeys, BTScanOpaqueData::numKilled, IndexScanDescData::opaque, BTScanOpaqueData::oppositeDirCheck, BTScanOpaqueData::orderProcs, palloc(), RelationGetDescr, RelationGetIndexScan(), BTScanOpaqueData::scanBehind, BTScanOpaqueData::skipScan, and IndexScanDescData::xs_itupdesc.

Referenced by bthandler().

◆ btbuildempty()

void btbuildempty ( Relation  index)

Definition at line 179 of file nbtree.c.

180{
181 bool allequalimage = _bt_allequalimage(index, false);
182 BulkWriteState *bulkstate;
183 BulkWriteBuffer metabuf;
184
186
187 /* Construct metapage. */
188 metabuf = smgr_bulk_get_buf(bulkstate);
189 _bt_initmetapage((Page) metabuf, P_NONE, 0, allequalimage);
190 smgr_bulk_write(bulkstate, BTREE_METAPAGE, metabuf, true);
191
192 smgr_bulk_finish(bulkstate);
193}
PageData * Page
Definition: bufpage.h:82
BulkWriteState * smgr_bulk_start_rel(Relation rel, ForkNumber forknum)
Definition: bulk_write.c:87
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition: bulk_write.c:323
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition: bulk_write.c:347
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition: bulk_write.c:130
void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level, bool allequalimage)
Definition: nbtpage.c:67
#define BTREE_METAPAGE
Definition: nbtree.h:149
bool _bt_allequalimage(Relation rel, bool debugmessage)
Definition: nbtutils.c:4327
@ INIT_FORKNUM
Definition: relpath.h:61
Definition: type.h:96

References _bt_allequalimage(), _bt_initmetapage(), BTREE_METAPAGE, INIT_FORKNUM, P_NONE, smgr_bulk_finish(), smgr_bulk_get_buf(), smgr_bulk_start_rel(), and smgr_bulk_write().

Referenced by bthandler().

◆ btbulkdelete()

IndexBulkDeleteResult * btbulkdelete ( IndexVacuumInfo info,
IndexBulkDeleteResult stats,
IndexBulkDeleteCallback  callback,
void *  callback_state 
)

Definition at line 1065 of file nbtree.c.

1067{
1068 Relation rel = info->index;
1069 BTCycleId cycleid;
1070
1071 /* allocate stats if first time through, else re-use existing struct */
1072 if (stats == NULL)
1074
1075 /* Establish the vacuum cycle ID to use for this scan */
1076 /* The ENSURE stuff ensures we clean up shared memory on failure */
1078 {
1079 cycleid = _bt_start_vacuum(rel);
1080
1081 btvacuumscan(info, stats, callback, callback_state, cycleid);
1082 }
1084 _bt_end_vacuum(rel);
1085
1086 return stats;
1087}
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
void * palloc0(Size size)
Definition: mcxt.c:1395
static void btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state, BTCycleId cycleid)
Definition: nbtree.c:1183
uint16 BTCycleId
Definition: nbtree.h:30
void _bt_end_vacuum(Relation rel)
Definition: nbtutils.c:3672
void _bt_end_vacuum_callback(int code, Datum arg)
Definition: nbtutils.c:3700
BTCycleId _bt_start_vacuum(Relation rel)
Definition: nbtutils.c:3615
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
Relation index
Definition: genam.h:73
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

References _bt_end_vacuum(), _bt_end_vacuum_callback(), _bt_start_vacuum(), btvacuumscan(), callback(), IndexVacuumInfo::index, palloc0(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, and PointerGetDatum().

Referenced by bthandler().

◆ btcanreturn()

bool btcanreturn ( Relation  index,
int  attno 
)

Definition at line 1745 of file nbtree.c.

1746{
1747 return true;
1748}

Referenced by bthandler().

◆ btendscan()

void btendscan ( IndexScanDesc  scan)

Definition at line 470 of file nbtree.c.

471{
472 BTScanOpaque so = (BTScanOpaque) scan->opaque;
473
474 /* we aren't holding any read locks, but gotta drop the pins */
476 {
477 /* Before leaving current page, deal with any killed items */
478 if (so->numKilled > 0)
479 _bt_killitems(scan);
481 }
482
483 so->markItemIndex = -1;
485
486 /* No need to invalidate positions, the RAM is about to be freed. */
487
488 /* Release storage */
489 if (so->keyData != NULL)
490 pfree(so->keyData);
491 /* so->arrayKeys and so->orderProcs are in arrayContext */
492 if (so->arrayContext != NULL)
494 if (so->killedItems != NULL)
495 pfree(so->killedItems);
496 if (so->currTuples != NULL)
497 pfree(so->currTuples);
498 /* so->markTuples should not be pfree'd, see btrescan */
499 pfree(so);
500}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
#define BTScanPosUnpinIfPinned(scanpos)
Definition: nbtree.h:1015
void _bt_killitems(IndexScanDesc scan)
Definition: nbtutils.c:3361

References _bt_killitems(), BTScanOpaqueData::arrayContext, BTScanPosIsValid, BTScanPosUnpinIfPinned, BTScanOpaqueData::currPos, BTScanOpaqueData::currTuples, if(), BTScanOpaqueData::keyData, BTScanOpaqueData::killedItems, BTScanOpaqueData::markItemIndex, BTScanOpaqueData::markPos, MemoryContextDelete(), BTScanOpaqueData::numKilled, IndexScanDescData::opaque, and pfree().

Referenced by bthandler().

◆ btestimateparallelscan()

Size btestimateparallelscan ( Relation  rel,
int  nkeys,
int  norderbys 
)

Definition at line 590 of file nbtree.c.

591{
593 Size estnbtreeshared,
594 genericattrspace;
595
596 /*
597 * Pessimistically assume that every input scan key will be output with
598 * its own SAOP array
599 */
600 estnbtreeshared = offsetof(BTParallelScanDescData, btps_arrElems) +
601 sizeof(int) * nkeys;
602
603 /* Single column indexes cannot possibly use a skip array */
604 if (nkeyatts == 1)
605 return estnbtreeshared;
606
607 /*
608 * Pessimistically assume that all attributes prior to the least
609 * significant attribute require a skip array (and an associated key)
610 */
611 genericattrspace = datumEstimateSpace((Datum) 0, false, true,
612 sizeof(Datum));
613 for (int attnum = 1; attnum < nkeyatts; attnum++)
614 {
615 CompactAttribute *attr;
616
617 /*
618 * We make the conservative assumption that every index column will
619 * also require a skip array.
620 *
621 * Every skip array must have space to store its scan key's sk_flags.
622 */
623 estnbtreeshared = add_size(estnbtreeshared, sizeof(int));
624
625 /* Consider space required to store a datum of opclass input type */
626 attr = TupleDescCompactAttr(rel->rd_att, attnum - 1);
627 if (attr->attbyval)
628 {
629 /* This index attribute stores pass-by-value datums */
630 Size estfixed = datumEstimateSpace((Datum) 0, false,
631 true, attr->attlen);
632
633 estnbtreeshared = add_size(estnbtreeshared, estfixed);
634 continue;
635 }
636
637 /*
638 * This index attribute stores pass-by-reference datums.
639 *
640 * Assume that serializing this array will use just as much space as a
641 * pass-by-value datum, in addition to space for the largest possible
642 * whole index tuple (this is not just a per-datum portion of the
643 * largest possible tuple because that'd be almost as large anyway).
644 *
645 * This is quite conservative, but it's not clear how we could do much
646 * better. The executor requires an up-front storage request size
647 * that reliably covers the scan's high watermark memory usage. We
648 * can't be sure of the real high watermark until the scan is over.
649 */
650 estnbtreeshared = add_size(estnbtreeshared, genericattrspace);
651 estnbtreeshared = add_size(estnbtreeshared, BTMaxItemSize);
652 }
653
654 return estnbtreeshared;
655}
int16_t int16
Definition: c.h:533
size_t Size
Definition: c.h:610
Size datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
Definition: datum.c:412
#define BTMaxItemSize
Definition: nbtree.h:165
int16 attnum
Definition: pg_attribute.h:74
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:533
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
int16 attlen
Definition: tupdesc.h:71
TupleDesc rd_att
Definition: rel.h:112
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175

References add_size(), CompactAttribute::attbyval, CompactAttribute::attlen, attnum, BTMaxItemSize, BTParallelScanDescData::btps_arrElems, datumEstimateSpace(), IndexRelationGetNumberOfKeyAttributes, RelationData::rd_att, and TupleDescCompactAttr().

Referenced by bthandler().

◆ btgetbitmap()

int64 btgetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

Definition at line 288 of file nbtree.c.

289{
290 BTScanOpaque so = (BTScanOpaque) scan->opaque;
291 int64 ntids = 0;
292 ItemPointer heapTid;
293
294 Assert(scan->heapRelation == NULL);
295
296 /* Each loop iteration performs another primitive index scan */
297 do
298 {
299 /* Fetch the first page & tuple */
301 {
302 /* Save tuple ID, and continue scanning */
303 heapTid = &scan->xs_heaptid;
304 tbm_add_tuples(tbm, heapTid, 1, false);
305 ntids++;
306
307 for (;;)
308 {
309 /*
310 * Advance to next tuple within page. This is the same as the
311 * easy case in _bt_next().
312 */
313 if (++so->currPos.itemIndex > so->currPos.lastItem)
314 {
315 /* let _bt_next do the heavy lifting */
316 if (!_bt_next(scan, ForwardScanDirection))
317 break;
318 }
319
320 /* Save tuple ID, and continue scanning */
321 heapTid = &so->currPos.items[so->currPos.itemIndex].heapTid;
322 tbm_add_tuples(tbm, heapTid, 1, false);
323 ntids++;
324 }
325 }
326 /* Now see if we need another primitive index scan */
328
329 return ntids;
330}
int64_t int64
Definition: c.h:535
bool _bt_first(IndexScanDesc scan, ScanDirection dir)
Definition: nbtsearch.c:887
bool _bt_next(IndexScanDesc scan, ScanDirection dir)
Definition: nbtsearch.c:1593
bool _bt_start_prim_scan(IndexScanDesc scan, ScanDirection dir)
Definition: nbtutils.c:1274
@ ForwardScanDirection
Definition: sdir.h:28
int lastItem
Definition: nbtree.h:996
BTScanPosItem items[MaxTIDsPerBTreePage]
Definition: nbtree.h:999
int itemIndex
Definition: nbtree.h:997
ItemPointerData heapTid
Definition: nbtree.h:957
ItemPointerData xs_heaptid
Definition: relscan.h:172
Relation heapRelation
Definition: relscan.h:136
void tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids, bool recheck)
Definition: tidbitmap.c:367

References _bt_first(), _bt_next(), _bt_start_prim_scan(), Assert(), BTScanOpaqueData::currPos, ForwardScanDirection, IndexScanDescData::heapRelation, BTScanPosItem::heapTid, BTScanPosData::itemIndex, BTScanPosData::items, BTScanPosData::lastItem, BTScanOpaqueData::numArrayKeys, IndexScanDescData::opaque, tbm_add_tuples(), and IndexScanDescData::xs_heaptid.

Referenced by bthandler().

◆ btgettreeheight()

int btgettreeheight ( Relation  rel)

Definition at line 1754 of file nbtree.c.

1755{
1756 return _bt_getrootheight(rel);
1757}
int _bt_getrootheight(Relation rel)
Definition: nbtpage.c:675

References _bt_getrootheight().

Referenced by bthandler().

◆ btgettuple()

bool btgettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 226 of file nbtree.c.

227{
228 BTScanOpaque so = (BTScanOpaque) scan->opaque;
229 bool res;
230
231 Assert(scan->heapRelation != NULL);
232
233 /* btree indexes are never lossy */
234 scan->xs_recheck = false;
235
236 /* Each loop iteration performs another primitive index scan */
237 do
238 {
239 /*
240 * If we've already initialized this scan, we can just advance it in
241 * the appropriate direction. If we haven't done so yet, we call
242 * _bt_first() to get the first item in the scan.
243 */
244 if (!BTScanPosIsValid(so->currPos))
245 res = _bt_first(scan, dir);
246 else
247 {
248 /*
249 * Check to see if we should kill the previously-fetched tuple.
250 */
251 if (scan->kill_prior_tuple)
252 {
253 /*
254 * Yes, remember it for later. (We'll deal with all such
255 * tuples at once right before leaving the index page.) The
256 * test for numKilled overrun is not just paranoia: if the
257 * caller reverses direction in the indexscan then the same
258 * item might get entered multiple times. It's not worth
259 * trying to optimize that, so we don't detect it, but instead
260 * just forget any excess entries.
261 */
262 if (so->killedItems == NULL)
263 so->killedItems = (int *)
264 palloc(MaxTIDsPerBTreePage * sizeof(int));
266 so->killedItems[so->numKilled++] = so->currPos.itemIndex;
267 }
268
269 /*
270 * Now continue the scan.
271 */
272 res = _bt_next(scan, dir);
273 }
274
275 /* If we have a tuple, return it ... */
276 if (res)
277 break;
278 /* ... otherwise see if we need another primitive index scan */
279 } while (so->numArrayKeys && _bt_start_prim_scan(scan, dir));
280
281 return res;
282}
#define MaxTIDsPerBTreePage
Definition: nbtree.h:186
bool kill_prior_tuple
Definition: relscan.h:147

References _bt_first(), _bt_next(), _bt_start_prim_scan(), Assert(), BTScanPosIsValid, BTScanOpaqueData::currPos, IndexScanDescData::heapRelation, BTScanPosData::itemIndex, IndexScanDescData::kill_prior_tuple, BTScanOpaqueData::killedItems, MaxTIDsPerBTreePage, BTScanOpaqueData::numArrayKeys, BTScanOpaqueData::numKilled, IndexScanDescData::opaque, palloc(), and IndexScanDescData::xs_recheck.

Referenced by bthandler().

◆ bthandler()

Datum bthandler ( PG_FUNCTION_ARGS  )

Definition at line 115 of file nbtree.c.

116{
118
120 amroutine->amsupport = BTNProcs;
121 amroutine->amoptsprocnum = BTOPTIONS_PROC;
122 amroutine->amcanorder = true;
123 amroutine->amcanorderbyop = false;
124 amroutine->amcanhash = false;
125 amroutine->amconsistentequality = true;
126 amroutine->amconsistentordering = true;
127 amroutine->amcanbackward = true;
128 amroutine->amcanunique = true;
129 amroutine->amcanmulticol = true;
130 amroutine->amoptionalkey = true;
131 amroutine->amsearcharray = true;
132 amroutine->amsearchnulls = true;
133 amroutine->amstorage = false;
134 amroutine->amclusterable = true;
135 amroutine->ampredlocks = true;
136 amroutine->amcanparallel = true;
137 amroutine->amcanbuildparallel = true;
138 amroutine->amcaninclude = true;
139 amroutine->amusemaintenanceworkmem = false;
140 amroutine->amsummarizing = false;
141 amroutine->amparallelvacuumoptions =
143 amroutine->amkeytype = InvalidOid;
144
145 amroutine->ambuild = btbuild;
146 amroutine->ambuildempty = btbuildempty;
147 amroutine->aminsert = btinsert;
148 amroutine->aminsertcleanup = NULL;
149 amroutine->ambulkdelete = btbulkdelete;
150 amroutine->amvacuumcleanup = btvacuumcleanup;
151 amroutine->amcanreturn = btcanreturn;
152 amroutine->amcostestimate = btcostestimate;
153 amroutine->amgettreeheight = btgettreeheight;
154 amroutine->amoptions = btoptions;
155 amroutine->amproperty = btproperty;
157 amroutine->amvalidate = btvalidate;
158 amroutine->amadjustmembers = btadjustmembers;
159 amroutine->ambeginscan = btbeginscan;
160 amroutine->amrescan = btrescan;
161 amroutine->amgettuple = btgettuple;
162 amroutine->amgetbitmap = btgetbitmap;
163 amroutine->amendscan = btendscan;
164 amroutine->ammarkpos = btmarkpos;
165 amroutine->amrestrpos = btrestrpos;
171
172 PG_RETURN_POINTER(amroutine);
173}
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
bool btcanreturn(Relation index, int attno)
Definition: nbtree.c:1745
StrategyNumber bttranslatecmptype(CompareType cmptype, Oid opfamily)
Definition: nbtree.c:1780
IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys)
Definition: nbtree.c:336
Size btestimateparallelscan(Relation rel, int nkeys, int norderbys)
Definition: nbtree.c:590
IndexBulkDeleteResult * btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
Definition: nbtree.c:1095
CompareType bttranslatestrategy(StrategyNumber strategy, Oid opfamily)
Definition: nbtree.c:1760
bool btgettuple(IndexScanDesc scan, ScanDirection dir)
Definition: nbtree.c:226
void btparallelrescan(IndexScanDesc scan)
Definition: nbtree.c:773
bool btinsert(Relation rel, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
Definition: nbtree.c:202
void btbuildempty(Relation index)
Definition: nbtree.c:179
int btgettreeheight(Relation rel)
Definition: nbtree.c:1754
void btinitparallelscan(void *target)
Definition: nbtree.c:757
IndexBulkDeleteResult * btbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
Definition: nbtree.c:1065
int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
Definition: nbtree.c:288
void btmarkpos(IndexScanDesc scan)
Definition: nbtree.c:506
void btendscan(IndexScanDesc scan)
Definition: nbtree.c:470
void btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
Definition: nbtree.c:385
void btrestrpos(IndexScanDesc scan)
Definition: nbtree.c:532
#define BTNProcs
Definition: nbtree.h:723
#define BTOPTIONS_PROC
Definition: nbtree.h:721
IndexBuildResult * btbuild(Relation heap, Relation index, IndexInfo *indexInfo)
Definition: nbtsort.c:296
char * btbuildphasename(int64 phasenum)
Definition: nbtutils.c:3796
bytea * btoptions(Datum reloptions, bool validate)
Definition: nbtutils.c:3750
bool btproperty(Oid index_oid, int attno, IndexAMProperty prop, const char *propname, bool *res, bool *isnull)
Definition: nbtutils.c:3773
bool btvalidate(Oid opclassoid)
Definition: nbtvalidate.c:40
void btadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
Definition: nbtvalidate.c:288
#define makeNode(_type_)
Definition: nodes.h:161
#define InvalidOid
Definition: postgres_ext.h:37
void btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Definition: selfuncs.c:7286
#define BTMaxStrategyNumber
Definition: stratnum.h:35
ambuildphasename_function ambuildphasename
Definition: amapi.h:306
ambuildempty_function ambuildempty
Definition: amapi.h:296
amvacuumcleanup_function amvacuumcleanup
Definition: amapi.h:300
bool amclusterable
Definition: amapi.h:270
amoptions_function amoptions
Definition: amapi.h:304
amestimateparallelscan_function amestimateparallelscan
Definition: amapi.h:318
amrestrpos_function amrestrpos
Definition: amapi.h:315
aminsert_function aminsert
Definition: amapi.h:297
amendscan_function amendscan
Definition: amapi.h:313
amtranslate_strategy_function amtranslatestrategy
Definition: amapi.h:323
uint16 amoptsprocnum
Definition: amapi.h:244
amparallelrescan_function amparallelrescan
Definition: amapi.h:320
Oid amkeytype
Definition: amapi.h:286
bool amconsistentordering
Definition: amapi.h:254
bool ampredlocks
Definition: amapi.h:272
uint16 amsupport
Definition: amapi.h:242
amtranslate_cmptype_function amtranslatecmptype
Definition: amapi.h:324
amcostestimate_function amcostestimate
Definition: amapi.h:302
bool amcanorderbyop
Definition: amapi.h:248
amadjustmembers_function amadjustmembers
Definition: amapi.h:308
ambuild_function ambuild
Definition: amapi.h:295
bool amstorage
Definition: amapi.h:268
uint16 amstrategies
Definition: amapi.h:240
bool amoptionalkey
Definition: amapi.h:262
amgettuple_function amgettuple
Definition: amapi.h:311
amcanreturn_function amcanreturn
Definition: amapi.h:301
bool amcanunique
Definition: amapi.h:258
amgetbitmap_function amgetbitmap
Definition: amapi.h:312
amproperty_function amproperty
Definition: amapi.h:305
ambulkdelete_function ambulkdelete
Definition: amapi.h:299
bool amsearcharray
Definition: amapi.h:264
bool amsummarizing
Definition: amapi.h:282
amvalidate_function amvalidate
Definition: amapi.h:307
ammarkpos_function ammarkpos
Definition: amapi.h:314
bool amcanmulticol
Definition: amapi.h:260
bool amusemaintenanceworkmem
Definition: amapi.h:280
ambeginscan_function ambeginscan
Definition: amapi.h:309
bool amcanparallel
Definition: amapi.h:274
amrescan_function amrescan
Definition: amapi.h:310
bool amcanorder
Definition: amapi.h:246
bool amcanbuildparallel
Definition: amapi.h:276
aminitparallelscan_function aminitparallelscan
Definition: amapi.h:319
uint8 amparallelvacuumoptions
Definition: amapi.h:284
aminsertcleanup_function aminsertcleanup
Definition: amapi.h:298
bool amcanbackward
Definition: amapi.h:256
amgettreeheight_function amgettreeheight
Definition: amapi.h:303
bool amcaninclude
Definition: amapi.h:278
bool amsearchnulls
Definition: amapi.h:266
bool amconsistentequality
Definition: amapi.h:252
bool amcanhash
Definition: amapi.h:250
#define VACUUM_OPTION_PARALLEL_BULKDEL
Definition: vacuum.h:48
#define VACUUM_OPTION_PARALLEL_COND_CLEANUP
Definition: vacuum.h:55

References IndexAmRoutine::amadjustmembers, IndexAmRoutine::ambeginscan, IndexAmRoutine::ambuild, IndexAmRoutine::ambuildempty, IndexAmRoutine::ambuildphasename, IndexAmRoutine::ambulkdelete, IndexAmRoutine::amcanbackward, IndexAmRoutine::amcanbuildparallel, IndexAmRoutine::amcanhash, IndexAmRoutine::amcaninclude, IndexAmRoutine::amcanmulticol, IndexAmRoutine::amcanorder, IndexAmRoutine::amcanorderbyop, IndexAmRoutine::amcanparallel, IndexAmRoutine::amcanreturn, IndexAmRoutine::amcanunique, IndexAmRoutine::amclusterable, IndexAmRoutine::amconsistentequality, IndexAmRoutine::amconsistentordering, IndexAmRoutine::amcostestimate, IndexAmRoutine::amendscan, IndexAmRoutine::amestimateparallelscan, IndexAmRoutine::amgetbitmap, IndexAmRoutine::amgettreeheight, IndexAmRoutine::amgettuple, IndexAmRoutine::aminitparallelscan, IndexAmRoutine::aminsert, IndexAmRoutine::aminsertcleanup, IndexAmRoutine::amkeytype, IndexAmRoutine::ammarkpos, IndexAmRoutine::amoptionalkey, IndexAmRoutine::amoptions, IndexAmRoutine::amoptsprocnum, IndexAmRoutine::amparallelrescan, IndexAmRoutine::amparallelvacuumoptions, IndexAmRoutine::ampredlocks, IndexAmRoutine::amproperty, IndexAmRoutine::amrescan, IndexAmRoutine::amrestrpos, IndexAmRoutine::amsearcharray, IndexAmRoutine::amsearchnulls, IndexAmRoutine::amstorage, IndexAmRoutine::amstrategies, IndexAmRoutine::amsummarizing, IndexAmRoutine::amsupport, IndexAmRoutine::amtranslatecmptype, IndexAmRoutine::amtranslatestrategy, IndexAmRoutine::amusemaintenanceworkmem, IndexAmRoutine::amvacuumcleanup, IndexAmRoutine::amvalidate, btadjustmembers(), btbeginscan(), btbuild(), btbuildempty(), btbuildphasename(), btbulkdelete(), btcanreturn(), btcostestimate(), btendscan(), btestimateparallelscan(), btgetbitmap(), btgettreeheight(), btgettuple(), btinitparallelscan(), btinsert(), btmarkpos(), BTMaxStrategyNumber, BTNProcs, btoptions(), BTOPTIONS_PROC, btparallelrescan(), btproperty(), btrescan(), btrestrpos(), bttranslatecmptype(), bttranslatestrategy(), btvacuumcleanup(), btvalidate(), InvalidOid, makeNode, PG_RETURN_POINTER, VACUUM_OPTION_PARALLEL_BULKDEL, and VACUUM_OPTION_PARALLEL_COND_CLEANUP.

◆ btinitparallelscan()

void btinitparallelscan ( void *  target)

Definition at line 757 of file nbtree.c.

758{
759 BTParallelScanDesc bt_target = (BTParallelScanDesc) target;
760
761 LWLockInitialize(&bt_target->btps_lock,
762 LWTRANCHE_PARALLEL_BTREE_SCAN);
766 ConditionVariableInit(&bt_target->btps_cv);
767}
void ConditionVariableInit(ConditionVariable *cv)
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:698

References BTPARALLEL_NOT_INITIALIZED, BTParallelScanDescData::btps_cv, BTParallelScanDescData::btps_lastCurrPage, BTParallelScanDescData::btps_lock, BTParallelScanDescData::btps_nextScanPage, BTParallelScanDescData::btps_pageStatus, ConditionVariableInit(), InvalidBlockNumber, and LWLockInitialize().

Referenced by bthandler().

◆ btinsert()

bool btinsert ( Relation  rel,
Datum values,
bool *  isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
bool  indexUnchanged,
IndexInfo indexInfo 
)

Definition at line 202 of file nbtree.c.

207{
208 bool result;
209 IndexTuple itup;
210
211 /* generate an index tuple */
212 itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
213 itup->t_tid = *ht_ctid;
214
215 result = _bt_doinsert(rel, itup, checkUnique, indexUnchanged, heapRel);
216
217 pfree(itup);
218
219 return result;
220}
static Datum values[MAXATTR]
Definition: bootstrap.c:153
IndexTuple index_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: indextuple.c:44
bool _bt_doinsert(Relation rel, IndexTuple itup, IndexUniqueCheck checkUnique, bool indexUnchanged, Relation heapRel)
Definition: nbtinsert.c:103
ItemPointerData t_tid
Definition: itup.h:37

References _bt_doinsert(), index_form_tuple(), pfree(), RelationGetDescr, IndexTupleData::t_tid, and values.

Referenced by bthandler().

◆ btmarkpos()

void btmarkpos ( IndexScanDesc  scan)

Definition at line 506 of file nbtree.c.

507{
508 BTScanOpaque so = (BTScanOpaque) scan->opaque;
509
510 /* There may be an old mark with a pin (but no lock). */
512
513 /*
514 * Just record the current itemIndex. If we later step to next page
515 * before releasing the marked position, _bt_steppage makes a full copy of
516 * the currPos struct in markPos. If (as often happens) the mark is moved
517 * before we leave the page, we don't have to do that work.
518 */
519 if (BTScanPosIsValid(so->currPos))
521 else
522 {
524 so->markItemIndex = -1;
525 }
526}

References BTScanPosInvalidate, BTScanPosIsValid, BTScanPosUnpinIfPinned, BTScanOpaqueData::currPos, BTScanPosData::itemIndex, BTScanOpaqueData::markItemIndex, BTScanOpaqueData::markPos, and IndexScanDescData::opaque.

Referenced by bthandler().

◆ btparallelrescan()

void btparallelrescan ( IndexScanDesc  scan)

Definition at line 773 of file nbtree.c.

774{
775 BTParallelScanDesc btscan;
776 ParallelIndexScanDesc parallel_scan = scan->parallel_scan;
777
778 Assert(parallel_scan);
779
780 btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan,
781 parallel_scan->ps_offset_am);
782
783 /*
784 * In theory, we don't need to acquire the LWLock here, because there
785 * shouldn't be any other workers running at this point, but we do so for
786 * consistency.
787 */
792 LWLockRelease(&btscan->btps_lock);
793}

References Assert(), BTPARALLEL_NOT_INITIALIZED, BTParallelScanDescData::btps_lastCurrPage, BTParallelScanDescData::btps_lock, BTParallelScanDescData::btps_nextScanPage, BTParallelScanDescData::btps_pageStatus, InvalidBlockNumber, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OffsetToPointer, IndexScanDescData::parallel_scan, and ParallelIndexScanDescData::ps_offset_am.

Referenced by bthandler().

◆ btreevacuumposting()

static BTVacuumPosting btreevacuumposting ( BTVacState vstate,
IndexTuple  posting,
OffsetNumber  updatedoffset,
int *  nremaining 
)
static

Definition at line 1696 of file nbtree.c.

1698{
1699 int live = 0;
1700 int nitem = BTreeTupleGetNPosting(posting);
1702 BTVacuumPosting vacposting = NULL;
1703
1704 for (int i = 0; i < nitem; i++)
1705 {
1706 if (!vstate->callback(items + i, vstate->callback_state))
1707 {
1708 /* Live table TID */
1709 live++;
1710 }
1711 else if (vacposting == NULL)
1712 {
1713 /*
1714 * First dead table TID encountered.
1715 *
1716 * It's now clear that we need to delete one or more dead table
1717 * TIDs, so start maintaining metadata describing how to update
1718 * existing posting list tuple.
1719 */
1720 vacposting = palloc(offsetof(BTVacuumPostingData, deletetids) +
1721 nitem * sizeof(uint16));
1722
1723 vacposting->itup = posting;
1724 vacposting->updatedoffset = updatedoffset;
1725 vacposting->ndeletedtids = 0;
1726 vacposting->deletetids[vacposting->ndeletedtids++] = i;
1727 }
1728 else
1729 {
1730 /* Second or subsequent dead table TID */
1731 vacposting->deletetids[vacposting->ndeletedtids++] = i;
1732 }
1733 }
1734
1735 *nremaining = live;
1736 return vacposting;
1737}
uint16_t uint16
Definition: c.h:537
static uint16 BTreeTupleGetNPosting(IndexTuple posting)
Definition: nbtree.h:519
static ItemPointer BTreeTupleGetPosting(IndexTuple posting)
Definition: nbtree.h:538
IndexBulkDeleteCallback callback
Definition: nbtree.h:335
void * callback_state
Definition: nbtree.h:336
uint16 deletetids[FLEXIBLE_ARRAY_MEMBER]
Definition: nbtree.h:922
uint16 ndeletedtids
Definition: nbtree.h:921
IndexTuple itup
Definition: nbtree.h:917
OffsetNumber updatedoffset
Definition: nbtree.h:918
static ItemArray items
Definition: test_tidstore.c:48

References BTreeTupleGetNPosting(), BTreeTupleGetPosting(), BTVacState::callback, BTVacState::callback_state, BTVacuumPostingData::deletetids, i, items, BTVacuumPostingData::itup, BTVacuumPostingData::ndeletedtids, palloc(), and BTVacuumPostingData::updatedoffset.

Referenced by btvacuumpage().

◆ btrescan()

void btrescan ( IndexScanDesc  scan,
ScanKey  scankey,
int  nscankeys,
ScanKey  orderbys,
int  norderbys 
)

Definition at line 385 of file nbtree.c.

387{
388 BTScanOpaque so = (BTScanOpaque) scan->opaque;
389
390 /* we aren't holding any read locks, but gotta drop the pins */
392 {
393 /* Before leaving current page, deal with any killed items */
394 if (so->numKilled > 0)
395 _bt_killitems(scan);
398 }
399
400 /*
401 * We prefer to eagerly drop leaf page pins before btgettuple returns.
402 * This avoids making VACUUM wait to acquire a cleanup lock on the page.
403 *
404 * We cannot safely drop leaf page pins during index-only scans due to a
405 * race condition involving VACUUM setting pages all-visible in the VM.
406 * It's also unsafe for plain index scans that use a non-MVCC snapshot.
407 *
408 * When we drop pins eagerly, the mechanism that marks so->killedItems[]
409 * index tuples LP_DEAD has to deal with concurrent TID recycling races.
410 * The scheme used to detect unsafe TID recycling won't work when scanning
411 * unlogged relations (since it involves saving an affected page's LSN).
412 * Opt out of eager pin dropping during unlogged relation scans for now
413 * (this is preferable to opting out of kill_prior_tuple LP_DEAD setting).
414 *
415 * Also opt out of dropping leaf page pins eagerly during bitmap scans.
416 * Pins cannot be held for more than an instant during bitmap scans either
417 * way, so we might as well avoid wasting cycles on acquiring page LSNs.
418 *
419 * See nbtree/README section on making concurrent TID recycling safe.
420 *
421 * Note: so->dropPin should never change across rescans.
422 */
423 so->dropPin = (!scan->xs_want_itup &&
426 scan->heapRelation != NULL);
427
428 so->markItemIndex = -1;
429 so->needPrimScan = false;
430 so->scanBehind = false;
431 so->oppositeDirCheck = false;
434
435 /*
436 * Allocate tuple workspace arrays, if needed for an index-only scan and
437 * not already done in a previous rescan call. To save on palloc
438 * overhead, both workspaces are allocated as one palloc block; only this
439 * function and btendscan know that.
440 *
441 * NOTE: this data structure also makes it safe to return data from a
442 * "name" column, even though btree name_ops uses an underlying storage
443 * datatype of cstring. The risk there is that "name" is supposed to be
444 * padded to NAMEDATALEN, but the actual index tuple is probably shorter.
445 * However, since we only return data out of tuples sitting in the
446 * currTuples array, a fetch of NAMEDATALEN bytes can at worst pull some
447 * data out of the markTuples array --- running off the end of memory for
448 * a SIGSEGV is not possible. Yeah, this is ugly as sin, but it beats
449 * adding special-case treatment for name_ops elsewhere.
450 */
451 if (scan->xs_want_itup && so->currTuples == NULL)
452 {
453 so->currTuples = (char *) palloc(BLCKSZ * 2);
454 so->markTuples = so->currTuples + BLCKSZ;
455 }
456
457 /*
458 * Reset the scan keys
459 */
460 if (scankey && scan->numberOfKeys > 0)
461 memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
462 so->numberOfKeys = 0; /* until _bt_preprocess_keys sets it */
463 so->numArrayKeys = 0; /* ditto */
464}
#define RelationNeedsWAL(relation)
Definition: rel.h:637
#define IsMVCCSnapshot(snapshot)
Definition: snapmgr.h:55
struct ScanKeyData * keyData
Definition: relscan.h:141
struct SnapshotData * xs_snapshot
Definition: relscan.h:138

References _bt_killitems(), BTScanPosInvalidate, BTScanPosIsValid, BTScanPosUnpinIfPinned, BTScanOpaqueData::currPos, BTScanOpaqueData::currTuples, BTScanOpaqueData::dropPin, IndexScanDescData::heapRelation, if(), IndexScanDescData::indexRelation, IsMVCCSnapshot, IndexScanDescData::keyData, BTScanOpaqueData::markItemIndex, BTScanOpaqueData::markPos, BTScanOpaqueData::markTuples, BTScanOpaqueData::needPrimScan, BTScanOpaqueData::numArrayKeys, BTScanOpaqueData::numberOfKeys, IndexScanDescData::numberOfKeys, BTScanOpaqueData::numKilled, IndexScanDescData::opaque, BTScanOpaqueData::oppositeDirCheck, palloc(), RelationNeedsWAL, BTScanOpaqueData::scanBehind, IndexScanDescData::xs_snapshot, and IndexScanDescData::xs_want_itup.

Referenced by bthandler().

◆ btrestrpos()

void btrestrpos ( IndexScanDesc  scan)

Definition at line 532 of file nbtree.c.

533{
534 BTScanOpaque so = (BTScanOpaque) scan->opaque;
535
536 if (so->markItemIndex >= 0)
537 {
538 /*
539 * The scan has never moved to a new page since the last mark. Just
540 * restore the itemIndex.
541 *
542 * NB: In this case we can't count on anything in so->markPos to be
543 * accurate.
544 */
546 }
547 else
548 {
549 /*
550 * The scan moved to a new page after last mark or restore, and we are
551 * now restoring to the marked page. We aren't holding any read
552 * locks, but if we're still holding the pin for the current position,
553 * we must drop it.
554 */
555 if (BTScanPosIsValid(so->currPos))
556 {
557 /* Before leaving current page, deal with any killed items */
558 if (so->numKilled > 0)
559 _bt_killitems(scan);
561 }
562
563 if (BTScanPosIsValid(so->markPos))
564 {
565 /* bump pin on mark buffer for assignment to current buffer */
566 if (BTScanPosIsPinned(so->markPos))
568 memcpy(&so->currPos, &so->markPos,
569 offsetof(BTScanPosData, items[1]) +
570 so->markPos.lastItem * sizeof(BTScanPosItem));
571 if (so->currTuples)
572 memcpy(so->currTuples, so->markTuples,
574 /* Reset the scan's array keys (see _bt_steppage for why) */
575 if (so->numArrayKeys)
576 {
578 so->needPrimScan = false;
579 }
580 }
581 else
583 }
584}
void IncrBufferRefCount(Buffer buffer)
Definition: bufmgr.c:5370
#define BTScanPosIsPinned(scanpos)
Definition: nbtree.h:1004
void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir)
Definition: nbtutils.c:613
Buffer buf
Definition: nbtree.h:964
int nextTupleOffset
Definition: nbtree.h:979
ScanDirection dir
Definition: nbtree.h:973

References _bt_killitems(), _bt_start_array_keys(), BTScanPosInvalidate, BTScanPosIsPinned, BTScanPosIsValid, BTScanPosUnpinIfPinned, BTScanPosData::buf, BTScanOpaqueData::currPos, BTScanOpaqueData::currTuples, BTScanPosData::dir, if(), IncrBufferRefCount(), BTScanPosData::itemIndex, items, BTScanPosData::lastItem, BTScanOpaqueData::markItemIndex, BTScanOpaqueData::markPos, BTScanOpaqueData::markTuples, BTScanOpaqueData::needPrimScan, BTScanPosData::nextTupleOffset, BTScanOpaqueData::numArrayKeys, BTScanOpaqueData::numKilled, and IndexScanDescData::opaque.

Referenced by bthandler().

◆ bttranslatecmptype()

StrategyNumber bttranslatecmptype ( CompareType  cmptype,
Oid  opfamily 
)

Definition at line 1780 of file nbtree.c.

1781{
1782 switch (cmptype)
1783 {
1784 case COMPARE_LT:
1785 return BTLessStrategyNumber;
1786 case COMPARE_LE:
1788 case COMPARE_EQ:
1789 return BTEqualStrategyNumber;
1790 case COMPARE_GE:
1792 case COMPARE_GT:
1794 default:
1795 return InvalidStrategy;
1796 }
1797}
@ COMPARE_LE
Definition: cmptype.h:35
@ COMPARE_GT
Definition: cmptype.h:38
@ COMPARE_EQ
Definition: cmptype.h:36
@ COMPARE_GE
Definition: cmptype.h:37
@ COMPARE_LT
Definition: cmptype.h:34
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define InvalidStrategy
Definition: stratnum.h:24
#define BTLessStrategyNumber
Definition: stratnum.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32

References BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, COMPARE_EQ, COMPARE_GE, COMPARE_GT, COMPARE_LE, COMPARE_LT, and InvalidStrategy.

Referenced by bthandler().

◆ bttranslatestrategy()

CompareType bttranslatestrategy ( StrategyNumber  strategy,
Oid  opfamily 
)

Definition at line 1760 of file nbtree.c.

1761{
1762 switch (strategy)
1763 {
1765 return COMPARE_LT;
1767 return COMPARE_LE;
1769 return COMPARE_EQ;
1771 return COMPARE_GE;
1773 return COMPARE_GT;
1774 default:
1775 return COMPARE_INVALID;
1776 }
1777}
@ COMPARE_INVALID
Definition: cmptype.h:33

References BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, COMPARE_EQ, COMPARE_GE, COMPARE_GT, COMPARE_INVALID, COMPARE_LE, and COMPARE_LT.

Referenced by bthandler().

◆ btvacuumcleanup()

IndexBulkDeleteResult * btvacuumcleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)

Definition at line 1095 of file nbtree.c.

1096{
1097 BlockNumber num_delpages;
1098
1099 /* No-op in ANALYZE ONLY mode */
1100 if (info->analyze_only)
1101 return stats;
1102
1103 /*
1104 * If btbulkdelete was called, we need not do anything (we just maintain
1105 * the information used within _bt_vacuum_needs_cleanup() by calling
1106 * _bt_set_cleanup_info() below).
1107 *
1108 * If btbulkdelete was _not_ called, then we have a choice to make: we
1109 * must decide whether or not a btvacuumscan() call is needed now (i.e.
1110 * whether the ongoing VACUUM operation can entirely avoid a physical scan
1111 * of the index). A call to _bt_vacuum_needs_cleanup() decides it for us
1112 * now.
1113 */
1114 if (stats == NULL)
1115 {
1116 /* Check if VACUUM operation can entirely avoid btvacuumscan() call */
1117 if (!_bt_vacuum_needs_cleanup(info->index))
1118 return NULL;
1119
1120 /*
1121 * Since we aren't going to actually delete any leaf items, there's no
1122 * need to go through all the vacuum-cycle-ID pushups here.
1123 *
1124 * Posting list tuples are a source of inaccuracy for cleanup-only
1125 * scans. btvacuumscan() will assume that the number of index tuples
1126 * from each page can be used as num_index_tuples, even though
1127 * num_index_tuples is supposed to represent the number of TIDs in the
1128 * index. This naive approach can underestimate the number of tuples
1129 * in the index significantly.
1130 *
1131 * We handle the problem by making num_index_tuples an estimate in
1132 * cleanup-only case.
1133 */
1135 btvacuumscan(info, stats, NULL, NULL, 0);
1136 stats->estimated_count = true;
1137 }
1138
1139 /*
1140 * Maintain num_delpages value in metapage for _bt_vacuum_needs_cleanup().
1141 *
1142 * num_delpages is the number of deleted pages now in the index that were
1143 * not safe to place in the FSM to be recycled just yet. num_delpages is
1144 * greater than 0 only when _bt_pagedel() actually deleted pages during
1145 * our call to btvacuumscan(). Even then, _bt_pendingfsm_finalize() must
1146 * have failed to place any newly deleted pages in the FSM just moments
1147 * ago. (Actually, there are edge cases where recycling of the current
1148 * VACUUM's newly deleted pages does not even become safe by the time the
1149 * next VACUUM comes around. See nbtree/README.)
1150 */
1151 Assert(stats->pages_deleted >= stats->pages_free);
1152 num_delpages = stats->pages_deleted - stats->pages_free;
1153 _bt_set_cleanup_info(info->index, num_delpages);
1154
1155 /*
1156 * It's quite possible for us to be fooled by concurrent page splits into
1157 * double-counting some index tuples, so disbelieve any total that exceeds
1158 * the underlying heap's count ... if we know that accurately. Otherwise
1159 * this might just make matters worse.
1160 */
1161 if (!info->estimated_count)
1162 {
1163 if (stats->num_index_tuples > info->num_heap_tuples)
1164 stats->num_index_tuples = info->num_heap_tuples;
1165 }
1166
1167 return stats;
1168}
uint32 BlockNumber
Definition: block.h:31
void _bt_set_cleanup_info(Relation rel, BlockNumber num_delpages)
Definition: nbtpage.c:232
bool _bt_vacuum_needs_cleanup(Relation rel)
Definition: nbtpage.c:179
BlockNumber pages_deleted
Definition: genam.h:109
BlockNumber pages_free
Definition: genam.h:110
double num_index_tuples
Definition: genam.h:106
double num_heap_tuples
Definition: genam.h:79
bool analyze_only
Definition: genam.h:75
bool estimated_count
Definition: genam.h:77

References _bt_set_cleanup_info(), _bt_vacuum_needs_cleanup(), IndexVacuumInfo::analyze_only, Assert(), btvacuumscan(), IndexVacuumInfo::estimated_count, IndexBulkDeleteResult::estimated_count, IndexVacuumInfo::index, IndexVacuumInfo::num_heap_tuples, IndexBulkDeleteResult::num_index_tuples, IndexBulkDeleteResult::pages_deleted, IndexBulkDeleteResult::pages_free, and palloc0().

Referenced by bthandler().

◆ btvacuumpage()

static BlockNumber btvacuumpage ( BTVacState vstate,
Buffer  buf 
)
static

Definition at line 1358 of file nbtree.c.

1359{
1360 IndexVacuumInfo *info = vstate->info;
1361 IndexBulkDeleteResult *stats = vstate->stats;
1363 void *callback_state = vstate->callback_state;
1364 Relation rel = info->index;
1365 Relation heaprel = info->heaprel;
1366 bool attempt_pagedel;
1367 BlockNumber blkno,
1368 backtrack_to;
1370 Page page;
1371 BTPageOpaque opaque;
1372
1373 blkno = scanblkno;
1374
1375backtrack:
1376
1377 attempt_pagedel = false;
1378 backtrack_to = P_NONE;
1379
1380 _bt_lockbuf(rel, buf, BT_READ);
1381 page = BufferGetPage(buf);
1382 opaque = NULL;
1383 if (!PageIsNew(page))
1384 {
1385 _bt_checkpage(rel, buf);
1386 opaque = BTPageGetOpaque(page);
1387 }
1388
1389 Assert(blkno <= scanblkno);
1390 if (blkno != scanblkno)
1391 {
1392 /*
1393 * We're backtracking.
1394 *
1395 * We followed a right link to a sibling leaf page (a page that
1396 * happens to be from a block located before scanblkno). The only
1397 * case we want to do anything with is a live leaf page having the
1398 * current vacuum cycle ID.
1399 *
1400 * The page had better be in a state that's consistent with what we
1401 * expect. Check for conditions that imply corruption in passing. It
1402 * can't be half-dead because only an interrupted VACUUM process can
1403 * leave pages in that state, so we'd definitely have dealt with it
1404 * back when the page was the scanblkno page (half-dead pages are
1405 * always marked fully deleted by _bt_pagedel(), barring corruption).
1406 */
1407 if (!opaque || !P_ISLEAF(opaque) || P_ISHALFDEAD(opaque))
1408 {
1409 Assert(false);
1410 ereport(LOG,
1411 (errcode(ERRCODE_INDEX_CORRUPTED),
1412 errmsg_internal("right sibling %u of scanblkno %u unexpectedly in an inconsistent state in index \"%s\"",
1413 blkno, scanblkno, RelationGetRelationName(rel))));
1414 _bt_relbuf(rel, buf);
1415 return scanblkno;
1416 }
1417
1418 /*
1419 * We may have already processed the page in an earlier call, when the
1420 * page was scanblkno. This happens when the leaf page split occurred
1421 * after the scan began, but before the right sibling page became the
1422 * scanblkno.
1423 *
1424 * Page may also have been deleted by current btvacuumpage() call,
1425 * since _bt_pagedel() sometimes deletes the right sibling page of
1426 * scanblkno in passing (it does so after we decided where to
1427 * backtrack to). We don't need to process this page as a deleted
1428 * page a second time now (in fact, it would be wrong to count it as a
1429 * deleted page in the bulk delete statistics a second time).
1430 */
1431 if (opaque->btpo_cycleid != vstate->cycleid || P_ISDELETED(opaque))
1432 {
1433 /* Done with current scanblkno (and all lower split pages) */
1434 _bt_relbuf(rel, buf);
1435 return scanblkno;
1436 }
1437 }
1438
1439 if (!opaque || BTPageIsRecyclable(page, heaprel))
1440 {
1441 /* Okay to recycle this page (which could be leaf or internal) */
1442 RecordFreeIndexPage(rel, blkno);
1443 stats->pages_deleted++;
1444 stats->pages_free++;
1445 }
1446 else if (P_ISDELETED(opaque))
1447 {
1448 /*
1449 * Already deleted page (which could be leaf or internal). Can't
1450 * recycle yet.
1451 */
1452 stats->pages_deleted++;
1453 }
1454 else if (P_ISHALFDEAD(opaque))
1455 {
1456 /* Half-dead leaf page (from interrupted VACUUM) -- finish deleting */
1457 attempt_pagedel = true;
1458
1459 /*
1460 * _bt_pagedel() will increment both pages_newly_deleted and
1461 * pages_deleted stats in all cases (barring corruption)
1462 */
1463 }
1464 else if (P_ISLEAF(opaque))
1465 {
1467 int ndeletable;
1469 int nupdatable;
1470 OffsetNumber offnum,
1471 minoff,
1472 maxoff;
1473 int nhtidsdead,
1474 nhtidslive;
1475
1476 /*
1477 * Trade in the initial read lock for a full cleanup lock on this
1478 * page. We must get such a lock on every leaf page over the course
1479 * of the vacuum scan, whether or not it actually contains any
1480 * deletable tuples --- see nbtree/README.
1481 */
1483
1484 /*
1485 * Check whether we need to backtrack to earlier pages. What we are
1486 * concerned about is a page split that happened since we started the
1487 * vacuum scan. If the split moved tuples on the right half of the
1488 * split (i.e. the tuples that sort high) to a block that we already
1489 * passed over, then we might have missed the tuples. We need to
1490 * backtrack now. (Must do this before possibly clearing btpo_cycleid
1491 * or deleting scanblkno page below!)
1492 */
1493 if (vstate->cycleid != 0 &&
1494 opaque->btpo_cycleid == vstate->cycleid &&
1495 !(opaque->btpo_flags & BTP_SPLIT_END) &&
1496 !P_RIGHTMOST(opaque) &&
1497 opaque->btpo_next < scanblkno)
1498 backtrack_to = opaque->btpo_next;
1499
1500 ndeletable = 0;
1501 nupdatable = 0;
1502 minoff = P_FIRSTDATAKEY(opaque);
1503 maxoff = PageGetMaxOffsetNumber(page);
1504 nhtidsdead = 0;
1505 nhtidslive = 0;
1506 if (callback)
1507 {
1508 /* btbulkdelete callback tells us what to delete (or update) */
1509 for (offnum = minoff;
1510 offnum <= maxoff;
1511 offnum = OffsetNumberNext(offnum))
1512 {
1513 IndexTuple itup;
1514
1515 itup = (IndexTuple) PageGetItem(page,
1516 PageGetItemId(page, offnum));
1517
1518 Assert(!BTreeTupleIsPivot(itup));
1519 if (!BTreeTupleIsPosting(itup))
1520 {
1521 /* Regular tuple, standard table TID representation */
1522 if (callback(&itup->t_tid, callback_state))
1523 {
1524 deletable[ndeletable++] = offnum;
1525 nhtidsdead++;
1526 }
1527 else
1528 nhtidslive++;
1529 }
1530 else
1531 {
1532 BTVacuumPosting vacposting;
1533 int nremaining;
1534
1535 /* Posting list tuple */
1536 vacposting = btreevacuumposting(vstate, itup, offnum,
1537 &nremaining);
1538 if (vacposting == NULL)
1539 {
1540 /*
1541 * All table TIDs from the posting tuple remain, so no
1542 * delete or update required
1543 */
1544 Assert(nremaining == BTreeTupleGetNPosting(itup));
1545 }
1546 else if (nremaining > 0)
1547 {
1548
1549 /*
1550 * Store metadata about posting list tuple in
1551 * updatable array for entire page. Existing tuple
1552 * will be updated during the later call to
1553 * _bt_delitems_vacuum().
1554 */
1555 Assert(nremaining < BTreeTupleGetNPosting(itup));
1556 updatable[nupdatable++] = vacposting;
1557 nhtidsdead += BTreeTupleGetNPosting(itup) - nremaining;
1558 }
1559 else
1560 {
1561 /*
1562 * All table TIDs from the posting list must be
1563 * deleted. We'll delete the index tuple completely
1564 * (no update required).
1565 */
1566 Assert(nremaining == 0);
1567 deletable[ndeletable++] = offnum;
1568 nhtidsdead += BTreeTupleGetNPosting(itup);
1569 pfree(vacposting);
1570 }
1571
1572 nhtidslive += nremaining;
1573 }
1574 }
1575 }
1576
1577 /*
1578 * Apply any needed deletes or updates. We issue just one
1579 * _bt_delitems_vacuum() call per page, so as to minimize WAL traffic.
1580 */
1581 if (ndeletable > 0 || nupdatable > 0)
1582 {
1583 Assert(nhtidsdead >= ndeletable + nupdatable);
1584 _bt_delitems_vacuum(rel, buf, deletable, ndeletable, updatable,
1585 nupdatable);
1586
1587 stats->tuples_removed += nhtidsdead;
1588 /* must recompute maxoff */
1589 maxoff = PageGetMaxOffsetNumber(page);
1590
1591 /* can't leak memory here */
1592 for (int i = 0; i < nupdatable; i++)
1593 pfree(updatable[i]);
1594 }
1595 else
1596 {
1597 /*
1598 * If the leaf page has been split during this vacuum cycle, it
1599 * seems worth expending a write to clear btpo_cycleid even if we
1600 * don't have any deletions to do. (If we do, _bt_delitems_vacuum
1601 * takes care of this.) This ensures we won't process the page
1602 * again.
1603 *
1604 * We treat this like a hint-bit update because there's no need to
1605 * WAL-log it.
1606 */
1607 Assert(nhtidsdead == 0);
1608 if (vstate->cycleid != 0 &&
1609 opaque->btpo_cycleid == vstate->cycleid)
1610 {
1611 opaque->btpo_cycleid = 0;
1612 MarkBufferDirtyHint(buf, true);
1613 }
1614 }
1615
1616 /*
1617 * If the leaf page is now empty, try to delete it; else count the
1618 * live tuples (live table TIDs in posting lists are counted as
1619 * separate live tuples). We don't delete when backtracking, though,
1620 * since that would require teaching _bt_pagedel() about backtracking
1621 * (doesn't seem worth adding more complexity to deal with that).
1622 *
1623 * We don't count the number of live TIDs during cleanup-only calls to
1624 * btvacuumscan (i.e. when callback is not set). We count the number
1625 * of index tuples directly instead. This avoids the expense of
1626 * directly examining all of the tuples on each page. VACUUM will
1627 * treat num_index_tuples as an estimate in cleanup-only case, so it
1628 * doesn't matter that this underestimates num_index_tuples
1629 * significantly in some cases.
1630 */
1631 if (minoff > maxoff)
1632 attempt_pagedel = (blkno == scanblkno);
1633 else if (callback)
1634 stats->num_index_tuples += nhtidslive;
1635 else
1636 stats->num_index_tuples += maxoff - minoff + 1;
1637
1638 Assert(!attempt_pagedel || nhtidslive == 0);
1639 }
1640
1641 if (attempt_pagedel)
1642 {
1643 MemoryContext oldcontext;
1644
1645 /* Run pagedel in a temp context to avoid memory leakage */
1647 oldcontext = MemoryContextSwitchTo(vstate->pagedelcontext);
1648
1649 /*
1650 * _bt_pagedel maintains the bulk delete stats on our behalf;
1651 * pages_newly_deleted and pages_deleted are likely to be incremented
1652 * during call
1653 */
1654 Assert(blkno == scanblkno);
1655 _bt_pagedel(rel, buf, vstate);
1656
1657 MemoryContextSwitchTo(oldcontext);
1658 /* pagedel released buffer, so we shouldn't */
1659 }
1660 else
1661 _bt_relbuf(rel, buf);
1662
1663 if (backtrack_to != P_NONE)
1664 {
1665 blkno = backtrack_to;
1666
1667 /* check for vacuum delay while not holding any buffer lock */
1668 vacuum_delay_point(false);
1669
1670 /*
1671 * We can't use _bt_getbuf() here because it always applies
1672 * _bt_checkpage(), which will barf on an all-zero page. We want to
1673 * recycle all-zero pages, not fail. Also, we want to use a
1674 * nondefault buffer access strategy.
1675 */
1677 info->strategy);
1678 goto backtrack;
1679 }
1680
1681 return scanblkno;
1682}
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:4198
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:5402
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:805
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:417
@ RBM_NORMAL
Definition: bufmgr.h:46
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
Definition: bufpage.h:354
static bool PageIsNew(const PageData *page)
Definition: bufpage.h:234
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition: bufpage.h:372
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1161
int errcode(int sqlerrcode)
Definition: elog.c:854
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:150
bool(* IndexBulkDeleteCallback)(ItemPointer itemptr, void *state)
Definition: genam.h:114
void RecordFreeIndexPage(Relation rel, BlockNumber freeBlock)
Definition: indexfsm.c:52
IndexTupleData * IndexTuple
Definition: itup.h:53
#define MaxIndexTuplesPerPage
Definition: itup.h:181
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
void _bt_relbuf(Relation rel, Buffer buf)
Definition: nbtpage.c:1023
void _bt_pagedel(Relation rel, Buffer leafbuf, BTVacState *vstate)
Definition: nbtpage.c:1802
void _bt_delitems_vacuum(Relation rel, Buffer buf, OffsetNumber *deletable, int ndeletable, BTVacuumPosting *updatable, int nupdatable)
Definition: nbtpage.c:1154
void _bt_checkpage(Relation rel, Buffer buf)
Definition: nbtpage.c:797
void _bt_upgradelockbufcleanup(Relation rel, Buffer buf)
Definition: nbtpage.c:1109
void _bt_lockbuf(Relation rel, Buffer buf, int access)
Definition: nbtpage.c:1039
static BTVacuumPosting btreevacuumposting(BTVacState *vstate, IndexTuple posting, OffsetNumber updatedoffset, int *nremaining)
Definition: nbtree.c:1696
#define P_ISHALFDEAD(opaque)
Definition: nbtree.h:225
static bool BTreeTupleIsPivot(IndexTuple itup)
Definition: nbtree.h:481
#define P_ISLEAF(opaque)
Definition: nbtree.h:221
#define BTPageGetOpaque(page)
Definition: nbtree.h:74
#define P_ISDELETED(opaque)
Definition: nbtree.h:223
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:370
#define P_RIGHTMOST(opaque)
Definition: nbtree.h:220
#define BT_READ
Definition: nbtree.h:730
static bool BTPageIsRecyclable(Page page, Relation heaprel)
Definition: nbtree.h:292
static bool BTreeTupleIsPosting(IndexTuple itup)
Definition: nbtree.h:493
#define BTP_SPLIT_END
Definition: nbtree.h:82
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static char * buf
Definition: pg_test_fsync.c:72
#define RelationGetRelationName(relation)
Definition: rel.h:548
@ MAIN_FORKNUM
Definition: relpath.h:58
BlockNumber btpo_next
Definition: nbtree.h:66
uint16 btpo_flags
Definition: nbtree.h:68
BTCycleId btpo_cycleid
Definition: nbtree.h:69
IndexBulkDeleteResult * stats
Definition: nbtree.h:334
BTCycleId cycleid
Definition: nbtree.h:337
MemoryContext pagedelcontext
Definition: nbtree.h:338
IndexVacuumInfo * info
Definition: nbtree.h:333
double tuples_removed
Definition: genam.h:107
BufferAccessStrategy strategy
Definition: genam.h:80
Relation heaprel
Definition: genam.h:74
void vacuum_delay_point(bool is_analyze)
Definition: vacuum.c:2423

References _bt_checkpage(), _bt_delitems_vacuum(), _bt_lockbuf(), _bt_pagedel(), _bt_relbuf(), _bt_upgradelockbufcleanup(), Assert(), BT_READ, BTP_SPLIT_END, BTPageGetOpaque, BTPageIsRecyclable(), BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_next, BTreeTupleGetNPosting(), BTreeTupleIsPivot(), BTreeTupleIsPosting(), btreevacuumposting(), buf, BufferGetBlockNumber(), BufferGetPage(), BTVacState::callback, callback(), BTVacState::callback_state, BTVacState::cycleid, ereport, errcode(), errmsg_internal(), IndexVacuumInfo::heaprel, i, IndexVacuumInfo::index, BTVacState::info, LOG, MAIN_FORKNUM, MarkBufferDirtyHint(), MaxIndexTuplesPerPage, MemoryContextReset(), MemoryContextSwitchTo(), IndexBulkDeleteResult::num_index_tuples, OffsetNumberNext, P_FIRSTDATAKEY, P_ISDELETED, P_ISHALFDEAD, P_ISLEAF, P_NONE, P_RIGHTMOST, BTVacState::pagedelcontext, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageIsNew(), IndexBulkDeleteResult::pages_deleted, IndexBulkDeleteResult::pages_free, pfree(), RBM_NORMAL, ReadBufferExtended(), RecordFreeIndexPage(), RelationGetRelationName, BTVacState::stats, IndexVacuumInfo::strategy, IndexTupleData::t_tid, IndexBulkDeleteResult::tuples_removed, and vacuum_delay_point().

Referenced by btvacuumscan().

◆ btvacuumscan()

static void btvacuumscan ( IndexVacuumInfo info,
IndexBulkDeleteResult stats,
IndexBulkDeleteCallback  callback,
void *  callback_state,
BTCycleId  cycleid 
)
static

Definition at line 1183 of file nbtree.c.

1186{
1187 Relation rel = info->index;
1188 BTVacState vstate;
1189 BlockNumber num_pages;
1190 bool needLock;
1192 ReadStream *stream = NULL;
1193
1194 /*
1195 * Reset fields that track information about the entire index now. This
1196 * avoids double-counting in the case where a single VACUUM command
1197 * requires multiple scans of the index.
1198 *
1199 * Avoid resetting the tuples_removed and pages_newly_deleted fields here,
1200 * since they track information about the VACUUM command, and so must last
1201 * across each call to btvacuumscan().
1202 *
1203 * (Note that pages_free is treated as state about the whole index, not
1204 * the current VACUUM. This is appropriate because RecordFreeIndexPage()
1205 * calls are idempotent, and get repeated for the same deleted pages in
1206 * some scenarios. The point for us is to track the number of recyclable
1207 * pages in the index at the end of the VACUUM command.)
1208 */
1209 stats->num_pages = 0;
1210 stats->num_index_tuples = 0;
1211 stats->pages_deleted = 0;
1212 stats->pages_free = 0;
1213
1214 /* Set up info to pass down to btvacuumpage */
1215 vstate.info = info;
1216 vstate.stats = stats;
1217 vstate.callback = callback;
1218 vstate.callback_state = callback_state;
1219 vstate.cycleid = cycleid;
1220
1221 /* Create a temporary memory context to run _bt_pagedel in */
1223 "_bt_pagedel",
1225
1226 /* Initialize vstate fields used by _bt_pendingfsm_finalize */
1227 vstate.bufsize = 0;
1228 vstate.maxbufsize = 0;
1229 vstate.pendingpages = NULL;
1230 vstate.npendingpages = 0;
1231 /* Consider applying _bt_pendingfsm_finalize optimization */
1232 _bt_pendingfsm_init(rel, &vstate, (callback == NULL));
1233
1234 /*
1235 * The outer loop iterates over all index pages except the metapage, in
1236 * physical order (we hope the kernel will cooperate in providing
1237 * read-ahead for speed). It is critical that we visit all leaf pages,
1238 * including ones added after we start the scan, else we might fail to
1239 * delete some deletable tuples. Hence, we must repeatedly check the
1240 * relation length. We must acquire the relation-extension lock while
1241 * doing so to avoid a race condition: if someone else is extending the
1242 * relation, there is a window where bufmgr/smgr have created a new
1243 * all-zero page but it hasn't yet been write-locked by _bt_getbuf(). If
1244 * we manage to scan such a page here, we'll improperly assume it can be
1245 * recycled. Taking the lock synchronizes things enough to prevent a
1246 * problem: either num_pages won't include the new page, or _bt_getbuf
1247 * already has write lock on the buffer and it will be fully initialized
1248 * before we can examine it. Also, we need not worry if a page is added
1249 * immediately after we look; the page splitting code already has
1250 * write-lock on the left page before it adds a right page, so we must
1251 * already have processed any tuples due to be moved into such a page.
1252 *
1253 * XXX: Now that new pages are locked with RBM_ZERO_AND_LOCK, I don't
1254 * think the use of the extension lock is still required.
1255 *
1256 * We can skip locking for new or temp relations, however, since no one
1257 * else could be accessing them.
1258 */
1259 needLock = !RELATION_IS_LOCAL(rel);
1260
1262
1263 /*
1264 * It is safe to use batchmode as block_range_read_stream_cb takes no
1265 * locks.
1266 */
1270 info->strategy,
1271 rel,
1274 &p,
1275 0);
1276 for (;;)
1277 {
1278 /* Get the current relation length */
1279 if (needLock)
1281 num_pages = RelationGetNumberOfBlocks(rel);
1282 if (needLock)
1284
1285 if (info->report_progress)
1287 num_pages);
1288
1289 /* Quit if we've scanned the whole relation */
1290 if (p.current_blocknum >= num_pages)
1291 break;
1292
1293 p.last_exclusive = num_pages;
1294
1295 /* Iterate over pages, then loop back to recheck relation length */
1296 while (true)
1297 {
1298 BlockNumber current_block;
1299 Buffer buf;
1300
1301 /* call vacuum_delay_point while not holding any buffer lock */
1302 vacuum_delay_point(false);
1303
1304 buf = read_stream_next_buffer(stream, NULL);
1305
1306 if (!BufferIsValid(buf))
1307 break;
1308
1309 current_block = btvacuumpage(&vstate, buf);
1310
1311 if (info->report_progress)
1313 current_block);
1314 }
1315
1316 /*
1317 * We have to reset the read stream to use it again. After returning
1318 * InvalidBuffer, the read stream API won't invoke our callback again
1319 * until the stream has been reset.
1320 */
1321 read_stream_reset(stream);
1322 }
1323
1324 read_stream_end(stream);
1325
1326 /* Set statistics num_pages field to final size of index */
1327 stats->num_pages = num_pages;
1328
1330
1331 /*
1332 * If there were any calls to _bt_pagedel() during scan of the index then
1333 * see if any of the resulting pages can be placed in the FSM now. When
1334 * it's not safe we'll have to leave it up to a future VACUUM operation.
1335 *
1336 * Finally, if we placed any pages in the FSM (either just now or during
1337 * the scan), forcibly update the upper-level FSM pages to ensure that
1338 * searchers can find them.
1339 */
1340 _bt_pendingfsm_finalize(rel, &vstate);
1341 if (stats->pages_free > 0)
1343}
void pgstat_progress_update_param(int index, int64 val)
int Buffer
Definition: buf.h:23
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:283
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:368
void IndexFreeSpaceMapVacuum(Relation rel)
Definition: indexfsm.c:71
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:424
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:474
#define ExclusiveLock
Definition: lockdefs.h:42
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
void _bt_pendingfsm_finalize(Relation rel, BTVacState *vstate)
Definition: nbtpage.c:2996
void _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly)
Definition: nbtpage.c:2954
static BlockNumber btvacuumpage(BTVacState *vstate, Buffer buf)
Definition: nbtree.c:1358
#define PROGRESS_SCAN_BLOCKS_DONE
Definition: progress.h:125
#define PROGRESS_SCAN_BLOCKS_TOTAL
Definition: progress.h:124
void read_stream_reset(ReadStream *stream)
Definition: read_stream.c:1044
Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
Definition: read_stream.c:791
ReadStream * read_stream_begin_relation(int flags, BufferAccessStrategy strategy, Relation rel, ForkNumber forknum, ReadStreamBlockNumberCB callback, void *callback_private_data, size_t per_buffer_data_size)
Definition: read_stream.c:737
void read_stream_end(ReadStream *stream)
Definition: read_stream.c:1089
BlockNumber block_range_read_stream_cb(ReadStream *stream, void *callback_private_data, void *per_buffer_data)
Definition: read_stream.c:162
#define READ_STREAM_MAINTENANCE
Definition: read_stream.h:28
#define READ_STREAM_USE_BATCHING
Definition: read_stream.h:64
#define READ_STREAM_FULL
Definition: read_stream.h:43
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:657
BTPendingFSM * pendingpages
Definition: nbtree.h:345
int npendingpages
Definition: nbtree.h:346
int bufsize
Definition: nbtree.h:343
int maxbufsize
Definition: nbtree.h:344
BlockNumber num_pages
Definition: genam.h:104
bool report_progress
Definition: genam.h:76

References _bt_pendingfsm_finalize(), _bt_pendingfsm_init(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, block_range_read_stream_cb(), BTREE_METAPAGE, btvacuumpage(), buf, BufferIsValid(), BTVacState::bufsize, BTVacState::callback, callback(), BTVacState::callback_state, BlockRangeReadStreamPrivate::current_blocknum, CurrentMemoryContext, BTVacState::cycleid, ExclusiveLock, IndexVacuumInfo::index, IndexFreeSpaceMapVacuum(), BTVacState::info, BlockRangeReadStreamPrivate::last_exclusive, LockRelationForExtension(), MAIN_FORKNUM, BTVacState::maxbufsize, MemoryContextDelete(), BTVacState::npendingpages, IndexBulkDeleteResult::num_index_tuples, IndexBulkDeleteResult::num_pages, BTVacState::pagedelcontext, IndexBulkDeleteResult::pages_deleted, IndexBulkDeleteResult::pages_free, BTVacState::pendingpages, pgstat_progress_update_param(), PROGRESS_SCAN_BLOCKS_DONE, PROGRESS_SCAN_BLOCKS_TOTAL, read_stream_begin_relation(), read_stream_end(), READ_STREAM_FULL, READ_STREAM_MAINTENANCE, read_stream_next_buffer(), read_stream_reset(), READ_STREAM_USE_BATCHING, RELATION_IS_LOCAL, RelationGetNumberOfBlocks, IndexVacuumInfo::report_progress, BTVacState::stats, IndexVacuumInfo::strategy, UnlockRelationForExtension(), and vacuum_delay_point().

Referenced by btbulkdelete(), and btvacuumcleanup().