#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; }