LCOV - differential code coverage report
Current view: top level - src/backend/access/nbtree - nbtsort.c (source / functions) Coverage Total Hit UNC UIC UBC GIC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 97.0 % 568 551 17 24 527 36
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 22 22 7 15 2
Baseline: 16@8cea358b128 Branches: 72.6 % 252 183 2 1 66 1 2 180
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 24 24 24
(240..) days: 96.9 % 544 527 17 527
Function coverage date bins:
[..60] days: 100.0 % 2 2 2
(240..) days: 100.0 % 20 20 5 15
Branch coverage date bins:
[..60] days: 50.0 % 4 2 2 2
(240..) days: 73.0 % 248 181 1 66 1 180

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nbtsort.c
                                  4                 :                :  *      Build a btree from sorted input by loading leaf pages sequentially.
                                  5                 :                :  *
                                  6                 :                :  * NOTES
                                  7                 :                :  *
                                  8                 :                :  * We use tuplesort.c to sort the given index tuples into order.
                                  9                 :                :  * Then we scan the index tuples in order and build the btree pages
                                 10                 :                :  * for each level.  We load source tuples into leaf-level pages.
                                 11                 :                :  * Whenever we fill a page at one level, we add a link to it to its
                                 12                 :                :  * parent level (starting a new parent level if necessary).  When
                                 13                 :                :  * done, we write out each final page on each level, adding it to
                                 14                 :                :  * its parent level.  When we have only one page on a level, it must be
                                 15                 :                :  * the root -- it can be attached to the btree metapage and we are done.
                                 16                 :                :  *
                                 17                 :                :  * It is not wise to pack the pages entirely full, since then *any*
                                 18                 :                :  * insertion would cause a split (and not only of the leaf page; the need
                                 19                 :                :  * for a split would cascade right up the tree).  The steady-state load
                                 20                 :                :  * factor for btrees is usually estimated at 70%.  We choose to pack leaf
                                 21                 :                :  * pages to the user-controllable fill factor (default 90%) while upper pages
                                 22                 :                :  * are always packed to 70%.  This gives us reasonable density (there aren't
                                 23                 :                :  * many upper pages if the keys are reasonable-size) without risking a lot of
                                 24                 :                :  * cascading splits during early insertions.
                                 25                 :                :  *
                                 26                 :                :  * We use the bulk smgr loading facility to bypass the buffer cache and
                                 27                 :                :  * WAL-log the pages efficiently.
                                 28                 :                :  *
                                 29                 :                :  * This code isn't concerned about the FSM at all. The caller is responsible
                                 30                 :                :  * for initializing that.
                                 31                 :                :  *
                                 32                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                 33                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 34                 :                :  *
                                 35                 :                :  * IDENTIFICATION
                                 36                 :                :  *    src/backend/access/nbtree/nbtsort.c
                                 37                 :                :  *
                                 38                 :                :  *-------------------------------------------------------------------------
                                 39                 :                :  */
                                 40                 :                : 
                                 41                 :                : #include "postgres.h"
                                 42                 :                : 
                                 43                 :                : #include "access/nbtree.h"
                                 44                 :                : #include "access/parallel.h"
                                 45                 :                : #include "access/relscan.h"
                                 46                 :                : #include "access/table.h"
                                 47                 :                : #include "access/xact.h"
                                 48                 :                : #include "access/xloginsert.h"
                                 49                 :                : #include "catalog/index.h"
                                 50                 :                : #include "commands/progress.h"
                                 51                 :                : #include "executor/instrument.h"
                                 52                 :                : #include "miscadmin.h"
                                 53                 :                : #include "pgstat.h"
                                 54                 :                : #include "storage/bulk_write.h"
                                 55                 :                : #include "tcop/tcopprot.h"        /* pgrminclude ignore */
                                 56                 :                : #include "utils/rel.h"
                                 57                 :                : #include "utils/sortsupport.h"
                                 58                 :                : #include "utils/tuplesort.h"
                                 59                 :                : 
                                 60                 :                : 
                                 61                 :                : /* Magic numbers for parallel state sharing */
                                 62                 :                : #define PARALLEL_KEY_BTREE_SHARED       UINT64CONST(0xA000000000000001)
                                 63                 :                : #define PARALLEL_KEY_TUPLESORT          UINT64CONST(0xA000000000000002)
                                 64                 :                : #define PARALLEL_KEY_TUPLESORT_SPOOL2   UINT64CONST(0xA000000000000003)
                                 65                 :                : #define PARALLEL_KEY_QUERY_TEXT         UINT64CONST(0xA000000000000004)
                                 66                 :                : #define PARALLEL_KEY_WAL_USAGE          UINT64CONST(0xA000000000000005)
                                 67                 :                : #define PARALLEL_KEY_BUFFER_USAGE       UINT64CONST(0xA000000000000006)
                                 68                 :                : 
                                 69                 :                : /*
                                 70                 :                :  * DISABLE_LEADER_PARTICIPATION disables the leader's participation in
                                 71                 :                :  * parallel index builds.  This may be useful as a debugging aid.
                                 72                 :                : #undef DISABLE_LEADER_PARTICIPATION
                                 73                 :                :  */
                                 74                 :                : 
                                 75                 :                : /*
                                 76                 :                :  * Status record for spooling/sorting phase.  (Note we may have two of
                                 77                 :                :  * these due to the special requirements for uniqueness-checking with
                                 78                 :                :  * dead tuples.)
                                 79                 :                :  */
                                 80                 :                : typedef struct BTSpool
                                 81                 :                : {
                                 82                 :                :     Tuplesortstate *sortstate;  /* state data for tuplesort.c */
                                 83                 :                :     Relation    heap;
                                 84                 :                :     Relation    index;
                                 85                 :                :     bool        isunique;
                                 86                 :                :     bool        nulls_not_distinct;
                                 87                 :                : } BTSpool;
                                 88                 :                : 
                                 89                 :                : /*
                                 90                 :                :  * Status for index builds performed in parallel.  This is allocated in a
                                 91                 :                :  * dynamic shared memory segment.  Note that there is a separate tuplesort TOC
                                 92                 :                :  * entry, private to tuplesort.c but allocated by this module on its behalf.
                                 93                 :                :  */
                                 94                 :                : typedef struct BTShared
                                 95                 :                : {
                                 96                 :                :     /*
                                 97                 :                :      * These fields are not modified during the sort.  They primarily exist
                                 98                 :                :      * for the benefit of worker processes that need to create BTSpool state
                                 99                 :                :      * corresponding to that used by the leader.
                                100                 :                :      */
                                101                 :                :     Oid         heaprelid;
                                102                 :                :     Oid         indexrelid;
                                103                 :                :     bool        isunique;
                                104                 :                :     bool        nulls_not_distinct;
                                105                 :                :     bool        isconcurrent;
                                106                 :                :     int         scantuplesortstates;
                                107                 :                : 
                                108                 :                :     /*
                                109                 :                :      * workersdonecv is used to monitor the progress of workers.  All parallel
                                110                 :                :      * participants must indicate that they are done before leader can use
                                111                 :                :      * mutable state that workers maintain during scan (and before leader can
                                112                 :                :      * proceed to tuplesort_performsort()).
                                113                 :                :      */
                                114                 :                :     ConditionVariable workersdonecv;
                                115                 :                : 
                                116                 :                :     /*
                                117                 :                :      * mutex protects all fields before heapdesc.
                                118                 :                :      *
                                119                 :                :      * These fields contain status information of interest to B-Tree index
                                120                 :                :      * builds that must work just the same when an index is built in parallel.
                                121                 :                :      */
                                122                 :                :     slock_t     mutex;
                                123                 :                : 
                                124                 :                :     /*
                                125                 :                :      * Mutable state that is maintained by workers, and reported back to
                                126                 :                :      * leader at end of parallel scan.
                                127                 :                :      *
                                128                 :                :      * nparticipantsdone is number of worker processes finished.
                                129                 :                :      *
                                130                 :                :      * reltuples is the total number of input heap tuples.
                                131                 :                :      *
                                132                 :                :      * havedead indicates if RECENTLY_DEAD tuples were encountered during
                                133                 :                :      * build.
                                134                 :                :      *
                                135                 :                :      * indtuples is the total number of tuples that made it into the index.
                                136                 :                :      *
                                137                 :                :      * brokenhotchain indicates if any worker detected a broken HOT chain
                                138                 :                :      * during build.
                                139                 :                :      */
                                140                 :                :     int         nparticipantsdone;
                                141                 :                :     double      reltuples;
                                142                 :                :     bool        havedead;
                                143                 :                :     double      indtuples;
                                144                 :                :     bool        brokenhotchain;
                                145                 :                : 
                                146                 :                :     /*
                                147                 :                :      * ParallelTableScanDescData data follows. Can't directly embed here, as
                                148                 :                :      * implementations of the parallel table scan desc interface might need
                                149                 :                :      * stronger alignment.
                                150                 :                :      */
                                151                 :                : } BTShared;
                                152                 :                : 
                                153                 :                : /*
                                154                 :                :  * Return pointer to a BTShared's parallel table scan.
                                155                 :                :  *
                                156                 :                :  * c.f. shm_toc_allocate as to why BUFFERALIGN is used, rather than just
                                157                 :                :  * MAXALIGN.
                                158                 :                :  */
                                159                 :                : #define ParallelTableScanFromBTShared(shared) \
                                160                 :                :     (ParallelTableScanDesc) ((char *) (shared) + BUFFERALIGN(sizeof(BTShared)))
                                161                 :                : 
                                162                 :                : /*
                                163                 :                :  * Status for leader in parallel index build.
                                164                 :                :  */
                                165                 :                : typedef struct BTLeader
                                166                 :                : {
                                167                 :                :     /* parallel context itself */
                                168                 :                :     ParallelContext *pcxt;
                                169                 :                : 
                                170                 :                :     /*
                                171                 :                :      * nparticipanttuplesorts is the exact number of worker processes
                                172                 :                :      * successfully launched, plus one leader process if it participates as a
                                173                 :                :      * worker (only DISABLE_LEADER_PARTICIPATION builds avoid leader
                                174                 :                :      * participating as a worker).
                                175                 :                :      */
                                176                 :                :     int         nparticipanttuplesorts;
                                177                 :                : 
                                178                 :                :     /*
                                179                 :                :      * Leader process convenience pointers to shared state (leader avoids TOC
                                180                 :                :      * lookups).
                                181                 :                :      *
                                182                 :                :      * btshared is the shared state for entire build.  sharedsort is the
                                183                 :                :      * shared, tuplesort-managed state passed to each process tuplesort.
                                184                 :                :      * sharedsort2 is the corresponding btspool2 shared state, used only when
                                185                 :                :      * building unique indexes.  snapshot is the snapshot used by the scan iff
                                186                 :                :      * an MVCC snapshot is required.
                                187                 :                :      */
                                188                 :                :     BTShared   *btshared;
                                189                 :                :     Sharedsort *sharedsort;
                                190                 :                :     Sharedsort *sharedsort2;
                                191                 :                :     Snapshot    snapshot;
                                192                 :                :     WalUsage   *walusage;
                                193                 :                :     BufferUsage *bufferusage;
                                194                 :                : } BTLeader;
                                195                 :                : 
                                196                 :                : /*
                                197                 :                :  * Working state for btbuild and its callback.
                                198                 :                :  *
                                199                 :                :  * When parallel CREATE INDEX is used, there is a BTBuildState for each
                                200                 :                :  * participant.
                                201                 :                :  */
                                202                 :                : typedef struct BTBuildState
                                203                 :                : {
                                204                 :                :     bool        isunique;
                                205                 :                :     bool        nulls_not_distinct;
                                206                 :                :     bool        havedead;
                                207                 :                :     Relation    heap;
                                208                 :                :     BTSpool    *spool;
                                209                 :                : 
                                210                 :                :     /*
                                211                 :                :      * spool2 is needed only when the index is a unique index. Dead tuples are
                                212                 :                :      * put into spool2 instead of spool in order to avoid uniqueness check.
                                213                 :                :      */
                                214                 :                :     BTSpool    *spool2;
                                215                 :                :     double      indtuples;
                                216                 :                : 
                                217                 :                :     /*
                                218                 :                :      * btleader is only present when a parallel index build is performed, and
                                219                 :                :      * only in the leader process. (Actually, only the leader has a
                                220                 :                :      * BTBuildState.  Workers have their own spool and spool2, though.)
                                221                 :                :      */
                                222                 :                :     BTLeader   *btleader;
                                223                 :                : } BTBuildState;
                                224                 :                : 
                                225                 :                : /*
                                226                 :                :  * Status record for a btree page being built.  We have one of these
                                227                 :                :  * for each active tree level.
                                228                 :                :  */
                                229                 :                : typedef struct BTPageState
                                230                 :                : {
                                231                 :                :     BulkWriteBuffer btps_buf;   /* workspace for page building */
                                232                 :                :     BlockNumber btps_blkno;     /* block # to write this page at */
                                233                 :                :     IndexTuple  btps_lowkey;    /* page's strict lower bound pivot tuple */
                                234                 :                :     OffsetNumber btps_lastoff;  /* last item offset loaded */
                                235                 :                :     Size        btps_lastextra; /* last item's extra posting list space */
                                236                 :                :     uint32      btps_level;     /* tree level (0 = leaf) */
                                237                 :                :     Size        btps_full;      /* "full" if less than this much free space */
                                238                 :                :     struct BTPageState *btps_next;  /* link to parent level, if any */
                                239                 :                : } BTPageState;
                                240                 :                : 
                                241                 :                : /*
                                242                 :                :  * Overall status record for index writing phase.
                                243                 :                :  */
                                244                 :                : typedef struct BTWriteState
                                245                 :                : {
                                246                 :                :     Relation    heap;
                                247                 :                :     Relation    index;
                                248                 :                :     BulkWriteState *bulkstate;
                                249                 :                :     BTScanInsert inskey;        /* generic insertion scankey */
                                250                 :                :     BlockNumber btws_pages_alloced; /* # pages allocated */
                                251                 :                : } BTWriteState;
                                252                 :                : 
                                253                 :                : 
                                254                 :                : static double _bt_spools_heapscan(Relation heap, Relation index,
                                255                 :                :                                   BTBuildState *buildstate, IndexInfo *indexInfo);
                                256                 :                : static void _bt_spooldestroy(BTSpool *btspool);
                                257                 :                : static void _bt_spool(BTSpool *btspool, ItemPointer self,
                                258                 :                :                       Datum *values, bool *isnull);
                                259                 :                : static void _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2);
                                260                 :                : static void _bt_build_callback(Relation index, ItemPointer tid, Datum *values,
                                261                 :                :                                bool *isnull, bool tupleIsAlive, void *state);
                                262                 :                : static BulkWriteBuffer _bt_blnewpage(BTWriteState *wstate, uint32 level);
                                263                 :                : static BTPageState *_bt_pagestate(BTWriteState *wstate, uint32 level);
                                264                 :                : static void _bt_slideleft(Page rightmostpage);
                                265                 :                : static void _bt_sortaddtup(Page page, Size itemsize,
                                266                 :                :                            IndexTuple itup, OffsetNumber itup_off,
                                267                 :                :                            bool newfirstdataitem);
                                268                 :                : static void _bt_buildadd(BTWriteState *wstate, BTPageState *state,
                                269                 :                :                          IndexTuple itup, Size truncextra);
                                270                 :                : static void _bt_sort_dedup_finish_pending(BTWriteState *wstate,
                                271                 :                :                                           BTPageState *state,
                                272                 :                :                                           BTDedupState dstate);
                                273                 :                : static void _bt_uppershutdown(BTWriteState *wstate, BTPageState *state);
                                274                 :                : static void _bt_load(BTWriteState *wstate,
                                275                 :                :                      BTSpool *btspool, BTSpool *btspool2);
                                276                 :                : static void _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent,
                                277                 :                :                                int request);
                                278                 :                : static void _bt_end_parallel(BTLeader *btleader);
                                279                 :                : static Size _bt_parallel_estimate_shared(Relation heap, Snapshot snapshot);
                                280                 :                : static double _bt_parallel_heapscan(BTBuildState *buildstate,
                                281                 :                :                                     bool *brokenhotchain);
                                282                 :                : static void _bt_leader_participate_as_worker(BTBuildState *buildstate);
                                283                 :                : static void _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
                                284                 :                :                                        BTShared *btshared, Sharedsort *sharedsort,
                                285                 :                :                                        Sharedsort *sharedsort2, int sortmem,
                                286                 :                :                                        bool progress);
                                287                 :                : 
                                288                 :                : 
                                289                 :                : /*
                                290                 :                :  *  btbuild() -- build a new btree index.
                                291                 :                :  */
                                292                 :                : IndexBuildResult *
 2263 rhaas@postgresql.org      293                 :CBC       22628 : btbuild(Relation heap, Relation index, IndexInfo *indexInfo)
                                294                 :                : {
                                295                 :                :     IndexBuildResult *result;
                                296                 :                :     BTBuildState buildstate;
                                297                 :                :     double      reltuples;
                                298                 :                : 
                                299                 :                : #ifdef BTREE_BUILD_STATS
                                300                 :                :     if (log_btree_build_stats)
                                301                 :                :         ResetUsage();
                                302                 :                : #endif                          /* BTREE_BUILD_STATS */
                                303                 :                : 
                                304                 :          22628 :     buildstate.isunique = indexInfo->ii_Unique;
  801 peter@eisentraut.org      305                 :          22628 :     buildstate.nulls_not_distinct = indexInfo->ii_NullsNotDistinct;
 2263 rhaas@postgresql.org      306                 :          22628 :     buildstate.havedead = false;
                                307                 :          22628 :     buildstate.heap = heap;
                                308                 :          22628 :     buildstate.spool = NULL;
                                309                 :          22628 :     buildstate.spool2 = NULL;
                                310                 :          22628 :     buildstate.indtuples = 0;
                                311                 :          22628 :     buildstate.btleader = NULL;
                                312                 :                : 
                                313                 :                :     /*
                                314                 :                :      * We expect to be called exactly once for any index relation. If that's
                                315                 :                :      * not the case, big trouble's what we have.
                                316                 :                :      */
                                317         [ -  + ]:          22628 :     if (RelationGetNumberOfBlocks(index) != 0)
 2263 rhaas@postgresql.org      318         [ #  # ]:UBC           0 :         elog(ERROR, "index \"%s\" already contains data",
                                319                 :                :              RelationGetRelationName(index));
                                320                 :                : 
 2263 rhaas@postgresql.org      321                 :CBC       22628 :     reltuples = _bt_spools_heapscan(heap, index, &buildstate, indexInfo);
                                322                 :                : 
                                323                 :                :     /*
                                324                 :                :      * Finish the build by (1) completing the sort of the spool file, (2)
                                325                 :                :      * inserting the sorted tuples into btree pages and (3) building the upper
                                326                 :                :      * levels.  Finally, it may also be necessary to end use of parallelism.
                                327                 :                :      */
                                328                 :          22622 :     _bt_leafbuild(buildstate.spool, buildstate.spool2);
                                329                 :          22580 :     _bt_spooldestroy(buildstate.spool);
                                330         [ +  + ]:          22580 :     if (buildstate.spool2)
                                331                 :             11 :         _bt_spooldestroy(buildstate.spool2);
                                332         [ +  + ]:          22580 :     if (buildstate.btleader)
                                333                 :             71 :         _bt_end_parallel(buildstate.btleader);
                                334                 :                : 
                                335                 :          22580 :     result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult));
                                336                 :                : 
                                337                 :          22580 :     result->heap_tuples = reltuples;
                                338                 :          22580 :     result->index_tuples = buildstate.indtuples;
                                339                 :                : 
                                340                 :                : #ifdef BTREE_BUILD_STATS
                                341                 :                :     if (log_btree_build_stats)
                                342                 :                :     {
                                343                 :                :         ShowUsage("BTREE BUILD STATS");
                                344                 :                :         ResetUsage();
                                345                 :                :     }
                                346                 :                : #endif                          /* BTREE_BUILD_STATS */
                                347                 :                : 
                                348                 :          22580 :     return result;
                                349                 :                : }
                                350                 :                : 
                                351                 :                : /*
                                352                 :                :  * Create and initialize one or two spool structures, and save them in caller's
                                353                 :                :  * buildstate argument.  May also fill-in fields within indexInfo used by index
                                354                 :                :  * builds.
                                355                 :                :  *
                                356                 :                :  * Scans the heap, possibly in parallel, filling spools with IndexTuples.  This
                                357                 :                :  * routine encapsulates all aspects of managing parallelism.  Caller need only
                                358                 :                :  * call _bt_end_parallel() in parallel case after it is done with spool/spool2.
                                359                 :                :  *
                                360                 :                :  * Returns the total number of heap tuples scanned.
                                361                 :                :  */
                                362                 :                : static double
                                363                 :          22628 : _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate,
                                364                 :                :                     IndexInfo *indexInfo)
                                365                 :                : {
 7823 bruce@momjian.us          366                 :          22628 :     BTSpool    *btspool = (BTSpool *) palloc0(sizeof(BTSpool));
 2263 rhaas@postgresql.org      367                 :          22628 :     SortCoordinate coordinate = NULL;
                                368                 :          22628 :     double      reltuples = 0;
                                369                 :                : 
                                370                 :                :     /*
                                371                 :                :      * We size the sort area as maintenance_work_mem rather than work_mem to
                                372                 :                :      * speed index creation.  This should be OK since a single backend can't
                                373                 :                :      * run multiple index creations in parallel (see also: notes on
                                374                 :                :      * parallelism and maintenance_work_mem below).
                                375                 :                :      */
 4093 tgl@sss.pgh.pa.us         376                 :          22628 :     btspool->heap = heap;
 8946                           377                 :          22628 :     btspool->index = index;
 2263 rhaas@postgresql.org      378                 :          22628 :     btspool->isunique = indexInfo->ii_Unique;
  801 peter@eisentraut.org      379                 :          22628 :     btspool->nulls_not_distinct = indexInfo->ii_NullsNotDistinct;
                                380                 :                : 
                                381                 :                :     /* Save as primary spool */
 2263 rhaas@postgresql.org      382                 :          22628 :     buildstate->spool = btspool;
                                383                 :                : 
                                384                 :                :     /* Report table scan phase started */
 1839 alvherre@alvh.no-ip.      385                 :          22628 :     pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                                386                 :                :                                  PROGRESS_BTREE_PHASE_INDEXBUILD_TABLESCAN);
                                387                 :                : 
                                388                 :                :     /* Attempt to launch parallel worker scan when required */
 2263 rhaas@postgresql.org      389         [ +  + ]:          22628 :     if (indexInfo->ii_ParallelWorkers > 0)
                                390                 :             71 :         _bt_begin_parallel(buildstate, indexInfo->ii_Concurrent,
                                391                 :                :                            indexInfo->ii_ParallelWorkers);
                                392                 :                : 
                                393                 :                :     /*
                                394                 :                :      * If parallel build requested and at least one worker process was
                                395                 :                :      * successfully launched, set up coordination state
                                396                 :                :      */
                                397         [ +  + ]:          22628 :     if (buildstate->btleader)
                                398                 :                :     {
                                399                 :             71 :         coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
                                400                 :             71 :         coordinate->isWorker = false;
                                401                 :             71 :         coordinate->nParticipants =
                                402                 :             71 :             buildstate->btleader->nparticipanttuplesorts;
                                403                 :             71 :         coordinate->sharedsort = buildstate->btleader->sharedsort;
                                404                 :                :     }
                                405                 :                : 
                                406                 :                :     /*
                                407                 :                :      * Begin serial/leader tuplesort.
                                408                 :                :      *
                                409                 :                :      * In cases where parallelism is involved, the leader receives the same
                                410                 :                :      * share of maintenance_work_mem as a serial sort (it is generally treated
                                411                 :                :      * in the same way as a serial sort once we return).  Parallel worker
                                412                 :                :      * Tuplesortstates will have received only a fraction of
                                413                 :                :      * maintenance_work_mem, though.
                                414                 :                :      *
                                415                 :                :      * We rely on the lifetime of the Leader Tuplesortstate almost not
                                416                 :                :      * overlapping with any worker Tuplesortstate's lifetime.  There may be
                                417                 :                :      * some small overlap, but that's okay because we rely on leader
                                418                 :                :      * Tuplesortstate only allocating a small, fixed amount of memory here.
                                419                 :                :      * When its tuplesort_performsort() is called (by our caller), and
                                420                 :                :      * significant amounts of memory are likely to be used, all workers must
                                421                 :                :      * have already freed almost all memory held by their Tuplesortstates
                                422                 :                :      * (they are about to go away completely, too).  The overall effect is
                                423                 :                :      * that maintenance_work_mem always represents an absolute high watermark
                                424                 :                :      * on the amount of memory used by a CREATE INDEX operation, regardless of
                                425                 :                :      * the use of parallelism or any other factor.
                                426                 :                :      */
                                427                 :          45256 :     buildstate->spool->sortstate =
                                428                 :          22628 :         tuplesort_begin_index_btree(heap, index, buildstate->isunique,
  801 peter@eisentraut.org      429                 :          22628 :                                     buildstate->nulls_not_distinct,
                                430                 :                :                                     maintenance_work_mem, coordinate,
                                431                 :                :                                     TUPLESORT_NONE);
                                432                 :                : 
                                433                 :                :     /*
                                434                 :                :      * If building a unique index, put dead tuples in a second spool to keep
                                435                 :                :      * them out of the uniqueness check.  We expect that the second spool (for
                                436                 :                :      * dead tuples) won't get very full, so we give it only work_mem.
                                437                 :                :      */
 2263 rhaas@postgresql.org      438         [ +  + ]:          22628 :     if (indexInfo->ii_Unique)
                                439                 :                :     {
                                440                 :          18334 :         BTSpool    *btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
                                441                 :          18334 :         SortCoordinate coordinate2 = NULL;
                                442                 :                : 
                                443                 :                :         /* Initialize secondary spool */
                                444                 :          18334 :         btspool2->heap = heap;
                                445                 :          18334 :         btspool2->index = index;
                                446                 :          18334 :         btspool2->isunique = false;
                                447                 :                :         /* Save as secondary spool */
                                448                 :          18334 :         buildstate->spool2 = btspool2;
                                449                 :                : 
                                450         [ +  + ]:          18334 :         if (buildstate->btleader)
                                451                 :                :         {
                                452                 :                :             /*
                                453                 :                :              * Set up non-private state that is passed to
                                454                 :                :              * tuplesort_begin_index_btree() about the basic high level
                                455                 :                :              * coordination of a parallel sort.
                                456                 :                :              */
                                457                 :             32 :             coordinate2 = (SortCoordinate) palloc0(sizeof(SortCoordinateData));
                                458                 :             32 :             coordinate2->isWorker = false;
                                459                 :             32 :             coordinate2->nParticipants =
                                460                 :             32 :                 buildstate->btleader->nparticipanttuplesorts;
                                461                 :             32 :             coordinate2->sharedsort = buildstate->btleader->sharedsort2;
                                462                 :                :         }
                                463                 :                : 
                                464                 :                :         /*
                                465                 :                :          * We expect that the second one (for dead tuples) won't get very
                                466                 :                :          * full, so we give it only work_mem
                                467                 :                :          */
                                468                 :          18334 :         buildstate->spool2->sortstate =
  801 peter@eisentraut.org      469                 :          18334 :             tuplesort_begin_index_btree(heap, index, false, false, work_mem,
                                470                 :                :                                         coordinate2, TUPLESORT_NONE);
                                471                 :                :     }
                                472                 :                : 
                                473                 :                :     /* Fill spool using either serial or parallel heap scan */
 2263 rhaas@postgresql.org      474         [ +  + ]:          22628 :     if (!buildstate->btleader)
 1839 alvherre@alvh.no-ip.      475                 :          22557 :         reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
                                476                 :                :                                            _bt_build_callback, (void *) buildstate,
                                477                 :                :                                            NULL);
                                478                 :                :     else
 2263 rhaas@postgresql.org      479                 :             71 :         reltuples = _bt_parallel_heapscan(buildstate,
                                480                 :                :                                           &indexInfo->ii_BrokenHotChain);
                                481                 :                : 
                                482                 :                :     /*
                                483                 :                :      * Set the progress target for the next phase.  Reset the block number
                                484                 :                :      * values set by table_index_build_scan
                                485                 :                :      */
                                486                 :                :     {
 1167 peter@eisentraut.org      487                 :          22622 :         const int   progress_index[] = {
                                488                 :                :             PROGRESS_CREATEIDX_TUPLES_TOTAL,
                                489                 :                :             PROGRESS_SCAN_BLOCKS_TOTAL,
                                490                 :                :             PROGRESS_SCAN_BLOCKS_DONE
                                491                 :                :         };
                                492                 :          22622 :         const int64 progress_vals[] = {
 1839 alvherre@alvh.no-ip.      493                 :          22622 :             buildstate->indtuples,
                                494                 :                :             0, 0
                                495                 :                :         };
                                496                 :                : 
 1167 peter@eisentraut.org      497                 :          22622 :         pgstat_progress_update_multi_param(3, progress_index, progress_vals);
                                498                 :                :     }
                                499                 :                : 
                                500                 :                :     /* okay, all heap tuples are spooled */
 2263 rhaas@postgresql.org      501   [ +  +  +  + ]:          22622 :     if (buildstate->spool2 && !buildstate->havedead)
                                502                 :                :     {
                                503                 :                :         /* spool2 turns out to be unnecessary */
                                504                 :          18323 :         _bt_spooldestroy(buildstate->spool2);
                                505                 :          18323 :         buildstate->spool2 = NULL;
                                506                 :                :     }
                                507                 :                : 
                                508                 :          22622 :     return reltuples;
                                509                 :                : }
                                510                 :                : 
                                511                 :                : /*
                                512                 :                :  * clean up a spool structure and its substructures.
                                513                 :                :  */
                                514                 :                : static void
 8946 tgl@sss.pgh.pa.us         515                 :          40914 : _bt_spooldestroy(BTSpool *btspool)
                                516                 :                : {
                                517                 :          40914 :     tuplesort_end(btspool->sortstate);
 7139 neilc@samurai.com         518                 :          40914 :     pfree(btspool);
10141 scrappy@hub.org           519                 :          40914 : }
                                520                 :                : 
                                521                 :                : /*
                                522                 :                :  * spool an index entry into the sort file.
                                523                 :                :  */
                                524                 :                : static void
 3575 rhaas@postgresql.org      525                 :        5959699 : _bt_spool(BTSpool *btspool, ItemPointer self, Datum *values, bool *isnull)
                                526                 :                : {
                                527                 :        5959699 :     tuplesort_putindextuplevalues(btspool->sortstate, btspool->index,
                                528                 :                :                                   self, values, isnull);
10141 scrappy@hub.org           529                 :        5959699 : }
                                530                 :                : 
                                531                 :                : /*
                                532                 :                :  * given a spool loaded by successive calls to _bt_spool,
                                533                 :                :  * create an entire btree.
                                534                 :                :  */
                                535                 :                : static void
 8648 inoue@tpf.co.jp           536                 :          22622 : _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
                                537                 :                : {
                                538                 :                :     BTWriteState wstate;
                                539                 :                : 
                                540                 :                : #ifdef BTREE_BUILD_STATS
                                541                 :                :     if (log_btree_build_stats)
                                542                 :                :     {
                                543                 :                :         ShowUsage("BTREE BUILD (Spool) STATISTICS");
                                544                 :                :         ResetUsage();
                                545                 :                :     }
                                546                 :                : #endif                          /* BTREE_BUILD_STATS */
                                547                 :                : 
                                548                 :                :     /* Execute the sort */
 1839 alvherre@alvh.no-ip.      549                 :          22622 :     pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                                550                 :                :                                  PROGRESS_BTREE_PHASE_PERFORMSORT_1);
 7722 tgl@sss.pgh.pa.us         551                 :          22622 :     tuplesort_performsort(btspool->sortstate);
 8648 inoue@tpf.co.jp           552         [ +  + ]:          22580 :     if (btspool2)
                                553                 :                :     {
 1839 alvherre@alvh.no-ip.      554                 :             11 :         pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                                555                 :                :                                      PROGRESS_BTREE_PHASE_PERFORMSORT_2);
 8648 inoue@tpf.co.jp           556                 :             11 :         tuplesort_performsort(btspool2->sortstate);
                                557                 :                :     }
                                558                 :                : 
 4093 tgl@sss.pgh.pa.us         559                 :          22580 :     wstate.heap = btspool->heap;
 7256                           560                 :          22580 :     wstate.index = btspool->index;
  309 pg@bowt.ie                561                 :          22580 :     wstate.inskey = _bt_mkscankey(wstate.index, NULL);
                                562                 :                :     /* _bt_mkscankey() won't set allequalimage without metapage */
 1509                           563                 :          22580 :     wstate.inskey->allequalimage = _bt_allequalimage(wstate.index, true);
                                564                 :                : 
                                565                 :                :     /* reserve the metapage */
 7256 tgl@sss.pgh.pa.us         566                 :          22580 :     wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
                                567                 :                : 
 1839 alvherre@alvh.no-ip.      568                 :          22580 :     pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                                569                 :                :                                  PROGRESS_BTREE_PHASE_LEAF_LOAD);
 7256 tgl@sss.pgh.pa.us         570                 :          22580 :     _bt_load(&wstate, btspool, btspool2);
