PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
blinsert.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/generic_xlog.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 "bloom.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, HeapTuple htup, 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, IndexInfo *indexInfo)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

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

Definition at line 115 of file blinsert.c.

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

Referenced by blhandler().

116 {
118  double reltuples;
119  BloomBuildState buildstate;
120 
121  if (RelationGetNumberOfBlocks(index) != 0)
122  elog(ERROR, "index \"%s\" already contains data",
123  RelationGetRelationName(index));
124 
125  /* Initialize the meta page */
126  BloomInitMetapage(index);
127 
128  /* Initialize the bloom build state */
129  memset(&buildstate, 0, sizeof(buildstate));
130  initBloomState(&buildstate.blstate, index);
132  "Bloom build temporary context",
134  initCachedPage(&buildstate);
135 
136  /* Do the heap scan */
137  reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
138  bloomBuildCallback, (void *) &buildstate);
139 
140  /*
141  * There are could be some items in cached page. Flush this page if
142  * needed.
143  */
144  if (buildstate.count > 0)
145  flushCachedPage(index, &buildstate);
146 
147  MemoryContextDelete(buildstate.tmpCtx);
148 
149  result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
150  result->heap_tuples = result->index_tuples = reltuples;
151 
152  return result;
153 }
static void bloomBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: blinsert.c:74
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
void initBloomState(BloomState *state, Relation index)
Definition: blutils.c:153
return result
Definition: formatting.c:1633
#define ERROR
Definition: elog.h:43
static void flushCachedPage(Relation index, BloomBuildState *buildstate)
Definition: blinsert.c:46
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
MemoryContext tmpCtx
Definition: blinsert.c:36
#define RelationGetRelationName(relation)
Definition: rel.h:436
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
static void initCachedPage(BloomBuildState *buildstate)
Definition: blinsert.c:63
double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state)
Definition: index.c:2175
void * palloc(Size size)
Definition: mcxt.c:849
BloomState blstate
Definition: blinsert.c:35
#define elog
Definition: elog.h:219
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32
void BloomInitMetapage(Relation index)
Definition: blutils.c:446
void blbuildempty ( Relation  index)

Definition at line 159 of file blinsert.c.

References BLOOM_METAPAGE_BLKNO, BloomFillMetapage(), INIT_FORKNUM, log_newpage(), RelFileNodeBackend::node, PageSetChecksumInplace(), palloc(), RelationData::rd_smgr, SMgrRelationData::smgr_rnode, smgrimmedsync(), and smgrwrite().

Referenced by blhandler().

160 {
161  Page metapage;
162 
163  /* Construct metapage. */
164  metapage = (Page) palloc(BLCKSZ);
165  BloomFillMetapage(index, metapage);
166 
167  /*
168  * Write the page and log it. It might seem that an immediate sync would
169  * be sufficient to guarantee that the file exists on disk, but recovery
170  * itself might remove it while replaying, for example, an
171  * XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE record. Therefore, we need
172  * this even when wal_level=minimal.
173  */
176  (char *) metapage, true);
178  BLOOM_METAPAGE_BLKNO, metapage, false);
179 
180  /*
181  * An immediate sync is required even if we xlog'd the page, because the
182  * write did not go through shared_buffers and therefore a concurrent
183  * checkpoint may have moved the redo pointer past our xlog record.
184  */
186 }
#define BLOOM_METAPAGE_BLKNO
Definition: bloom.h:77
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:647
RelFileNode node
Definition: relfilenode.h:74
void BloomFillMetapage(Relation index, Page metaPage)
Definition: blutils.c:414
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1199
void * palloc(Size size)
Definition: mcxt.c:849
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:972
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734
Pointer Page
Definition: bufpage.h:74
bool blinsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
IndexInfo indexInfo 
)

Definition at line 192 of file blinsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Assert, BLOOM_METAPAGE_BLKNO, BloomFormTuple(), BloomInitPage(), BloomNewBuffer(), BloomPageAddItem(), BloomPageGetMeta, BloomPageIsDeleted, buffer, 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(), and UnlockReleaseBuffer().

Referenced by blhandler().

