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/tableam.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, ItemPointer tid, 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, bool indexUnchanged, IndexInfo *indexInfo)
 

Function Documentation

◆ spgbuild()

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

Definition at line 75 of file spginsert.c.

76 {
77  IndexBuildResult *result;
78  double reltuples;
79  SpGistBuildState buildstate;
80  Buffer metabuffer,
81  rootbuffer,
82  nullbuffer;
83 
85  elog(ERROR, "index \"%s\" already contains data",
87 
88  /*
89  * Initialize the meta page and root pages
90  */
91  metabuffer = SpGistNewBuffer(index);
92  rootbuffer = SpGistNewBuffer(index);
93  nullbuffer = SpGistNewBuffer(index);
94 
98 
100 
101  SpGistInitMetapage(BufferGetPage(metabuffer));
102  MarkBufferDirty(metabuffer);
103  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
104  MarkBufferDirty(rootbuffer);
106  MarkBufferDirty(nullbuffer);
107 
108 
110 
111  UnlockReleaseBuffer(metabuffer);
112  UnlockReleaseBuffer(rootbuffer);
113  UnlockReleaseBuffer(nullbuffer);
114 
115  /*
116  * Now insert all the heap data into the index
117  */
118  initSpGistState(&buildstate.spgstate, index);
119  buildstate.spgstate.isBuild = true;
120  buildstate.indtuples = 0;
121 
123  "SP-GiST build temporary context",
125 
126  reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
127  spgistBuildCallback, (void *) &buildstate,
128  NULL);
129 
130  MemoryContextDelete(buildstate.tmpCtx);
131 
133 
134  /*
135  * We didn't write WAL records as we built the index, so if WAL-logging is
136  * required, write all pages to the WAL now.
137  */
138  if (RelationNeedsWAL(index))
139  {
142  true);
143  }
144 
145  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
146  result->heap_tuples = reltuples;
147  result->index_tuples = buildstate.indtuples;
148 
149  return result;
150 }
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3386
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4590
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2198
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:229
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:350
#define ERROR
Definition: elog.h:39
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc0(Size size)
Definition: mcxt.c:1257
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403
#define AllocSetContextCreate
Definition: memutils.h:126
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:150
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
#define RelationGetRelationName(relation)
Definition: rel.h:538
#define RelationNeedsWAL(relation)
Definition: rel.h:629
@ MAIN_FORKNUM
Definition: relpath.h:50
static void spgistBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:43
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
#define SPGIST_NULLS
#define SPGIST_LEAF
#define SPGIST_ROOT_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:332
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:423
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:367
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:695
void SpGistInitMetapage(Page page)
Definition: spgutils.c:705
double heap_tuples
Definition: genam.h:32
double index_tuples
Definition: genam.h:33
MemoryContext tmpCtx
Definition: spginsert.c:37
SpGistState spgstate
Definition: spginsert.c:35
Definition: type.h:95
static double table_index_build_scan(Relation table_rel, Relation index_rel, struct IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition: tableam.h:1772
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1271

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), BufferGetBlockNumber(), BufferGetPage(), CurrentMemoryContext, elog(), END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, SpGistBuildState::indtuples, initSpGistState(), SpGistState::isBuild, log_newpage_range(), MAIN_FORKNUM, MarkBufferDirty(), MemoryContextDelete(), palloc0(), RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, spgistBuildCallback(), SpGistInitBuffer(), SpGistInitMetapage(), SpGistNewBuffer(), SpGistUpdateMetaPage(), SpGistBuildState::spgstate, START_CRIT_SECTION, table_index_build_scan(), SpGistBuildState::tmpCtx, and UnlockReleaseBuffer().

Referenced by spghandler().

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 156 of file spginsert.c.

