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

Commit7ac4a38

Browse files
committed
Don't create "holes" in BufFiles, in the new logtape code.
The "Simplify tape block format" commit ignored the rule that blocksreturned by ltsGetFreeBlock() must be written out in the same order, atleast in the first write pass. To fix, relax that requirement, by makingltsWriteBlock() to detect if it's about to create a "hole" in theunderlying BufFile, and fill it with zeros instead.Reported, analysed, and reviewed by Peter Geoghegan.Discussion:https://www.postgresql.org/message-id/CAM3SWZRWdNtkhiG0GyiX_1mUAypiK3dV6-6542pYe2iEL-foTA@mail.gmail.com
1 parentbc1686f commit7ac4a38

File tree

1 file changed

+41
-11
lines changed

1 file changed

+41
-11
lines changed

‎src/backend/utils/sort/logtape.c

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,17 @@ typedef struct LogicalTape
152152
structLogicalTapeSet
153153
{
154154
BufFile*pfile;/* underlying file for whole tape set */
155-
longnFileBlocks;/* # of blocks used in underlying file */
155+
156+
/*
157+
* File size tracking. nBlocksWritten is the size of the underlying file,
158+
* in BLCKSZ blocks. nBlocksAllocated is the number of blocks allocated
159+
* by ltsGetFreeBlock(), and it is always greater than or equal to
160+
* nBlocksWritten. Blocks between nBlocksAllocated and nBlocksWritten are
161+
* blocks that have been allocated for a tape, but have not been written
162+
* to the underlying file yet.
163+
*/
164+
longnBlocksAllocated;/* # of blocks allocated */
165+
longnBlocksWritten;/* # of blocks used in underlying file */
156166

157167
/*
158168
* We store the numbers of recycled-and-available blocks in freeBlocks[].
@@ -187,21 +197,43 @@ static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum);
187197
/*
188198
* Write a block-sized buffer to the specified block of the underlying file.
189199
*
190-
* NB: should not attempt to write beyond current end of file (ie, create
191-
* "holes" in file), since BufFile doesn't allow that. The first write pass
192-
* must write blocks sequentially.
193-
*
194200
* No need for an error return convention; we ereport() on any error.
195201
*/
196202
staticvoid
197203
ltsWriteBlock(LogicalTapeSet*lts,longblocknum,void*buffer)
198204
{
205+
/*
206+
* BufFile does not support "holes", so if we're about to write a block
207+
* that's past the current end of file, fill the space between the current
208+
* end of file and the target block with zeros.
209+
*
210+
* This should happen rarely, otherwise you are not writing very
211+
* sequentially. In current use, this only happens when the sort ends
212+
* writing a run, and switches to another tape. The last block of the
213+
* previous tape isn't flushed to disk until the end of the sort, so you
214+
* get one-block hole, where the last block of the previous tape will
215+
* later go.
216+
*/
217+
while (blocknum>lts->nBlocksWritten)
218+
{
219+
charzerobuf[BLCKSZ];
220+
221+
MemSet(zerobuf,0,sizeof(zerobuf));
222+
223+
ltsWriteBlock(lts,lts->nBlocksWritten,zerobuf);
224+
}
225+
226+
/* Write the requested block */
199227
if (BufFileSeekBlock(lts->pfile,blocknum)!=0||
200228
BufFileWrite(lts->pfile,buffer,BLCKSZ)!=BLCKSZ)
201229
ereport(ERROR,
202230
(errcode_for_file_access(),
203231
errmsg("could not write block %ld of temporary file: %m",
204232
blocknum)));
233+
234+
/* Update nBlocksWritten, if we extended the file */
235+
if (blocknum==lts->nBlocksWritten)
236+
lts->nBlocksWritten++;
205237
}
206238

207239
/*
@@ -281,9 +313,6 @@ freeBlocks_cmp(const void *a, const void *b)
281313

282314
/*
283315
* Select a currently unused block for writing to.
284-
*
285-
* NB: should only be called when writer is ready to write immediately,
286-
* to ensure that first write pass is sequential.
287316
*/
288317
staticlong
289318
ltsGetFreeBlock(LogicalTapeSet*lts)
@@ -304,7 +333,7 @@ ltsGetFreeBlock(LogicalTapeSet *lts)
304333
returnlts->freeBlocks[--lts->nFreeBlocks];
305334
}
306335
else
307-
returnlts->nFileBlocks++;
336+
returnlts->nBlocksAllocated++;
308337
}
309338

310339
/*
@@ -360,7 +389,8 @@ LogicalTapeSetCreate(int ntapes)
360389
lts= (LogicalTapeSet*)palloc(offsetof(LogicalTapeSet,tapes)+
361390
ntapes*sizeof(LogicalTape));
362391
lts->pfile=BufFileCreateTemp(false);
363-
lts->nFileBlocks=0L;
392+
lts->nBlocksAllocated=0L;
393+
lts->nBlocksWritten=0L;
364394
lts->forgetFreeSpace= false;
365395
lts->blocksSorted= true;/* a zero-length array is sorted ... */
366396
lts->freeBlocksLen=32;/* reasonable initial guess */
@@ -858,5 +888,5 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
858888
long
859889
LogicalTapeSetBlocks(LogicalTapeSet*lts)
860890
{
861-
returnlts->nFileBlocks;
891+
returnlts->nBlocksAllocated;
862892
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp