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

Commitdb03cf3

Browse files
committed
Code review/prettification for generic_xlog.c.
Improve commentary, use more specific names for the delta fields,const-ify pointer arguments where possible, avoid assuming thatinitializing only the first element of a local array will guaranteethat the remaining elements end up as we need them. (I think thatcode in generic_redo actually worked, but only because InvalidBufferis zero; this is a particularly ugly way of depending on that ...)
1 parent2dd318d commitdb03cf3

File tree

1 file changed

+92
-67
lines changed

1 file changed

+92
-67
lines changed

‎src/backend/access/transam/generic_xlog.c

Lines changed: 92 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
* - length of page region (OffsetNumber)
2828
* - data - the data to place into the region ('length' number of bytes)
2929
*
30-
* Unchanged regions of a page are not represented in its delta. As a
31-
*result,a delta can be more compact than the full page image. But having
32-
*anunchanged regionin the middle oftwo fragments that is smaller than
33-
*the fragmentheader (offset andlength) does not pay off in terms of the
34-
*overall size ofthe delta. For this reason, webreakfragmentsonly if
35-
*the unchanged region isbigger thanMATCH_THRESHOLD.
30+
* Unchanged regions of a page are not represented in its delta. As a result,
31+
* a delta can be more compact than the full page image. But having an
32+
* unchanged regionbetweentwo fragments that is smaller than the fragment
33+
* header (offset+length) does not pay off in terms of the overall size of
34+
* the delta.For this reason, wemerge adjacentfragmentsif the unchanged
35+
*region between them is<=MATCH_THRESHOLD bytes.
3636
*
3737
* The worst case for delta sizes occurs when we did not find any unchanged
3838
* region in the page. The size of the delta will be the size of the page plus
@@ -41,16 +41,16 @@
4141
*/
4242
#defineFRAGMENT_HEADER_SIZE(2 * sizeof(OffsetNumber))
4343
#defineMATCH_THRESHOLDFRAGMENT_HEADER_SIZE
44-
#defineMAX_DELTA_SIZEBLCKSZ + FRAGMENT_HEADER_SIZE
44+
#defineMAX_DELTA_SIZE(BLCKSZ + FRAGMENT_HEADER_SIZE)
4545

4646
/* Struct of generic xlog data for single page */
4747
typedefstruct
4848
{
4949
Bufferbuffer;/* registered buffer */
50-
charimage[BLCKSZ];/* copy of page image for modification */
51-
chardata[MAX_DELTA_SIZE];/* delta between page images */
52-
intdataLen;/* space consumed in data field */
5350
boolfullImage;/* are we taking a full image of this page? */
51+
intdeltaLen;/* space consumed in delta field */
52+
charimage[BLCKSZ];/* copy of page image for modification */
53+
chardelta[MAX_DELTA_SIZE];/* delta between page images */
5454
}PageData;
5555

5656
/* State of generic xlog record construction */
@@ -61,22 +61,26 @@ struct GenericXLogState
6161
};
6262

6363
staticvoidwriteFragment(PageData*pageData,OffsetNumberoffset,
64-
OffsetNumberlen,Pointerdata);
65-
staticvoidwriteDelta(PageData*pageData);
66-
staticvoidapplyPageRedo(Pagepage,Pointerdata,SizedataSize);
64+
OffsetNumberlen,constchar*data);
65+
staticvoidcomputeDelta(PageData*pageData);
66+
staticvoidapplyPageRedo(Pagepage,constchar*delta,SizedeltaSize);
67+
6768

