Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit384cad5

Browse files
committed
Fix two distinct errors in creation of GIN_INSERT_LISTPAGE xlog records.
In practice these mistakes were always masked when full_page_writes was on,because XLogInsert would always choose to log the full page, and thenginRedoInsertListPage wouldn't try to do anything. But with full_page_writesoff a WAL replay failure was certain.The GIN_INSERT_LISTPAGE record type could probably be eliminated entirelyin favor of using XLOG_HEAP_NEWPAGE, but I refrained from doing that nowsince it would have required a significantly more invasive patch.In passing do a little bit of code cleanup, including making the accountingfor free space on GIN list pages more precise. (This wasn't a bug as theerrors were always in the conservative direction.)Per report from Simon. Back-patch to 8.4 which contains the identical code.
1 parentf3ef948 commit384cad5

File tree

1 file changed

+44
-34
lines changed

1 file changed

+44
-34
lines changed

‎src/backend/access/gin/ginfast.c

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
1313
* IDENTIFICATION
14-
*$PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.3 2009/06/11 14:48:53 momjian Exp $
14+
*$PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.4 2009/09/15 20:31:30 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -41,13 +41,15 @@ typedef struct DatumArray
4141

4242
/*
4343
* Build a pending-list page from the given array of tuples, and write it out.
44+
*
45+
* Returns amount of free space left on the page.
4446
*/
4547
staticint32
4648
writeListPage(Relationindex,Bufferbuffer,
4749
IndexTuple*tuples,int32ntuples,BlockNumberrightlink)
4850
{
4951
Pagepage=BufferGetPage(buffer);
50-
inti,
52+
int32i,
5153
freesize,
5254
size=0;
5355
OffsetNumberl,
@@ -100,8 +102,6 @@ writeListPage(Relation index, Buffer buffer,
100102
GinPageGetOpaque(page)->maxoff=0;
101103
}
102104

103-
freesize=PageGetFreeSpace(page);
104-
105105
MarkBufferDirty(buffer);
106106

107107
if (!index->rd_istemp)
@@ -110,26 +110,30 @@ writeListPage(Relation index, Buffer buffer,
110110
ginxlogInsertListPagedata;
111111
XLogRecPtrrecptr;
112112

113-
rdata[0].buffer=buffer;
114-
rdata[0].buffer_std= true;
113+
data.node=index->rd_node;
114+
data.blkno=BufferGetBlockNumber(buffer);
115+
data.rightlink=rightlink;
116+
data.ntuples=ntuples;
117+
118+
rdata[0].buffer=InvalidBuffer;
115119
rdata[0].data= (char*)&data;
116120
rdata[0].len=sizeof(ginxlogInsertListPage);
117121
rdata[0].next=rdata+1;
118122

119-
rdata[1].buffer=InvalidBuffer;
123+
rdata[1].buffer=buffer;
124+
rdata[1].buffer_std= true;
120125
rdata[1].data=workspace;
121126
rdata[1].len=size;
122127
rdata[1].next=NULL;
123128

124-
data.blkno=BufferGetBlockNumber(buffer);
125-
data.rightlink=rightlink;
126-
data.ntuples=ntuples;
127-
128129
recptr=XLogInsert(RM_GIN_ID,XLOG_GIN_INSERT_LISTPAGE,rdata);
129130
PageSetLSN(page,recptr);
130131
PageSetTLI(page,ThisTimeLineID);
131132
}
132133

134+
/* get free space before releasing buffer */
135+
freesize=PageGetExactFreeSpace(page);
136+
133137
UnlockReleaseBuffer(buffer);
134138

135139
END_CRIT_SECTION();
@@ -165,7 +169,8 @@ makeSublist(Relation index, IndexTuple *tuples, int32 ntuples,
165169
{
166170
res->nPendingPages++;
167171
writeListPage(index,prevBuffer,
168-
tuples+startTuple,i-startTuple,
172+
tuples+startTuple,
173+
i-startTuple,
169174
BufferGetBlockNumber(curBuffer));
170175
}
171176
else
@@ -180,7 +185,7 @@ makeSublist(Relation index, IndexTuple *tuples, int32 ntuples,
180185

181186
tupsize=MAXALIGN(IndexTupleSize(tuples[i]))+sizeof(ItemIdData);
182187

183-
if (size+tupsize >=GinListPageSize)
188+
if (size+tupsize>GinListPageSize)
184189
{
185190
/* won't fit, force a new page and reprocess */
186191
i--;
@@ -197,7 +202,8 @@ makeSublist(Relation index, IndexTuple *tuples, int32 ntuples,
197202
*/
198203
res->tail=BufferGetBlockNumber(curBuffer);
199204
res->tailFreeSize=writeListPage(index,curBuffer,
200-
tuples+startTuple,ntuples-startTuple,
205+
tuples+startTuple,
206+
ntuples-startTuple,
201207
InvalidBlockNumber);
202208
res->nPendingPages++;
203209
/* that was only one heap tuple */
@@ -237,7 +243,7 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
237243
metabuffer=ReadBuffer(index,GIN_METAPAGE_BLKNO);
238244
metapage=BufferGetPage(metabuffer);
239245

240-
if (collector->sumsize+collector->ntuples*sizeof(ItemIdData)>GIN_PAGE_FREESIZE)
246+
if (collector->sumsize+collector->ntuples*sizeof(ItemIdData)>GinListPageSize)
241247
{
242248
/*
243249
* Total size is greater than one page => make sublist
@@ -265,13 +271,12 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
265271

266272
if (separateList)
267273
{
268-
GinMetaPageDatasublist;
269-
270274
/*
271275
* We should make sublist separately and append it to the tail
272276
*/
273-
memset(&sublist,0,sizeof(GinMetaPageData));
277+
GinMetaPageDatasublist;
274278

279+
memset(&sublist,0,sizeof(GinMetaPageData));
275280
makeSublist(index,collector->tuples,collector->ntuples,&sublist);
276281

277282
/*
@@ -283,45 +288,44 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
283288
if (metadata->head==InvalidBlockNumber)
284289
{
285290
/*
286-
*Sublist becomes main list
291+
*Main list is empty, so just copy sublist into main list
287292
*/
288293
START_CRIT_SECTION();
294+
289295
memcpy(metadata,&sublist,sizeof(GinMetaPageData));
290-
memcpy(&data.metadata,&sublist,sizeof(GinMetaPageData));
291296
}
292297
else
293298
{
294299
/*
295-
*merge lists
300+
*Merge lists
296301
*/
297-
298302
data.prevTail=metadata->tail;
303+
data.newRightlink=sublist.head;
304+
299305
buffer=ReadBuffer(index,metadata->tail);
300306
LockBuffer(buffer,GIN_EXCLUSIVE);
301307
page=BufferGetPage(buffer);
308+
302309
Assert(GinPageGetOpaque(page)->rightlink==InvalidBlockNumber);
303310

304311
START_CRIT_SECTION();
305312

306313
GinPageGetOpaque(page)->rightlink=sublist.head;
314+
315+
MarkBufferDirty(buffer);
316+
307317
metadata->tail=sublist.tail;
308318
metadata->tailFreeSize=sublist.tailFreeSize;
309319

310320
metadata->nPendingPages+=sublist.nPendingPages;
311321
metadata->nPendingHeapTuples+=sublist.nPendingHeapTuples;
312-
313-
memcpy(&data.metadata,metadata,sizeof(GinMetaPageData));
314-
data.newRightlink=sublist.head;
315-
316-
MarkBufferDirty(buffer);
317322
}
318323
}
319324
else
320325
{
321326
/*
322-
* Insert into tail page, metapage is already locked
327+
* Insert into tail page. Metapage is already locked
323328
*/
324-
325329
OffsetNumberl,
326330
off;
327331
inti,
@@ -331,6 +335,7 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
331335
buffer=ReadBuffer(index,metadata->tail);
332336
LockBuffer(buffer,GIN_EXCLUSIVE);
333337
page=BufferGetPage(buffer);
338+
334339
off= (PageIsEmpty(page)) ?FirstOffsetNumber :
335340
OffsetNumberNext(PageGetMaxOffsetNumber(page));
336341

@@ -368,20 +373,24 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
368373
off++;
369374
}
370375

371-
metadata->tailFreeSize-=collector->sumsize+collector->ntuples*sizeof(ItemIdData);
372-
memcpy(&data.metadata,metadata,sizeof(GinMetaPageData));
376+
Assert((ptr-rdata[1].data) <=collector->sumsize);
377+
378+
metadata->tailFreeSize=PageGetExactFreeSpace(page);
379+
373380
MarkBufferDirty(buffer);
374381
}
375382

376383
/*
377-
*Make real write
384+
*Write metabuffer, make xlog entry
378385
*/
379-
380386
MarkBufferDirty(metabuffer);
387+
381388
if (!index->rd_istemp)
382389
{
383390
XLogRecPtrrecptr;
384391

392+
memcpy(&data.metadata,metadata,sizeof(GinMetaPageData));
393+
385394
recptr=XLogInsert(RM_GIN_ID,XLOG_GIN_UPDATE_META_PAGE,rdata);
386395
PageSetLSN(metapage,recptr);
387396
PageSetTLI(metapage,ThisTimeLineID);
@@ -552,7 +561,6 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
552561
metadata->nPendingPages=0;
553562
metadata->nPendingHeapTuples=0;
554563
}
555-
memcpy(&data.metadata,metadata,sizeof(GinMetaPageData));
556564

557565
MarkBufferDirty(metabuffer);
558566

@@ -567,6 +575,8 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
567575
{
568576
XLogRecPtrrecptr;
569577

578+
memcpy(&data.metadata,metadata,sizeof(GinMetaPageData));
579+
570580
recptr=XLogInsert(RM_GIN_ID,XLOG_GIN_DELETE_LISTPAGE,rdata);
571581
PageSetLSN(metapage,recptr);
572582
PageSetTLI(metapage,ThisTimeLineID);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp