PostgreSQL Source Code  git master
blinsert.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/generic_xlog.h"
#include "access/tableam.h"
#include "bloom.h"
#include "catalog/index.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for blinsert.c:

Go to the source code of this file.

Data Structures

struct  BloomBuildState
 

Functions

static void flushCachedPage (Relation index, BloomBuildState *buildstate)
 
static void initCachedPage (BloomBuildState *buildstate)
 
static void bloomBuildCallback (Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
 
IndexBuildResultblbuild (Relation heap, Relation index, IndexInfo *indexInfo)
 
void blbuildempty (Relation index)
 
bool blinsert (Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

◆ blbuild()

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

Definition at line 121 of file blinsert.c.

122 {
123  IndexBuildResult *result;
124  double reltuples;
125  BloomBuildState buildstate;
126 
128  elog(ERROR, "index \"%s\" already contains data",
130 
131  /* Initialize the meta page */
133 
134  /* Initialize the bloom build state */
135  memset(&buildstate, 0, sizeof(buildstate));
136  initBloomState(&buildstate.blstate, index);
138  "Bloom build temporary context",
140  initCachedPage(&buildstate);
141 
142  /* Do the heap scan */
143  reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
144  bloomBuildCallback, (void *) &buildstate,
145  NULL);
146 
147  /* Flush last page if needed (it will be, unless heap was empty) */
148  if (buildstate.count > 0)
149  flushCachedPage(index, &buildstate);
150 
151  MemoryContextDelete(buildstate.tmpCtx);
152 
153  result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
154  result->heap_tuples = reltuples;
155  result->index_tuples = buildstate.indtuples;
156 
157  return result;
158 }
static void initCachedPage(BloomBuildState *buildstate)
Definition: blinsert.c:64
static void flushCachedPage(Relation index, BloomBuildState *buildstate)
Definition: blinsert.c:47
static void bloomBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: blinsert.c:74
void BloomInitMetapage(Relation index, ForkNumber forknum)
Definition: blutils.c:448
void initBloomState(BloomState *state, Relation index)
Definition: blutils.c:163
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:281
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void * palloc(Size size)
Definition: mcxt.c:1316
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define RelationGetRelationName(relation)
Definition: rel.h:539
@ MAIN_FORKNUM
Definition: relpath.h:50
int64 indtuples
Definition: blinsert.c:36
BloomState blstate
Definition: blinsert.c:35
MemoryContext tmpCtx
Definition: blinsert.c:37
double heap_tuples
Definition: genam.h:32
double index_tuples
Definition: genam.h:33
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:1785

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bloomBuildCallback(), BloomInitMetapage(), BloomBuildState::blstate, BloomBuildState::count, CurrentMemoryContext, elog, ERROR, flushCachedPage(), IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, BloomBuildState::indtuples, initBloomState(), initCachedPage(), MAIN_FORKNUM, MemoryContextDelete(), palloc(), RelationGetNumberOfBlocks, RelationGetRelationName, table_index_build_scan(), and BloomBuildState::tmpCtx.

Referenced by blhandler().

◆ blbuildempty()

void blbuildempty ( Relation  index)

Definition at line 164 of file blinsert.c.

165 {
166  /* Initialize the meta page */
168 }
@ INIT_FORKNUM
Definition: relpath.h:53

References BloomInitMetapage(), and INIT_FORKNUM.

Referenced by blhandler().

◆ blinsert()

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

Definition at line 174 of file blinsert.c.

179 {
180  BloomState blstate;
181  BloomTuple *itup;
182  MemoryContext oldCtx;
183  MemoryContext insertCtx;
184  BloomMetaPageData *metaData;
185  Buffer buffer,
186  metaBuffer;
187  Page page,
188  metaPage;
190  OffsetNumber nStart;
192 
194  "Bloom insert temporary context",
196 
197  oldCtx = MemoryContextSwitchTo(insertCtx);
198 
199  initBloomState(&blstate, index);
200  itup = BloomFormTuple(&blstate, ht_ctid, values, isnull);
201 
202  /*
203  * At first, try to insert new tuple to the first page in notFullPage
204  * array. If successful, we don't need to modify the meta page.
205  */
206  metaBuffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
207  LockBuffer(metaBuffer, BUFFER_LOCK_SHARE);
208  metaData = BloomPageGetMeta(BufferGetPage(metaBuffer));
209 
210  if (metaData->nEnd > metaData->nStart)
211  {
212  blkno = metaData->notFullPage[metaData->nStart];
213  Assert(blkno != InvalidBlockNumber);
214 
215  /* Don't hold metabuffer lock while doing insert */
216  LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
217 
218  buffer = ReadBuffer(index, blkno);
220 
222  page = GenericXLogRegisterBuffer(state, buffer, 0);
223 
224  /*
225  * We might have found a page that was recently deleted by VACUUM. If
226  * so, we can reuse it, but we must reinitialize it.
227  */
228  if (PageIsNew(page) || BloomPageIsDeleted(page))
229  BloomInitPage(page, 0);
230 
231  if (BloomPageAddItem(&blstate, page, itup))
232  {
233  /* Success! Apply the change, clean up, and exit */
235  UnlockReleaseBuffer(buffer);
236  ReleaseBuffer(metaBuffer);
237  MemoryContextSwitchTo(oldCtx);
238  MemoryContextDelete(insertCtx);
239  return false;
240  }
241 
242  /* Didn't fit, must try other pages */
244  UnlockReleaseBuffer(buffer);
245  }
246  else
247  {
248  /* No entries in notFullPage */
249  LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
250  }
251 
252  /*
253  * Try other pages in notFullPage array. We will have to change nStart in
254  * metapage. Thus, grab exclusive lock on metapage.
255  */
256  LockBuffer(metaBuffer, BUFFER_LOCK_EXCLUSIVE);
257 
258  /* nStart might have changed while we didn't have lock */
259  nStart = metaData->nStart;
260 
261  /* Skip first page if we already tried it above */
262  if (nStart < metaData->nEnd &&
263  blkno == metaData->notFullPage[nStart])
264  nStart++;
265 
266  /*
267  * This loop iterates for each page we try from the notFullPage array, and
268  * will also initialize a GenericXLogState for the fallback case of having
269  * to allocate a new page.
270  */
271  for (;;)
272  {
274 
275  /* get modifiable copy of metapage */
276  metaPage = GenericXLogRegisterBuffer(state, metaBuffer, 0);
277  metaData = BloomPageGetMeta(metaPage);
278 
279  if (nStart >= metaData->nEnd)
280  break; /* no more entries in notFullPage array */
281 
282  blkno = metaData->notFullPage[nStart];
283  Assert(blkno != InvalidBlockNumber);
284 
285  buffer = ReadBuffer(index, blkno);
287  page = GenericXLogRegisterBuffer(state, buffer, 0);
288 
289  /* Basically same logic as above */
290  if (PageIsNew(page) || BloomPageIsDeleted(page))
291  BloomInitPage(page, 0);
292 
293  if (BloomPageAddItem(&blstate, page, itup))
294  {
295  /* Success! Apply the changes, clean up, and exit */
296  metaData->nStart = nStart;
298  UnlockReleaseBuffer(buffer);
299  UnlockReleaseBuffer(metaBuffer);
300  MemoryContextSwitchTo(oldCtx);
301  MemoryContextDelete(insertCtx);
302  return false;
303  }
304 
305  /* Didn't fit, must try other pages */
307  UnlockReleaseBuffer(buffer);
308  nStart++;
309  }
310 
311  /*
312  * Didn't find place to insert in notFullPage array. Allocate new page.
313  * (XXX is it good to do this while holding ex-lock on the metapage??)
314  */
315  buffer = BloomNewBuffer(index);
316 
318  BloomInitPage(page, 0);
319 
320  if (!BloomPageAddItem(&blstate, page, itup))
321  {
322  /* We shouldn't be here since we're inserting to an empty page */
323  elog(ERROR, "could not add new bloom tuple to empty page");
324  }
325 
326  /* Reset notFullPage array to contain just this new page */
327  metaData->nStart = 0;
328  metaData->nEnd = 1;
329  metaData->notFullPage[0] = BufferGetBlockNumber(buffer);
330 
331  /* Apply the changes, clean up, and exit */
333 
334  UnlockReleaseBuffer(buffer);
335  UnlockReleaseBuffer(metaBuffer);
336 
337  MemoryContextSwitchTo(oldCtx);
338  MemoryContextDelete(insertCtx);
339 
340  return false;
341 }
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
BloomTuple * BloomFormTuple(BloomState *state, ItemPointer iptr, Datum *values, bool *isnull)
Definition: blutils.c:295
void BloomInitPage(Page page, uint16 flags)
Definition: blutils.c:401
#define BloomPageGetMeta(page)
Definition: bloom.h:136
bool BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple)
Definition: blutils.c:320
Buffer BloomNewBuffer(Relation index)
Definition: blutils.c:355
#define BloomPageIsDeleted(page)
Definition: bloom.h:64
#define BLOOM_METAPAGE_BLKNO
Definition: bloom.h:78
static Datum values[MAXATTR]
Definition: bootstrap.c:152
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3667
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4850
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4867
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5085
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:745
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:197
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:198
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:408
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:199
Pointer Page
Definition: bufpage.h:78
static bool PageIsNew(Page page)
Definition: bufpage.h:230
#define Assert(condition)
Definition: c.h:858
Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags)
Definition: generic_xlog.c:299
GenericXLogState * GenericXLogStart(Relation relation)
Definition: generic_xlog.c:269
XLogRecPtr GenericXLogFinish(GenericXLogState *state)
Definition: generic_xlog.c:337
void GenericXLogAbort(GenericXLogState *state)
Definition: generic_xlog.c:444
#define GENERIC_XLOG_FULL_IMAGE
Definition: generic_xlog.h:26
uint16 OffsetNumber
Definition: off.h:24
MemoryContextSwitchTo(old_ctx)
FreeBlockNumberArray notFullPage
Definition: bloom.h:127
uint16 nEnd
Definition: bloom.h:125
uint16 nStart
Definition: bloom.h:124
Definition: regguts.h:323

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BLOOM_METAPAGE_BLKNO, BloomFormTuple(), BloomInitPage(), BloomNewBuffer(), BloomPageAddItem(), BloomPageGetMeta, BloomPageIsDeleted, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage(), CurrentMemoryContext, elog, ERROR, GENERIC_XLOG_FULL_IMAGE, GenericXLogAbort(), GenericXLogFinish(), GenericXLogRegisterBuffer(), GenericXLogStart(), initBloomState(), InvalidBlockNumber, LockBuffer(), MemoryContextDelete(), MemoryContextSwitchTo(), BloomMetaPageData::nEnd, BloomMetaPageData::notFullPage, BloomMetaPageData::nStart, PageIsNew(), ReadBuffer(), ReleaseBuffer(), UnlockReleaseBuffer(), and values.

