summaryrefslogtreecommitdiff
path: root/src/backend/access/gin/gindatapage.c
diff options
context:
space:
mode:
authorTeodor Sigaev <teodor@sigaev.ru>2007-06-04 15:59:20 +0000
committerTeodor Sigaev <teodor@sigaev.ru>2007-06-04 15:59:20 +0000
commit07bd1db152e95a44722c1fd23572dfeaf8e07eaf (patch)
tree858afe1cda3fb0df8e86ae252c137db835bfe28a /src/backend/access/gin/gindatapage.c
parent6209cb3f7d32c5806ed0a985e4afa66649befb70 (diff)
Fix bundle bugs of GIN:
- Fix possible deadlock between UPDATE and VACUUM queries. Bug never was observed in 8.2, but it still exist there. HEAD is more sensitive to bug after recent "ring" of buffer improvements. - Fix WAL creation: if parent page is stored as is after split then incomplete split isn't removed during replay. This happens rather rare, only on large tables with a lot of updates/inserts. - Fix WAL replay: there was wrong test of XLR_BKP_BLOCK_* for left page after deletion of page. That causes wrong rightlink field: it pointed to deleted page. - add checking of match of clearing incomplete split - cleanup incomplete split list after proceeding All of this chages doesn't change on-disk storage, so backpatch... But second point may be an issue for replaying logs from previous version.
Diffstat (limited to 'src/backend/access/gin/gindatapage.c')
-rw-r--r--src/backend/access/gin/gindatapage.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 9c9712b4465..64098d70400 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/gindatapage.c,v 1.5 2006/11/12 06:55:53 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/gindatapage.c,v 1.5.2.1 2007/06/04 15:59:19 teodor Exp $
*-------------------------------------------------------------------------
*/
@@ -358,6 +358,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
static XLogRecData rdata[3];
int sizeofitem = GinSizeOfItem(page);
static ginxlogInsert data;
+ int cnt=0;
*prdata = rdata;
Assert(GinPageIsData(page));
@@ -372,21 +373,33 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
data.isData = TRUE;
data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
- rdata[0].buffer = buf;
- rdata[0].buffer_std = FALSE;
- rdata[0].data = NULL;
- rdata[0].len = 0;
- rdata[0].next = &rdata[1];
+ /*
+ * Prevent full page write if child's split occurs. That is needed
+ * to remove incomplete splits while replaying WAL
+ *
+ * data.updateBlkno contains new block number (of newly created right page)
+ * for recently splited page.
+ */
+ if ( data.updateBlkno == InvalidBlockNumber )
+ {
+ rdata[0].buffer = buf;
+ rdata[0].buffer_std = FALSE;
+ rdata[0].data = NULL;
+ rdata[0].len = 0;
+ rdata[0].next = &rdata[1];
+ cnt++;
+ }
- rdata[1].buffer = InvalidBuffer;
- rdata[1].data = (char *) &data;
- rdata[1].len = sizeof(ginxlogInsert);
- rdata[1].next = &rdata[2];
+ rdata[cnt].buffer = InvalidBuffer;
+ rdata[cnt].data = (char *) &data;
+ rdata[cnt].len = sizeof(ginxlogInsert);
+ rdata[cnt].next = &rdata[cnt+1];
+ cnt++;
- rdata[2].buffer = InvalidBuffer;
- rdata[2].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
- rdata[2].len = sizeofitem;
- rdata[2].next = NULL;
+ rdata[cnt].buffer = InvalidBuffer;
+ rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
+ rdata[cnt].len = sizeofitem;
+ rdata[cnt].next = NULL;
if (GinPageIsLeaf(page))
{
@@ -402,7 +415,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
btree->curitem++;
}
data.nitem = btree->curitem - savedPos;
- rdata[2].len = sizeofitem * data.nitem;
+ rdata[cnt].len = sizeofitem * data.nitem;
}
else
{