6869
/*
69-
* Write next fragment into delta.
70+
* Write next fragment into pageData's delta.
71+
*
72+
* The fragment has the given offset and length, and data points to the
73+
* actual data (of length length).
7074
*/
7175
staticvoid
7276
writeFragment(PageData*pageData,OffsetNumberoffset,OffsetNumberlength,
73-
Pointerdata)
77+
constchar*data)
7478
{
75-
Pointerptr=pageData->data+pageData->dataLen;
79+
char*ptr=pageData->delta+pageData->deltaLen;
7680

77-
/*Check if we have enough space */
78-
Assert(pageData->dataLen+sizeof(offset)+
79-
sizeof(length)+length <=sizeof(pageData->data));
81+
/*Verify we have enough space */
82+
Assert(pageData->deltaLen+sizeof(offset)+
83+
sizeof(length)+length <=sizeof(pageData->delta));
8084

8185
/* Write fragment data */
8286
memcpy(ptr,&offset,sizeof(offset));
@@ -86,14 +90,14 @@ writeFragment(PageData *pageData, OffsetNumber offset, OffsetNumber length,
8690
memcpy(ptr,data,length);
8791
ptr+=length;
8892

89-
pageData->dataLen=ptr-pageData->data;
93+
pageData->deltaLen=ptr-pageData->delta;
9094
}
9195

9296
/*
93-
*Makedelta for given page.
97+
*Compute thedelta record for given page.
9498
*/
9599
staticvoid
96-
writeDelta(PageData*pageData)
100+
computeDelta(PageData*pageData)
97101
{
98102
Pagepage=BufferGetPage(pageData->buffer,NULL,NULL,
99103
BGP_NO_SNAPSHOT_TEST),
@@ -106,6 +110,8 @@ writeDelta(PageData *pageData)
106110
imageLower= ((PageHeader)image)->pd_lower,
107111
imageUpper= ((PageHeader)image)->pd_upper;
108112

113+
pageData->deltaLen=0;
114+
109115
for (i=0;i<BLCKSZ;i++)
110116
{
111117
boolmatch;
@@ -181,22 +187,22 @@ writeDelta(PageData *pageData)
181187
chartmp[BLCKSZ];
182188

183189
memcpy(tmp,image,BLCKSZ);
184-
applyPageRedo(tmp,pageData->data,pageData->dataLen);
185-
if (memcmp(tmp,page,pageLower)
186-
||memcmp(tmp+pageUpper,page+pageUpper,BLCKSZ-pageUpper))
190+
applyPageRedo(tmp,pageData->delta,pageData->deltaLen);
191+
if (memcmp(tmp,page,pageLower)!=0||
192+
memcmp(tmp+pageUpper,page+pageUpper,BLCKSZ-pageUpper)!=0)
187193
elog(ERROR,"result of generic xlog apply does not match");
188194
}
189195
#endif
190196
}
191197

192198
/*
193-
* Start new generic xlog record.
199+
* Start new generic xlog record for modifications to specified relation.
194200
*/
195201
GenericXLogState*
196202
GenericXLogStart(Relationrelation)
197203
{
198-
inti;
199204
GenericXLogState*state;
205+
inti;
200206

201207
state= (GenericXLogState*)palloc(sizeof(GenericXLogState));
202208

@@ -209,24 +215,30 @@ GenericXLogStart(Relation relation)
209215

210216
/*
211217
* Register new buffer for generic xlog record.
218+
*
219+
* Returns pointer to the page's image in the GenericXLogState, which
220+
* is what the caller should modify.
221+
*
222+
* If the buffer is already registered, just return its existing entry.
212223
*/
213224
Page
214225
GenericXLogRegister(GenericXLogState*state,Bufferbuffer,boolisNew)
215226
{
216227
intblock_id;
217228

218-
/*Place new buffer to unused slot in array */
229+
/*Search array for existing entry or first unused slot */
219230
for (block_id=0;block_id<MAX_GENERIC_XLOG_PAGES;block_id++)
220231
{
221232
PageData*page=&state->pages[block_id];
222233

223234
if (BufferIsInvalid(page->buffer))
224235
{
236+
/* Empty slot, so use it (there cannot be a match later) */
225237
page->buffer=buffer;
226-
memcpy(page->image,BufferGetPage(buffer,NULL,NULL,
227-
BGP_NO_SNAPSHOT_TEST),BLCKSZ);
228-
page->dataLen=0;
229238
page->fullImage=isNew;
239+
memcpy(page->image,
240+
BufferGetPage(buffer,NULL,NULL,BGP_NO_SNAPSHOT_TEST),
241+
BLCKSZ);
230242
return (Page)page->image;
231243
}
232244
elseif (page->buffer==buffer)
@@ -239,15 +251,16 @@ GenericXLogRegister(GenericXLogState *state, Buffer buffer, bool isNew)
239251
}
240252
}
241253

242-
elog(ERROR,"maximum numberof %d generic xlog buffers is exceeded",
254+
elog(ERROR,"maximum number%d of generic xlog buffers is exceeded",
243255
MAX_GENERIC_XLOG_PAGES);
244-
245256
/* keep compiler quiet */
246257
returnNULL;
247258
}
248259

249260
/*
250261
* Unregister particular buffer for generic xlog record.
262+
*
263+
* XXX this is dangerous and should go away.
251264
*/
252265
void
253266
GenericXLogUnregister(GenericXLogState*state,Bufferbuffer)
@@ -274,7 +287,8 @@ GenericXLogUnregister(GenericXLogState *state, Buffer buffer)
274287
}
275288

276289
/*
277-
* Put all changes in registered buffers to generic xlog record.
290+
* Apply changes represented by GenericXLogState to the actual buffers,
291+
* and emit a generic xlog record.
278292
*/
279293
XLogRecPtr
280294
GenericXLogFinish(GenericXLogState*state)
@@ -291,33 +305,35 @@ GenericXLogFinish(GenericXLogState *state)
291305

292306
for (i=0;i<MAX_GENERIC_XLOG_PAGES;i++)
293307
{
308+
PageData*pageData=&state->pages[i];
309+
Pagepage;
294310
chartmp[BLCKSZ];
295-
PageData*page=&state->pages[i];
296311

297-
if (BufferIsInvalid(page->buffer))
312+
if (BufferIsInvalid(pageData->buffer))
298313
continue;
299314

315+
page=BufferGetPage(pageData->buffer,NULL,NULL,
316+
BGP_NO_SNAPSHOT_TEST);
317+
300318
/* Swap current and saved page image. */
301-
memcpy(tmp,page->image,BLCKSZ);
302-
memcpy(page->image,BufferGetPage(page->buffer,NULL,NULL,
303-
BGP_NO_SNAPSHOT_TEST),BLCKSZ);
304-
memcpy(BufferGetPage(page->buffer,NULL,NULL,
305-
BGP_NO_SNAPSHOT_TEST),tmp,BLCKSZ);
319+
memcpy(tmp,pageData->image,BLCKSZ);
320+
memcpy(pageData->image,page,BLCKSZ);
321+
memcpy(page,tmp,BLCKSZ);
306322

307-
if (page->fullImage)
323+
if (pageData->fullImage)
308324
{
309325
/* A full page image does not require anything special */
310-
XLogRegisterBuffer(i,page->buffer,REGBUF_FORCE_IMAGE);
326+
XLogRegisterBuffer(i,pageData->buffer,REGBUF_FORCE_IMAGE);
311327
}
312328
else
313329
{
314330
/*
315-
* In normal mode, calculate delta and write it as data
331+
* In normal mode, calculate delta and write it asxlogdata
316332
* associated with this page.
317333
*/
318-
XLogRegisterBuffer(i,page->buffer,REGBUF_STANDARD);
319-
writeDelta(page);
320-
XLogRegisterBufData(i,page->data,page->dataLen);
334+
XLogRegisterBuffer(i,pageData->buffer,REGBUF_STANDARD);
335+
computeDelta(pageData);
336+
XLogRegisterBufData(i,pageData->delta,pageData->deltaLen);
321337
}
322338
}
323339

@@ -327,13 +343,13 @@ GenericXLogFinish(GenericXLogState *state)
327343
/* Set LSN and mark buffers dirty */
328344
for (i=0;i<MAX_GENERIC_XLOG_PAGES;i++)
329345
{
330-
PageData*page=&state->pages[i];
346+
PageData*pageData=&state->pages[i];
331347

332-
if (BufferIsInvalid(page->buffer))
348+
if (BufferIsInvalid(pageData->buffer))
333349
continue;
334-
PageSetLSN(BufferGetPage(page->buffer,NULL,NULL,
350+
PageSetLSN(BufferGetPage(pageData->buffer,NULL,NULL,
335351
BGP_NO_SNAPSHOT_TEST),lsn);
336-
MarkBufferDirty(page->buffer);
352+
MarkBufferDirty(pageData->buffer);
337353
}
338354
END_CRIT_SECTION();
339355
}
@@ -343,13 +359,15 @@ GenericXLogFinish(GenericXLogState *state)
343359
START_CRIT_SECTION();
344360
for (i=0;i<MAX_GENERIC_XLOG_PAGES;i++)
345361
{
346-
PageData*page=&state->pages[i];
362+
PageData*pageData=&state->pages[i];
347363

348-
if (BufferIsInvalid(page->buffer))
364+
if (BufferIsInvalid(pageData->buffer))
349365
continue;
350-
memcpy(BufferGetPage(page->buffer,NULL,NULL,
351-
BGP_NO_SNAPSHOT_TEST),page->image,BLCKSZ);
352-
MarkBufferDirty(page->buffer);
366+
memcpy(BufferGetPage(pageData->buffer,NULL,NULL,
367+
BGP_NO_SNAPSHOT_TEST),
368+
pageData->image,
369+
BLCKSZ);
370+
MarkBufferDirty(pageData->buffer);
353371
}
354372
END_CRIT_SECTION();
355373
}
@@ -360,7 +378,9 @@ GenericXLogFinish(GenericXLogState *state)
360378
}
361379