Referenced by blhandler().

◆ bloomBuildCallback()

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

Definition at line 74 of file blinsert.c.

76 {
77  BloomBuildState *buildstate = (BloomBuildState *) state;
78  MemoryContext oldCtx;
79  BloomTuple *itup;
80 
81  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
82 
83  itup = BloomFormTuple(&buildstate->blstate, tid, values, isnull);
84 
85  /* Try to add next item to cached page */
86  if (BloomPageAddItem(&buildstate->blstate, buildstate->data.data, itup))
87  {
88  /* Next item was added successfully */
89  buildstate->count++;
90  }
91  else
92  {
93  /* Cached page is full, flush it out and make a new one */
94  flushCachedPage(index, buildstate);
95 
97 
98  initCachedPage(buildstate);
99 
100  if (!BloomPageAddItem(&buildstate->blstate, buildstate->data.data, itup))
101  {
102  /* We shouldn't be here since we're inserting to the empty page */
103  elog(ERROR, "could not add new bloom tuple to empty page");
104  }
105 
106  /* Next item was added successfully */
107  buildstate->count++;
108  }
109 
110  /* Update total tuple count */
111  buildstate->indtuples += 1;
112 
113  MemoryContextSwitchTo(oldCtx);
114  MemoryContextReset(buildstate->tmpCtx);
115 }
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
PGAlignedBlock data
Definition: blinsert.c:39
char data[BLCKSZ]
Definition: c.h:1119

References BloomFormTuple(), BloomPageAddItem(), BloomBuildState::blstate, CHECK_FOR_INTERRUPTS, BloomBuildState::count, BloomBuildState::data, PGAlignedBlock::data, elog, ERROR, flushCachedPage(), BloomBuildState::indtuples, initCachedPage(), MemoryContextReset(), MemoryContextSwitchTo(), BloomBuildState::tmpCtx, and values.

Referenced by blbuild().

◆ flushCachedPage()

static void flushCachedPage ( Relation  index,
BloomBuildState buildstate 
)
static

◆ initCachedPage()

static void initCachedPage ( BloomBuildState buildstate)
static

Definition at line 64 of file blinsert.c.

65 {
66  BloomInitPage(buildstate->data.data, 0);
67  buildstate->count = 0;
68 }

References BloomInitPage(), BloomBuildState::count, BloomBuildState::data, and PGAlignedBlock::data.

Referenced by blbuild(), and bloomBuildCallback().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 27 of file blinsert.c.