/* * Per-tuple callback from IndexBuildHeapScan. */ static void bloomBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state) { BloomBuildState *buildstate = (BloomBuildState *) state; MemoryContext oldCtx; BloomTuple *itup; oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx); itup = BloomFormTuple(&buildstate->blstate, &htup->t_self, values, isnull); /* Try to add next item to cached page */ if (BloomPageAddItem(&buildstate->blstate, buildstate->data, itup)) { /* Next item was added successfully */ buildstate->count++; } else { /* Cached page is full, flush it out and make a new one */ flushCachedPage(index, buildstate); CHECK_FOR_INTERRUPTS(); initCachedPage(buildstate); if (!BloomPageAddItem(&buildstate->blstate, buildstate->data, itup)) { /* We shouldn't be here since we're inserting to the empty page */ elog(ERROR, "could not add new bloom tuple to empty page"); } /* Next item was added successfully */ buildstate->count++; } /* Update total tuple count */ buildstate->indtuples += 1; MemoryContextSwitchTo(oldCtx); MemoryContextReset(buildstate->tmpCtx); }
/* * Build a new bloom index. */ IndexBuildResult * blbuild(Relation heap, Relation index, IndexInfo *indexInfo) { IndexBuildResult *result; double reltuples; BloomBuildState buildstate; if (RelationGetNumberOfBlocks(index) != 0) elog(ERROR, "index \"%s\" already contains data", RelationGetRelationName(index)); /* Initialize the meta page */ BloomInitMetapage(index); /* Initialize the bloom build state */ memset(&buildstate, 0, sizeof(buildstate)); initBloomState(&buildstate.blstate, index); buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext, "Bloom build temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); initCachedPage(&buildstate); /* Do the heap scan */ reltuples = IndexBuildHeapScan(heap, index, indexInfo, true, bloomBuildCallback, (void *) &buildstate); /* * There are could be some items in cached page. Flush this page * if needed. */ if (buildstate.count > 0) flushCachedPage(index, &buildstate); MemoryContextDelete(buildstate.tmpCtx); result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult)); result->heap_tuples = result->index_tuples = reltuples; return result; }