196 {
197  BloomState blstate;
198  BloomTuple *itup;
199  MemoryContext oldCtx;
200  MemoryContext insertCtx;
201  BloomMetaPageData *metaData;
202  Buffer buffer,
203  metaBuffer;
204  Page page,
205  metaPage;
207  OffsetNumber nStart;
209 
211  "Bloom insert temporary context",
213 
214  oldCtx = MemoryContextSwitchTo(insertCtx);
215 
216  initBloomState(&blstate, index);
217  itup = BloomFormTuple(&blstate, ht_ctid, values, isnull);
218 
219  /*
220  * At first, try to insert new tuple to the first page in notFullPage
221  * array. If successful, we don't need to modify the meta page.
222  */
223  metaBuffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
224  LockBuffer(metaBuffer, BUFFER_LOCK_SHARE);
225  metaData = BloomPageGetMeta(BufferGetPage(metaBuffer));
226 
227  if (metaData->nEnd > metaData->nStart)
228  {
229  Page page;
230 
231  blkno = metaData->notFullPage[metaData->nStart];
232  Assert(blkno != InvalidBlockNumber);
233 
234  /* Don't hold metabuffer lock while doing insert */
235  LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
236 
237  buffer = ReadBuffer(index, blkno);
239 
240  state = GenericXLogStart(index);
241  page = GenericXLogRegisterBuffer(state, buffer, 0);
242 
243  /*
244  * We might have found a page that was recently deleted by VACUUM. If
245  * so, we can reuse it, but we must reinitialize it.
246  */
247  if (PageIsNew(page) || BloomPageIsDeleted(page))
248  BloomInitPage(page, 0);
249 
250  if (BloomPageAddItem(&blstate, page, itup))
251  {
252  /* Success! Apply the change, clean up, and exit */
253  GenericXLogFinish(state);
254  UnlockReleaseBuffer(buffer);
255  ReleaseBuffer(metaBuffer);
256  MemoryContextSwitchTo(oldCtx);
257  MemoryContextDelete(insertCtx);
258  return false;
259  }
260 
261  /* Didn't fit, must try other pages */
262  GenericXLogAbort(state);
263  UnlockReleaseBuffer(buffer);
264  }
265  else
266  {
267  /* No entries in notFullPage */
268  LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
269  }
270 
271  /*
272  * Try other pages in notFullPage array. We will have to change nStart in
273  * metapage. Thus, grab exclusive lock on metapage.
274  */
275  LockBuffer(metaBuffer, BUFFER_LOCK_EXCLUSIVE);
276 
277  /* nStart might have changed while we didn't have lock */
278  nStart = metaData->nStart;
279 
280  /* Skip first page if we already tried it above */
281  if (nStart < metaData->nEnd &&
282  blkno == metaData->notFullPage[nStart])
283  nStart++;
284 
285  /*
286  * This loop iterates for each page we try from the notFullPage array, and
287  * will also initialize a GenericXLogState for the fallback case of having
288  * to allocate a new page.
289  */
290  for (;;)
291  {
292  state = GenericXLogStart(index);
293 
294  /* get modifiable copy of metapage */
295  metaPage = GenericXLogRegisterBuffer(state, metaBuffer, 0);
296  metaData = BloomPageGetMeta(metaPage);
297 
298  if (nStart >= metaData->nEnd)
299  break; /* no more entries in notFullPage array */
300 
301  blkno = metaData->notFullPage[nStart];
302  Assert(blkno != InvalidBlockNumber);
303 
304  buffer = ReadBuffer(index, blkno);
306  page = GenericXLogRegisterBuffer(state, buffer, 0);
307 
308  /* Basically same logic as above */
309  if (PageIsNew(page) || BloomPageIsDeleted(page))
310  BloomInitPage(page, 0);
311 
312  if (BloomPageAddItem(&blstate, page, itup))
313  {
314  /* Success! Apply the changes, clean up, and exit */
315  metaData->nStart = nStart;
316  GenericXLogFinish(state);
317  UnlockReleaseBuffer(buffer);
318  UnlockReleaseBuffer(metaBuffer);
319  MemoryContextSwitchTo(oldCtx);
320  MemoryContextDelete(insertCtx);
321  return false;
322  }
323 
324  /* Didn't fit, must try other pages */
325  GenericXLogAbort(state);
326  UnlockReleaseBuffer(buffer);
327  nStart++;
328  }
329 
330  /*
331  * Didn't find place to insert in notFullPage array. Allocate new page.
332  * (XXX is it good to do this while holding ex-lock on the metapage??)
333  */
334  buffer = BloomNewBuffer(index);
335 
336  page = GenericXLogRegisterBuffer(state, buffer, GENERIC_XLOG_FULL_IMAGE);
337  BloomInitPage(page, 0);
338 
339  if (!BloomPageAddItem(&blstate, page, itup))
340  {
341  /* We shouldn't be here since we're inserting to an empty page */
342  elog(ERROR, "could not add new bloom tuple to empty page");
343  }
344 
345  /* Reset notFullPage array to contain just this new page */
346  metaData->nStart = 0;
347  metaData->nEnd = 1;
348  metaData->notFullPage[0] = BufferGetBlockNumber(buffer);
349 
350  /* Apply the changes, clean up, and exit */
351  GenericXLogFinish(state);
352 
353  UnlockReleaseBuffer(buffer);
354  UnlockReleaseBuffer(metaBuffer);
355 
356  MemoryContextSwitchTo(oldCtx);
357  MemoryContextDelete(insertCtx);
358 
359  return false;
360 }
#define BLOOM_METAPAGE_BLKNO
Definition: bloom.h:77
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
#define BloomPageIsDeleted(page)
Definition: bloom.h:63
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
void initBloomState(BloomState *state, Relation index)
Definition: blutils.c:153
uint16 nEnd
Definition: bloom.h:124
Buffer BloomNewBuffer(Relation index)
Definition: blutils.c:344
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags)
Definition: generic_xlog.c:298
uint16 OffsetNumber
Definition: off.h:24
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
void BloomInitPage(Page page, uint16 flags)
Definition: blutils.c:398
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
bool BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple)
Definition: blutils.c:309
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
FreeBlockNumberArray notFullPage
Definition: bloom.h:126
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BloomPageGetMeta(page)
Definition: bloom.h:135
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#define Assert(condition)
Definition: c.h:676
Definition: regguts.h:298
BloomTuple * BloomFormTuple(BloomState *state, ItemPointer iptr, Datum *values, bool *isnull)
Definition: blutils.c:284
XLogRecPtr GenericXLogFinish(GenericXLogState *state)
Definition: generic_xlog.c:336
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define InvalidBlockNumber
Definition: block.h:33
uint16 nStart
Definition: bloom.h:123
static Datum values[MAXATTR]
Definition: bootstrap.c:163
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define PageIsNew(page)
Definition: bufpage.h:225
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
void GenericXLogAbort(GenericXLogState *state)
Definition: generic_xlog.c:447
#define elog
Definition: elog.h:219
int Buffer
Definition: buf.h:23
#define GENERIC_XLOG_FULL_IMAGE
Definition: generic_xlog.h:26
GenericXLogState * GenericXLogStart(Relation relation)
Definition: generic_xlog.c:270
Pointer Page
Definition: bufpage.h:74
static void bloomBuildCallback ( Relation  index,
HeapTuple  htup,
Datum values,
bool isnull,
bool  tupleIsAlive,
void *  state 
)
static

