@@ -141,14 +141,6 @@ typedef struct LogicalTape
141141 long curBlockNumber ; /* this block's logical blk# within tape */
142142 int pos ; /* next read/write position in buffer */
143143 int nbytes ; /* total # of valid bytes in buffer */
144-
145- /*
146- * Desired buffer size to use when reading. To keep things simple, we use
147- * a single-block buffer when writing, or when reading a frozen tape. But
148- * when we are reading and will only read forwards, we allocate a larger
149- * buffer, determined by read_buffer_size.
150- */
151- int read_buffer_size ;
152144} LogicalTape ;
153145
154146/*
@@ -609,7 +601,6 @@ LogicalTapeSetCreate(int ntapes)
609601 lt -> lastBlockBytes = 0 ;
610602 lt -> buffer = NULL ;
611603 lt -> buffer_size = 0 ;
612- lt -> read_buffer_size = BLCKSZ ;
613604 lt -> curBlockNumber = 0L ;
614605 lt -> pos = 0 ;
615606 lt -> nbytes = 0 ;
@@ -739,102 +730,133 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
739730}
740731
741732/*
742- * Rewind logical tape and switch from writing to reading or vice versa .
733+ * Rewind logical tape and switch from writing to reading.
743734 *
744- * Unless the tape has been "frozen" in read state, forWrite must be the
745- * opposite of the previous tape state.
735+ * The tape must currently be in writing state, or "frozen" in read state.
736+ *
737+ * 'buffer_size' specifies how much memory to use for the read buffer. It
738+ * does not include the memory needed for the indirect blocks. Regardless
739+ * of the argument, the actual amount of memory used is between BLCKSZ and
740+ * MaxAllocSize, and is a multiple of BLCKSZ. The given value is rounded
741+ * down and truncated to fit those constraints, if necessary. If the tape
742+ * is frozen, the 'buffer_size' argument is ignored, and a small BLCKSZ byte
743+ * buffer is used.
746744 */
747745void
748- LogicalTapeRewind (LogicalTapeSet * lts , int tapenum , bool forWrite )
746+ LogicalTapeRewindForRead (LogicalTapeSet * lts , int tapenum , size_t buffer_size )
749747{
750748 LogicalTape * lt ;
751749 long datablocknum ;
752750
753751 Assert (tapenum >= 0 && tapenum < lts -> nTapes );
754752 lt = & lts -> tapes [tapenum ];
755753
756- if (!forWrite )
754+ /*
755+ * Round and cap buffer_size if needed.
756+ */
757+ if (lt -> frozen )
758+ buffer_size = BLCKSZ ;
759+ else
757760 {
758- if (lt -> writing )
759- {
760- /*
761- * Completion of a write phase. Flush last partial data block,
762- * flush any partial indirect blocks, rewind for normal
763- * (destructive) read.
764- */
765- if (lt -> dirty )
766- ltsDumpBuffer (lts , lt );
767- lt -> lastBlockBytes = lt -> nbytes ;
768- lt -> writing = false;
769- datablocknum = ltsRewindIndirectBlock (lts , lt -> indirect , false);
770- }
771- else
772- {
773- /*
774- * This is only OK if tape is frozen; we rewind for (another) read
775- * pass.
776- */
777- Assert (lt -> frozen );
778- datablocknum = ltsRewindFrozenIndirectBlock (lts , lt -> indirect );
779- }
761+ /* need at least one block */
762+ if (buffer_size < BLCKSZ )
763+ buffer_size = BLCKSZ ;
780764
781- /* Allocate a read buffer (unless the tape is empty) */
782- if (lt -> buffer )
783- pfree (lt -> buffer );
784- lt -> buffer = NULL ;
785- lt -> buffer_size = 0 ;
786- if (datablocknum != -1L )
787- {
788- lt -> buffer = palloc (lt -> read_buffer_size );
789- lt -> buffer_size = lt -> read_buffer_size ;
790- }
765+ /*
766+ * palloc() larger than MaxAllocSize would fail (a multi-gigabyte
767+ * buffer is unlikely to be helpful, anyway)
768+ */
769+ if (buffer_size > MaxAllocSize )
770+ buffer_size = MaxAllocSize ;
791771
792- /* Read the first block, or reset if tape is empty */
793- lt -> curBlockNumber = 0L ;
794- lt -> pos = 0 ;
795- lt -> nbytes = 0 ;
796- if (datablocknum != -1L )
797- ltsReadFillBuffer (lts , lt , datablocknum );
772+ /* round down to BLCKSZ boundary */
773+ buffer_size -= buffer_size % BLCKSZ ;
774+ }
775+
776+ if (lt -> writing )
777+ {
778+ /*
779+ * Completion of a write phase. Flush last partial data block, flush
780+ * any partial indirect blocks, rewind for normal (destructive) read.
781+ */
782+ if (lt -> dirty )
783+ ltsDumpBuffer (lts , lt );
784+ lt -> lastBlockBytes = lt -> nbytes ;
785+ lt -> writing = false;
786+ datablocknum = ltsRewindIndirectBlock (lts , lt -> indirect , false);
798787 }
799788 else
800789 {
801790 /*
802- * Completion of a read phase. Rewind and prepare for write.
803- *
804- * NOTE: we assume the caller has read the tape to the end; otherwise
805- * untouched data and indirect blocks will not have been freed. We
806- * could add more code to free any unread blocks, but in current usage
807- * of this module it'd be useless code.
791+ * This is only OK if tape is frozen; we rewind for (another) read
792+ * pass.
808793 */
809- IndirectBlock * ib ,
810- * nextib ;
794+ Assert (lt -> frozen );
795+ datablocknum = ltsRewindFrozenIndirectBlock (lts , lt -> indirect );
796+ }
811797
812- Assert (!lt -> writing && !lt -> frozen );
813- /* Must truncate the indirect-block hierarchy down to one level. */
814- if (lt -> indirect )
815- {
816- for (ib = lt -> indirect -> nextup ; ib != NULL ; ib = nextib )
817- {
818- nextib = ib -> nextup ;
819- pfree (ib );
820- }
821- lt -> indirect -> nextSlot = 0 ;
822- lt -> indirect -> nextup = NULL ;
823- }
824- lt -> writing = true;
825- lt -> dirty = false;
826- lt -> numFullBlocks = 0L ;
827- lt -> lastBlockBytes = 0 ;
828- lt -> curBlockNumber = 0L ;
829- lt -> pos = 0 ;
830- lt -> nbytes = 0 ;
798+ /* Allocate a read buffer (unless the tape is empty) */
799+ if (lt -> buffer )
800+ pfree (lt -> buffer );
801+ lt -> buffer = NULL ;
802+ lt -> buffer_size = 0 ;
803+ if (datablocknum != -1L )
804+ {
805+ lt -> buffer = palloc (buffer_size );
806+ lt -> buffer_size = buffer_size ;
807+ }
831808
832- if (lt -> buffer )
809+ /* Read the first block, or reset if tape is empty */
810+ lt -> curBlockNumber = 0L ;
811+ lt -> pos = 0 ;
812+ lt -> nbytes = 0 ;
813+ if (datablocknum != -1L )
814+ ltsReadFillBuffer (lts , lt , datablocknum );
815+ }
816+
817+ /*
818+ * Rewind logical tape and switch from reading to writing.
819+ *
820+ * NOTE: we assume the caller has read the tape to the end; otherwise
821+ * untouched data and indirect blocks will not have been freed. We
822+ * could add more code to free any unread blocks, but in current usage
823+ * of this module it'd be useless code.
824+ */
825+ void
826+ LogicalTapeRewindForWrite (LogicalTapeSet * lts , int tapenum )
827+ {
828+ LogicalTape * lt ;
829+ IndirectBlock * ib ,
830+ * nextib ;
831+
832+ Assert (tapenum >= 0 && tapenum < lts -> nTapes );
833+ lt = & lts -> tapes [tapenum ];
834+
835+ Assert (!lt -> writing && !lt -> frozen );
836+ /* Must truncate the indirect-block hierarchy down to one level. */
837+ if (lt -> indirect )
838+ {
839+ for (ib = lt -> indirect -> nextup ; ib != NULL ; ib = nextib )
833840 {
834- pfree (lt -> buffer );
835- lt -> buffer = NULL ;
836- lt -> buffer_size = 0 ;
841+ nextib = ib -> nextup ;
842+ pfree (ib );
837843 }
844+ lt -> indirect -> nextSlot = 0 ;
845+ lt -> indirect -> nextup = NULL ;
846+ }
847+ lt -> writing = true;
848+ lt -> dirty = false;
849+ lt -> numFullBlocks = 0L ;
850+ lt -> lastBlockBytes = 0 ;
851+ lt -> curBlockNumber = 0L ;
852+ lt -> pos = 0 ;
853+ lt -> nbytes = 0 ;
854+
855+ if (lt -> buffer )
856+ {
857+ pfree (lt -> buffer );
858+ lt -> buffer = NULL ;
859+ lt -> buffer_size = 0 ;
838860 }
839861}
840862
@@ -1105,28 +1127,3 @@ LogicalTapeSetBlocks(LogicalTapeSet *lts)
11051127{
11061128 return lts -> nFileBlocks ;
11071129}
1108-
1109- /*
1110- * Set buffer size to use, when reading from given tape.
1111- */
1112- void
1113- LogicalTapeAssignReadBufferSize (LogicalTapeSet * lts , int tapenum , size_t avail_mem )
1114- {
1115- LogicalTape * lt ;
1116-
1117- Assert (tapenum >= 0 && tapenum < lts -> nTapes );
1118- lt = & lts -> tapes [tapenum ];
1119-
1120- /*
1121- * The buffer size must be a multiple of BLCKSZ in size, so round the
1122- * given value down to nearest BLCKSZ. Make sure we have at least one
1123- * page. Also, don't go above MaxAllocSize, to avoid erroring out. A
1124- * multi-gigabyte buffer is unlikely to be helpful, anyway.
1125- */
1126- if (avail_mem < BLCKSZ )
1127- avail_mem = BLCKSZ ;
1128- if (avail_mem > MaxAllocSize )
1129- avail_mem = MaxAllocSize ;
1130- avail_mem -= avail_mem % BLCKSZ ;
1131- lt -> read_buffer_size = avail_mem ;
1132- }
0 commit comments