@@ -201,6 +201,7 @@ static long ltsGetFreeBlock(LogicalTapeSet *lts);
201
201
static void ltsReleaseBlock (LogicalTapeSet * lts , long blocknum );
202
202
static void ltsConcatWorkerTapes (LogicalTapeSet * lts , TapeShare * shared ,
203
203
SharedFileSet * fileset );
204
+ static void ltsInitReadBuffer (LogicalTapeSet * lts , LogicalTape * lt );
204
205
205
206
206
207
/*
@@ -535,6 +536,27 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared,
535
536
lts -> nHoleBlocks = lts -> nBlocksAllocated - nphysicalblocks ;
536
537
}
537
538
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
+
538
560
/*
539
561
* Create a set of logical tapes in a temporary underlying file.
540
562
*
@@ -821,15 +843,9 @@ LogicalTapeRewindForRead(LogicalTapeSet *lts, int tapenum, size_t buffer_size)
821
843
lt -> buffer_size = 0 ;
822
844
if (lt -> firstBlockNumber != -1L )
823
845
{
824
- lt -> buffer = palloc ( buffer_size );
846
+ /* the buffer is lazily allocated, but set the size here */
825
847
lt -> buffer_size = buffer_size ;
826
848
}
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 );
833
849
}
834
850
835
851
/*
@@ -878,6 +894,9 @@ LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
878
894
lt = & lts -> tapes [tapenum ];
879
895
Assert (!lt -> writing );
880
896
897
+ if (lt -> buffer == NULL )
898
+ ltsInitReadBuffer (lts , lt );
899
+
881
900
while (size > 0 )
882
901
{
883
902
if (lt -> pos >= lt -> nbytes )
@@ -1015,6 +1034,9 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
1015
1034
Assert (lt -> frozen );
1016
1035
Assert (lt -> buffer_size == BLCKSZ );
1017
1036
1037
+ if (lt -> buffer == NULL )
1038
+ ltsInitReadBuffer (lts , lt );
1039
+
1018
1040
/*
1019
1041
* Easy case for seek within current block.
1020
1042
*/
@@ -1087,6 +1109,9 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
1087
1109
Assert (offset >= 0 && offset <= TapeBlockPayloadSize );
1088
1110
Assert (lt -> buffer_size == BLCKSZ );
1089
1111
1112
+ if (lt -> buffer == NULL )
1113
+ ltsInitReadBuffer (lts , lt );
1114
+
1090
1115
if (blocknum != lt -> curBlockNumber )
1091
1116
{
1092
1117
ltsReadBlock (lts , blocknum , (void * ) lt -> buffer );
@@ -1114,6 +1139,10 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
1114
1139
1115
1140
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
1116
1141
lt = & lts -> tapes [tapenum ];
1142
+
1143
+ if (lt -> buffer == NULL )
1144
+ ltsInitReadBuffer (lts , lt );
1145
+
1117
1146
Assert (lt -> offsetBlockNumber == 0L );
1118
1147
1119
1148
/* With a larger buffer, 'pos' wouldn't be the same as offset within page */
0 commit comments