src/backend/utils/sort/logtape.c
/*
 * "Freeze" the contents of a tape so that it can be read multiple times
 * and/or read backwards.  Once a tape is frozen, its contents will not
 * be released until the LogicalTapeSet is destroyed.  This is expected
 * to be used only for the final output pass of a merge.
 *
 * This *must* be called just at the end of a write pass, before the
 * tape is rewound (after rewind is too late!).  It performs a rewind
 * and switch to read mode "for free".  An immediately following rewind-
 * for-read call is OK but not necessary.
 */
"Freeze" the contents of a tape so that it can be read multiple times
and/or read backwards.  Once a tape is frozen, its contents will not
be released until the LogicalTapeSet is destroyed.  This is expected
to be used only for the final output pass of a merge.

This *must* be called just at the end of a write pass, before the
tape is rewound (after rewind is too late!).  It performs a rewind
and switch to read mode "for free".  An immediately following rewind
for-read call is OK but not necessary.
" Freeze " the contents of a tape so that it can be read multiple times and / or read backwards . Once a tape is frozen its contents will not be released until the LogicalTapeSet is destroyed . This is expected to be used only for the final output pass of a merge . This * must * be called just at the end of a write pass before the tape is rewound ( after rewind is too late! ) . It performs a rewind and switch to read mode " for free " . An immediately following rewind for - read call is OK but not necessary .
void
LogicalTapeFreeze(LogicalTapeSet *lts, int tapenum)
{
	LogicalTape *lt;
	long		datablocknum;
	Assert(tapenum >= 0 && tapenum < lts->nTapes);
	lt = &lts->tapes[tapenum];
	Assert(lt->writing);
	if (lt->dirty)
		ltsDumpBuffer(lts, lt);
	lt->lastBlockBytes = lt->nbytes;
	lt->writing = false;
	lt->frozen = true;
	datablocknum = ltsRewindIndirectBlock(lts, lt->indirect, true);
	if (!lt->buffer || lt->buffer_size != BLCKSZ)
	{
		if (lt->buffer)
			pfree(lt->buffer);
		lt->buffer = palloc(BLCKSZ);
		lt->buffer_size = BLCKSZ;
	}
	lt->curBlockNumber = 0L;
	lt->pos = 0;
	lt->nbytes = 0;
	if (datablocknum != -1L)
	{
		ltsReadBlock(lts, datablocknum, (void *) lt->buffer);
		lt->nbytes = (lt->curBlockNumber < lt->numFullBlocks) ?
			BLCKSZ : lt->lastBlockBytes;
	}
}
void LogicalTapeFreeze ( LogicalTapeSet * lts , int tapenum ) { LogicalTape * lt ; long datablocknum ; Assert ( tapenum >= 0 && tapenum < lts -> nTapes ) ; lt = & lts -> tapes [ tapenum ] ; Assert ( lt -> writing ) ; if ( lt -> dirty ) ltsDumpBuffer ( lts , lt ) ; lt -> lastBlockBytes = lt -> nbytes ; lt -> writing = false ; lt -> frozen = true ; datablocknum = ltsRewindIndirectBlock ( lts , lt -> indirect , true ) ; if ( ! lt -> buffer || lt -> buffer_size != BLCKSZ ) { if ( lt -> buffer ) pfree ( lt -> buffer ) ; lt -> buffer = palloc ( BLCKSZ ) ; lt -> buffer_size = BLCKSZ ; } lt -> curBlockNumber = 0L ; lt -> pos = 0 ; lt -> nbytes = 0 ; if ( datablocknum != -1L ) { ltsReadBlock ( lts , datablocknum , ( void * ) lt -> buffer ) ; lt -> nbytes = ( lt -> curBlockNumber < lt -> numFullBlocks ) ? BLCKSZ : lt -> lastBlockBytes ; } }
"Freeze" the contents of a tape so that it can be read multiple times
 and/or read backwards.
" Freeze " the contents of a tape so that it can be read multiple times and / or read backwards .
/*
	 * Completion of a write phase.  Flush last partial data block, flush any
	 * partial indirect blocks, rewind for nondestructive read.
	 */ /*
	 * The seek and backspace functions assume a single block read buffer.
	 * That's OK with current usage.  A larger buffer is helpful to make the
	 * read pattern of the backing file look more sequential to the OS, when
	 * we're reading from multiple tapes.  But at the end of a sort, when a
	 * tape is frozen, we only read from a single tape anyway.
	 */ /* Read the first block, or reset if tape is empty */