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

Commit 8fd04cb

Browse files
committed
Fix full-page writes of internal GIN pages.
Insertion to a non-leaf GIN page didn't make a full-page image of the page, which is wrong. The code used to do it correctly, but was changed (commit 853d1c3) because the redo-routine didn't track incomplete splits correctly when the page was restored from a full page image. Of course, that was not right way to fix it, the redo routine should've been fixed instead. The redo-routine was surreptitiously fixed in 2010 (commit 4016bde), so all we need to do now is revert the code that creates the record to its original form. This doesn't change the format of the WAL record. Backpatch to all supported versions.
1 parent b44ae48 commit 8fd04cb

File tree

2 files changed

+34
-50
lines changed

2 files changed

+34
-50
lines changed

src/backend/access/gin/gindatapage.c

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,6 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
381381
{
382382
Page page = BufferGetPage(buf);
383383
int sizeofitem = GinSizeOfDataPageItem(page);
384-
int cnt = 0;
385384

386385
/* these must be static so they can be returned to caller */
387386
static XLogRecData rdata[3];
@@ -401,32 +400,25 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
401400
data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
402401

403402
/*
404-
* Prevent full page write if child's split occurs. That is needed to
405-
* remove incomplete splits while replaying WAL
406-
*
407-
* data.updateBlkno contains new block number (of newly created right
408-
* page) for recently splited page.
403+
* For incomplete-split tracking, we need updateBlkno information and the
404+
* inserted item even when we make a full page image of the page, so put
405+
* the buffer reference in a separate XLogRecData entry.
409406
*/
410-
if (data.updateBlkno == InvalidBlockNumber)
411-
{
412-
rdata[0].buffer = buf;
413-
rdata[0].buffer_std = FALSE;
414-
rdata[0].data = NULL;
415-
rdata[0].len = 0;
416-
rdata[0].next = &rdata[1];
417-
cnt++;
418-
}
407+
rdata[0].buffer = buf;
408+
rdata[0].buffer_std = FALSE;
409+
rdata[0].data = NULL;
410+
rdata[0].len = 0;
411+
rdata[0].next = &rdata[1];
419412

420-
rdata[cnt].buffer = InvalidBuffer;
421-
rdata[cnt].data = (char *) &data;
422-
rdata[cnt].len = sizeof(ginxlogInsert);
423-
rdata[cnt].next = &rdata[cnt + 1];
424-
cnt++;
413+
rdata[1].buffer = InvalidBuffer;
414+
rdata[1].data = (char *) &data;
415+
rdata[1].len = sizeof(ginxlogInsert);
416+
rdata[1].next = &rdata[2];
425417

426-
rdata[cnt].buffer = InvalidBuffer;
427-
rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
428-
rdata[cnt].len = sizeofitem;
429-
rdata[cnt].next = NULL;
418+
rdata[2].buffer = InvalidBuffer;
419+
rdata[2].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
420+
rdata[2].len = sizeofitem;
421+
rdata[2].next = NULL;
430422

431423
if (GinPageIsLeaf(page))
432424
{
@@ -442,7 +434,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
442434
btree->curitem++;
443435
}
444436
data.nitem = btree->curitem - savedPos;
445-
rdata[cnt].len = sizeofitem * data.nitem;
437+
rdata[2].len = sizeofitem * data.nitem;
446438
}
447439
else
448440
{

src/backend/access/gin/ginentrypage.c

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,6 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
486486
{
487487
Page page = BufferGetPage(buf);
488488
OffsetNumber placed;
489-
int cnt = 0;
490489

491490
/* these must be static so they can be returned to caller */
492491
static XLogRecData rdata[3];
@@ -509,32 +508,25 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
509508
data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
510509

511510
/*
512-
* Prevent full page write if child's split occurs. That is needed to
513-
* remove incomplete splits while replaying WAL
514-
*
515-
* data.updateBlkno contains new block number (of newly created right
516-
* page) for recently splited page.
511+
* For incomplete-split tracking, we need updateBlkno information and the
512+
* inserted item even when we make a full page image of the page, so put
513+
* the buffer reference in a separate XLogRecData entry.
517514
*/
518-
if (data.updateBlkno == InvalidBlockNumber)
519-
{
520-
rdata[0].buffer = buf;
521-
rdata[0].buffer_std = TRUE;
522-
rdata[0].data = NULL;
523-
rdata[0].len = 0;
524-
rdata[0].next = &rdata[1];
525-
cnt++;
526-
}
527-
528-
rdata[cnt].buffer = InvalidBuffer;
529-
rdata[cnt].data = (char *) &data;
530-
rdata[cnt].len = sizeof(ginxlogInsert);
531-
rdata[cnt].next = &rdata[cnt + 1];
532-
cnt++;
515+
rdata[0].buffer = buf;
516+
rdata[0].buffer_std = TRUE;
517+
rdata[0].data = NULL;
518+
rdata[0].len = 0;
519+
rdata[0].next = &rdata[1];
533520

534-
rdata[cnt].buffer = InvalidBuffer;
535-
rdata[cnt].data = (char *) btree->entry;
536-
rdata[cnt].len = IndexTupleSize(btree->entry);
537-
rdata[cnt].next = NULL;
521+
rdata[1].buffer = InvalidBuffer;
522+
rdata[1].data = (char *) &data;
523+
rdata[1].len = sizeof(ginxlogInsert);
524+
rdata[1].next = &rdata[2];
525+
526+
rdata[2].buffer = InvalidBuffer;
527+
rdata[2].data = (char *) btree->entry;
528+
rdata[2].len = IndexTupleSize(btree->entry);
529+
rdata[2].next = NULL;
538530

539531
btree->entry = NULL;
540532
}

0 commit comments

Comments
 (0)