@@ -191,8 +191,8 @@ struct LogicalTapeSet
191191 Size freeBlocksLen ; /* current allocated length of freeBlocks[] */
192192
193193 /* The array of logical tapes. */
194- int nTapes ; /* # of logical tapes in set */
195- LogicalTape tapes [ FLEXIBLE_ARRAY_MEMBER ] ; /* has nTapes nentries */
194+ int nTapes ; /* # of logical tapes in set */
195+ LogicalTape * tapes ; /* has nTapes nentries */
196196};
197197
198198static void ltsWriteBlock (LogicalTapeSet * lts , long blocknum , void * buffer );
@@ -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 ltsInitTape (LogicalTape * lt );
204205static void ltsInitReadBuffer (LogicalTapeSet * lts , LogicalTape * lt );
205206
206207
@@ -536,6 +537,27 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared,
536537 lts -> nHoleBlocks = lts -> nBlocksAllocated - nphysicalblocks ;
537538}
538539
540+ /*
541+ * Initialize per-tape struct. Note we allocate the I/O buffer lazily.
542+ */
543+ static void
544+ ltsInitTape (LogicalTape * lt )
545+ {
546+ lt -> writing = true;
547+ lt -> frozen = false;
548+ lt -> dirty = false;
549+ lt -> firstBlockNumber = -1L ;
550+ lt -> curBlockNumber = -1L ;
551+ lt -> nextBlockNumber = -1L ;
552+ lt -> offsetBlockNumber = 0L ;
553+ lt -> buffer = NULL ;
554+ lt -> buffer_size = 0 ;
555+ /* palloc() larger than MaxAllocSize would fail */
556+ lt -> max_size = MaxAllocSize ;
557+ lt -> pos = 0 ;
558+ lt -> nbytes = 0 ;
559+ }
560+
539561/*
540562 * Lazily allocate and initialize the read buffer. This avoids waste when many
541563 * tapes are open at once, but not all are active between rewinding and
@@ -579,15 +601,13 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset,
579601 int worker )
580602{
581603 LogicalTapeSet * lts ;
582- LogicalTape * lt ;
583604 int i ;
584605
585606 /*
586607 * Create top-level struct including per-tape LogicalTape structs.
587608 */
588609 Assert (ntapes > 0 );
589- lts = (LogicalTapeSet * ) palloc (offsetof(LogicalTapeSet , tapes ) +
590- ntapes * sizeof (LogicalTape ));
610+ lts = (LogicalTapeSet * ) palloc (sizeof (LogicalTapeSet ));
591611 lts -> nBlocksAllocated = 0L ;
592612 lts -> nBlocksWritten = 0L ;
593613 lts -> nHoleBlocks = 0L ;
@@ -596,30 +616,10 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset,
596616 lts -> freeBlocks = (long * ) palloc (lts -> freeBlocksLen * sizeof (long ));
597617 lts -> nFreeBlocks = 0 ;
598618 lts -> nTapes = ntapes ;
619+ lts -> tapes = (LogicalTape * ) palloc (ntapes * sizeof (LogicalTape ));
599620
600- /*
601- * Initialize per-tape structs. Note we allocate the I/O buffer and the
602- * first block for a tape only when it is first actually written to. This
603- * avoids wasting memory space when tuplesort.c overestimates the number
604- * of tapes needed.
605- */
606621 for (i = 0 ; i < ntapes ; i ++ )
607- {
608- lt = & lts -> tapes [i ];
609- lt -> writing = true;
610- lt -> frozen = false;
611- lt -> dirty = false;
612- lt -> firstBlockNumber = -1L ;
613- lt -> curBlockNumber = -1L ;
614- lt -> nextBlockNumber = -1L ;
615- lt -> offsetBlockNumber = 0L ;
616- lt -> buffer = NULL ;
617- lt -> buffer_size = 0 ;
618- /* palloc() larger than MaxAllocSize would fail */
619- lt -> max_size = MaxAllocSize ;
620- lt -> pos = 0 ;
621- lt -> nbytes = 0 ;
622- }
622+ ltsInitTape (& lts -> tapes [i ]);
623623
624624 /*
625625 * Create temp BufFile storage as required.
@@ -1004,6 +1004,25 @@ LogicalTapeFreeze(LogicalTapeSet *lts, int tapenum, TapeShare *share)
10041004 }
10051005}
10061006
1007+ /*
1008+ * Add additional tapes to this tape set. Not intended to be used when any
1009+ * tapes are frozen.
1010+ */
1011+ void
1012+ LogicalTapeSetExtend (LogicalTapeSet * lts , int nAdditional )
1013+ {
1014+ int i ;
1015+ int nTapesOrig = lts -> nTapes ;
1016+
1017+ lts -> nTapes += nAdditional ;
1018+
1019+ lts -> tapes = (LogicalTape * ) repalloc (
1020+ lts -> tapes , lts -> nTapes * sizeof (LogicalTape ));
1021+
1022+ for (i = nTapesOrig ; i < lts -> nTapes ; i ++ )
1023+ ltsInitTape (& lts -> tapes [i ]);
1024+ }
1025+
10071026/*
10081027 * Backspace the tape a given number of bytes. (We also support a more
10091028 * general seek interface, see below.)
0 commit comments