Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0a59976

Browse files
committed
Apply CORE-367-WAL patch
1 parent 884a5d3 commit 0a59976

File tree

17 files changed

+126
-91
lines changed

17 files changed

+126
-91
lines changed

src/backend/access/brin/brin_pageops.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ brin_metapage_init(Page page, BlockNumber pagesPerRange, uint16 version)
497497
* revmap page to be created when the index is.
498498
*/
499499
metadata->lastRevmapPage = 0;
500+
((PageHeader) page)->pd_lower += sizeof(BrinMetaPageData);
500501
}
501502

502503
/*

src/backend/access/gin/ginbtree.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
387387
/* It will fit, perform the insertion */
388388
START_CRIT_SECTION();
389389

390-
if (RelationNeedsWAL(btree->index))
390+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
391391
{
392392
XLogBeginInsert();
393393
XLogRegisterBuffer(0, stack->buffer, REGBUF_STANDARD);
@@ -408,7 +408,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
408408
MarkBufferDirty(childbuf);
409409
}
410410

411-
if (RelationNeedsWAL(btree->index))
411+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
412412
{
413413
XLogRecPtr recptr;
414414
ginxlogInsert xlrec;
@@ -565,7 +565,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
565565
}
566566

567567
/* write WAL record */
568-
if (RelationNeedsWAL(btree->index))
568+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
569569
{
570570
XLogRecPtr recptr;
571571

src/backend/access/gin/gindatapage.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ dataBeginPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
591591
* Great, all the items fit on a single page. If needed, prepare data
592592
* for a WAL record describing the changes we'll make.
593593
*/
594-
if (RelationNeedsWAL(btree->index))
594+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
595595
computeLeafRecompressWALData(leaf);
596596

597597
/*
@@ -628,6 +628,7 @@ dataBeginPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
628628
* subsequent insertions will probably also go to the end. This packs
629629
* the index somewhat tighter when appending to a table, which is very
630630
* common.
631+
*
631632
*/
632633
if (!btree->isBuild)
633634
{
@@ -717,7 +718,7 @@ dataExecPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
717718
dataPlaceToPageLeafRecompress(buf, leaf);
718719

719720
/* If needed, register WAL data built by computeLeafRecompressWALData */
720-
if (RelationNeedsWAL(btree->index))
721+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
721722
{
722723
XLogRegisterBufData(0, leaf->walinfo, leaf->walinfolen);
723724
}
@@ -1150,7 +1151,7 @@ dataExecPlaceToPageInternal(GinBtree btree, Buffer buf, GinBtreeStack *stack,
11501151
pitem = (PostingItem *) insertdata;
11511152
GinDataPageAddPostingItem(page, pitem, off);
11521153

1153-
if (RelationNeedsWAL(btree->index))
1154+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
11541155
{
11551156
/*
11561157
* This must be static, because it has to survive until XLogInsert,
@@ -1767,6 +1768,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
17671768
Pointer ptr;
17681769
int nrootitems;
17691770
int rootsize;
1771+
bool is_build = (buildStats != NULL);
17701772

17711773
/* Construct the new root page in memory first. */
17721774
tmppage = (Page) palloc(BLCKSZ);
@@ -1814,7 +1816,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
18141816
PageRestoreTempPage(tmppage, page);
18151817
MarkBufferDirty(buffer);
18161818

1817-
if (RelationNeedsWAL(index))
1819+
if (RelationNeedsWAL(index) && !is_build)
18181820
{
18191821
XLogRecPtr recptr;
18201822
ginxlogCreatePostingTree data;

src/backend/access/gin/ginentrypage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ entryExecPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack,
570570
elog(ERROR, "failed to add item to index page in \"%s\"",
571571
RelationGetRelationName(btree->index));
572572

573-
if (RelationNeedsWAL(btree->index))
573+
if (RelationNeedsWAL(btree->index) && !btree->isBuild)
574574
{
575575
/*
576576
* This must be static, because it has to survive until XLogInsert,

src/backend/access/gin/gininsert.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "access/gin_private.h"
1818
#include "access/xloginsert.h"
19+
#include "access/generic_xlog.h"
1920
#include "catalog/index.h"
2021
#include "miscadmin.h"
2122
#include "storage/bufmgr.h"
@@ -191,6 +192,7 @@ ginEntryInsert(GinState *ginstate,
191192
buildStats->nEntries++;
192193

193194
ginPrepareEntryScan(&btree, attnum, key, category, ginstate);
195+
btree.isBuild = (buildStats != NULL);
194196

195197
stack = ginFindLeafPage(&btree, false, NULL);
196198
page = BufferGetPage(stack->buffer);
@@ -341,24 +343,6 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
341343
GinInitBuffer(RootBuffer, GIN_LEAF);
342344
MarkBufferDirty(RootBuffer);
343345

344-
if (RelationNeedsWAL(index))
345-
{
346-
XLogRecPtr recptr;
347-
Page page;
348-
349-
XLogBeginInsert();
350-
XLogRegisterBuffer(0, MetaBuffer, REGBUF_WILL_INIT);
351-
XLogRegisterBuffer(1, RootBuffer, REGBUF_WILL_INIT);
352-
353-
recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_CREATE_INDEX);
354-
355-
page = BufferGetPage(RootBuffer);
356-
PageSetLSN(page, recptr);
357-
358-
page = BufferGetPage(MetaBuffer);
359-
PageSetLSN(page, recptr);
360-
}
361-
362346
UnlockReleaseBuffer(MetaBuffer);
363347
UnlockReleaseBuffer(RootBuffer);
364348
END_CRIT_SECTION();
@@ -412,7 +396,10 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
412396
* Update metapage stats
413397
*/
414398
buildstate.buildStats.nTotalPages = RelationGetNumberOfBlocks(index);
415-
ginUpdateStats(index, &buildstate.buildStats);
399+
ginUpdateStats(index, &buildstate.buildStats, true);
400+
401+
if (RelationNeedsWAL(index))
402+
generate_xlog_for_rel(index);
416403

417404
/*
418405
* Return statistics

src/backend/access/gin/ginutil.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ GinInitMetabuffer(Buffer b)
342342
metadata->nDataPages = 0;
343343
metadata->nEntries = 0;
344344
metadata->ginVersion = GIN_CURRENT_VERSION;
345+
346+
((PageHeader) page)->pd_lower += sizeof(GinMetaPageData);
345347
}
346348

347349
/*
@@ -626,7 +628,7 @@ ginGetStats(Relation index, GinStatsData *stats)
626628
* Note: nPendingPages and ginVersion are *not* copied over
627629
*/
628630
void
629-
ginUpdateStats(Relation index, const GinStatsData *stats)
631+
ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build)
630632
{
631633
Buffer metabuffer;
632634
Page metapage;
@@ -646,7 +648,7 @@ ginUpdateStats(Relation index, const GinStatsData *stats)
646648

647649
MarkBufferDirty(metabuffer);
648650

649-
if (RelationNeedsWAL(index))
651+
if (RelationNeedsWAL(index) && !is_build)
650652
{
651653
XLogRecPtr recptr;
652654
ginxlogUpdateMeta data;

src/backend/access/gin/ginvacuum.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
731731

732732
/* Update the metapage with accurate page and entry counts */
733733
idxStat.nTotalPages = npages;
734-
ginUpdateStats(info->index, &idxStat);
734+
ginUpdateStats(info->index, &idxStat, false);
735735

736736
/* Finally, vacuum the FSM */
737737
IndexFreeSpaceMapVacuum(info->index);

src/backend/access/gist/gist.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ gistinsert(Relation r, Datum *values, bool *isnull,
162162
values, isnull, true /* size is currently bogus */ );
163163
itup->t_tid = *ht_ctid;
164164

165-
gistdoinsert(r, itup, 0, giststate);
165+
gistdoinsert(r, itup, 0, giststate, false);
166166

167167
/* cleanup */
168168
MemoryContextSwitchTo(oldCxt);
@@ -208,7 +208,8 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
208208
BlockNumber *newblkno,
209209
Buffer leftchildbuf,
210210
List **splitinfo,
211-
bool markfollowright)
211+
bool markfollowright,
212+
bool is_build)
212213
{
213214
BlockNumber blkno = BufferGetBlockNumber(buffer);
214215
Page page = BufferGetPage(buffer);
@@ -444,7 +445,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
444445
* insertion for that. NB: The number of pages and data segments
445446
* specified here must match the calculations in gistXLogSplit()!
446447
*/
447-
if (RelationNeedsWAL(rel))
448+
if (RelationNeedsWAL(rel) && !is_build)
448449
XLogEnsureRecordSpace(npage, 1 + npage * 2);
449450

450451
START_CRIT_SECTION();
@@ -465,18 +466,20 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
465466
PageRestoreTempPage(dist->page, BufferGetPage(dist->buffer));
466467
dist->page = BufferGetPage(dist->buffer);
467468

468-
/* Write the WAL record */
469-
if (RelationNeedsWAL(rel))
469+
/*
470+
* Write the WAL record.
471+
* Do not write XLog entry if the insertion is caused by
472+
* index build process.
473+
*/
474+
if (RelationNeedsWAL(rel) && !is_build)
470475
recptr = gistXLogSplit(is_leaf,
471-
dist, oldrlink, oldnsn, leftchildbuf,
472-
markfollowright);
476+
dist, oldrlink, oldnsn, leftchildbuf,
477+
markfollowright);
473478
else
474479
recptr = gistGetFakeLSN(rel);
475480

476481
for (ptr = dist; ptr; ptr = ptr->next)
477-
{
478482
PageSetLSN(ptr->page, recptr);
479-
}
480483

481484
/*
482485
* Return the new child buffers to the caller.
@@ -512,7 +515,8 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
512515
if (BufferIsValid(leftchildbuf))
513516
MarkBufferDirty(leftchildbuf);
514517

515-
if (RelationNeedsWAL(rel))
518+
519+
if (RelationNeedsWAL(rel) && !is_build)
516520
{
517521
OffsetNumber ndeloffs = 0,
518522
deloffs[1];
@@ -535,6 +539,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
535539
PageSetLSN(page, recptr);
536540
}
537541

542+
538543
if (newblkno)
539544
*newblkno = blkno;
540545
}
@@ -551,17 +556,28 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
551556
* the full page image. There's a chicken-and-egg problem: if we updated
552557
* the child pages first, we wouldn't know the recptr of the WAL record
553558
* we're about to write.
559+
*
560+
* We use fakeLSNs for inserions caused by index build. And when it is
561+
* finished, we write generic_xlog entry for each index page and update
562+
* all LSNs. In order to keep NSNs less then LSNs after this update, we
563+
* set NSN to InvalidXLogRecPtr, which is the smallest possible NSN.
554564
*/
565+
555566
if (BufferIsValid(leftchildbuf))
556567
{
557568
Page leftpg = BufferGetPage(leftchildbuf);
569+
XLogRecPtr fakerecptr = InvalidXLogRecPtr;
558570

559-
GistPageSetNSN(leftpg, recptr);
560-
GistClearFollowRight(leftpg);
571+
if (!is_build)
572+
GistPageSetNSN(leftpg, recptr);
573+
else
574+
GistPageSetNSN(leftpg, fakerecptr);
561575

576+
GistClearFollowRight(leftpg);
562577
PageSetLSN(leftpg, recptr);
563578
}
564579

580+
565581
END_CRIT_SECTION();
566582

567583
return is_split;
@@ -573,7 +589,8 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
573589
* so it does not bother releasing palloc'd allocations.
574590
*/
575591
void
576-
gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
592+
gistdoinsert(Relation r, IndexTuple itup, Size freespace,
593+
GISTSTATE *giststate, bool is_build)
577594
{
578595
ItemId iid;
579596
IndexTuple idxtuple;
@@ -585,6 +602,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
585602
memset(&state, 0, sizeof(GISTInsertState));
586603
state.freespace = freespace;
587604
state.r = r;
605+
state.is_build = is_build;
588606

589607
/* Start from the root */
590608
firststack.blkno = GIST_ROOT_BLKNO;
@@ -1194,7 +1212,7 @@ gistinserttuples(GISTInsertState *state, GISTInsertStack *stack,
11941212
oldoffnum, NULL,
11951213
leftchild,
11961214
&splitinfo,
1197-
true);
1215+
true, state->is_build);
11981216

11991217
/*
12001218
* Before recursing up in case the page was split, release locks on the

src/backend/access/gist/gistbuild.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "access/genam.h"
2020
#include "access/gist_private.h"
2121
#include "access/xloginsert.h"
22+
#include "access/generic_xlog.h"
2223
#include "catalog/index.h"
2324
#include "miscadmin.h"
2425
#include "optimizer/cost.h"
@@ -177,18 +178,12 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
177178

178179
MarkBufferDirty(buffer);
179180

180-
if (RelationNeedsWAL(index))
181-
{
182-
XLogRecPtr recptr;
183-
184-
XLogBeginInsert();
185-
XLogRegisterBuffer(0, buffer, REGBUF_WILL_INIT);
186-
187-
recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_CREATE_INDEX);
188-
PageSetLSN(page, recptr);
189-
}
190-
else
191-
PageSetLSN(page, gistGetFakeLSN(heap));
181+
/*
182+
* Do not write index pages to WAL unitl index build is finished.
183+
* But we still need increasing LSNs on each page, so use FakeLSN,
184+
* even for relations which eventually need WAL.
185+
*/
186+
PageSetLSN(page, gistGetFakeLSN(heap));
192187

193188
UnlockReleaseBuffer(buffer);
194189

@@ -221,6 +216,15 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
221216

222217
freeGISTstate(buildstate.giststate);
223218

219+
/*
220+
* Create generic wal records for all pages of relation, if necessary.
221+
* It seems reasonable not to generate WAL, if we recieved interrupt
222+
* signal.
223+
*/
224+
CHECK_FOR_INTERRUPTS();
225+
if (RelationNeedsWAL(index))
226+
generate_xlog_for_rel(index);
227+
224228
/*
225229
* Return statistics
226230
*/
@@ -483,7 +487,7 @@ gistBuildCallback(Relation index,
483487
* locked, we call gistdoinsert directly.
484488
*/
485489
gistdoinsert(index, itup, buildstate->freespace,
486-
buildstate->giststate);
490+
buildstate->giststate, true);
487491
}
488492

489493
/* Update tuple count and total size. */
@@ -689,7 +693,7 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
689693
itup, ntup, oldoffnum, &placed_to_blk,
690694
InvalidBuffer,
691695
&splitinfo,
692-
false);
696+
false, true);
693697

694698
/*
695699
* If this is a root split, update the root path item kept in memory. This

src/backend/access/gist/gistutil.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ gistproperty(Oid index_oid, int attno,
914914
* Temporary and unlogged GiST indexes are not WAL-logged, but we need LSNs
915915
* to detect concurrent page splits anyway. This function provides a fake
916916
* sequence of LSNs for that purpose.
917+
* Persistent relations are also not WAL-logged while we build index.
917918
*/
918919
XLogRecPtr
919920
gistGetFakeLSN(Relation rel)
@@ -934,7 +935,6 @@ gistGetFakeLSN(Relation rel)
934935
* Unlogged relations are accessible from other backends, and survive
935936
* (clean) restarts. GetFakeLSNForUnloggedRel() handles that for us.
936937
*/
937-
Assert(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED);
938938
return GetFakeLSNForUnloggedRel();
939939
}
940940
}

0 commit comments

Comments
 (0)