Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

ginbulk.c File Reference

#include "postgres.h"
#include "access/gin_private.h"
#include "utils/datum.h"
#include "utils/memutils.h"
Include dependency graph for ginbulk.c:

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 RBNodeginAllocEntryAccumulator (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)
ItemPointerDataginGetBAEntry (BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)

Define Documentation

#define DEF_NENTRY   2048

Definition at line 22 of file ginbulk.c.

Referenced by ginAllocEntryAccumulator().

#define DEF_NPTR   5

Definition at line 23 of file ginbulk.c.


Function Documentation

static int cmpEntryAccumulator ( const RBNode a,
const RBNode b,
void *  arg 
) [static]
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  ) 
static void ginCombineData ( RBNode existing,
const RBNode newdata,
void *  arg 
) [static]

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