362380
/*
363-
* Abort generic xlog record.
381+
* Abort generic xlog record construction. No changes are applied to buffers.
382+
*
383+
* Note: caller is responsible for releasing locks/pins on buffers, if needed.
364384
*/
365385
void
366386
GenericXLogAbort(GenericXLogState*state)
@@ -372,10 +392,10 @@ GenericXLogAbort(GenericXLogState *state)
372392
* Apply delta to given page image.
373393
*/
374394
staticvoid
375-
applyPageRedo(Pagepage,Pointerdata,SizedataSize)
395+
applyPageRedo(Pagepage,constchar*delta,SizedeltaSize)
376396
{
377-
Pointerptr=data,
378-
end=data+dataSize;
397+
constchar*ptr=delta;
398+
constchar*end=delta+deltaSize;
379399

380400
while (ptr<end)
381401
{
@@ -399,10 +419,11 @@ applyPageRedo(Page page, Pointer data, Size dataSize)
399419
void
400420
generic_redo(XLogReaderState*record)
401421
{
402-
uint8block_id;
403-
Bufferbuffers[MAX_GENERIC_XLOG_PAGES]= {InvalidBuffer};
404422
XLogRecPtrlsn=record->EndRecPtr;
423+
Bufferbuffers[MAX_GENERIC_XLOG_PAGES];
424+
uint8block_id;
405425

426+
/* Protect limited size of buffers[] array */
406427
Assert(record->max_block_id<MAX_GENERIC_XLOG_PAGES);
407428

408429
/* Iterate over blocks */
@@ -411,20 +432,24 @@ generic_redo(XLogReaderState *record)
411432
XLogRedoActionaction;
412433

413434
if (!XLogRecHasBlockRef(record,block_id))
435+
{
436+
buffers[block_id]=InvalidBuffer;
414437
continue;
438+
}
415439

416440
action=XLogReadBufferForRedo(record,block_id,&buffers[block_id]);
417441

418442
/* Apply redo to given block if needed */
419443
if (action==BLK_NEEDS_REDO)
420444
{
421-
PointerblockData;
422-
SizeblockDataSize;
423445
Pagepage;
446+
char*blockDelta;
447+
SizeblockDeltaSize;
424448

425-
page=BufferGetPage(buffers[block_id],NULL,NULL,BGP_NO_SNAPSHOT_TEST);
426-
blockData=XLogRecGetBlockData(record,block_id,&blockDataSize);
427-
applyPageRedo(page,blockData,blockDataSize);
449+
page=BufferGetPage(buffers[block_id],NULL,NULL,
450+
BGP_NO_SNAPSHOT_TEST);
451+
blockDelta=XLogRecGetBlockData(record,block_id,&blockDeltaSize);
452+
applyPageRedo(page,blockDelta,blockDeltaSize);
428453

429454
PageSetLSN(page,lsn);
430455
MarkBufferDirty(buffers[block_id]);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp