43
43
#include "miscadmin.h"
44
44
#include "optimizer/optimizer.h"
45
45
#include "storage/bufmgr.h"
46
- #include "storage/smgr.h"
46
+ #include "storage/bulk_write.h"
47
+
47
48
#include "utils/memutils.h"
48
49
#include "utils/rel.h"
49
50
#include "utils/tuplesort.h"
@@ -106,11 +107,8 @@ typedef struct
106
107
Tuplesortstate * sortstate ; /* state data for tuplesort.c */
107
108
108
109
BlockNumber pages_allocated ;
109
- BlockNumber pages_written ;
110
110
111
- int ready_num_pages ;
112
- BlockNumber ready_blknos [XLR_MAX_BLOCK_ID ];
113
- Page ready_pages [XLR_MAX_BLOCK_ID ];
111
+ BulkWriteState * bulkstate ;
114
112
} GISTBuildState ;
115
113
116
114
#define GIST_SORTED_BUILD_PAGE_NUM 4
@@ -142,7 +140,6 @@ static void gist_indexsortbuild_levelstate_add(GISTBuildState *state,
142
140
IndexTuple itup );
143
141
static void gist_indexsortbuild_levelstate_flush (GISTBuildState * state ,
144
142
GistSortedBuildLevelState * levelstate );
145
- static void gist_indexsortbuild_flush_ready_pages (GISTBuildState * state );
146
143
147
144
static void gistInitBuffering (GISTBuildState * buildstate );
148
145
static int calculatePagesPerBuffer (GISTBuildState * buildstate , int levelStep );
@@ -405,27 +402,18 @@ gist_indexsortbuild(GISTBuildState *state)
405
402
{
406
403
IndexTuple itup ;
407
404
GistSortedBuildLevelState * levelstate ;
408
- Page page ;
405
+ BulkWriteBuffer rootbuf ;
409
406
410
- state -> pages_allocated = 0 ;
411
- state -> pages_written = 0 ;
412
- state -> ready_num_pages = 0 ;
407
+ /* Reserve block 0 for the root page */
408
+ state -> pages_allocated = 1 ;
413
409
414
- /*
415
- * Write an empty page as a placeholder for the root page. It will be
416
- * replaced with the real root page at the end.
417
- */
418
- page = palloc_aligned (BLCKSZ , PG_IO_ALIGN_SIZE , MCXT_ALLOC_ZERO );
419
- smgrextend (RelationGetSmgr (state -> indexrel ), MAIN_FORKNUM , GIST_ROOT_BLKNO ,
420
- page , true);
421
- state -> pages_allocated ++ ;
422
- state -> pages_written ++ ;
410
+ state -> bulkstate = smgr_bulk_start_rel (state -> indexrel , MAIN_FORKNUM );
423
411
424
412
/* Allocate a temporary buffer for the first leaf page batch. */
425
413
levelstate = palloc0 (sizeof (GistSortedBuildLevelState ));
426
- levelstate -> pages [0 ] = page ;
414
+ levelstate -> pages [0 ] = palloc ( BLCKSZ ) ;
427
415
levelstate -> parent = NULL ;
428
- gistinitpage (page , F_LEAF );
416
+ gistinitpage (levelstate -> pages [ 0 ] , F_LEAF );
429
417
430
418
/*
431
419
* Fill index pages with tuples in the sorted order.
@@ -455,31 +443,15 @@ gist_indexsortbuild(GISTBuildState *state)
455
443
levelstate = parent ;
456
444
}
457
445
458
- gist_indexsortbuild_flush_ready_pages (state );
459
-
460
446
/* Write out the root */
461
447
PageSetLSN (levelstate -> pages [0 ], GistBuildLSN );
462
- PageSetChecksumInplace (levelstate -> pages [0 ], GIST_ROOT_BLKNO );
463
- smgrwrite (RelationGetSmgr (state -> indexrel ), MAIN_FORKNUM , GIST_ROOT_BLKNO ,
464
- levelstate -> pages [0 ], true);
465
- if (RelationNeedsWAL (state -> indexrel ))
466
- log_newpage (& state -> indexrel -> rd_locator , MAIN_FORKNUM , GIST_ROOT_BLKNO ,
467
- levelstate -> pages [0 ], true);
468
-
469
- pfree (levelstate -> pages [0 ]);
448
+ rootbuf = smgr_bulk_get_buf (state -> bulkstate );
449
+ memcpy (rootbuf , levelstate -> pages [0 ], BLCKSZ );
450
+ smgr_bulk_write (state -> bulkstate , GIST_ROOT_BLKNO , rootbuf , true);
451
+
470
452
pfree (levelstate );
471
453
472
- /*
473
- * When we WAL-logged index pages, we must nonetheless fsync index files.
474
- * Since we're building outside shared buffers, a CHECKPOINT occurring
475
- * during the build has no way to flush the previously written data to
476
- * disk (indeed it won't know the index even exists). A crash later on
477
- * would replay WAL from the checkpoint, therefore it wouldn't replay our
478
- * earlier WAL entries. If we do not fsync those pages here, they might
479
- * still not be on disk when the crash occurs.
480
- */
481
- if (RelationNeedsWAL (state -> indexrel ))
482
- smgrimmedsync (RelationGetSmgr (state -> indexrel ), MAIN_FORKNUM );
454
+ smgr_bulk_finish (state -> bulkstate );
483
455
}
484
456
485
457
/*
@@ -509,8 +481,7 @@ gist_indexsortbuild_levelstate_add(GISTBuildState *state,
509
481
levelstate -> current_page ++ ;
510
482
511
483
if (levelstate -> pages [levelstate -> current_page ] == NULL )
512
- levelstate -> pages [levelstate -> current_page ] =
513
- palloc_aligned (BLCKSZ , PG_IO_ALIGN_SIZE , 0 );
484
+ levelstate -> pages [levelstate -> current_page ] = palloc0 (BLCKSZ );
514
485
515
486
newPage = levelstate -> pages [levelstate -> current_page ];
516
487
gistinitpage (newPage , old_page_flags );
@@ -573,14 +544,16 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
573
544
for (; dist != NULL ; dist = dist -> next )
574
545
{
575
546
char * data ;
547
+ BulkWriteBuffer buf ;
576
548
Page target ;
577
549
578
550
/* check once per page */
579
551
CHECK_FOR_INTERRUPTS ();
580
552
581
553
/* Create page and copy data */
582
554
data = (char * ) (dist -> list );
583
- target = palloc_aligned (BLCKSZ , PG_IO_ALIGN_SIZE , MCXT_ALLOC_ZERO );
555
+ buf = smgr_bulk_get_buf (state -> bulkstate );
556
+ target = (Page ) buf ;
584
557
gistinitpage (target , isleaf ? F_LEAF : 0 );
585
558
for (int i = 0 ; i < dist -> block .num ; i ++ )
586
559
{
@@ -593,20 +566,6 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
593
566
}
594
567
union_tuple = dist -> itup ;
595
568
596
- if (state -> ready_num_pages == XLR_MAX_BLOCK_ID )
597
- gist_indexsortbuild_flush_ready_pages (state );
598
-
599
- /*
600
- * The page is now complete. Assign a block number to it, and add it
601
- * to the list of finished pages. (We don't write it out immediately,
602
- * because we want to WAL-log the pages in batches.)
603
- */
604
- blkno = state -> pages_allocated ++ ;
605
- state -> ready_blknos [state -> ready_num_pages ] = blkno ;
606
- state -> ready_pages [state -> ready_num_pages ] = target ;
607
- state -> ready_num_pages ++ ;
608
- ItemPointerSetBlockNumber (& (union_tuple -> t_tid ), blkno );
609
-
610
569
/*
611
570
* Set the right link to point to the previous page. This is just for
612
571
* debugging purposes: GiST only follows the right link if a page is
@@ -621,6 +580,15 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
621
580
*/
622
581
if (levelstate -> last_blkno )
623
582
GistPageGetOpaque (target )-> rightlink = levelstate -> last_blkno ;
583
+
584
+ /*
585
+ * The page is now complete. Assign a block number to it, and pass it
586
+ * to the bulk writer.
587
+ */
588
+ blkno = state -> pages_allocated ++ ;
589
+ PageSetLSN (target , GistBuildLSN );
590
+ smgr_bulk_write (state -> bulkstate , blkno , buf , true);
591
+ ItemPointerSetBlockNumber (& (union_tuple -> t_tid ), blkno );
624
592
levelstate -> last_blkno = blkno ;
625
593
626
594
/*
@@ -631,7 +599,7 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
631
599
if (parent == NULL )
632
600
{
633
601
parent = palloc0 (sizeof (GistSortedBuildLevelState ));
634
- parent -> pages [0 ] = ( Page ) palloc_aligned ( BLCKSZ , PG_IO_ALIGN_SIZE , 0 );
602
+ parent -> pages [0 ] = palloc ( BLCKSZ );
635
603
parent -> parent = NULL ;
636
604
gistinitpage (parent -> pages [0 ], 0 );
637
605
@@ -641,39 +609,6 @@ gist_indexsortbuild_levelstate_flush(GISTBuildState *state,
641
609
}
642
610
}
643
611
644
- static void
645
- gist_indexsortbuild_flush_ready_pages (GISTBuildState * state )
646
- {
647
- if (state -> ready_num_pages == 0 )
648
- return ;
649
-
650
- for (int i = 0 ; i < state -> ready_num_pages ; i ++ )
651
- {
652
- Page page = state -> ready_pages [i ];
653
- BlockNumber blkno = state -> ready_blknos [i ];
654
-
655
- /* Currently, the blocks must be buffered in order. */
656
- if (blkno != state -> pages_written )
657
- elog (ERROR , "unexpected block number to flush GiST sorting build" );
658
-
659
- PageSetLSN (page , GistBuildLSN );
660
- PageSetChecksumInplace (page , blkno );
661
- smgrextend (RelationGetSmgr (state -> indexrel ), MAIN_FORKNUM , blkno , page ,
662
- true);
663
-
664
- state -> pages_written ++ ;
665
- }
666
-
667
- if (RelationNeedsWAL (state -> indexrel ))
668
- log_newpages (& state -> indexrel -> rd_locator , MAIN_FORKNUM , state -> ready_num_pages ,
669
- state -> ready_blknos , state -> ready_pages , true);
670
-
671
- for (int i = 0 ; i < state -> ready_num_pages ; i ++ )
672
- pfree (state -> ready_pages [i ]);
673
-
674
- state -> ready_num_pages = 0 ;
675
- }
676
-
677
612
678
613
/*-------------------------------------------------------------------------
679
614
* Routines for non-sorted build
0 commit comments