PostgreSQL Source Code  git master
spginsert.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/spgist_private.h"
#include "access/spgxlog.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "catalog/index.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for spginsert.c:

Go to the source code of this file.

Data Structures

struct  SpGistBuildState
 

Functions

static void spgistBuildCallback (Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
 
IndexBuildResultspgbuild (Relation heap, Relation index, IndexInfo *indexInfo)
 
void spgbuildempty (Relation index)
 
bool spginsert (Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, IndexInfo *indexInfo)
 

Function Documentation

◆ spgbuild()

IndexBuildResult* spgbuild ( Relation  heap,
Relation  index,
IndexInfo indexInfo 
)

Definition at line 74 of file spginsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BufferGetBlockNumber(), BufferGetPage, CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, IndexBuildHeapScan(), SpGistBuildState::indtuples, initSpGistState(), SpGistState::isBuild, MarkBufferDirty(), MemoryContextDelete(), PageSetLSN, palloc0(), REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, reltuples, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, spgistBuildCallback(), SpGistInitBuffer(), SpGistInitMetapage(), SpGistNewBuffer(), SpGistUpdateMetaPage(), SpGistBuildState::spgstate, START_CRIT_SECTION, SpGistBuildState::tmpCtx, UnlockReleaseBuffer(), XLOG_SPGIST_CREATE_INDEX, XLogBeginInsert(), XLogInsert(), and XLogRegisterBuffer().

Referenced by spghandler().

75 {
76  IndexBuildResult *result;
77  double reltuples;
78  SpGistBuildState buildstate;
79  Buffer metabuffer,
80  rootbuffer,
81  nullbuffer;
82 
83  if (RelationGetNumberOfBlocks(index) != 0)
84  elog(ERROR, "index \"%s\" already contains data",
86 
87  /*
88  * Initialize the meta page and root pages
89  */
90  metabuffer = SpGistNewBuffer(index);
91  rootbuffer = SpGistNewBuffer(index);
92  nullbuffer = SpGistNewBuffer(index);
93 
97 
99 
100  SpGistInitMetapage(BufferGetPage(metabuffer));
101  MarkBufferDirty(metabuffer);
102  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
103  MarkBufferDirty(rootbuffer);
105  MarkBufferDirty(nullbuffer);
106 
107  if (RelationNeedsWAL(index))
108  {
109  XLogRecPtr recptr;
110 
111  XLogBeginInsert();
112 
113  /*
114  * Replay will re-initialize the pages, so don't take full pages
115  * images. No other data to log.
116  */
120 
121  recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_CREATE_INDEX);
122 
123  PageSetLSN(BufferGetPage(metabuffer), recptr);
124  PageSetLSN(BufferGetPage(rootbuffer), recptr);
125  PageSetLSN(BufferGetPage(nullbuffer), recptr);
126  }
127 
129 
130  UnlockReleaseBuffer(metabuffer);
131  UnlockReleaseBuffer(rootbuffer);
132  UnlockReleaseBuffer(nullbuffer);
133 
134  /*
135  * Now insert all the heap data into the index
136  */
137  initSpGistState(&buildstate.spgstate, index);
138  buildstate.spgstate.isBuild = true;
139  buildstate.indtuples = 0;
140 
142  "SP-GiST build temporary context",
144 
145  reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
146  spgistBuildCallback, (void *) &buildstate,
147  NULL);
148 
149  MemoryContextDelete(buildstate.tmpCtx);
150 
151  SpGistUpdateMetaPage(index);
152 
153  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
154  result->heap_tuples = reltuples;
155  result->index_tuples = buildstate.indtuples;
156 
157  return result;
158 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:270
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define SPGIST_NULLS
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
SpGistState spgstate
Definition: spginsert.c:34
#define SPGIST_ROOT_BLKNO
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define XLOG_SPGIST_CREATE_INDEX
Definition: spgxlog.h:21
double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
Definition: index.c:2418
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define SPGIST_NULL_BLKNO
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:175
#define RelationGetRelationName(relation)
Definition: rel.h:441
static void spgistBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:42
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:544
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void * palloc0(Size size)
Definition: mcxt.c:955
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:205
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
void SpGistInitMetapage(Page page)
Definition: spgutils.c:554
#define RelationNeedsWAL(relation)
Definition: rel.h:510
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
MemoryContext tmpCtx
Definition: spginsert.c:36
#define elog
Definition: elog.h:219
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
float4 reltuples
Definition: pg_class.h:44
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 164 of file spginsert.c.

References INIT_FORKNUM, log_newpage(), RelFileNodeBackend::node, PageSetChecksumInplace(), palloc(), RelationData::rd_smgr, SMgrRelationData::smgr_rnode, smgrimmedsync(), smgrwrite(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitMetapage(), and SpGistInitPage().

Referenced by spghandler().

165 {
166  Page page;
167 
168  /* Construct metapage. */
169  page = (Page) palloc(BLCKSZ);
170  SpGistInitMetapage(page);
171 
172  /*
173  * Write the page and log it unconditionally. This is important
174  * particularly for indexes created on tablespaces and databases whose
175  * creation happened after the last redo pointer as recovery removes any
176  * of their existing content when the corresponding create records are
177  * replayed.
178  */
181  (char *) page, true);
183  SPGIST_METAPAGE_BLKNO, page, true);
184 
185  /* Likewise for the root page. */
187 
190  (char *) page, true);
192  SPGIST_ROOT_BLKNO, page, true);
193 
194  /* Likewise for the null-tuples root page. */
196 
199  (char *) page, true);
201  SPGIST_NULL_BLKNO, page, true);
202 
203  /*
204  * An immediate sync is required even if we xlog'd the pages, because the
205  * writes did not go through shared buffers and therefore a concurrent
206  * checkpoint may have moved the redo pointer past our xlog record.
207  */
209 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
#define SPGIST_NULLS
#define SPGIST_ROOT_BLKNO
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
#define SPGIST_NULL_BLKNO
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:647
#define SPGIST_METAPAGE_BLKNO
RelFileNode node
Definition: relfilenode.h:74
void SpGistInitMetapage(Page page)
Definition: spgutils.c:554
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1195
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:529
void * palloc(Size size)
Definition: mcxt.c:924
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:972
#define SPGIST_LEAF
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734
Pointer Page
Definition: bufpage.h:74