10141 scrappy@hub.org           571                 :          22580 : }
                                572                 :                : 
                                573                 :                : /*
                                574                 :                :  * Per-tuple callback for table_index_build_scan
                                575                 :                :  */
                                576                 :                : static void
 2263 rhaas@postgresql.org      577                 :        5959699 : _bt_build_callback(Relation index,
                                578                 :                :                    ItemPointer tid,
                                579                 :                :                    Datum *values,
                                580                 :                :                    bool *isnull,
                                581                 :                :                    bool tupleIsAlive,
                                582                 :                :                    void *state)
                                583                 :                : {
                                584                 :        5959699 :     BTBuildState *buildstate = (BTBuildState *) state;
                                585                 :                : 
                                586                 :                :     /*
                                587                 :                :      * insert the index tuple into the appropriate spool file for subsequent
                                588                 :                :      * processing
                                589                 :                :      */
                                590   [ +  +  +  + ]:        5959699 :     if (tupleIsAlive || buildstate->spool2 == NULL)
 1619 andres@anarazel.de        591                 :        5959469 :         _bt_spool(buildstate->spool, tid, values, isnull);
                                592                 :                :     else
                                593                 :                :     {
                                594                 :                :         /* dead tuples are put into spool2 */
 2263 rhaas@postgresql.org      595                 :            230 :         buildstate->havedead = true;
 1619 andres@anarazel.de        596                 :            230 :         _bt_spool(buildstate->spool2, tid, values, isnull);
                                597                 :                :     }
                                598                 :                : 
 2263 rhaas@postgresql.org      599                 :        5959699 :     buildstate->indtuples += 1;
                                600                 :        5959699 : }
                                601                 :                : 
                                602                 :                : /*
                                603                 :                :  * allocate workspace for a new, clean btree page, not linked to any siblings.
                                604                 :                :  */
                                605                 :                : static BulkWriteBuffer
   51 heikki.linnakangas@i      606                 :GNC       24231 : _bt_blnewpage(BTWriteState *wstate, uint32 level)
                                607                 :                : {
                                608                 :                :     BulkWriteBuffer buf;
                                609                 :                :     Page        page;
                                610                 :                :     BTPageOpaque opaque;
                                611                 :                : 
                                612                 :          24231 :     buf = smgr_bulk_get_buf(wstate->bulkstate);
                                613                 :          24231 :     page = (Page) buf;
                                614                 :                : 
                                615                 :                :     /* Zero the page and set up standard page header info */
 7256 tgl@sss.pgh.pa.us         616                 :CBC       24231 :     _bt_pageinit(page, BLCKSZ);
                                617                 :                : 
                                618                 :                :     /* Initialize BT opaque state */
  744 michael@paquier.xyz       619                 :          24231 :     opaque = BTPageGetOpaque(page);
 9716 bruce@momjian.us          620                 :          24231 :     opaque->btpo_prev = opaque->btpo_next = P_NONE;
 1145 pg@bowt.ie                621                 :          24231 :     opaque->btpo_level = level;
 7723 tgl@sss.pgh.pa.us         622                 :          24231 :     opaque->btpo_flags = (level > 0) ? 0 : BTP_LEAF;
 6551                           623                 :          24231 :     opaque->btpo_cycleid = 0;
                                624                 :                : 
                                625                 :                :     /* Make the P_HIKEY line pointer appear allocated */
 7256                           626                 :          24231 :     ((PageHeader) page)->pd_lower += sizeof(ItemIdData);
                                627                 :                : 
   51 heikki.linnakangas@i      628                 :GNC       24231 :     return buf;
                                629                 :                : }
                                630                 :                : 
                                631                 :                : /*
                                632                 :                :  * emit a completed btree page, and release the working storage.
                                633                 :                :  */
                                634                 :                : static void
                                635                 :          46811 : _bt_blwritepage(BTWriteState *wstate, BulkWriteBuffer buf, BlockNumber blkno)
                                636                 :                : {
                                637                 :          46811 :     smgr_bulk_write(wstate->bulkstate, blkno, buf, true);
                                638                 :                :     /* smgr_bulk_write took ownership of 'buf' */
 7723 tgl@sss.pgh.pa.us         639                 :CBC       46811 : }
                                640                 :                : 
                                641                 :                : /*
                                642                 :                :  * allocate and initialize a new BTPageState.  the returned structure
                                643                 :                :  * is suitable for immediate use by _bt_buildadd.
                                644                 :                :  */
                                645                 :                : static BTPageState *
 7256                           646                 :           5527 : _bt_pagestate(BTWriteState *wstate, uint32 level)
                                647                 :                : {
 7823 bruce@momjian.us          648                 :           5527 :     BTPageState *state = (BTPageState *) palloc0(sizeof(BTPageState));
                                649                 :                : 
                                650                 :                :     /* create initial page for level */
   51 heikki.linnakangas@i      651                 :GNC        5527 :     state->btps_buf = _bt_blnewpage(wstate, level);
                                652                 :                : 
                                653                 :                :     /* and assign it a page position */
 7256 tgl@sss.pgh.pa.us         654                 :CBC        5527 :     state->btps_blkno = wstate->btws_pages_alloced++;
                                655                 :                : 
 1620 pg@bowt.ie                656                 :           5527 :     state->btps_lowkey = NULL;
                                657                 :                :     /* initialize lastoff so first item goes into P_FIRSTKEY */
 8668 tgl@sss.pgh.pa.us         658                 :           5527 :     state->btps_lastoff = P_HIKEY;
 1509 pg@bowt.ie                659                 :           5527 :     state->btps_lastextra = 0;
 8668 tgl@sss.pgh.pa.us         660                 :           5527 :     state->btps_level = level;
                                661                 :                :     /* set "full" threshold based on level.  See notes at head of file. */
 6495                           662         [ +  + ]:           5527 :     if (level > 0)
 6487                           663                 :           1114 :         state->btps_full = (BLCKSZ * (100 - BTREE_NONLEAF_FILLFACTOR) / 100);
                                664                 :                :     else
 1602 michael@paquier.xyz       665   [ +  -  -  +  :           4413 :         state->btps_full = BTGetTargetPageFreeSpace(wstate->index);
                                              +  + ]
                                666                 :                : 
                                667                 :                :     /* no parent level, yet */
 7403 neilc@samurai.com         668                 :           5527 :     state->btps_next = NULL;
                                669                 :                : 
 8668 tgl@sss.pgh.pa.us         670                 :           5527 :     return state;
                                671                 :                : }
                                672                 :                : 
                                673                 :                : /*
                                674                 :                :  * Slide the array of ItemIds from the page back one slot (from P_FIRSTKEY to
                                675                 :                :  * P_HIKEY, overwriting P_HIKEY).
                                676                 :                :  *
                                677                 :                :  * _bt_blnewpage() makes the P_HIKEY line pointer appear allocated, but the
                                678                 :                :  * rightmost page on its level is not supposed to get a high key.  Now that
                                679                 :                :  * it's clear that this page is a rightmost page, remove the unneeded empty
                                680                 :                :  * P_HIKEY line pointer space.
                                681                 :                :  */
                                682                 :                : static void
 1378 pg@bowt.ie                683                 :           5527 : _bt_slideleft(Page rightmostpage)
                                684                 :                : {
                                685                 :                :     OffsetNumber off;
                                686                 :                :     OffsetNumber maxoff;
                                687                 :                :     ItemId      previi;
                                688                 :                : 
                                689                 :           5527 :     maxoff = PageGetMaxOffsetNumber(rightmostpage);
                                690         [ -  + ]:           5527 :     Assert(maxoff >= P_FIRSTKEY);
                                691                 :           5527 :     previi = PageGetItemId(rightmostpage, P_HIKEY);
                                692         [ +  + ]:         319790 :     for (off = P_FIRSTKEY; off <= maxoff; off = OffsetNumberNext(off))
                                693                 :                :     {
                                694                 :         314263 :         ItemId      thisii = PageGetItemId(rightmostpage, off);
                                695                 :                : 
                                696                 :         314263 :         *previi = *thisii;
                                697                 :         314263 :         previi = thisii;
                                698                 :                :     }
                                699                 :           5527 :     ((PageHeader) rightmostpage)->pd_lower -= sizeof(ItemIdData);
10141 scrappy@hub.org           700                 :           5527 : }
                                701                 :                : 
                                702                 :                : /*
                                703                 :                :  * Add an item to a page being built.
                                704                 :                :  *
                                705                 :                :  * This is very similar to nbtinsert.c's _bt_pgaddtup(), but this variant
                                706                 :                :  * raises an error directly.
                                707                 :                :  *
                                708                 :                :  * Note that our nbtsort.c caller does not know yet if the page will be
                                709                 :                :  * rightmost.  Offset P_FIRSTKEY is always assumed to be the first data key by
                                710                 :                :  * caller.  Page that turns out to be the rightmost on its level is fixed by
                                711                 :                :  * calling _bt_slideleft().
                                712                 :                :  */
                                713                 :                : static void
 8668 tgl@sss.pgh.pa.us         714                 :        5347041 : _bt_sortaddtup(Page page,
                                715                 :                :                Size itemsize,
                                716                 :                :                IndexTuple itup,
                                717                 :                :                OffsetNumber itup_off,
                                718                 :                :                bool newfirstdataitem)
                                719                 :                : {
                                720                 :                :     IndexTupleData trunctuple;
                                721                 :                : 
 1462 pg@bowt.ie                722         [ +  + ]:        5347041 :     if (newfirstdataitem)
                                723                 :                :     {
 6654 tgl@sss.pgh.pa.us         724                 :           1176 :         trunctuple = *itup;
                                725                 :           1176 :         trunctuple.t_info = sizeof(IndexTupleData);
 1468 pg@bowt.ie                726                 :           1176 :         BTreeTupleSetNAtts(&trunctuple, 0, false);
 6654 tgl@sss.pgh.pa.us         727                 :           1176 :         itup = &trunctuple;
                                728                 :           1176 :         itemsize = sizeof(IndexTupleData);
                                729                 :                :     }
                                730                 :                : 
                                731         [ -  + ]:        5347041 :     if (PageAddItem(page, (Item) itup, itemsize, itup_off,
                                732                 :                :                     false, false) == InvalidOffsetNumber)
 7573 tgl@sss.pgh.pa.us         733         [ #  # ]:UBC           0 :         elog(ERROR, "failed to add item to the index page");
 9923 scrappy@hub.org           734                 :CBC     5347041 : }
                                735                 :                : 
                                736                 :                : /*----------
                                737                 :                :  * Add an item to a disk page from the sort output (or add a posting list
                                738                 :                :  * item formed from the sort output).
                                739                 :                :  *
                                740                 :                :  * We must be careful to observe the page layout conventions of nbtsearch.c:
                                741                 :                :  * - rightmost pages start data items at P_HIKEY instead of at P_FIRSTKEY.
                                742                 :                :  * - on non-leaf pages, the key portion of the first item need not be
                                743                 :                :  *   stored, we should store only the link.
                                744                 :                :  *
                                745                 :                :  * A leaf page being built looks like:
                                746                 :                :  *
                                747                 :                :  * +----------------+---------------------------------+
                                748                 :                :  * | PageHeaderData | linp0 linp1 linp2 ...           |
                                749                 :                :  * +-----------+----+---------------------------------+
                                750                 :                :  * | ... linpN |                                      |
                                751                 :                :  * +-----------+--------------------------------------+
                                752                 :                :  * |     ^ last                                       |
                                753                 :                :  * |                                                  |
                                754                 :                :  * +-------------+------------------------------------+
                                755                 :                :  * |             | itemN ...                          |
                                756                 :                :  * +-------------+------------------+-----------------+
                                757                 :                :  * |          ... item3 item2 item1 | "special space" |
                                758                 :                :  * +--------------------------------+-----------------+
                                759                 :                :  *
                                760                 :                :  * Contrast this with the diagram in bufpage.h; note the mismatch
                                761                 :                :  * between linps and items.  This is because we reserve linp0 as a
                                762                 :                :  * placeholder for the pointer to the "high key" item; when we have
                                763                 :                :  * filled up the page, we will set linp0 to point to itemN and clear
                                764                 :                :  * linpN.  On the other hand, if we find this is the last (rightmost)
                                765                 :                :  * page, we leave the items alone and slide the linp array over.  If
                                766                 :                :  * the high key is to be truncated, offset 1 is deleted, and we insert
                                767                 :                :  * the truncated high key at offset 1.
                                768                 :                :  *
                                769                 :                :  * 'last' pointer indicates the last offset added to the page.
                                770                 :                :  *
                                771                 :                :  * 'truncextra' is the size of the posting list in itup, if any.  This
                                772                 :                :  * information is stashed for the next call here, when we may benefit
                                773                 :                :  * from considering the impact of truncating away the posting list on
                                774                 :                :  * the page before deciding to finish the page off.  Posting lists are
                                775                 :                :  * often relatively large, so it is worth going to the trouble of
                                776                 :                :  * accounting for the saving from truncating away the posting list of
                                777                 :                :  * the tuple that becomes the high key (that may be the only way to
                                778                 :                :  * get close to target free space on the page).  Note that this is
                                779                 :                :  * only used for the soft fillfactor-wise limit, not the critical hard
                                780                 :                :  * limit.
                                781                 :                :  *----------
                                782                 :                :  */
                                783                 :                : static void
 1509 pg@bowt.ie                784                 :        5328337 : _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup,
                                785                 :                :              Size truncextra)
                                786                 :                : {
                                787                 :                :     BulkWriteBuffer nbuf;
                                788                 :                :     Page        npage;
                                789                 :                :     BlockNumber nblkno;
                                790                 :                :     OffsetNumber last_off;
                                791                 :                :     Size        last_truncextra;
                                792                 :                :     Size        pgspc;
                                793                 :                :     Size        itupsz;
                                794                 :                :     bool        isleaf;
                                795                 :                : 
                                796                 :                :     /*
                                797                 :                :      * This is a handy place to check for cancel interrupts during the btree
                                798                 :                :      * load phase of index creation.
                                799                 :                :      */
 6610 tgl@sss.pgh.pa.us         800         [ +  + ]:        5328337 :     CHECK_FOR_INTERRUPTS();
                                801                 :                : 
   51 heikki.linnakangas@i      802                 :GNC     5328337 :     nbuf = state->btps_buf;
                                803                 :        5328337 :     npage = (Page) nbuf;
 7256 tgl@sss.pgh.pa.us         804                 :CBC     5328337 :     nblkno = state->btps_blkno;
 9716 bruce@momjian.us          805                 :        5328337 :     last_off = state->btps_lastoff;
 1509 pg@bowt.ie                806                 :        5328337 :     last_truncextra = state->btps_lastextra;
                                807                 :        5328337 :     state->btps_lastextra = truncextra;
                                808                 :                : 
 9716 bruce@momjian.us          809                 :        5328337 :     pgspc = PageGetFreeSpace(npage);
 2237 tgl@sss.pgh.pa.us         810                 :        5328337 :     itupsz = IndexTupleSize(itup);
 6654                           811                 :        5328337 :     itupsz = MAXALIGN(itupsz);
                                812                 :                :     /* Leaf case has slightly different rules due to suffix truncation */
 1809 pg@bowt.ie                813                 :        5328337 :     isleaf = (state->btps_level == 0);
                                814                 :                : 
                                815                 :                :     /*
                                816                 :                :      * Check whether the new item can fit on a btree page on current level at
                                817                 :                :      * all.
                                818                 :                :      *
                                819                 :                :      * Every newly built index will treat heap TID as part of the keyspace,
                                820                 :                :      * which imposes the requirement that new high keys must occasionally have
                                821                 :                :      * a heap TID appended within _bt_truncate().  That may leave a new pivot
                                822                 :                :      * tuple one or two MAXALIGN() quantums larger than the original
                                823                 :                :      * firstright tuple it's derived from.  v4 deals with the problem by
                                824                 :                :      * decreasing the limit on the size of tuples inserted on the leaf level
                                825                 :                :      * by the same small amount.  Enforce the new v4+ limit on the leaf level,
                                826                 :                :      * and the old limit on internal levels, since pivot tuples may need to
                                827                 :                :      * make use of the reserved space.  This should never fail on internal
                                828                 :                :      * pages.
                                829                 :                :      */
 1852                           830         [ +  + ]:        5328337 :     if (unlikely(itupsz > BTMaxItemSize(npage)))
 1809                           831                 :            132 :         _bt_check_third_page(wstate->index, wstate->heap, isleaf, npage,
                                832                 :                :                              itup);
                                833                 :                : 
                                834                 :                :     /*
                                835                 :                :      * Check to see if current page will fit new item, with space left over to
                                836                 :                :      * append a heap TID during suffix truncation when page is a leaf page.
                                837                 :                :      *
                                838                 :                :      * It is guaranteed that we can fit at least 2 non-pivot tuples plus a
                                839                 :                :      * high key with heap TID when finishing off a leaf page, since we rely on
                                840                 :                :      * _bt_check_third_page() rejecting oversized non-pivot tuples.  On
                                841                 :                :      * internal pages we can always fit 3 pivot tuples with larger internal
                                842                 :                :      * page tuple limit (includes page high key).
                                843                 :                :      *
                                844                 :                :      * Most of the time, a page is only "full" in the sense that the soft
                                845                 :                :      * fillfactor-wise limit has been exceeded.  However, we must always leave
                                846                 :                :      * at least two items plus a high key on each page before starting a new
                                847                 :                :      * page.  Disregard fillfactor and insert on "full" current page if we
                                848                 :                :      * don't have the minimum number of items yet.  (Note that we deliberately
                                849                 :                :      * assume that suffix truncation neither enlarges nor shrinks new high key
                                850                 :                :      * when applying soft limit, except when last tuple has a posting list.)
                                851                 :                :      */
 1475                           852   [ +  +  -  + ]:        5328337 :     Assert(last_truncextra == 0 || isleaf);
 1809                           853   [ +  +  +  + ]:        5328337 :     if (pgspc < itupsz + (isleaf ? MAXALIGN(sizeof(ItemPointerData)) : 0) ||
 1509                           854   [ +  +  +  - ]:        5327763 :         (pgspc + last_truncextra < state->btps_full && last_off > P_FIRSTKEY))
                                855                 :                :     {
                                856                 :                :         /*
                                857                 :                :          * Finish off the page and write it out.
                                858                 :                :          */
   51 heikki.linnakangas@i      859                 :GNC       18704 :         BulkWriteBuffer obuf = nbuf;
 9715 bruce@momjian.us          860                 :CBC       18704 :         Page        opage = npage;
 7168                           861                 :          18704 :         BlockNumber oblkno = nblkno;
                                862                 :                :         ItemId      ii;
                                863                 :                :         ItemId      hii;
                                864                 :                :         IndexTuple  oitup;
                                865                 :                : 
                                866                 :                :         /* Create new page of same level */
   51 heikki.linnakangas@i      867                 :GNC       18704 :         nbuf = _bt_blnewpage(wstate, state->btps_level);
                                868                 :          18704 :         npage = (Page) nbuf;
                                869                 :                : 
                                870                 :                :         /* and assign it a page position */
 7256 tgl@sss.pgh.pa.us         871                 :CBC       18704 :         nblkno = wstate->btws_pages_alloced++;
                                872                 :                : 
                                873                 :                :         /*
                                874                 :                :          * We copy the last item on the page into the new page, and then
                                875                 :                :          * rearrange the old page so that the 'last item' becomes its high key
                                876                 :                :          * rather than a true data item.  There had better be at least two
                                877                 :                :          * items on the page already, else the page would be empty of useful
                                878                 :                :          * data.
                                879                 :                :          */
 8668                           880         [ -  + ]:          18704 :         Assert(last_off > P_FIRSTKEY);
                                881                 :          18704 :         ii = PageGetItemId(opage, last_off);
 6654                           882                 :          18704 :         oitup = (IndexTuple) PageGetItem(opage, ii);
 1462 pg@bowt.ie                883                 :          18704 :         _bt_sortaddtup(npage, ItemIdGetLength(ii), oitup, P_FIRSTKEY,
                                884                 :          18704 :                        !isleaf);
                                885                 :                : 
                                886                 :                :         /*
                                887                 :                :          * Move 'last' into the high key position on opage.  _bt_blnewpage()
                                888                 :                :          * allocated empty space for a line pointer when opage was first
                                889                 :                :          * created, so this is a matter of rearranging already-allocated space
                                890                 :                :          * on page, and initializing high key line pointer. (Actually, leaf
                                891                 :                :          * pages must also swap oitup with a truncated version of oitup, which
                                892                 :                :          * is sometimes larger than oitup, though never by more than the space
                                893                 :                :          * needed to append a heap TID.)
                                894                 :                :          */
 9716 bruce@momjian.us          895                 :          18704 :         hii = PageGetItemId(opage, P_HIKEY);
                                896                 :          18704 :         *hii = *ii;
 6059 tgl@sss.pgh.pa.us         897                 :          18704 :         ItemIdSetUnused(ii);    /* redundant */
 9716 bruce@momjian.us          898                 :          18704 :         ((PageHeader) opage)->pd_lower -= sizeof(ItemIdData);
                                899                 :                : 
 1809 pg@bowt.ie                900         [ +  + ]:          18704 :         if (isleaf)
                                901                 :                :         {
                                902                 :                :             IndexTuple  lastleft;
                                903                 :                :             IndexTuple  truncated;
                                904                 :                : 
                                905                 :                :             /*
                                906                 :                :              * Truncate away any unneeded attributes from high key on leaf
                                907                 :                :              * level.  This is only done at the leaf level because downlinks
                                908                 :                :              * in internal pages are either negative infinity items, or get
                                909                 :                :              * their contents from copying from one level down.  See also:
                                910                 :                :              * _bt_split().
                                911                 :                :              *
                                912                 :                :              * We don't try to bias our choice of split point to make it more
                                913                 :                :              * likely that _bt_truncate() can truncate away more attributes,
                                914                 :                :              * whereas the split point used within _bt_split() is chosen much
                                915                 :                :              * more delicately.  Even still, the lastleft and firstright
                                916                 :                :              * tuples passed to _bt_truncate() here are at least not fully
                                917                 :                :              * equal to each other when deduplication is used, unless there is
                                918                 :                :              * a large group of duplicates (also, unique index builds usually
                                919                 :                :              * have few or no spool2 duplicates).  When the split point is
                                920                 :                :              * between two unequal tuples, _bt_truncate() will avoid including
                                921                 :                :              * a heap TID in the new high key, which is the most important
                                922                 :                :              * benefit of suffix truncation.
                                923                 :                :              *
                                924                 :                :              * Overwrite the old item with new truncated high key directly.
                                925                 :                :              * oitup is already located at the physical beginning of tuple
                                926                 :                :              * space, so this should directly reuse the existing tuple space.
                                927                 :                :              */
 1852                           928                 :          18642 :             ii = PageGetItemId(opage, OffsetNumberPrev(last_off));
                                929                 :          18642 :             lastleft = (IndexTuple) PageGetItem(opage, ii);
                                930                 :                : 
 1475                           931         [ -  + ]:          18642 :             Assert(IndexTupleSize(oitup) > last_truncextra);
 1852                           932                 :          18642 :             truncated = _bt_truncate(wstate->index, lastleft, oitup,
                                933                 :                :                                      wstate->inskey);
 1706                           934         [ -  + ]:          18642 :             if (!PageIndexTupleOverwrite(opage, P_HIKEY, (Item) truncated,
                                935                 :          18642 :                                          IndexTupleSize(truncated)))
 1706 pg@bowt.ie                936         [ #  # ]:UBC           0 :                 elog(ERROR, "failed to add high key to the index page");
 2187 teodor@sigaev.ru          937                 :CBC       18642 :             pfree(truncated);
                                938                 :                : 
                                939                 :                :             /* oitup should continue to point to the page's high key */
                                940                 :          18642 :             hii = PageGetItemId(opage, P_HIKEY);
                                941                 :          18642 :             oitup = (IndexTuple) PageGetItem(opage, hii);
                                942                 :                :         }
                                943                 :                : 
                                944                 :                :         /*
                                945                 :                :          * Link the old page into its parent, using its low key.  If we don't
                                946                 :                :          * have a parent, we have to create one; this adds a new btree level.
                                947                 :                :          */
 7403 neilc@samurai.com         948         [ +  + ]:          18704 :         if (state->btps_next == NULL)
 7256 tgl@sss.pgh.pa.us         949                 :           1114 :             state->btps_next = _bt_pagestate(wstate, state->btps_level + 1);
                                950                 :                : 
 1620 pg@bowt.ie                951   [ +  -  +  -  :          18704 :         Assert((BTreeTupleGetNAtts(state->btps_lowkey, wstate->index) <=
                                     +  -  +  +  -  
                                           -  -  + ]
                                952                 :                :                 IndexRelationGetNumberOfKeyAttributes(wstate->index) &&
                                953                 :                :                 BTreeTupleGetNAtts(state->btps_lowkey, wstate->index) > 0) ||
                                954                 :                :                P_LEFTMOST(BTPageGetOpaque(opage)));
                                955   [ +  -  +  +  :          18704 :         Assert(BTreeTupleGetNAtts(state->btps_lowkey, wstate->index) == 0 ||
                                              -  + ]
                                956                 :                :                !P_LEFTMOST(BTPageGetOpaque(opage)));
 1581                           957                 :          18704 :         BTreeTupleSetDownLink(state->btps_lowkey, oblkno);
 1509                           958                 :          18704 :         _bt_buildadd(wstate, state->btps_next, state->btps_lowkey, 0);
 1620                           959                 :          18704 :         pfree(state->btps_lowkey);
                                960                 :                : 
                                961                 :                :         /*
                                962                 :                :          * Save a copy of the high key from the old page.  It is also the low
                                963                 :                :          * key for the new page.
                                964                 :                :          */
                                965                 :          18704 :         state->btps_lowkey = CopyIndexTuple(oitup);
                                966                 :                : 
                                967                 :                :         /*
                                968                 :                :          * Set the sibling links for both pages.
                                969                 :                :          */
                                970                 :                :         {
  744 michael@paquier.xyz       971                 :          18704 :             BTPageOpaque oopaque = BTPageGetOpaque(opage);
                                972                 :          18704 :             BTPageOpaque nopaque = BTPageGetOpaque(npage);
                                973                 :                : 
 7256 tgl@sss.pgh.pa.us         974                 :          18704 :             oopaque->btpo_next = nblkno;
                                975                 :          18704 :             nopaque->btpo_prev = oblkno;
 2489                           976                 :          18704 :             nopaque->btpo_next = P_NONE; /* redundant */
                                977                 :                :         }
                                978                 :                : 
                                979                 :                :         /*
                                980                 :                :          * Write out the old page. _bt_blwritepage takes ownership of the
                                981                 :                :          * 'opage' buffer.
                                982                 :                :          */
   51 heikki.linnakangas@i      983                 :GNC       18704 :         _bt_blwritepage(wstate, obuf, oblkno);
                                984                 :                : 
                                985                 :                :         /*
                                986                 :                :          * Reset last_off to point to new page
                                987                 :                :          */
 8668 tgl@sss.pgh.pa.us         988                 :CBC       18704 :         last_off = P_FIRSTKEY;
                                989                 :                :     }
                                990                 :                : 
                                991                 :                :     /*
                                992                 :                :      * By here, either original page is still the current page, or a new page
                                993                 :                :      * was created that became the current page.  Either way, the current page
                                994                 :                :      * definitely has space for new item.
                                995                 :                :      *
                                996                 :                :      * If the new item is the first for its page, it must also be the first
                                997                 :                :      * item on its entire level.  On later same-level pages, a low key for a
                                998                 :                :      * page will be copied from the prior page in the code above.  Generate a
                                999                 :                :      * minus infinity low key here instead.
                               1000                 :                :      */
                               1001         [ +  + ]:        5328337 :     if (last_off == P_HIKEY)
                               1002                 :                :     {
 1620 pg@bowt.ie               1003         [ -  + ]:           5527 :         Assert(state->btps_lowkey == NULL);
                               1004                 :           5527 :         state->btps_lowkey = palloc0(sizeof(IndexTupleData));
                               1005                 :           5527 :         state->btps_lowkey->t_info = sizeof(IndexTupleData);
 1468                          1006                 :           5527 :         BTreeTupleSetNAtts(state->btps_lowkey, 0, false);
                               1007                 :                :     }
                               1008                 :                : 
                               1009                 :                :     /*
                               1010                 :                :      * Add the new item into the current page.
                               1011                 :                :      */
 8668 tgl@sss.pgh.pa.us        1012                 :        5328337 :     last_off = OffsetNumberNext(last_off);
 1462 pg@bowt.ie               1013                 :        5328337 :     _bt_sortaddtup(npage, itupsz, itup, last_off,
                               1014   [ +  +  +  + ]:        5328337 :                    !isleaf && last_off == P_FIRSTKEY);
                               1015                 :                : 
   51 heikki.linnakangas@i     1016                 :GNC     5328337 :     state->btps_buf = nbuf;
 7256 tgl@sss.pgh.pa.us        1017                 :CBC     5328337 :     state->btps_blkno = nblkno;
 9716 bruce@momjian.us         1018                 :        5328337 :     state->btps_lastoff = last_off;
 9923 scrappy@hub.org          1019                 :        5328337 : }
                               1020                 :                : 
                               1021                 :                : /*
                               1022                 :                :  * Finalize pending posting list tuple, and add it to the index.  Final tuple
                               1023                 :                :  * is based on saved base tuple, and saved list of heap TIDs.
                               1024                 :                :  *
                               1025                 :                :  * This is almost like _bt_dedup_finish_pending(), but it adds a new tuple
                               1026                 :                :  * using _bt_buildadd().
                               1027                 :                :  */
                               1028                 :                : static void
 1509 pg@bowt.ie               1029                 :        2338909 : _bt_sort_dedup_finish_pending(BTWriteState *wstate, BTPageState *state,
                               1030                 :                :                               BTDedupState dstate)
                               1031                 :                : {
                               1032         [ -  + ]:        2338909 :     Assert(dstate->nitems > 0);
                               1033                 :                : 
                               1034         [ +  + ]:        2338909 :     if (dstate->nitems == 1)
                               1035                 :        2320532 :         _bt_buildadd(wstate, state, dstate->base, 0);
                               1036                 :                :     else
                               1037                 :                :     {
                               1038                 :                :         IndexTuple  postingtuple;
                               1039                 :                :         Size        truncextra;
                               1040                 :                : 
                               1041                 :                :         /* form a tuple with a posting list */
                               1042                 :          18377 :         postingtuple = _bt_form_posting(dstate->base,
                               1043                 :                :                                         dstate->htids,
                               1044                 :                :                                         dstate->nhtids);
                               1045                 :                :         /* Calculate posting list overhead */
                               1046                 :          36754 :         truncextra = IndexTupleSize(postingtuple) -
                               1047                 :          18377 :             BTreeTupleGetPostingOffset(postingtuple);
                               1048                 :                : 
                               1049                 :          18377 :         _bt_buildadd(wstate, state, postingtuple, truncextra);
                               1050                 :          18377 :         pfree(postingtuple);
                               1051                 :                :     }
                               1052                 :                : 
 1395                          1053                 :        2338909 :     dstate->nmaxitems = 0;
 1509                          1054                 :        2338909 :     dstate->nhtids = 0;
                               1055                 :        2338909 :     dstate->nitems = 0;
                               1056                 :        2338909 :     dstate->phystupsize = 0;
                               1057                 :        2338909 : }
                               1058                 :                : 
                               1059                 :                : /*
                               1060                 :                :  * Finish writing out the completed btree.
                               1061                 :                :  */
                               1062                 :                : static void
 7256 tgl@sss.pgh.pa.us        1063                 :          22580 : _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
                               1064                 :                : {
                               1065                 :                :     BTPageState *s;
 7168 bruce@momjian.us         1066                 :          22580 :     BlockNumber rootblkno = P_NONE;
 7503 tgl@sss.pgh.pa.us        1067                 :          22580 :     uint32      rootlevel = 0;
                               1068                 :                :     BulkWriteBuffer metabuf;
                               1069                 :                : 
                               1070                 :                :     /*
                               1071                 :                :      * Each iteration of this loop completes one more level of the tree.
                               1072                 :                :      */
 7403 neilc@samurai.com        1073         [ +  + ]:          28107 :     for (s = state; s != NULL; s = s->btps_next)
                               1074                 :                :     {
                               1075                 :                :         BlockNumber blkno;
                               1076                 :                :         BTPageOpaque opaque;
                               1077                 :                : 
 7256 tgl@sss.pgh.pa.us        1078                 :           5527 :         blkno = s->btps_blkno;
   51 heikki.linnakangas@i     1079                 :GNC        5527 :         opaque = BTPageGetOpaque((Page) s->btps_buf);
                               1080                 :                : 
                               1081                 :                :         /*
                               1082                 :                :          * We have to link the last page on this level to somewhere.
                               1083                 :                :          *
                               1084                 :                :          * If we're at the top, it's the root, so attach it to the metapage.
                               1085                 :                :          * Otherwise, add an entry for it to its parent using its low key.
                               1086                 :                :          * This may cause the last page of the parent level to split, but
                               1087                 :                :          * that's not a problem -- we haven't gotten to it yet.
                               1088                 :                :          */
 7403 neilc@samurai.com        1089         [ +  + ]:CBC        5527 :         if (s->btps_next == NULL)
                               1090                 :                :         {
 8668 tgl@sss.pgh.pa.us        1091                 :           4413 :             opaque->btpo_flags |= BTP_ROOT;
 7503                          1092                 :           4413 :             rootblkno = blkno;
                               1093                 :           4413 :             rootlevel = s->btps_level;
                               1094                 :                :         }
                               1095                 :                :         else
                               1096                 :                :         {
 1620 pg@bowt.ie               1097   [ +  -  +  -  :           1114 :             Assert((BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) <=
                                     +  -  -  +  -  
                                           -  -  - ]
                               1098                 :                :                     IndexRelationGetNumberOfKeyAttributes(wstate->index) &&
                               1099                 :                :                     BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) > 0) ||
                               1100                 :                :                    P_LEFTMOST(opaque));
                               1101   [ +  -  +  -  :           1114 :             Assert(BTreeTupleGetNAtts(s->btps_lowkey, wstate->index) == 0 ||
                                              -  + ]
                               1102                 :                :                    !P_LEFTMOST(opaque));
 1581                          1103                 :           1114 :             BTreeTupleSetDownLink(s->btps_lowkey, blkno);
 1509                          1104                 :           1114 :             _bt_buildadd(wstate, s->btps_next, s->btps_lowkey, 0);
 1620                          1105                 :           1114 :             pfree(s->btps_lowkey);
                               1106                 :           1114 :             s->btps_lowkey = NULL;
                               1107                 :                :         }
                               1108                 :                : 
                               1109                 :                :         /*
                               1110                 :                :          * This is the rightmost page, so the ItemId array needs to be slid
                               1111                 :                :          * back one slot.  Then we can dump out the page.
                               1112                 :                :          */
   51 heikki.linnakangas@i     1113                 :GNC        5527 :         _bt_slideleft((Page) s->btps_buf);
                               1114                 :           5527 :         _bt_blwritepage(wstate, s->btps_buf, s->btps_blkno);
                               1115                 :           5527 :         s->btps_buf = NULL;      /* writepage took ownership of the buffer */
                               1116                 :                :     }
                               1117                 :                : 
                               1118                 :                :     /*
                               1119                 :                :      * As the last step in the process, construct the metapage and make it
                               1120                 :                :      * point to the new root (unless we had no data at all, in which case it's
                               1121                 :                :      * set to point to "P_NONE").  This changes the index to the "valid" state
                               1122                 :                :      * by filling in a valid magic number in the metapage.
                               1123                 :                :      */
                               1124                 :          22580 :     metabuf = smgr_bulk_get_buf(wstate->bulkstate);
                               1125                 :          22580 :     _bt_initmetapage((Page) metabuf, rootblkno, rootlevel,
 1509 pg@bowt.ie               1126                 :CBC       22580 :                      wstate->inskey->allequalimage);
   51 heikki.linnakangas@i     1127                 :GNC       22580 :     _bt_blwritepage(wstate, metabuf, BTREE_METAPAGE);
