@@ -201,6 +201,7 @@ static long ltsGetFreeBlock(LogicalTapeSet *lts);
201201static void ltsReleaseBlock (LogicalTapeSet * lts , long blocknum );
202202static void ltsConcatWorkerTapes (LogicalTapeSet * lts , TapeShare * shared ,
203203 SharedFileSet * fileset );
204+ static void ltsInitReadBuffer (LogicalTapeSet * lts , LogicalTape * lt );
204205
205206
206207/*
@@ -535,6 +536,27 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared,
535536 lts -> nHoleBlocks = lts -> nBlocksAllocated - nphysicalblocks ;
536537}
537538
539+ /*
540+ * Lazily allocate and initialize the read buffer. This avoids waste when many
541+ * tapes are open at once, but not all are active between rewinding and
542+ * reading.
543+ */
544+ static void
545+ ltsInitReadBuffer (LogicalTapeSet * lts , LogicalTape * lt )
546+ {
547+ if (lt -> firstBlockNumber != -1L )
548+ {
549+ Assert (lt -> buffer_size > 0 );
550+ lt -> buffer = palloc (lt -> buffer_size );
551+ }
552+
553+ /* Read the first block, or reset if tape is empty */
554+ lt -> nextBlockNumber = lt -> firstBlockNumber ;
555+ lt -> pos = 0 ;
556+ lt -> nbytes = 0 ;
557+ ltsReadFillBuffer (lts , lt );
558+ }
559+
538560/*
539561 * Create a set of logical tapes in a temporary underlying file.
540562 *
@@ -821,15 +843,9 @@ LogicalTapeRewindForRead(LogicalTapeSet *lts, int tapenum, size_t buffer_size)
821843 lt -> buffer_size = 0 ;
822844 if (lt -> firstBlockNumber != -1L )
823845 {
824- lt -> buffer = palloc ( buffer_size );
846+ /* the buffer is lazily allocated, but set the size here */
825847 lt -> buffer_size = buffer_size ;
826848 }
827-
828- /* Read the first block, or reset if tape is empty */
829- lt -> nextBlockNumber = lt -> firstBlockNumber ;
830- lt -> pos = 0 ;
831- lt -> nbytes = 0 ;
832- ltsReadFillBuffer (lts , lt );
833849}
834850
835851/*
@@ -878,6 +894,9 @@ LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
878894 lt = & lts -> tapes [tapenum ];
879895 Assert (!lt -> writing );
880896
897+ if (lt -> buffer == NULL )
898+ ltsInitReadBuffer (lts , lt );
899+
881900 while (size > 0 )
882901 {
883902 if (lt -> pos >= lt -> nbytes )
@@ -1015,6 +1034,9 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
10151034 Assert (lt -> frozen );
10161035 Assert (lt -> buffer_size == BLCKSZ );
10171036
1037+ if (lt -> buffer == NULL )
1038+ ltsInitReadBuffer (lts , lt );
1039+
10181040 /*
10191041 * Easy case for seek within current block.
10201042 */
@@ -1087,6 +1109,9 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
10871109 Assert (offset >= 0 && offset <= TapeBlockPayloadSize );
10881110 Assert (lt -> buffer_size == BLCKSZ );
10891111
1112+ if (lt -> buffer == NULL )
1113+ ltsInitReadBuffer (lts , lt );
1114+
10901115 if (blocknum != lt -> curBlockNumber )
10911116 {
10921117 ltsReadBlock (lts , blocknum , (void * ) lt -> buffer );
@@ -1114,6 +1139,10 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
11141139
11151140 Assert (tapenum >= 0 && tapenum < lts -> nTapes );
11161141 lt = & lts -> tapes [tapenum ];
1142+
1143+ if (lt -> buffer == NULL )
1144+ ltsInitReadBuffer (lts , lt );
1145+
11171146 Assert (lt -> offsetBlockNumber == 0L );
11181147
11191148 /* With a larger buffer, 'pos' wouldn't be the same as offset within page */
0 commit comments