]> granicus.if.org Git - postgresql/commitdiff
Fix another palloc in critical section.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sat, 5 Apr 2014 19:02:28 +0000 (22:02 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sat, 5 Apr 2014 19:15:58 +0000 (22:15 +0300)
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.

src/backend/access/gin/gindatapage.c
src/test/regress/expected/create_index.out
src/test/regress/sql/create_index.sql

index 21ce79fc0b12fbde4a0e3b4e27748361b8802bbe..70801bd05cbecdb03ed2edaa5bc8a4b95f14faa2 100644 (file)
@@ -1706,22 +1706,16 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
 {
        BlockNumber blkno;
        Buffer          buffer;
+       Page            tmppage;
        Page            page;
        Pointer         ptr;
        int                     nrootitems;
        int                     rootsize;
 
-       /*
-        * Create the root page.
-        */
-       buffer = GinNewBuffer(index);
-       page = BufferGetPage(buffer);
-       blkno = BufferGetBlockNumber(buffer);
-
-       START_CRIT_SECTION();
-
-       GinInitPage(page, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
-       GinPageGetOpaque(page)->rightlink = InvalidBlockNumber;
+       /* Construct the new root page in memory first. */
+       tmppage = (Page) palloc(BLCKSZ);
+       GinInitPage(tmppage, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
+       GinPageGetOpaque(tmppage)->rightlink = InvalidBlockNumber;
 
        /*
         * 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;
        rootsize = 0;
-       ptr = (Pointer) GinDataLeafPageGetPostingList(page);
+       ptr = (Pointer) GinDataLeafPageGetPostingList(tmppage);
        while (nrootitems < nitems)
        {
                GinPostingList *segment;
@@ -1750,10 +1744,19 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
                nrootitems += npacked;
                pfree(segment);
        }
-       GinDataLeafPageSetPostingListSize(page, rootsize);
-       MarkBufferDirty(buffer);
+       GinDataLeafPageSetPostingListSize(tmppage, rootsize);
 
-       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))
        {
@@ -1787,6 +1790,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
        if (buildStats)
                buildStats->nDataPages++;
 
+       elog(DEBUG2, "created GIN posting tree with %d items", nrootitems);
+
        /*
         * Add any remaining TIDs to the newly-created posting tree.
         */
index d10253b9e9b94220e2a18ad6344fe6113d327a87..f13b4f8a08d15b7de9e66b272f4377d9f94fcdd8 100644 (file)
@@ -2221,6 +2221,20 @@ RESET enable_seqscan;
 RESET enable_indexscan;
 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
 --
 CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops);
index 8ac1d1d280f6516856ca0884f9ba5d950092d232..cd5c58d468cf8745caa1d00a1453d1daabb496fd 100644 (file)
@@ -636,6 +636,20 @@ RESET enable_seqscan;
 RESET enable_indexscan;
 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
 --