10141 scrappy@hub.org          1128                 :CBC       22580 : }
                               1129                 :                : 
                               1130                 :                : /*
                               1131                 :                :  * Read tuples in correct sort order from tuplesort, and load them into
                               1132                 :                :  * btree leaves.
                               1133                 :                :  */
                               1134                 :                : static void
 7256 tgl@sss.pgh.pa.us        1135                 :          22580 : _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
                               1136                 :                : {
 8668                          1137                 :          22580 :     BTPageState *state = NULL;
 8648 inoue@tpf.co.jp          1138                 :          22580 :     bool        merge = (btspool2 != NULL);
                               1139                 :                :     IndexTuple  itup,
 6654 tgl@sss.pgh.pa.us        1140                 :          22580 :                 itup2 = NULL;
                               1141                 :                :     bool        load1;
 7256                          1142                 :          22580 :     TupleDesc   tupdes = RelationGetDescr(wstate->index);
                               1143                 :                :     int         i,
 2199 teodor@sigaev.ru         1144                 :          22580 :                 keysz = IndexRelationGetNumberOfKeyAttributes(wstate->index);
                               1145                 :                :     SortSupport sortKeys;
 1812 alvherre@alvh.no-ip.     1146                 :          22580 :     int64       tuples_done = 0;
                               1147                 :                :     bool        deduplicate;
                               1148                 :                : 
   51 heikki.linnakangas@i     1149                 :GNC       22580 :     wstate->bulkstate = smgr_bulk_start_rel(wstate->index, MAIN_FORKNUM);
                               1150                 :                : 
 1367 pg@bowt.ie               1151   [ +  +  +  +  :CBC       26751 :     deduplicate = wstate->inskey->allequalimage && !btspool->isunique &&
                                              +  - ]
 1509                          1152   [ +  -  -  +  :           4171 :         BTGetDeduplicateItems(wstate->index);
                                        +  +  +  - ]
                               1153                 :                : 
 8648 inoue@tpf.co.jp          1154         [ +  + ]:          22580 :     if (merge)
                               1155                 :                :     {
                               1156                 :                :         /*
                               1157                 :                :          * Another BTSpool for dead tuples exists. Now we have to merge
                               1158                 :                :          * btspool and btspool2.
                               1159                 :                :          */
                               1160                 :                : 
                               1161                 :                :         /* the preparation of merge */
 2680 rhaas@postgresql.org     1162                 :             11 :         itup = tuplesort_getindextuple(btspool->sortstate, true);
                               1163                 :             11 :         itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
                               1164                 :                : 
                               1165                 :                :         /* Prepare SortSupport data for each column */
 3446                          1166                 :             11 :         sortKeys = (SortSupport) palloc0(keysz * sizeof(SortSupportData));
                               1167                 :                : 
                               1168         [ +  + ]:             23 :         for (i = 0; i < keysz; i++)
                               1169                 :                :         {
                               1170                 :             12 :             SortSupport sortKey = sortKeys + i;
 1852 pg@bowt.ie               1171                 :             12 :             ScanKey     scanKey = wstate->inskey->scankeys + i;
                               1172                 :                :             int16       strategy;
                               1173                 :                : 
 3446 rhaas@postgresql.org     1174                 :             12 :             sortKey->ssup_cxt = CurrentMemoryContext;
                               1175                 :             12 :             sortKey->ssup_collation = scanKey->sk_collation;
                               1176                 :             12 :             sortKey->ssup_nulls_first =
                               1177                 :             12 :                 (scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
                               1178                 :             12 :             sortKey->ssup_attno = scanKey->sk_attno;
                               1179                 :                :             /* Abbreviation is not supported here */
 3373                          1180                 :             12 :             sortKey->abbreviate = false;
                               1181                 :                : 
  534 peter@eisentraut.org     1182         [ -  + ]:             12 :             Assert(sortKey->ssup_attno != 0);
                               1183                 :                : 
 3446 rhaas@postgresql.org     1184         [ -  + ]:             12 :             strategy = (scanKey->sk_flags & SK_BT_DESC) != 0 ?
                               1185                 :                :                 BTGreaterStrategyNumber : BTLessStrategyNumber;
                               1186                 :                : 
                               1187                 :             12 :             PrepareSortSupportFromIndexRel(wstate->index, strategy, sortKey);
                               1188                 :                :         }
                               1189                 :                : 
                               1190                 :                :         for (;;)
                               1191                 :                :         {
 8424 bruce@momjian.us         1192                 :           1641 :             load1 = true;       /* load BTSpool next ? */
 6654 tgl@sss.pgh.pa.us        1193         [ +  + ]:           1641 :             if (itup2 == NULL)
                               1194                 :                :             {
                               1195         [ +  + ]:             77 :                 if (itup == NULL)
 8648 inoue@tpf.co.jp          1196                 :             11 :                     break;
                               1197                 :                :             }
 6654 tgl@sss.pgh.pa.us        1198         [ +  + ]:           1564 :             else if (itup != NULL)
                               1199                 :                :             {
 1852 pg@bowt.ie               1200                 :           1477 :                 int32       compare = 0;
                               1201                 :                : 
 8648 inoue@tpf.co.jp          1202         [ +  + ]:           1592 :                 for (i = 1; i <= keysz; i++)
                               1203                 :                :                 {
                               1204                 :                :                     SortSupport entry;
                               1205                 :                :                     Datum       attrDatum1,
                               1206                 :                :                                 attrDatum2;
                               1207                 :                :                     bool        isNull1,
                               1208                 :                :                                 isNull2;
                               1209                 :                : 
 3446 rhaas@postgresql.org     1210                 :           1501 :                     entry = sortKeys + i - 1;
 6305 tgl@sss.pgh.pa.us        1211                 :           1501 :                     attrDatum1 = index_getattr(itup, i, tupdes, &isNull1);
                               1212                 :           1501 :                     attrDatum2 = index_getattr(itup2, i, tupdes, &isNull2);
                               1213                 :                : 
 3446 rhaas@postgresql.org     1214                 :           1501 :                     compare = ApplySortComparator(attrDatum1, isNull1,
                               1215                 :                :                                                   attrDatum2, isNull2,
                               1216                 :                :                                                   entry);
 6305 tgl@sss.pgh.pa.us        1217         [ +  + ]:           1501 :                     if (compare > 0)
                               1218                 :                :                     {
                               1219                 :            128 :                         load1 = false;
                               1220                 :           1386 :                         break;
                               1221                 :                :                     }
                               1222         [ +  + ]:           1373 :                     else if (compare < 0)
                               1223                 :           1258 :                         break;
                               1224                 :                :                 }
                               1225                 :                : 
                               1226                 :                :                 /*
                               1227                 :                :                  * If key values are equal, we sort on ItemPointer.  This is
                               1228                 :                :                  * required for btree indexes, since heap TID is treated as an
                               1229                 :                :                  * implicit last key attribute in order to ensure that all
                               1230                 :                :                  * keys in the index are physically unique.
                               1231                 :                :                  */
 1852 pg@bowt.ie               1232         [ +  + ]:           1477 :                 if (compare == 0)
                               1233                 :                :                 {
                               1234                 :             91 :                     compare = ItemPointerCompare(&itup->t_tid, &itup2->t_tid);
                               1235         [ -  + ]:             91 :                     Assert(compare != 0);
                               1236         [ +  + ]:             91 :                     if (compare > 0)
                               1237                 :             15 :                         load1 = false;
                               1238                 :                :                 }
                               1239                 :                :             }
                               1240                 :                :             else
 8648 inoue@tpf.co.jp          1241                 :             87 :                 load1 = false;
                               1242                 :                : 
                               1243                 :                :             /* When we see first tuple, create first index page */
                               1244         [ +  + ]:           1630 :             if (state == NULL)
 7256 tgl@sss.pgh.pa.us        1245                 :             11 :                 state = _bt_pagestate(wstate, 0);
                               1246                 :                : 
 8648 inoue@tpf.co.jp          1247         [ +  + ]:           1630 :             if (load1)
                               1248                 :                :             {
 1509 pg@bowt.ie               1249                 :           1400 :                 _bt_buildadd(wstate, state, itup, 0);
 2680 rhaas@postgresql.org     1250                 :           1400 :                 itup = tuplesort_getindextuple(btspool->sortstate, true);
                               1251                 :                :             }
                               1252                 :                :             else
                               1253                 :                :             {
 1509 pg@bowt.ie               1254                 :            230 :                 _bt_buildadd(wstate, state, itup2, 0);
 2680 rhaas@postgresql.org     1255                 :            230 :                 itup2 = tuplesort_getindextuple(btspool2->sortstate, true);
                               1256                 :                :             }
                               1257                 :                : 
                               1258                 :                :             /* Report progress */
 1839 alvherre@alvh.no-ip.     1259                 :           1630 :             pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE,
                               1260                 :                :                                          ++tuples_done);
                               1261                 :                :         }
 3446 rhaas@postgresql.org     1262                 :             11 :         pfree(sortKeys);
                               1263                 :                :     }
 1509 pg@bowt.ie               1264         [ +  + ]:          22569 :     else if (deduplicate)
                               1265                 :                :     {
                               1266                 :                :         /* merge is unnecessary, deduplicate into posting lists */
                               1267                 :                :         BTDedupState dstate;
                               1268                 :                : 
                               1269                 :           4171 :         dstate = (BTDedupState) palloc(sizeof(BTDedupStateData));
                               1270                 :           4171 :         dstate->deduplicate = true; /* unused */
 1395                          1271                 :           4171 :         dstate->nmaxitems = 0;   /* unused */
 1509                          1272                 :           4171 :         dstate->maxpostingsize = 0; /* set later */
                               1273                 :                :         /* Metadata about base tuple of current pending posting list */
                               1274                 :           4171 :         dstate->base = NULL;
                               1275                 :           4171 :         dstate->baseoff = InvalidOffsetNumber;   /* unused */
                               1276                 :           4171 :         dstate->basetupsize = 0;
                               1277                 :                :         /* Metadata about current pending posting list TIDs */
                               1278                 :           4171 :         dstate->htids = NULL;
                               1279                 :           4171 :         dstate->nhtids = 0;
                               1280                 :           4171 :         dstate->nitems = 0;
                               1281                 :           4171 :         dstate->phystupsize = 0; /* unused */
                               1282                 :           4171 :         dstate->nintervals = 0; /* unused */
                               1283                 :                : 
                               1284                 :        2994071 :         while ((itup = tuplesort_getindextuple(btspool->sortstate,
                               1285         [ +  + ]:        2994071 :                                                true)) != NULL)
                               1286                 :                :         {
                               1287                 :                :             /* When we see first tuple, create first index page */
                               1288         [ +  + ]:        2989900 :             if (state == NULL)
                               1289                 :                :             {
                               1290                 :           1147 :                 state = _bt_pagestate(wstate, 0);
                               1291                 :                : 
                               1292                 :                :                 /*
                               1293                 :                :                  * Limit size of posting list tuples to 1/10 space we want to
                               1294                 :                :                  * leave behind on the page, plus space for final item's line
                               1295                 :                :                  * pointer.  This is equal to the space that we'd like to
                               1296                 :                :                  * leave behind on each leaf page when fillfactor is 90,
                               1297                 :                :                  * allowing us to get close to fillfactor% space utilization
                               1298                 :                :                  * when there happen to be a great many duplicates.  (This
                               1299                 :                :                  * makes higher leaf fillfactor settings ineffective when
                               1300                 :                :                  * building indexes that have many duplicates, but packing
                               1301                 :                :                  * leaf pages full with few very large tuples doesn't seem
                               1302                 :                :                  * like a useful goal.)
                               1303                 :                :                  */
                               1304                 :           1147 :                 dstate->maxpostingsize = MAXALIGN_DOWN((BLCKSZ * 10 / 100)) -
                               1305                 :                :                     sizeof(ItemIdData);
   51 heikki.linnakangas@i     1306   [ +  -  -  + ]:GNC        1147 :                 Assert(dstate->maxpostingsize <= BTMaxItemSize((Page) state->btps_buf) &&
                               1307                 :                :                        dstate->maxpostingsize <= INDEX_SIZE_MASK);
 1509 pg@bowt.ie               1308                 :CBC        1147 :                 dstate->htids = palloc(dstate->maxpostingsize);
                               1309                 :                : 
                               1310                 :                :                 /* start new pending posting list with itup copy */
                               1311                 :           1147 :                 _bt_dedup_start_pending(dstate, CopyIndexTuple(itup),
                               1312                 :                :                                         InvalidOffsetNumber);
                               1313                 :                :             }
                               1314         [ +  + ]:        2988753 :             else if (_bt_keep_natts_fast(wstate->index, dstate->base,
                               1315         [ +  + ]:         654844 :                                          itup) > keysz &&
                               1316                 :         654844 :                      _bt_dedup_save_htid(dstate, itup))
                               1317                 :                :             {
                               1318                 :                :                 /*
                               1319                 :                :                  * Tuple is equal to base tuple of pending posting list.  Heap
                               1320                 :                :                  * TID from itup has been saved in state.
                               1321                 :                :                  */
                               1322                 :                :             }
                               1323                 :                :             else
                               1324                 :                :             {
                               1325                 :                :                 /*
                               1326                 :                :                  * Tuple is not equal to pending posting list tuple, or
                               1327                 :                :                  * _bt_dedup_save_htid() opted to not merge current item into
                               1328                 :                :                  * pending posting list.
                               1329                 :                :                  */
                               1330                 :        2337762 :                 _bt_sort_dedup_finish_pending(wstate, state, dstate);
                               1331                 :        2337762 :                 pfree(dstate->base);
                               1332                 :                : 
                               1333                 :                :                 /* start new pending posting list with itup copy */
                               1334                 :        2337762 :                 _bt_dedup_start_pending(dstate, CopyIndexTuple(itup),
                               1335                 :                :                                         InvalidOffsetNumber);
                               1336                 :                :             }
                               1337                 :                : 
                               1338                 :                :             /* Report progress */
                               1339                 :        2989900 :             pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE,
                               1340                 :                :                                          ++tuples_done);
                               1341                 :                :         }
                               1342                 :                : 
                               1343         [ +  + ]:           4171 :         if (state)
                               1344                 :                :         {
                               1345                 :                :             /*
                               1346                 :                :              * Handle the last item (there must be a last item when the
                               1347                 :                :              * tuplesort returned one or more tuples)
                               1348                 :                :              */
                               1349                 :           1147 :             _bt_sort_dedup_finish_pending(wstate, state, dstate);
                               1350                 :           1147 :             pfree(dstate->base);
                               1351                 :           1147 :             pfree(dstate->htids);
                               1352                 :                :         }
                               1353                 :                : 
                               1354                 :           4171 :         pfree(dstate);
                               1355                 :                :     }
                               1356                 :                :     else
                               1357                 :                :     {
                               1358                 :                :         /* merging and deduplication are both unnecessary */
 6654 tgl@sss.pgh.pa.us        1359                 :        2986378 :         while ((itup = tuplesort_getindextuple(btspool->sortstate,
 2680 rhaas@postgresql.org     1360         [ +  + ]:        2986378 :                                                true)) != NULL)
                               1361                 :                :         {
                               1362                 :                :             /* When we see first tuple, create first index page */
 8648 inoue@tpf.co.jp          1363         [ +  + ]:        2967980 :             if (state == NULL)
 7256 tgl@sss.pgh.pa.us        1364                 :           3255 :                 state = _bt_pagestate(wstate, 0);
                               1365                 :                : 
 1509 pg@bowt.ie               1366                 :        2967980 :             _bt_buildadd(wstate, state, itup, 0);
                               1367                 :                : 
                               1368                 :                :             /* Report progress */
 1839 alvherre@alvh.no-ip.     1369                 :        2967980 :             pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE,
                               1370                 :                :                                          ++tuples_done);
                               1371                 :                :         }
                               1372                 :                :     }
                               1373                 :                : 
                               1374                 :                :     /* Close down final pages and write the metapage */
 7256 tgl@sss.pgh.pa.us        1375                 :          22580 :     _bt_uppershutdown(wstate, state);
   51 heikki.linnakangas@i     1376                 :GNC       22580 :     smgr_bulk_finish(wstate->bulkstate);
