diff options
Diffstat (limited to 'src/backend/access/gin')
| -rw-r--r-- | src/backend/access/gin/ginbtree.c | 16 | ||||
| -rw-r--r-- | src/backend/access/gin/ginbulk.c | 134 | ||||
| -rw-r--r-- | src/backend/access/gin/ginentrypage.c | 6 | ||||
| -rw-r--r-- | src/backend/access/gin/ginfast.c | 4 | ||||
| -rw-r--r-- | src/backend/access/gin/gininsert.c | 5 |
5 files changed, 98 insertions, 67 deletions
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c index bb150a46893..ed3286651fc 100644 --- a/src/backend/access/gin/ginbtree.c +++ b/src/backend/access/gin/ginbtree.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginbtree.c,v 1.15 2010/01/02 16:57:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginbtree.c,v 1.15.6.1 2010/08/01 02:12:51 tgl Exp $ *------------------------------------------------------------------------- */ @@ -267,6 +267,8 @@ findParents(GinBtree btree, GinBtreeStack *stack, /* * Insert value (stored in GinBtree) to tree described by stack + * + * NB: the passed-in stack is freed, as though by freeGinBtreeStack. */ void ginInsertValue(GinBtree btree, GinBtreeStack *stack) @@ -308,10 +310,11 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack) PageSetTLI(page, ThisTimeLineID); } - UnlockReleaseBuffer(stack->buffer); + LockBuffer(stack->buffer, GIN_UNLOCK); END_CRIT_SECTION(); - freeGinBtreeStack(stack->parent); + freeGinBtreeStack(stack); + return; } else @@ -325,7 +328,6 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack) */ newlpage = btree->splitPage(btree, stack->buffer, rbuffer, stack->off, &rdata); - ((ginxlogSplit *) (rdata->data))->rootBlkno = rootBlkno; parent = stack->parent; @@ -341,7 +343,6 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack) ((ginxlogSplit *) (rdata->data))->isRootSplit = TRUE; ((ginxlogSplit *) (rdata->data))->rrlink = InvalidBlockNumber; - page = BufferGetPage(stack->buffer); lpage = BufferGetPage(lbuffer); rpage = BufferGetPage(rbuffer); @@ -375,10 +376,11 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack) UnlockReleaseBuffer(rbuffer); UnlockReleaseBuffer(lbuffer); - UnlockReleaseBuffer(stack->buffer); - + LockBuffer(stack->buffer, GIN_UNLOCK); END_CRIT_SECTION(); + freeGinBtreeStack(stack); + return; } else diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c index bb726e69f4c..094479ccb18 100644 --- a/src/backend/access/gin/ginbulk.c +++ b/src/backend/access/gin/ginbulk.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginbulk.c,v 1.19 2010/02/26 02:00:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginbulk.c,v 1.19.4.1 2010/08/01 02:12:51 tgl Exp $ *------------------------------------------------------------------------- */ @@ -19,17 +19,21 @@ #include "utils/memutils.h" -#define DEF_NENTRY 2048 -#define DEF_NPTR 4 +#define DEF_NENTRY 2048 /* EntryAccumulator allocation quantum */ +#define DEF_NPTR 5 /* ItemPointer initial allocation quantum */ -static void * -ginAppendData(void *old, void *new, void *arg) -{ - EntryAccumulator *eo = (EntryAccumulator *) old, - *en = (EntryAccumulator *) new; +/* Combiner function for rbtree.c */ +static void +ginCombineData(RBNode *existing, const RBNode *newdata, void *arg) +{ + EntryAccumulator *eo = (EntryAccumulator *) existing; + const EntryAccumulator *en = (const EntryAccumulator *) newdata; BuildAccumulator *accum = (BuildAccumulator *) arg; + /* + * Note this code assumes that newdata contains only one itempointer. + */ if (eo->number >= eo->length) { accum->allocatedMemory -= GetMemoryChunkSpace(eo->list); @@ -53,29 +57,57 @@ ginAppendData(void *old, void *new, void *arg) eo->list[eo->number] = en->list[0]; eo->number++; - - return old; } +/* Comparator function for rbtree.c */ static int -cmpEntryAccumulator(const void *a, const void *b, void *arg) +cmpEntryAccumulator(const RBNode *a, const RBNode *b, void *arg) { - EntryAccumulator *ea = (EntryAccumulator *) a; - EntryAccumulator *eb = (EntryAccumulator *) b; + const EntryAccumulator *ea = (const EntryAccumulator *) a; + const EntryAccumulator *eb = (const EntryAccumulator *) b; BuildAccumulator *accum = (BuildAccumulator *) arg; return compareAttEntries(accum->ginstate, ea->attnum, ea->value, eb->attnum, eb->value); } +/* Allocator function for rbtree.c */ +static RBNode * +ginAllocEntryAccumulator(void *arg) +{ + BuildAccumulator *accum = (BuildAccumulator *) arg; + EntryAccumulator *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->length >= DEF_NENTRY) + { + accum->entryallocator = palloc(sizeof(EntryAccumulator) * DEF_NENTRY); + accum->allocatedMemory += GetMemoryChunkSpace(accum->entryallocator); + accum->length = 0; + } + + /* Allocate new RBNode from current chunk */ + ea = accum->entryallocator + accum->length; + accum->length++; + + return (RBNode *) ea; +} + void ginInitBA(BuildAccumulator *accum) { accum->allocatedMemory = 0; + accum->length = 0; accum->entryallocator = NULL; - accum->tree = rb_create(cmpEntryAccumulator, ginAppendData, NULL, accum); - accum->iterator = NULL; - accum->tmpList = NULL; + accum->tree = rb_create(sizeof(EntryAccumulator), + cmpEntryAccumulator, + ginCombineData, + ginAllocEntryAccumulator, + NULL, /* no freefunc needed */ + (void *) accum); } /* @@ -104,55 +136,41 @@ getDatumCopy(BuildAccumulator *accum, OffsetNumber attnum, Datum value) static void ginInsertEntry(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum entry) { - EntryAccumulator *key, - *ea; + EntryAccumulator key; + EntryAccumulator *ea; + bool isNew; /* - * Allocate memory by rather big chunk to decrease overhead, we don't keep - * pointer to previously allocated chunks because they will free by - * MemoryContextReset() call. + * For the moment, fill only the fields of key that will be looked at + * by cmpEntryAccumulator or ginCombineData. */ - if (accum->entryallocator == NULL || accum->length >= DEF_NENTRY) - { - accum->entryallocator = palloc(sizeof(EntryAccumulator) * DEF_NENTRY); - accum->allocatedMemory += GetMemoryChunkSpace(accum->entryallocator); - accum->length = 0; - } + key.attnum = attnum; + key.value = entry; + /* temporarily set up single-entry itempointer list */ + key.list = heapptr; - /* "Allocate" new key in chunk */ - key = accum->entryallocator + accum->length; - accum->length++; + ea = (EntryAccumulator *) rb_insert(accum->tree, (RBNode *) &key, &isNew); - key->attnum = attnum; - key->value = entry; - /* To prevent multiple palloc/pfree cycles, we reuse array */ - if (accum->tmpList == NULL) - accum->tmpList = - (ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR); - key->list = accum->tmpList; - key->list[0] = *heapptr; - - ea = rb_insert(accum->tree, key); - - if (ea == NULL) + if (isNew) { /* - * The key has been inserted, so continue initialization. + * Finish initializing new tree entry, including making permanent + * copies of the datum and itempointer. */ - key->value = getDatumCopy(accum, attnum, entry); - key->length = DEF_NPTR; - key->number = 1; - key->shouldSort = FALSE; - accum->allocatedMemory += GetMemoryChunkSpace(key->list); - accum->tmpList = NULL; + ea->value = getDatumCopy(accum, attnum, entry); + ea->length = DEF_NPTR; + ea->number = 1; + ea->shouldSort = FALSE; + ea->list = + (ItemPointerData *) palloc(sizeof(ItemPointerData) * DEF_NPTR); + ea->list[0] = *heapptr; + accum->allocatedMemory += GetMemoryChunkSpace(ea->list); } else { /* - * The key has been appended, so "free" allocated key by decrementing - * chunk's counter. + * ginCombineData did everything needed. */ - accum->length--; } } @@ -214,16 +232,20 @@ qsortCompareItemPointers(const void *a, const void *b) return res; } +/* Prepare to read out the rbtree contents using ginGetEntry */ +void +ginBeginBAScan(BuildAccumulator *accum) +{ + rb_begin_iterate(accum->tree, LeftRightWalk); +} + ItemPointerData * ginGetEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *value, uint32 *n) { EntryAccumulator *entry; ItemPointerData *list; - if (accum->iterator == NULL) - accum->iterator = rb_begin_iterate(accum->tree, LeftRightWalk); - - entry = rb_iterate(accum->iterator); + entry = (EntryAccumulator *) rb_iterate(accum->tree); if (entry == NULL) return NULL; diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index 6d307c8d59a..1896e09a544 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.24 2010/02/26 02:00:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.24.4.1 2010/08/01 02:12:51 tgl Exp $ *------------------------------------------------------------------------- */ @@ -615,7 +615,7 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR } /* - * return newly allocate rightmost tuple + * return newly allocated rightmost tuple */ IndexTuple ginPageGetLinkItup(Buffer buf) @@ -646,10 +646,12 @@ entryFillRoot(GinBtree btree, Buffer root, Buffer lbuf, Buffer rbuf) itup = ginPageGetLinkItup(lbuf); if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber) elog(ERROR, "failed to add item to index root page"); + pfree(itup); itup = ginPageGetLinkItup(rbuf); if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber) elog(ERROR, "failed to add item to index root page"); + pfree(itup); } void diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index f8e0b5ad40f..7aaab3a132e 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.7 2010/02/11 14:29:50 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.7.6.1 2010/08/01 02:12:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -786,6 +786,7 @@ ginInsertCleanup(Relation index, GinState *ginstate, * significant amount of time - so, run it without locking pending * list. */ + ginBeginBAScan(&accum); while ((list = ginGetEntry(&accum, &attnum, &entry, &nlist)) != NULL) { ginEntryInsert(index, ginstate, attnum, entry, list, nlist, FALSE); @@ -820,6 +821,7 @@ ginInsertCleanup(Relation index, GinState *ginstate, ginInitBA(&accum); processPendingPage(&accum, &datums, page, maxoff + 1); + ginBeginBAScan(&accum); while ((list = ginGetEntry(&accum, &attnum, &entry, &nlist)) != NULL) ginEntryInsert(index, ginstate, attnum, entry, list, nlist, FALSE); } diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index e2a5e8b0135..951d6166a00 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.26 2010/02/11 14:29:50 teodor Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.26.6.1 2010/08/01 02:12:51 tgl Exp $ *------------------------------------------------------------------------- */ @@ -176,6 +176,7 @@ ginEntryInsert(Relation index, GinState *ginstate, gdi = prepareScanPostingTree(index, rootPostingTree, FALSE); gdi->btree.isBuild = isBuild; insertItemPointer(gdi, items, nitem); + pfree(gdi); return; } @@ -254,6 +255,7 @@ ginBuildCallback(Relation index, HeapTuple htup, Datum *values, uint32 nlist; OffsetNumber attnum; + ginBeginBAScan(&buildstate->accum); while ((list = ginGetEntry(&buildstate->accum, &attnum, &entry, &nlist)) != NULL) { /* there could be many entries, so be willing to abort here */ @@ -360,6 +362,7 @@ ginbuild(PG_FUNCTION_ARGS) /* dump remaining entries to the index */ oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx); + ginBeginBAScan(&buildstate.accum); while ((list = ginGetEntry(&buildstate.accum, &attnum, &entry, &nlist)) != NULL) { /* there could be many entries, so be willing to abort here */ |
