src/backend/utils/sort/logtape.c
/*
 * Backspace the tape a given number of bytes.  (We also support a more
 * general seek interface, see below.)
 *
 * *Only* a frozen-for-read tape can be backed up; we don't support
 * random access during write, and an unfrozen read tape may have
 * already discarded the desired data!
 *
 * Return value is TRUE if seek successful, FALSE if there isn't that much
 * data before the current point (in which case there's no state change).
 */
Backspace the tape a given number of bytes.  (We also support a more
general seek interface, see below.)

*Only* a frozen-for-read tape can be backed up; we don't support
random access during write, and an unfrozen read tape may have
already discarded the desired data!

Return value is TRUE if seek successful, FALSE if there isn't that much
data before the current point (in which case there's no state change).
Backspace the tape a given number of bytes . ( We also support a more general seek interface see below . ) * Only * a frozen - for - read tape can be backed up ; we don ' t support random access during write and an unfrozen read tape may have already discarded the desired data! Return value is TRUE if seek successful FALSE if there isn ' t that much data before the current point ( in which case there ' s no state change ) .
bool
LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
{
	LogicalTape *lt;
	long		nblocks;
	int			newpos;
	Assert(tapenum >= 0 && tapenum < lts->nTapes);
	lt = &lts->tapes[tapenum];
	Assert(lt->frozen);
	Assert(lt->buffer_size == BLCKSZ);
	if (size <= (size_t) lt->pos)
	{
		lt->pos -= (int) size;
		return true;
	}
	size -= (size_t) lt->pos;	
	nblocks = size / BLCKSZ;
	size = size % BLCKSZ;
	if (size)
	{
		nblocks++;
		newpos = (int) (BLCKSZ - size);
	}
	else
		newpos = 0;
	if (nblocks > lt->curBlockNumber)
		return false;			
	while (nblocks-- > 0)
	{
		long		datablocknum = ltsRecallPrevBlockNum(lts, lt->indirect);
		if (datablocknum == -1L)
			elog(ERROR, "unexpected end of tape");
		lt->curBlockNumber--;
		if (nblocks == 0)
		{
			ltsReadBlock(lts, datablocknum, (void *) lt->buffer);
			lt->nbytes = BLCKSZ;
		}
	}
	lt->pos = newpos;
	return true;
}
bool LogicalTapeBackspace ( LogicalTapeSet * lts , int tapenum , size_t size ) { LogicalTape * lt ; long nblocks ; int newpos ; Assert ( tapenum >= 0 && tapenum < lts -> nTapes ) ; lt = & lts -> tapes [ tapenum ] ; Assert ( lt -> frozen ) ; Assert ( lt -> buffer_size == BLCKSZ ) ; if ( size <= ( size_t ) lt -> pos ) { lt -> pos -= ( int ) size ; return true ; } size -= ( size_t ) lt -> pos ; nblocks = size / BLCKSZ ; size = size % BLCKSZ ; if ( size ) { nblocks ++ ; newpos = ( int ) ( BLCKSZ - size ) ; } else newpos = 0 ; if ( nblocks > lt -> curBlockNumber ) return false ; while ( nblocks -- > 0 ) { long datablocknum = ltsRecallPrevBlockNum ( lts , lt -> indirect ) ; if ( datablocknum == -1L ) elog ( ERROR , " " ) ; lt -> curBlockNumber -- ; if ( nblocks == 0 ) { ltsReadBlock ( lts , datablocknum , ( void * ) lt -> buffer ) ; lt -> nbytes = BLCKSZ ; } } lt -> pos = newpos ; return true ; }
Backspace the tape a given number of bytes.
Backspace the tape a given number of bytes .
/*
	 * Easy case for seek within current block.
	 */ /*
	 * Not-so-easy case.  Figure out whether it's possible at all.
	 */ /* part within this block */ /* a seek too far... */ /*
	 * OK, we need to back up nblocks blocks.  This implementation would be
	 * pretty inefficient for long seeks, but we really aren't expecting that
	 * (a seek over one tuple is typical).
	 */