10141 scrappy@hub.org          1377                 :CBC       22580 : }
                               1378                 :                : 
                               1379                 :                : /*
                               1380                 :                :  * Create parallel context, and launch workers for leader.
                               1381                 :                :  *
                               1382                 :                :  * buildstate argument should be initialized (with the exception of the
                               1383                 :                :  * tuplesort state in spools, which may later be created based on shared
                               1384                 :                :  * state initially set up here).
                               1385                 :                :  *
                               1386                 :                :  * isconcurrent indicates if operation is CREATE INDEX CONCURRENTLY.
                               1387                 :                :  *
                               1388                 :                :  * request is the target number of parallel worker processes to launch.
                               1389                 :                :  *
                               1390                 :                :  * Sets buildstate's BTLeader, which caller must use to shut down parallel
                               1391                 :                :  * mode by passing it to _bt_end_parallel() at the very end of its index
                               1392                 :                :  * build.  If not even a single worker process can be launched, this is
                               1393                 :                :  * never set, and caller should proceed with a serial index build.
                               1394                 :                :  */
                               1395                 :                : static void
 2263 rhaas@postgresql.org     1396                 :             71 : _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
                               1397                 :                : {
                               1398                 :                :     ParallelContext *pcxt;
                               1399                 :                :     int         scantuplesortstates;
                               1400                 :                :     Snapshot    snapshot;
                               1401                 :                :     Size        estbtshared;
                               1402                 :                :     Size        estsort;
                               1403                 :                :     BTShared   *btshared;
                               1404                 :                :     Sharedsort *sharedsort;
                               1405                 :                :     Sharedsort *sharedsort2;
                               1406                 :             71 :     BTSpool    *btspool = buildstate->spool;
                               1407                 :             71 :     BTLeader   *btleader = (BTLeader *) palloc0(sizeof(BTLeader));
                               1408                 :                :     WalUsage   *walusage;
                               1409                 :                :     BufferUsage *bufferusage;
                               1410                 :             71 :     bool        leaderparticipates = true;
                               1411                 :                :     int         querylen;
                               1412                 :                : 
                               1413                 :                : #ifdef DISABLE_LEADER_PARTICIPATION
                               1414                 :                :     leaderparticipates = false;
                               1415                 :                : #endif
                               1416                 :                : 
                               1417                 :                :     /*
                               1418                 :                :      * Enter parallel mode, and create context for parallel build of btree
                               1419                 :                :      * index
                               1420                 :                :      */
                               1421                 :             71 :     EnterParallelMode();
                               1422         [ -  + ]:             71 :     Assert(request > 0);
                               1423                 :             71 :     pcxt = CreateParallelContext("postgres", "_bt_parallel_build_main",
                               1424                 :                :                                  request);
                               1425                 :                : 
                               1426         [ +  - ]:             71 :     scantuplesortstates = leaderparticipates ? request + 1 : request;
                               1427                 :                : 
                               1428                 :                :     /*
                               1429                 :                :      * Prepare for scan of the base relation.  In a normal index build, we use
                               1430                 :                :      * SnapshotAny because we must retrieve all tuples and do our own time
                               1431                 :                :      * qual checks (because we have to index RECENTLY_DEAD tuples).  In a
                               1432                 :                :      * concurrent build, we take a regular MVCC snapshot and index whatever's
                               1433                 :                :      * live according to that.
                               1434                 :                :      */
                               1435         [ +  - ]:             71 :     if (!isconcurrent)
                               1436                 :             71 :         snapshot = SnapshotAny;
                               1437                 :                :     else
 2263 rhaas@postgresql.org     1438                 :UBC           0 :         snapshot = RegisterSnapshot(GetTransactionSnapshot());
                               1439                 :                : 
                               1440                 :                :     /*
                               1441                 :                :      * Estimate size for our own PARALLEL_KEY_BTREE_SHARED workspace, and
                               1442                 :                :      * PARALLEL_KEY_TUPLESORT tuplesort workspace
                               1443                 :                :      */
 1861 andres@anarazel.de       1444                 :CBC          71 :     estbtshared = _bt_parallel_estimate_shared(btspool->heap, snapshot);
 2263 rhaas@postgresql.org     1445                 :             71 :     shm_toc_estimate_chunk(&pcxt->estimator, estbtshared);
                               1446                 :             71 :     estsort = tuplesort_estimate_shared(scantuplesortstates);
                               1447                 :             71 :     shm_toc_estimate_chunk(&pcxt->estimator, estsort);
                               1448                 :                : 
                               1449                 :                :     /*
                               1450                 :                :      * Unique case requires a second spool, and so we may have to account for
                               1451                 :                :      * another shared workspace for that -- PARALLEL_KEY_TUPLESORT_SPOOL2
                               1452                 :                :      */
                               1453         [ +  + ]:             71 :     if (!btspool->isunique)
                               1454                 :             39 :         shm_toc_estimate_keys(&pcxt->estimator, 2);
                               1455                 :                :     else
                               1456                 :                :     {
                               1457                 :             32 :         shm_toc_estimate_chunk(&pcxt->estimator, estsort);
                               1458                 :             32 :         shm_toc_estimate_keys(&pcxt->estimator, 3);
                               1459                 :                :     }
                               1460                 :                : 
                               1461                 :                :     /*
                               1462                 :                :      * Estimate space for WalUsage and BufferUsage -- PARALLEL_KEY_WAL_USAGE
                               1463                 :                :      * and PARALLEL_KEY_BUFFER_USAGE.
                               1464                 :                :      *
                               1465                 :                :      * If there are no extensions loaded that care, we could skip this.  We
                               1466                 :                :      * have no way of knowing whether anyone's looking at pgWalUsage or
                               1467                 :                :      * pgBufferUsage, so do it unconditionally.
                               1468                 :                :      */
 1471 akapila@postgresql.o     1469                 :             71 :     shm_toc_estimate_chunk(&pcxt->estimator,
                               1470                 :                :                            mul_size(sizeof(WalUsage), pcxt->nworkers));
                               1471                 :             71 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
 1466                          1472                 :             71 :     shm_toc_estimate_chunk(&pcxt->estimator,
                               1473                 :                :                            mul_size(sizeof(BufferUsage), pcxt->nworkers));
                               1474                 :             71 :     shm_toc_estimate_keys(&pcxt->estimator, 1);
                               1475                 :                : 
                               1476                 :                :     /* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */
 1261 noah@leadboat.com        1477         [ +  - ]:             71 :     if (debug_query_string)
                               1478                 :                :     {
                               1479                 :             71 :         querylen = strlen(debug_query_string);
                               1480                 :             71 :         shm_toc_estimate_chunk(&pcxt->estimator, querylen + 1);
                               1481                 :             71 :         shm_toc_estimate_keys(&pcxt->estimator, 1);
                               1482                 :                :     }
                               1483                 :                :     else
 1261 noah@leadboat.com        1484                 :UBC           0 :         querylen = 0;           /* keep compiler quiet */
                               1485                 :                : 
                               1486                 :                :     /* Everyone's had a chance to ask for space, so now create the DSM */
 2263 rhaas@postgresql.org     1487                 :CBC          71 :     InitializeParallelDSM(pcxt);
                               1488                 :                : 
                               1489                 :                :     /* If no DSM segment was available, back out (do serial build) */
 1530 tmunro@postgresql.or     1490         [ -  + ]:             71 :     if (pcxt->seg == NULL)
                               1491                 :                :     {
 1530 tmunro@postgresql.or     1492   [ #  #  #  # ]:UBC           0 :         if (IsMVCCSnapshot(snapshot))
                               1493                 :              0 :             UnregisterSnapshot(snapshot);
                               1494                 :              0 :         DestroyParallelContext(pcxt);
                               1495                 :              0 :         ExitParallelMode();
                               1496                 :              0 :         return;
                               1497                 :                :     }
                               1498                 :                : 
                               1499                 :                :     /* Store shared build state, for which we reserved space */
 2263 rhaas@postgresql.org     1500                 :CBC          71 :     btshared = (BTShared *) shm_toc_allocate(pcxt->toc, estbtshared);
                               1501                 :                :     /* Initialize immutable state */
                               1502                 :             71 :     btshared->heaprelid = RelationGetRelid(btspool->heap);
                               1503                 :             71 :     btshared->indexrelid = RelationGetRelid(btspool->index);
                               1504                 :             71 :     btshared->isunique = btspool->isunique;
  801 peter@eisentraut.org     1505                 :             71 :     btshared->nulls_not_distinct = btspool->nulls_not_distinct;
 2263 rhaas@postgresql.org     1506                 :             71 :     btshared->isconcurrent = isconcurrent;
                               1507                 :             71 :     btshared->scantuplesortstates = scantuplesortstates;
                               1508                 :             71 :     ConditionVariableInit(&btshared->workersdonecv);
                               1509                 :             71 :     SpinLockInit(&btshared->mutex);
                               1510                 :                :     /* Initialize mutable state */
                               1511                 :             71 :     btshared->nparticipantsdone = 0;
                               1512                 :             71 :     btshared->reltuples = 0.0;
                               1513                 :             71 :     btshared->havedead = false;
                               1514                 :             71 :     btshared->indtuples = 0.0;
                               1515                 :             71 :     btshared->brokenhotchain = false;
 1861 andres@anarazel.de       1516                 :             71 :     table_parallelscan_initialize(btspool->heap,
                               1517                 :                :                                   ParallelTableScanFromBTShared(btshared),
                               1518                 :                :                                   snapshot);
                               1519                 :                : 
                               1520                 :                :     /*
                               1521                 :                :      * Store shared tuplesort-private state, for which we reserved space.
                               1522                 :                :      * Then, initialize opaque state using tuplesort routine.
                               1523                 :                :      */
 2263 rhaas@postgresql.org     1524                 :             71 :     sharedsort = (Sharedsort *) shm_toc_allocate(pcxt->toc, estsort);
                               1525                 :             71 :     tuplesort_initialize_shared(sharedsort, scantuplesortstates,
                               1526                 :                :                                 pcxt->seg);
                               1527                 :                : 
                               1528                 :             71 :     shm_toc_insert(pcxt->toc, PARALLEL_KEY_BTREE_SHARED, btshared);
                               1529                 :             71 :     shm_toc_insert(pcxt->toc, PARALLEL_KEY_TUPLESORT, sharedsort);
                               1530                 :                : 
                               1531                 :                :     /* Unique case requires a second spool, and associated shared state */
                               1532         [ +  + ]:             71 :     if (!btspool->isunique)
                               1533                 :             39 :         sharedsort2 = NULL;
                               1534                 :                :     else
                               1535                 :                :     {
                               1536                 :                :         /*
                               1537                 :                :          * Store additional shared tuplesort-private state, for which we
                               1538                 :                :          * reserved space.  Then, initialize opaque state using tuplesort
                               1539                 :                :          * routine.
                               1540                 :                :          */
                               1541                 :             32 :         sharedsort2 = (Sharedsort *) shm_toc_allocate(pcxt->toc, estsort);
                               1542                 :             32 :         tuplesort_initialize_shared(sharedsort2, scantuplesortstates,
                               1543                 :                :                                     pcxt->seg);
                               1544                 :                : 
                               1545                 :             32 :         shm_toc_insert(pcxt->toc, PARALLEL_KEY_TUPLESORT_SPOOL2, sharedsort2);
                               1546                 :                :     }
                               1547                 :                : 
                               1548                 :                :     /* Store query string for workers */
 1261 noah@leadboat.com        1549         [ +  - ]:             71 :     if (debug_query_string)
                               1550                 :                :     {
                               1551                 :                :         char       *sharedquery;
                               1552                 :                : 
                               1553                 :             71 :         sharedquery = (char *) shm_toc_allocate(pcxt->toc, querylen + 1);
                               1554                 :             71 :         memcpy(sharedquery, debug_query_string, querylen + 1);
                               1555                 :             71 :         shm_toc_insert(pcxt->toc, PARALLEL_KEY_QUERY_TEXT, sharedquery);
                               1556                 :                :     }
                               1557                 :                : 
                               1558                 :                :     /*
                               1559                 :                :      * Allocate space for each worker's WalUsage and BufferUsage; no need to
                               1560                 :                :      * initialize.
                               1561                 :                :      */
 1471 akapila@postgresql.o     1562                 :             71 :     walusage = shm_toc_allocate(pcxt->toc,
                               1563                 :             71 :                                 mul_size(sizeof(WalUsage), pcxt->nworkers));
                               1564                 :             71 :     shm_toc_insert(pcxt->toc, PARALLEL_KEY_WAL_USAGE, walusage);
 1466                          1565                 :             71 :     bufferusage = shm_toc_allocate(pcxt->toc,
                               1566                 :             71 :                                    mul_size(sizeof(BufferUsage), pcxt->nworkers));
                               1567                 :             71 :     shm_toc_insert(pcxt->toc, PARALLEL_KEY_BUFFER_USAGE, bufferusage);
                               1568                 :                : 
                               1569                 :                :     /* Launch workers, saving status for leader/caller */
 2263 rhaas@postgresql.org     1570                 :             71 :     LaunchParallelWorkers(pcxt);
                               1571                 :             71 :     btleader->pcxt = pcxt;
                               1572                 :             71 :     btleader->nparticipanttuplesorts = pcxt->nworkers_launched;
                               1573         [ +  - ]:             71 :     if (leaderparticipates)
                               1574                 :             71 :         btleader->nparticipanttuplesorts++;
                               1575                 :             71 :     btleader->btshared = btshared;
                               1576                 :             71 :     btleader->sharedsort = sharedsort;
                               1577                 :             71 :     btleader->sharedsort2 = sharedsort2;
                               1578                 :             71 :     btleader->snapshot = snapshot;
 1471 akapila@postgresql.o     1579                 :             71 :     btleader->walusage = walusage;
 1466                          1580                 :             71 :     btleader->bufferusage = bufferusage;
                               1581                 :                : 
                               1582                 :                :     /* If no workers were successfully launched, back out (do serial build) */
 2263 rhaas@postgresql.org     1583         [ -  + ]:             71 :     if (pcxt->nworkers_launched == 0)
                               1584                 :                :     {
 2263 rhaas@postgresql.org     1585                 :UBC           0 :         _bt_end_parallel(btleader);
                               1586                 :              0 :         return;
                               1587                 :                :     }
                               1588                 :                : 
                               1589                 :                :     /* Save leader state now that it's clear build will be parallel */
 2263 rhaas@postgresql.org     1590                 :CBC          71 :     buildstate->btleader = btleader;
                               1591                 :                : 
                               1592                 :                :     /* Join heap scan ourselves */
                               1593         [ +  - ]:             71 :     if (leaderparticipates)
                               1594                 :             71 :         _bt_leader_participate_as_worker(buildstate);
                               1595                 :                : 
                               1596                 :                :     /*
                               1597                 :                :      * Caller needs to wait for all launched workers when we return.  Make
                               1598                 :                :      * sure that the failure-to-start case will not hang forever.
                               1599                 :                :      */
                               1600                 :             71 :     WaitForParallelWorkersToAttach(pcxt);
                               1601                 :                : }
                               1602                 :                : 
                               1603                 :                : /*
                               1604                 :                :  * Shut down workers, destroy parallel context, and end parallel mode.
                               1605                 :                :  */
                               1606                 :                : static void
                               1607                 :             71 : _bt_end_parallel(BTLeader *btleader)
                               1608                 :                : {
                               1609                 :                :     int         i;
                               1610                 :                : 
                               1611                 :                :     /* Shutdown worker processes */
                               1612                 :             71 :     WaitForParallelWorkersToFinish(btleader->pcxt);
                               1613                 :                : 
                               1614                 :                :     /*
                               1615                 :                :      * Next, accumulate WAL usage.  (This must wait for the workers to finish,
                               1616                 :                :      * or we might get incomplete data.)
                               1617                 :                :      */
 1471 akapila@postgresql.o     1618         [ +  + ]:            142 :     for (i = 0; i < btleader->pcxt->nworkers_launched; i++)
 1466                          1619                 :             71 :         InstrAccumParallelQuery(&btleader->bufferusage[i], &btleader->walusage[i]);
                               1620                 :                : 
                               1621                 :                :     /* Free last reference to MVCC snapshot, if one was used */
 2263 rhaas@postgresql.org     1622   [ +  -  -  + ]:             71 :     if (IsMVCCSnapshot(btleader->snapshot))
 2263 rhaas@postgresql.org     1623                 :UBC           0 :         UnregisterSnapshot(btleader->snapshot);
 2263 rhaas@postgresql.org     1624                 :CBC          71 :     DestroyParallelContext(btleader->pcxt);
                               1625                 :             71 :     ExitParallelMode();
                               1626                 :             71 : }
                               1627                 :                : 
                               1628                 :                : /*
                               1629                 :                :  * Returns size of shared memory required to store state for a parallel
                               1630                 :                :  * btree index build based on the snapshot its parallel scan will use.
                               1631                 :                :  */
                               1632                 :                : static Size
 1861 andres@anarazel.de       1633                 :             71 : _bt_parallel_estimate_shared(Relation heap, Snapshot snapshot)
                               1634                 :                : {
                               1635                 :                :     /* c.f. shm_toc_allocate as to why BUFFERALIGN is used */
                               1636                 :             71 :     return add_size(BUFFERALIGN(sizeof(BTShared)),
                               1637                 :                :                     table_parallelscan_estimate(heap, snapshot));
                               1638                 :                : }
                               1639                 :                : 
                               1640                 :                : /*
                               1641                 :                :  * Within leader, wait for end of heap scan.
                               1642                 :                :  *
                               1643                 :                :  * When called, parallel heap scan started by _bt_begin_parallel() will
                               1644                 :                :  * already be underway within worker processes (when leader participates
                               1645                 :                :  * as a worker, we should end up here just as workers are finishing).
                               1646                 :                :  *
                               1647                 :                :  * Fills in fields needed for ambuild statistics, and lets caller set
                               1648                 :                :  * field indicating that some worker encountered a broken HOT chain.
                               1649                 :                :  *
                               1650                 :                :  * Returns the total number of heap tuples scanned.
                               1651                 :                :  */
                               1652                 :                : static double
 2263 rhaas@postgresql.org     1653                 :             71 : _bt_parallel_heapscan(BTBuildState *buildstate, bool *brokenhotchain)
                               1654                 :                : {
                               1655                 :             71 :     BTShared   *btshared = buildstate->btleader->btshared;
                               1656                 :                :     int         nparticipanttuplesorts;
                               1657                 :                :     double      reltuples;
                               1658                 :                : 
                               1659                 :             71 :     nparticipanttuplesorts = buildstate->btleader->nparticipanttuplesorts;
                               1660                 :                :     for (;;)
                               1661                 :                :     {
                               1662         [ -  + ]:            187 :         SpinLockAcquire(&btshared->mutex);
                               1663         [ +  + ]:            187 :         if (btshared->nparticipantsdone == nparticipanttuplesorts)
                               1664                 :                :         {
                               1665                 :             71 :             buildstate->havedead = btshared->havedead;
                               1666                 :             71 :             buildstate->indtuples = btshared->indtuples;
                               1667                 :             71 :             *brokenhotchain = btshared->brokenhotchain;
                               1668                 :             71 :             reltuples = btshared->reltuples;
                               1669                 :             71 :             SpinLockRelease(&btshared->mutex);
                               1670                 :             71 :             break;
                               1671                 :                :         }
                               1672                 :            116 :         SpinLockRelease(&btshared->mutex);
                               1673                 :                : 
                               1674                 :            116 :         ConditionVariableSleep(&btshared->workersdonecv,
                               1675                 :                :                                WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN);
                               1676                 :                :     }
                               1677                 :                : 
                               1678                 :             71 :     ConditionVariableCancelSleep();
                               1679                 :                : 
                               1680                 :             71 :     return reltuples;
                               1681                 :                : }
                               1682                 :                : 
                               1683                 :                : /*
                               1684                 :                :  * Within leader, participate as a parallel worker.
                               1685                 :                :  */
                               1686                 :                : static void
                               1687                 :             71 : _bt_leader_participate_as_worker(BTBuildState *buildstate)
                               1688                 :                : {
                               1689                 :             71 :     BTLeader   *btleader = buildstate->btleader;
                               1690                 :                :     BTSpool    *leaderworker;
                               1691                 :                :     BTSpool    *leaderworker2;
                               1692                 :                :     int         sortmem;
                               1693                 :                : 
                               1694                 :                :     /* Allocate memory and initialize private spool */
                               1695                 :             71 :     leaderworker = (BTSpool *) palloc0(sizeof(BTSpool));
                               1696                 :             71 :     leaderworker->heap = buildstate->spool->heap;
                               1697                 :             71 :     leaderworker->index = buildstate->spool->index;
                               1698                 :             71 :     leaderworker->isunique = buildstate->spool->isunique;
  801 peter@eisentraut.org     1699                 :             71 :     leaderworker->nulls_not_distinct = buildstate->spool->nulls_not_distinct;
                               1700                 :                : 
                               1701                 :                :     /* Initialize second spool, if required */
 2263 rhaas@postgresql.org     1702         [ +  + ]:             71 :     if (!btleader->btshared->isunique)
                               1703                 :             39 :         leaderworker2 = NULL;
                               1704                 :                :     else
                               1705                 :                :     {
                               1706                 :                :         /* Allocate memory for worker's own private secondary spool */
                               1707                 :             32 :         leaderworker2 = (BTSpool *) palloc0(sizeof(BTSpool));
                               1708                 :                : 
                               1709                 :                :         /* Initialize worker's own secondary spool */
                               1710                 :             32 :         leaderworker2->heap = leaderworker->heap;
                               1711                 :             32 :         leaderworker2->index = leaderworker->index;
                               1712                 :             32 :         leaderworker2->isunique = false;
                               1713                 :                :     }
                               1714                 :                : 
                               1715                 :                :     /*
                               1716                 :                :      * Might as well use reliable figure when doling out maintenance_work_mem
                               1717                 :                :      * (when requested number of workers were not launched, this will be
                               1718                 :                :      * somewhat higher than it is for other workers).
                               1719                 :                :      */
                               1720                 :             71 :     sortmem = maintenance_work_mem / btleader->nparticipanttuplesorts;
                               1721                 :                : 
                               1722                 :                :     /* Perform work common to all participants */
                               1723                 :             71 :     _bt_parallel_scan_and_sort(leaderworker, leaderworker2, btleader->btshared,
                               1724                 :                :                                btleader->sharedsort, btleader->sharedsort2,
                               1725                 :                :                                sortmem, true);
                               1726                 :                : 
                               1727                 :                : #ifdef BTREE_BUILD_STATS
                               1728                 :                :     if (log_btree_build_stats)
                               1729                 :                :     {
                               1730                 :                :         ShowUsage("BTREE BUILD (Leader Partial Spool) STATISTICS");
                               1731                 :                :         ResetUsage();
                               1732                 :                :     }
                               1733                 :                : #endif                          /* BTREE_BUILD_STATS */
                               1734                 :             71 : }
                               1735                 :                : 
                               1736                 :                : /*
                               1737                 :                :  * Perform work within a launched parallel process.
                               1738                 :                :  */
                               1739                 :                : void
                               1740                 :             71 : _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
                               1741                 :                : {
                               1742                 :                :     char       *sharedquery;
                               1743                 :                :     BTSpool    *btspool;
                               1744                 :                :     BTSpool    *btspool2;
                               1745                 :                :     BTShared   *btshared;
                               1746                 :                :     Sharedsort *sharedsort;
                               1747                 :                :     Sharedsort *sharedsort2;
                               1748                 :                :     Relation    heapRel;
                               1749                 :                :     Relation    indexRel;
                               1750                 :                :     LOCKMODE    heapLockmode;
                               1751                 :                :     LOCKMODE    indexLockmode;
                               1752                 :                :     WalUsage   *walusage;
                               1753                 :                :     BufferUsage *bufferusage;
                               1754                 :                :     int         sortmem;
                               1755                 :                : 
                               1756                 :                : #ifdef BTREE_BUILD_STATS
                               1757                 :                :     if (log_btree_build_stats)
                               1758                 :                :         ResetUsage();
                               1759                 :                : #endif                          /* BTREE_BUILD_STATS */
                               1760                 :                : 
                               1761                 :                :     /*
                               1762                 :                :      * The only possible status flag that can be set to the parallel worker is
                               1763                 :                :      * PROC_IN_SAFE_IC.
                               1764                 :                :      */
  877 akapila@postgresql.o     1765   [ -  +  -  - ]:             71 :     Assert((MyProc->statusFlags == 0) ||
                               1766                 :                :            (MyProc->statusFlags == PROC_IN_SAFE_IC));
                               1767                 :                : 
                               1768                 :                :     /* Set debug_query_string for individual workers first */
 1261 noah@leadboat.com        1769                 :             71 :     sharedquery = shm_toc_lookup(toc, PARALLEL_KEY_QUERY_TEXT, true);
 2215 rhaas@postgresql.org     1770                 :             71 :     debug_query_string = sharedquery;
                               1771                 :                : 
                               1772                 :                :     /* Report the query string from leader */
                               1773                 :             71 :     pgstat_report_activity(STATE_RUNNING, debug_query_string);
                               1774                 :                : 
                               1775                 :                :     /* Look up nbtree shared state */
 2263                          1776                 :             71 :     btshared = shm_toc_lookup(toc, PARALLEL_KEY_BTREE_SHARED, false);
                               1777                 :                : 
                               1778                 :                :     /* Open relations using lock modes known to be obtained by index.c */
                               1779         [ +  - ]:             71 :     if (!btshared->isconcurrent)
                               1780                 :                :     {
                               1781                 :             71 :         heapLockmode = ShareLock;
                               1782                 :             71 :         indexLockmode = AccessExclusiveLock;
                               1783                 :                :     }
                               1784                 :                :     else
                               1785                 :                :     {
 2263 rhaas@postgresql.org     1786                 :UBC           0 :         heapLockmode = ShareUpdateExclusiveLock;
                               1787                 :              0 :         indexLockmode = RowExclusiveLock;
                               1788                 :                :     }
                               1789                 :                : 
                               1790                 :                :     /* Open relations within worker */
 1910 andres@anarazel.de       1791                 :CBC          71 :     heapRel = table_open(btshared->heaprelid, heapLockmode);
 2263 rhaas@postgresql.org     1792                 :             71 :     indexRel = index_open(btshared->indexrelid, indexLockmode);
                               1793                 :                : 
                               1794                 :                :     /* Initialize worker's own spool */
                               1795                 :             71 :     btspool = (BTSpool *) palloc0(sizeof(BTSpool));
                               1796                 :             71 :     btspool->heap = heapRel;
                               1797                 :             71 :     btspool->index = indexRel;
                               1798                 :             71 :     btspool->isunique = btshared->isunique;
  801 peter@eisentraut.org     1799                 :             71 :     btspool->nulls_not_distinct = btshared->nulls_not_distinct;
                               1800                 :                : 
                               1801                 :                :     /* Look up shared state private to tuplesort.c */
 2263 rhaas@postgresql.org     1802                 :             71 :     sharedsort = shm_toc_lookup(toc, PARALLEL_KEY_TUPLESORT, false);
                               1803                 :             71 :     tuplesort_attach_shared(sharedsort, seg);
                               1804         [ +  + ]:             71 :     if (!btshared->isunique)
                               1805                 :                :     {
                               1806                 :             39 :         btspool2 = NULL;
                               1807                 :             39 :         sharedsort2 = NULL;
                               1808                 :                :     }
                               1809                 :                :     else
                               1810                 :                :     {
                               1811                 :                :         /* Allocate memory for worker's own private secondary spool */
                               1812                 :             32 :         btspool2 = (BTSpool *) palloc0(sizeof(BTSpool));
                               1813                 :                : 
                               1814                 :                :         /* Initialize worker's own secondary spool */
                               1815                 :             32 :         btspool2->heap = btspool->heap;
                               1816                 :             32 :         btspool2->index = btspool->index;
                               1817                 :             32 :         btspool2->isunique = false;
                               1818                 :                :         /* Look up shared state private to tuplesort.c */
                               1819                 :             32 :         sharedsort2 = shm_toc_lookup(toc, PARALLEL_KEY_TUPLESORT_SPOOL2, false);
                               1820                 :             32 :         tuplesort_attach_shared(sharedsort2, seg);
                               1821                 :                :     }
                               1822                 :                : 
                               1823                 :                :     /* Prepare to track buffer usage during parallel execution */
 1471 akapila@postgresql.o     1824                 :             71 :     InstrStartParallelQuery();
                               1825                 :                : 
                               1826                 :                :     /* Perform sorting of spool, and possibly a spool2 */
 2263 rhaas@postgresql.org     1827                 :             71 :     sortmem = maintenance_work_mem / btshared->scantuplesortstates;
                               1828                 :             71 :     _bt_parallel_scan_and_sort(btspool, btspool2, btshared, sharedsort,
                               1829                 :                :                                sharedsort2, sortmem, false);
                               1830                 :                : 
                               1831                 :                :     /* Report WAL/buffer usage during parallel execution */
 1466 akapila@postgresql.o     1832                 :             71 :     bufferusage = shm_toc_lookup(toc, PARALLEL_KEY_BUFFER_USAGE, false);
 1471                          1833                 :             71 :     walusage = shm_toc_lookup(toc, PARALLEL_KEY_WAL_USAGE, false);
 1466                          1834                 :             71 :     InstrEndParallelQuery(&bufferusage[ParallelWorkerNumber],
                               1835                 :             71 :                           &walusage[ParallelWorkerNumber]);
                               1836                 :                : 
                               1837                 :                : #ifdef BTREE_BUILD_STATS
                               1838                 :                :     if (log_btree_build_stats)
                               1839                 :                :     {
                               1840                 :                :         ShowUsage("BTREE BUILD (Worker Partial Spool) STATISTICS");
                               1841                 :                :         ResetUsage();
                               1842                 :                :     }
                               1843                 :                : #endif                          /* BTREE_BUILD_STATS */
                               1844                 :                : 
 2263 rhaas@postgresql.org     1845                 :             71 :     index_close(indexRel, indexLockmode);
 1910 andres@anarazel.de       1846                 :             71 :     table_close(heapRel, heapLockmode);
 2263 rhaas@postgresql.org     1847                 :             71 : }
                               1848                 :                : 
                               1849                 :                : /*
                               1850                 :                :  * Perform a worker's portion of a parallel sort.
                               1851                 :                :  *
                               1852                 :                :  * This generates a tuplesort for passed btspool, and a second tuplesort
                               1853                 :                :  * state if a second btspool is need (i.e. for unique index builds).  All
                               1854                 :                :  * other spool fields should already be set when this is called.
                               1855                 :                :  *
                               1856                 :                :  * sortmem is the amount of working memory to use within each worker,
                               1857                 :                :  * expressed in KBs.
                               1858                 :                :  *
                               1859                 :                :  * When this returns, workers are done, and need only release resources.
                               1860                 :                :  */
                               1861                 :                : static void
                               1862                 :            142 : _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2,
                               1863                 :                :                            BTShared *btshared, Sharedsort *sharedsort,
                               1864                 :                :                            Sharedsort *sharedsort2, int sortmem, bool progress)
                               1865                 :                : {
                               1866                 :                :     SortCoordinate coordinate;
                               1867                 :                :     BTBuildState buildstate;
                               1868                 :                :     TableScanDesc scan;
                               1869                 :                :     double      reltuples;
                               1870                 :                :     IndexInfo  *indexInfo;
                               1871                 :                : 
                               1872                 :                :     /* Initialize local tuplesort coordination state */
                               1873                 :            142 :     coordinate = palloc0(sizeof(SortCoordinateData));
                               1874                 :            142 :     coordinate->isWorker = true;
                               1875                 :            142 :     coordinate->nParticipants = -1;
                               1876                 :            142 :     coordinate->sharedsort = sharedsort;
                               1877                 :                : 
                               1878                 :                :     /* Begin "partial" tuplesort */
                               1879                 :            284 :     btspool->sortstate = tuplesort_begin_index_btree(btspool->heap,
                               1880                 :                :                                                      btspool->index,
                               1881                 :            142 :                                                      btspool->isunique,
  801 peter@eisentraut.org     1882                 :            142 :                                                      btspool->nulls_not_distinct,
                               1883                 :                :                                                      sortmem, coordinate,
                               1884                 :                :                                                      TUPLESORT_NONE);
                               1885                 :                : 
                               1886                 :                :     /*
                               1887                 :                :      * Just as with serial case, there may be a second spool.  If so, a
                               1888                 :                :      * second, dedicated spool2 partial tuplesort is required.
                               1889                 :                :      */
 2263 rhaas@postgresql.org     1890         [ +  + ]:            142 :     if (btspool2)
                               1891                 :                :     {
                               1892                 :                :         SortCoordinate coordinate2;
                               1893                 :                : 
                               1894                 :                :         /*
                               1895                 :                :          * We expect that the second one (for dead tuples) won't get very
                               1896                 :                :          * full, so we give it only work_mem (unless sortmem is less for
                               1897                 :                :          * worker).  Worker processes are generally permitted to allocate
                               1898                 :                :          * work_mem independently.
                               1899                 :                :          */
                               1900                 :             64 :         coordinate2 = palloc0(sizeof(SortCoordinateData));
                               1901                 :             64 :         coordinate2->isWorker = true;
                               1902                 :             64 :         coordinate2->nParticipants = -1;
                               1903                 :             64 :         coordinate2->sharedsort = sharedsort2;
                               1904                 :             64 :         btspool2->sortstate =
  801 peter@eisentraut.org     1905                 :             64 :             tuplesort_begin_index_btree(btspool->heap, btspool->index, false, false,
                               1906                 :                :                                         Min(sortmem, work_mem), coordinate2,
                               1907                 :                :                                         false);
                               1908                 :                :     }
                               1909                 :                : 
                               1910                 :                :     /* Fill in buildstate for _bt_build_callback() */
 2263 rhaas@postgresql.org     1911                 :            142 :     buildstate.isunique = btshared->isunique;
  801 peter@eisentraut.org     1912                 :            142 :     buildstate.nulls_not_distinct = btshared->nulls_not_distinct;
 2263 rhaas@postgresql.org     1913                 :            142 :     buildstate.havedead = false;
                               1914                 :            142 :     buildstate.heap = btspool->heap;
                               1915                 :            142 :     buildstate.spool = btspool;
                               1916                 :            142 :     buildstate.spool2 = btspool2;
                               1917                 :            142 :     buildstate.indtuples = 0;
                               1918                 :            142 :     buildstate.btleader = NULL;
                               1919                 :                : 
                               1920                 :                :     /* Join parallel scan */
                               1921                 :            142 :     indexInfo = BuildIndexInfo(btspool->index);
                               1922                 :            142 :     indexInfo->ii_Concurrent = btshared->isconcurrent;
 1839 alvherre@alvh.no-ip.     1923                 :            142 :     scan = table_beginscan_parallel(btspool->heap,
                               1924                 :                :                                     ParallelTableScanFromBTShared(btshared));
 1845 andres@anarazel.de       1925                 :            142 :     reltuples = table_index_build_scan(btspool->heap, btspool->index, indexInfo,
                               1926                 :                :                                        true, progress, _bt_build_callback,
                               1927                 :                :                                        (void *) &buildstate, scan);
                               1928                 :                : 
                               1929                 :                :     /* Execute this worker's part of the sort */
 1038 alvherre@alvh.no-ip.     1930         [ +  + ]:            142 :     if (progress)
                               1931                 :             71 :         pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                               1932                 :                :                                      PROGRESS_BTREE_PHASE_PERFORMSORT_1);
 2263 rhaas@postgresql.org     1933                 :            142 :     tuplesort_performsort(btspool->sortstate);
                               1934         [ +  + ]:            142 :     if (btspool2)
                               1935                 :                :     {
 1038 alvherre@alvh.no-ip.     1936         [ +  + ]:             64 :         if (progress)
                               1937                 :             32 :             pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE,
                               1938                 :                :                                          PROGRESS_BTREE_PHASE_PERFORMSORT_2);
 2263 rhaas@postgresql.org     1939                 :             64 :         tuplesort_performsort(btspool2->sortstate);
                               1940                 :                :     }
                               1941                 :                : 
                               1942                 :                :     /*
                               1943                 :                :      * Done.  Record ambuild statistics, and whether we encountered a broken
                               1944                 :                :      * HOT chain.
                               1945                 :                :      */
                               1946         [ -  + ]:            142 :     SpinLockAcquire(&btshared->mutex);
                               1947                 :            142 :     btshared->nparticipantsdone++;
                               1948                 :            142 :     btshared->reltuples += reltuples;
                               1949         [ -  + ]:            142 :     if (buildstate.havedead)
 2263 rhaas@postgresql.org     1950                 :UBC           0 :         btshared->havedead = true;
 2263 rhaas@postgresql.org     1951                 :CBC         142 :     btshared->indtuples += buildstate.indtuples;
                               1952         [ -  + ]:            142 :     if (indexInfo->ii_BrokenHotChain)
 2263 rhaas@postgresql.org     1953                 :UBC           0 :         btshared->brokenhotchain = true;
 2263 rhaas@postgresql.org     1954                 :CBC         142 :     SpinLockRelease(&btshared->mutex);
                               1955                 :                : 
                               1956                 :                :     /* Notify leader */
                               1957                 :            142 :     ConditionVariableSignal(&btshared->workersdonecv);
                               1958                 :                : 
                               1959                 :                :     /* We can end tuplesorts immediately */
                               1960                 :            142 :     tuplesort_end(btspool->sortstate);
                               1961         [ +  + ]:            142 :     if (btspool2)
                               1962                 :             64 :         tuplesort_end(btspool2->sortstate);
                               1963                 :            142 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622