◆ spginsert()

bool spginsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
IndexInfo indexInfo 
)

Definition at line 215 of file spginsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, initSpGistState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), spgdoinsert(), and SpGistUpdateMetaPage().

Referenced by spghandler().

219 {
220  SpGistState spgstate;
221  MemoryContext oldCtx;
222  MemoryContext insertCtx;
223 
225  "SP-GiST insert temporary context",
227  oldCtx = MemoryContextSwitchTo(insertCtx);
228 
229  initSpGistState(&spgstate, index);
230 
231  /*
232  * We might have to repeat spgdoinsert() multiple times, if conflicts
233  * occur with concurrent insertions. If so, reset the insertCtx each time
234  * to avoid cumulative memory consumption. That means we also have to
235  * redo initSpGistState(), but it's cheap enough not to matter.
236  */
237  while (!spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull))
238  {
239  MemoryContextReset(insertCtx);
240  initSpGistState(&spgstate, index);
241  }
242 
243  SpGistUpdateMetaPage(index);
244 
245  MemoryContextSwitchTo(oldCtx);
246  MemoryContextDelete(insertCtx);
247 
248  /* return false since we've not done any unique check */
249  return false;
250 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:270
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum datum, bool isnull)
Definition: spgdoinsert.c:1891
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:175
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ spgistBuildCallback()

static void spgistBuildCallback ( Relation  index,
HeapTuple  htup,
Datum values,
bool isnull,
bool  tupleIsAlive,
void *  state 
)
static

Definition at line 42 of file spginsert.c.

References SpGistBuildState::indtuples, MemoryContextReset(), MemoryContextSwitchTo(), spgdoinsert(), SpGistBuildState::spgstate, HeapTupleData::t_self, and SpGistBuildState::tmpCtx.

Referenced by spgbuild().

44 {
45  SpGistBuildState *buildstate = (SpGistBuildState *) state;
46  MemoryContext oldCtx;
47 
48  /* Work in temp context, and reset it after each tuple */
49  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
50 
51  /*
52  * Even though no concurrent insertions can be happening, we still might
53  * get a buffer-locking failure due to bgwriter or checkpointer taking a
54  * lock on some buffer. So we need to be willing to retry. We can flush
55  * any temp data when retrying.
56  */
57  while (!spgdoinsert(index, &buildstate->spgstate, &htup->t_self,
58  *values, *isnull))
59  {
60  MemoryContextReset(buildstate->tmpCtx);
61  }
62 
63  /* Update total tuple count */
64  buildstate->indtuples += 1;
65 
66  MemoryContextSwitchTo(oldCtx);
67  MemoryContextReset(buildstate->tmpCtx);
68 }
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum datum, bool isnull)
Definition: spgdoinsert.c:1891
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
SpGistState spgstate
Definition: spginsert.c:34
ItemPointerData t_self
Definition: htup.h:65
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:164
MemoryContext tmpCtx
Definition: spginsert.c:36