Fix another palloc in critical section.

Also add a regression test for a GIN index with enough items with the same
key, so that a GIN posting tree gets created. Apparently none of the
existing GIN tests were large enough for that.

This code is new, no backpatching required.
This commit is contained in:
Heikki Linnakangas 2014-04-05 22:02:28 +03:00
parent 6862ca6970
commit ffbba6ee12
3 changed files with 48 additions and 15 deletions

View File

@ -1706,22 +1706,16 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
{ {
BlockNumber blkno; BlockNumber blkno;
Buffer buffer; Buffer buffer;
Page tmppage;
Page page; Page page;
Pointer ptr; Pointer ptr;
int nrootitems; int nrootitems;
int rootsize; int rootsize;
/* /* Construct the new root page in memory first. */
* Create the root page. tmppage = (Page) palloc(BLCKSZ);
*/ GinInitPage(tmppage, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
buffer = GinNewBuffer(index); GinPageGetOpaque(tmppage)->rightlink = InvalidBlockNumber;
page = BufferGetPage(buffer);
blkno = BufferGetBlockNumber(buffer);
START_CRIT_SECTION();
GinInitPage(page, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
GinPageGetOpaque(page)->rightlink = InvalidBlockNumber;
/* /*
* Write as many of the items to the root page as fit. In segments * Write as many of the items to the root page as fit. In segments
@ -1729,7 +1723,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
*/ */
nrootitems = 0; nrootitems = 0;
rootsize = 0; rootsize = 0;
ptr = (Pointer) GinDataLeafPageGetPostingList(page); ptr = (Pointer) GinDataLeafPageGetPostingList(tmppage);
while (nrootitems < nitems) while (nrootitems < nitems)
{ {
GinPostingList *segment; GinPostingList *segment;
@ -1750,10 +1744,19 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
nrootitems += npacked; nrootitems += npacked;
pfree(segment); pfree(segment);
} }
GinDataLeafPageSetPostingListSize(page, rootsize); GinDataLeafPageSetPostingListSize(tmppage, rootsize);
MarkBufferDirty(buffer);
elog(DEBUG2, "created GIN posting tree with %d items", nrootitems); /*
* All set. Get a new physical page, and copy the in-memory page to it.
*/
buffer = GinNewBuffer(index);
page = BufferGetPage(buffer);
blkno = BufferGetBlockNumber(buffer);
START_CRIT_SECTION();
PageRestoreTempPage(tmppage, page);
MarkBufferDirty(buffer);
if (RelationNeedsWAL(index)) if (RelationNeedsWAL(index))
{ {
@ -1787,6 +1790,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
if (buildStats) if (buildStats)
buildStats->nDataPages++; buildStats->nDataPages++;
elog(DEBUG2, "created GIN posting tree with %d items", nrootitems);
/* /*
* Add any remaining TIDs to the newly-created posting tree. * Add any remaining TIDs to the newly-created posting tree.
*/ */

View File

@ -2221,6 +2221,20 @@ RESET enable_seqscan;
RESET enable_indexscan; RESET enable_indexscan;
RESET enable_bitmapscan; RESET enable_bitmapscan;
-- --
-- Try a GIN index with a lot of items with same key. (GIN creates a posting
-- tree when there are enough duplicates)
--
CREATE TABLE array_gin_test (a int[]);
INSERT INTO array_gin_test SELECT ARRAY[1, g%5, g] FROM generate_series(1, 10000) g;
CREATE INDEX array_gin_test_idx ON array_gin_test USING gin (a);
SELECT COUNT(*) FROM array_gin_test WHERE a @> '{2}';
count
-------
2000
(1 row)
DROP TABLE array_gin_test;
--
-- HASH -- HASH
-- --
CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops); CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops);

View File

@ -636,6 +636,20 @@ RESET enable_seqscan;
RESET enable_indexscan; RESET enable_indexscan;
RESET enable_bitmapscan; RESET enable_bitmapscan;
--
-- Try a GIN index with a lot of items with same key. (GIN creates a posting
-- tree when there are enough duplicates)
--
CREATE TABLE array_gin_test (a int[]);
INSERT INTO array_gin_test SELECT ARRAY[1, g%5, g] FROM generate_series(1, 10000) g;
CREATE INDEX array_gin_test_idx ON array_gin_test USING gin (a);
SELECT COUNT(*) FROM array_gin_test WHERE a @> '{2}';
DROP TABLE array_gin_test;
-- --
-- HASH -- HASH
-- --