Definition at line 74 of file blinsert.c.

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

Referenced by blbuild().

76 {
77  BloomBuildState *buildstate = (BloomBuildState *) state;
78  MemoryContext oldCtx;
79  BloomTuple *itup;
80 
81  oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
82 
83  itup = BloomFormTuple(&buildstate->blstate, &htup->t_self, values, isnull);
84 
85  /* Try to add next item to cached page */
86  if (BloomPageAddItem(&buildstate->blstate, buildstate->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, 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 
107  MemoryContextSwitchTo(oldCtx);
108  MemoryContextReset(buildstate->tmpCtx);
109 }
char data[BLCKSZ]
Definition: blinsert.c:38
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
#define ERROR
Definition: elog.h:43
static void flushCachedPage(Relation index, BloomBuildState *buildstate)
Definition: blinsert.c:46
ItemPointerData t_self
Definition: htup.h:65
MemoryContext tmpCtx
Definition: blinsert.c:36
bool BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple)
Definition: blutils.c:309
static void initCachedPage(BloomBuildState *buildstate)
Definition: blinsert.c:63
Definition: regguts.h:298
BloomTuple * BloomFormTuple(BloomState *state, ItemPointer iptr, Datum *values, bool *isnull)
Definition: blutils.c:284
static Datum values[MAXATTR]
Definition: bootstrap.c:163
BloomState blstate
Definition: blinsert.c:35
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
static void flushCachedPage ( Relation  index,
BloomBuildState buildstate 
)
static

Definition at line 46 of file blinsert.c.

References BloomNewBuffer(), buffer, BloomBuildState::data, GENERIC_XLOG_FULL_IMAGE, GenericXLogFinish(), GenericXLogRegisterBuffer(), GenericXLogStart(), and UnlockReleaseBuffer().

Referenced by blbuild(), and bloomBuildCallback().

47 {
48  Page page;
49  Buffer buffer = BloomNewBuffer(index);
51 
52  state = GenericXLogStart(index);
54  memcpy(page, buildstate->data, BLCKSZ);
55  GenericXLogFinish(state);
56  UnlockReleaseBuffer(buffer);
57 }
Buffer BloomNewBuffer(Relation index)
Definition: blutils.c:344
char data[BLCKSZ]
Definition: blinsert.c:38
Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags)
Definition: generic_xlog.c:298
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
Definition: regguts.h:298
XLogRecPtr GenericXLogFinish(GenericXLogState *state)
Definition: generic_xlog.c:336
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
int Buffer
Definition: buf.h:23
#define GENERIC_XLOG_FULL_IMAGE
Definition: generic_xlog.h:26
GenericXLogState * GenericXLogStart(Relation relation)
Definition: generic_xlog.c:270
Pointer Page
Definition: bufpage.h:74
static void initCachedPage ( BloomBuildState buildstate)
static

Definition at line 63 of file blinsert.c.

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

Referenced by blbuild(), and bloomBuildCallback().

64 {
65  memset(buildstate->data, 0, BLCKSZ);
66  BloomInitPage(buildstate->data, 0);
67  buildstate->count = 0;
68 }
char data[BLCKSZ]
Definition: blinsert.c:38
void BloomInitPage(Page page, uint16 flags)
Definition: blutils.c:398

Variable Documentation

PG_MODULE_MAGIC

Definition at line 27 of file blinsert.c.