#include "postgres.h"#include "access/gin_private.h"#include "utils/datum.h"#include "utils/memutils.h"
Go to the source code of this file.
Defines | |
| #define | DEF_NENTRY 2048 |
| #define | DEF_NPTR 5 |
Functions | |
| static void | ginCombineData (RBNode *existing, const RBNode *newdata, void *arg) |
| static int | cmpEntryAccumulator (const RBNode *a, const RBNode *b, void *arg) |
| static RBNode * | ginAllocEntryAccumulator (void *arg) |
| void | ginInitBA (BuildAccumulator *accum) |
| static Datum | getDatumCopy (BuildAccumulator *accum, OffsetNumber attnum, Datum value) |
| static void | ginInsertBAEntry (BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum key, GinNullCategory category) |
| void | ginInsertBAEntries (BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries) |
| static int | qsortCompareItemPointers (const void *a, const void *b) |
| void | ginBeginBAScan (BuildAccumulator *accum) |
| ItemPointerData * | ginGetBAEntry (BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n) |
| #define DEF_NENTRY 2048 |
Definition at line 22 of file ginbulk.c.
Referenced by ginAllocEntryAccumulator().
Definition at line 64 of file ginbulk.c.
References GinEntryAccumulator::attnum, GinEntryAccumulator::category, ginCompareAttEntries(), BuildAccumulator::ginstate, and GinEntryAccumulator::key.
Referenced by ginInitBA().
{
const GinEntryAccumulator *ea = (const GinEntryAccumulator *) a;
const GinEntryAccumulator *eb = (const GinEntryAccumulator *) b;
BuildAccumulator *accum = (BuildAccumulator *) arg;
return ginCompareAttEntries(accum->ginstate,
ea->attnum, ea->key, ea->category,
eb->attnum, eb->key, eb->category);
}
| static Datum getDatumCopy | ( | BuildAccumulator * | accum, | |
| OffsetNumber | attnum, | |||
| Datum | value | |||
| ) | [static] |
Definition at line 120 of file ginbulk.c.
References BuildAccumulator::allocatedMemory, tupleDesc::attrs, datumCopy(), DatumGetPointer, GetMemoryChunkSpace(), BuildAccumulator::ginstate, and GinState::origTupdesc.
Referenced by ginInsertBAEntry().
{
Form_pg_attribute att = accum->ginstate->origTupdesc->attrs[attnum - 1];
Datum res;
if (att->attbyval)
res = value;
else
{
res = datumCopy(value, false, att->attlen);
accum->allocatedMemory += GetMemoryChunkSpace(DatumGetPointer(res));
}
return res;
}
| static RBNode* ginAllocEntryAccumulator | ( | void * | arg | ) | [static] |
Definition at line 77 of file ginbulk.c.
References BuildAccumulator::allocatedMemory, DEF_NENTRY, BuildAccumulator::eas_used, BuildAccumulator::entryallocator, GetMemoryChunkSpace(), NULL, and palloc().
Referenced by ginInitBA().
{
BuildAccumulator *accum = (BuildAccumulator *) arg;
GinEntryAccumulator *ea;
/*
* Allocate memory by rather big chunks to decrease overhead. We have no
* need to reclaim RBNodes individually, so this costs nothing.
*/
if (accum->entryallocator == NULL || accum->eas_used >= DEF_NENTRY)
{
accum->entryallocator = palloc(sizeof(GinEntryAccumulator) * DEF_NENTRY);
accum->allocatedMemory += GetMemoryChunkSpace(accum->entryallocator);
accum->eas_used = 0;
}
/* Allocate new RBNode from current chunk */
ea = accum->entryallocator + accum->eas_used;
accum->eas_used++;
return (RBNode *) ea;
}
| void ginBeginBAScan | ( | BuildAccumulator * | accum | ) |
Definition at line 248 of file ginbulk.c.
References LeftRightWalk, rb_begin_iterate(), and BuildAccumulator::tree.
Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().
{
rb_begin_iterate(accum->tree, LeftRightWalk);
}
Definition at line 28 of file ginbulk.c.
References BuildAccumulator::allocatedMemory, Assert, GinEntryAccumulator::count, FALSE, GetMemoryChunkSpace(), ginCompareItemPointers(), GinEntryAccumulator::list, GinEntryAccumulator::maxcount, repalloc(), and GinEntryAccumulator::shouldSort.
Referenced by ginInitBA().
{
GinEntryAccumulator *eo = (GinEntryAccumulator *) existing;
const GinEntryAccumulator *en = (const GinEntryAccumulator *) newdata;
BuildAccumulator *accum = (BuildAccumulator *) arg;
/*
* Note this code assumes that newdata contains only one itempointer.
*/
if (eo->count >= eo->maxcount)
{
accum->allocatedMemory -= GetMemoryChunkSpace(eo->list);
eo->maxcount *= 2;
eo->list = (ItemPointerData *)
repalloc(eo->list, sizeof(ItemPointerData) * eo->maxcount);
accum->allocatedMemory += GetMemoryChunkSpace(eo->list);
}
/* If item pointers are not ordered, they will need to be sorted later */
if (eo->shouldSort == FALSE)
{
int res;
res = ginCompareItemPointers(eo->list + eo->count - 1, en->list);
Assert(res != 0);
if (res > 0)
eo->shouldSort = TRUE;
}
eo->list[eo->count] = en->list[0];
eo->count++;
}
| ItemPointerData* ginGetBAEntry | ( | BuildAccumulator * | accum, | |
| OffsetNumber * | attnum, | |||
| Datum * | key, | |||
| GinNullCategory * | category, | |||
| uint32 * | n | |||
| ) |
Definition at line 259 of file ginbulk.c.
References Assert, GinEntryAccumulator::attnum, GinEntryAccumulator::category, GinEntryAccumulator::count, GinEntryAccumulator::key, GinEntryAccumulator::list, sort-test::list, NULL, qsort, qsortCompareItemPointers(), rb_iterate(), GinEntryAccumulator::shouldSort, and BuildAccumulator::tree.
Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().
{
GinEntryAccumulator *entry;
ItemPointerData *list;
entry = (GinEntryAccumulator *) rb_iterate(accum->tree);
if (entry == NULL)
return NULL; /* no more entries */
*attnum = entry->attnum;
*key = entry->key;
*category = entry->category;
list = entry->list;
*n = entry->count;
Assert(list != NULL && entry->count > 0);
if (entry->shouldSort && entry->count > 1)
qsort(list, entry->count, sizeof(ItemPointerData),
qsortCompareItemPointers);
return list;
}
| void ginInitBA | ( | BuildAccumulator * | accum | ) |
Definition at line 101 of file ginbulk.c.
References BuildAccumulator::allocatedMemory, cmpEntryAccumulator(), BuildAccumulator::eas_used, BuildAccumulator::entryallocator, ginAllocEntryAccumulator(), ginCombineData(), NULL, rb_create(), and BuildAccumulator::tree.
Referenced by ginbuild(), ginBuildCallback(), and ginInsertCleanup().
{
/* accum->ginstate is intentionally not set here */
accum->allocatedMemory = 0;
accum->entryallocator = NULL;
accum->eas_used = 0;
accum->tree = rb_create(sizeof(GinEntryAccumulator),
cmpEntryAccumulator,
ginCombineData,
ginAllocEntryAccumulator,
NULL, /* no freefunc needed */
(void *) accum);
}
| void ginInsertBAEntries | ( | BuildAccumulator * | accum, | |
| ItemPointer | heapptr, | |||
| OffsetNumber | attnum, | |||
| Datum * | entries, | |||
| GinNullCategory * | categories, | |||
| int32 | nentries | |||
| ) |
Definition at line 201 of file ginbulk.c.
References Assert, FirstOffsetNumber, ginInsertBAEntry(), i, and ItemPointerIsValid.
Referenced by ginHeapTupleBulkInsert(), and processPendingPage().
{
uint32 step = nentries;
if (nentries <= 0)
return;
Assert(ItemPointerIsValid(heapptr) && attnum >= FirstOffsetNumber);
/*
* step will contain largest power of 2 and <= nentries
*/
step |= (step >> 1);
step |= (step >> 2);
step |= (step >> 4);
step |= (step >> 8);
step |= (step >> 16);
step >>= 1;
step++;
while (step > 0)
{
int i;
for (i = step - 1; i < nentries && i >= 0; i += step << 1 /* *2 */ )
ginInsertBAEntry(accum, heapptr, attnum,
entries[i], categories[i]);
step >>= 1; /* /2 */
}
}
| static void ginInsertBAEntry | ( | BuildAccumulator * | accum, | |
| ItemPointer | heapptr, | |||
| OffsetNumber | attnum, | |||
| Datum | key, | |||
| GinNullCategory | category | |||
| ) | [static] |
Definition at line 139 of file ginbulk.c.
References BuildAccumulator::allocatedMemory, GinEntryAccumulator::attnum, GinEntryAccumulator::category, GinEntryAccumulator::count, getDatumCopy(), GetMemoryChunkSpace(), GIN_CAT_NORM_KEY, GinEntryAccumulator::key, GinEntryAccumulator::list, GinEntryAccumulator::maxcount, palloc(), rb_insert(), GinEntryAccumulator::shouldSort, and BuildAccumulator::tree.
Referenced by ginInsertBAEntries().
{
GinEntryAccumulator eatmp;
GinEntryAccumulator *ea;
bool isNew;
/*
* For the moment, fill only the fields of eatmp that will be looked at by
* cmpEntryAccumulator or ginCombineData.
*/
eatmp.attnum = attnum;
eatmp.key = key;
eatmp.category = category;
/* temporarily set up single-entry itempointer list */
eatmp.list = heapptr;
ea = (GinEntryAccumulator *) rb_insert(accum->tree, (RBNode *) &eatmp,
&isNew);
if (isNew)
{
/*
* Finish initializing new tree entry, including making permanent
* copies of the datum (if it's not null) and itempointer.
*/
if (category == GIN_CAT_NORM_KEY)
ea->key = getDatumCopy(accum, attnum, key);
ea->maxcount = DEF_NPTR;
ea->count = 1;
ea->shouldSort = FALSE;
ea->list =
(ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR);
ea->list[0] = *heapptr;
accum->allocatedMemory += GetMemoryChunkSpace(ea->list);
}
else
{
/*
* ginCombineData did everything needed.
*/
}
}
| static int qsortCompareItemPointers | ( | const void * | a, | |
| const void * | b | |||
| ) | [static] |
Definition at line 237 of file ginbulk.c.
References Assert, and ginCompareItemPointers().
Referenced by ginGetBAEntry().
{
int res = ginCompareItemPointers((ItemPointer) a, (ItemPointer) b);
/* Assert that there are no equal item pointers being sorted */
Assert(res != 0);
return res;
}
1.7.1