157 {
158  Buffer metabuffer,
159  rootbuffer,
160  nullbuffer;
161 
162  /*
163  * Initialize the meta page and root pages
164  */
165  metabuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
166  LockBuffer(metabuffer, BUFFER_LOCK_EXCLUSIVE);
167  rootbuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
168  LockBuffer(rootbuffer, BUFFER_LOCK_EXCLUSIVE);
169  nullbuffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
170  LockBuffer(nullbuffer, BUFFER_LOCK_EXCLUSIVE);
171 
175 
177 
178  SpGistInitMetapage(BufferGetPage(metabuffer));
179  MarkBufferDirty(metabuffer);
180  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
181  MarkBufferDirty(rootbuffer);
183  MarkBufferDirty(nullbuffer);
184 
185  log_newpage_buffer(metabuffer, true);
186  log_newpage_buffer(rootbuffer, true);
187  log_newpage_buffer(nullbuffer, true);
188 
190 
191  UnlockReleaseBuffer(metabuffer);
192  UnlockReleaseBuffer(rootbuffer);
193  UnlockReleaseBuffer(nullbuffer);
194 }
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4808
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:782
#define P_NEW
Definition: bufmgr.h:152
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:159
@ RBM_NORMAL
Definition: bufmgr.h:44
@ INIT_FORKNUM
Definition: relpath.h:53
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1238

References Assert(), BUFFER_LOCK_EXCLUSIVE, BufferGetBlockNumber(), BufferGetPage(), END_CRIT_SECTION, INIT_FORKNUM, LockBuffer(), log_newpage_buffer(), MarkBufferDirty(), P_NEW, RBM_NORMAL, ReadBufferExtended(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitBuffer(), SpGistInitMetapage(), START_CRIT_SECTION, and UnlockReleaseBuffer().

Referenced by spghandler().

◆ spginsert()

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

Definition at line 200 of file spginsert.c.

205 {
206  SpGistState spgstate;
207  MemoryContext oldCtx;
208  MemoryContext insertCtx;
209 
211  "SP-GiST insert temporary context",
213  oldCtx = MemoryContextSwitchTo(insertCtx);
214 
215  initSpGistState(&spgstate, index);
216 
217  /*
218  * We might have to repeat spgdoinsert() multiple times, if conflicts
219  * occur with concurrent insertions. If so, reset the insertCtx each time
220  * to avoid cumulative memory consumption. That means we also have to
221  * redo initSpGistState(), but it's cheap enough not to matter.
222  */
223  while (!spgdoinsert(index, &spgstate, ht_ctid, values, isnull))
224  {
225  MemoryContextReset(insertCtx);
226  initSpGistState(&spgstate, index);
227  }
228 
230 
231  MemoryContextSwitchTo(oldCtx);
232  MemoryContextDelete(insertCtx);
233 
234  /* return false since we've not done any unique check */
235  return false;
236 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:330
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum *datums, bool *isnulls)
Definition: spgdoinsert.c:1915

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

Referenced by spghandler().

◆ spgistBuildCallback()

static void spgistBuildCallback ( Relation  index,
ItemPointer  tid,
Datum values,
bool isnull,
bool  tupleIsAlive,
void *  state 
)
static

Definition at line 43 of file spginsert.c.

45 {
46  SpGistBuildState *buildstate = (SpGistBuildState *) state;
47  MemoryContext oldCtx;
48 
49  /* Work in temp context, and reset it after each tuple */
50  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
51 
52  /*
53  * Even though no concurrent insertions can be happening, we still might
54  * get a buffer-locking failure due to bgwriter or checkpointer taking a
55  * lock on some buffer. So we need to be willing to retry. We can flush
56  * any temp data when retrying.
57  */
58  while (!spgdoinsert(index, &buildstate->spgstate, tid,
59  values, isnull))
60  {
61  MemoryContextReset(buildstate->tmpCtx);
62  }
63 
64  /* Update total tuple count */
65  buildstate->indtuples += 1;
66 
67  MemoryContextSwitchTo(oldCtx);
68  MemoryContextReset(buildstate->tmpCtx);
69 }
Definition: regguts.h:323

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

Referenced by spgbuild().