PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
blinsert.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/generic_xlog.h"
#include "access/tableam.h"
#include "bloom.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "storage/bufmgr.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

 PG_MODULE_MAGIC_EXT (.name="bloom",.version=PG_VERSION)
 
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)
 

Function Documentation

◆ blbuild()

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

Definition at line 122 of file blinsert.c.

123{
124 IndexBuildResult *result;
125 double reltuples;
126 BloomBuildState buildstate;
127
129 elog(ERROR, "index \"%s\" already contains data",
131
132 /* Initialize the meta page */
134
135 /* Initialize the bloom build state */
136 memset(&buildstate, 0, sizeof(buildstate));
137 initBloomState(&buildstate.blstate, index);
139 "Bloom build temporary context",
141 initCachedPage(&buildstate);
142
143 /* Do the heap scan */
144 reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
145 bloomBuildCallback, &buildstate,
146 NULL);
147
148 /* Flush last page if needed (it will be, unless heap was empty) */
149 if (buildstate.count > 0)
150 flushCachedPage(index, &buildstate);
151
152 MemoryContextDelete(buildstate.tmpCtx);
153
154 result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
155 result->heap_tuples = reltuples;
156 result->index_tuples = buildstate.indtuples;
157
158 return result;
159}
static void initCachedPage(BloomBuildState *buildstate)
Definition: blinsert.c:65
static void flushCachedPage(Relation index, BloomBuildState *buildstate)
Definition: blinsert.c:48
static void bloomBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: blinsert.c:75
void BloomInitMetapage(Relation index, ForkNumber forknum)
Definition: blutils.c:451
void initBloomState(BloomState *state, Relation index)
Definition: blutils.c:166
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:283
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void * palloc(Size size)
Definition: mcxt.c:1943
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
#define RelationGetRelationName(relation)
Definition: rel.h:550
@ MAIN_FORKNUM
Definition: relpath.h:58
int64 indtuples
Definition: blinsert.c:37
BloomState blstate
Definition: blinsert.c:36
MemoryContext tmpCtx
Definition: blinsert.c:38
double heap_tuples
Definition: genam.h:55
double index_tuples
Definition: genam.h:56
Definition: type.h:96
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:1735

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 165 of file blinsert.c.

166{
167 /* Initialize the meta page */
169}
@ INIT_FORKNUM
Definition: relpath.h:61

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 175 of file blinsert.c.

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

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

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 65 of file blinsert.c.

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

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

Referenced by blbuild(), and bloomBuildCallback().

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "bloom",
version = PG_VERSION 
)