@@ -154,6 +154,11 @@ bool trace_sort = false;
154154bool optimize_bounded_sort = true;
155155#endif
156156
157+ #if PG_VERSION_NUM < 100000
158+ /* Provide fallback for old version of tape interface for 9.6 */
159+ #define LogicalTapeRewindForRead (x , y , z ) LogicalTapeRewind((x), (y), false)
160+ #define LogicalTapeRewindForWrite (x , y ) LogicalTapeRewind((x), (y), true)
161+ #endif
157162
158163/*
159164 * The objects we actually sort are SortTuple structs. These contain
@@ -300,6 +305,9 @@ struct Tuplesortstate
300305 int memtupsize ; /* allocated length of memtuples array */
301306 bool growmemtuples ; /* memtuples' growth still underway? */
302307
308+ /* Buffer size to use for reading input tapes, during merge. */
309+ size_t read_buffer_size ;
310+
303311 /*
304312 * While building initial runs, this is the current output run number
305313 * (starting at 0). Afterwards, it is the number of initial runs we made.
@@ -2364,6 +2372,8 @@ mergeruns(Tuplesortstate *state)
23642372 svTape ,
23652373 svRuns ,
23662374 svDummy ;
2375+ int numTapes ;
2376+ int numInputTapes ;
23672377
23682378 Assert (state -> status == TSS_BUILDRUNS );
23692379 Assert (state -> memtupcount == 0 );
@@ -2383,9 +2393,33 @@ mergeruns(Tuplesortstate *state)
23832393 return ;
23842394 }
23852395
2396+ /*
2397+ * If we had fewer runs than tapes, refund the memory that we imagined we
2398+ * would need for the tape buffers of the unused tapes.
2399+ *
2400+ * numTapes and numInputTapes reflect the actual number of tapes we will
2401+ * use. Note that the output tape's tape number is maxTapes - 1, so the
2402+ * tape numbers of the used tapes are not consecutive, and you cannot just
2403+ * loop from 0 to numTapes to visit all used tapes!
2404+ */
2405+ if (state -> Level == 1 )
2406+ {
2407+ numInputTapes = state -> currentRun ;
2408+ numTapes = numInputTapes + 1 ;
2409+ FREEMEM (state , (state -> maxTapes - numTapes ) * TAPE_BUFFER_OVERHEAD );
2410+ }
2411+ else
2412+ {
2413+ numInputTapes = state -> tapeRange ;
2414+ numTapes = state -> maxTapes ;
2415+ }
2416+
2417+ state -> read_buffer_size = Max (state -> availMem / numInputTapes , 0 );
2418+ USEMEM (state , state -> read_buffer_size * numInputTapes );
2419+
23862420 /* End of step D2: rewind all output tapes to prepare for merging */
23872421 for (tapenum = 0 ; tapenum < state -> tapeRange ; tapenum ++ )
2388- LogicalTapeRewind (state -> tapeset , tapenum , false );
2422+ LogicalTapeRewindForRead (state -> tapeset , tapenum , state -> read_buffer_size );
23892423
23902424 for (;;)
23912425 {
@@ -2448,11 +2482,10 @@ mergeruns(Tuplesortstate *state)
24482482 if (-- state -> Level == 0 )
24492483 break ;
24502484 /* rewind output tape T to use as new input */
2451- LogicalTapeRewind (state -> tapeset , state -> tp_tapenum [state -> tapeRange ],
2452- false );
2485+ LogicalTapeRewindForRead (state -> tapeset , state -> tp_tapenum [state -> tapeRange ],
2486+ state -> read_buffer_size );
24532487 /* rewind used-up input tape P, and prepare it for write pass */
2454- LogicalTapeRewind (state -> tapeset , state -> tp_tapenum [state -> tapeRange - 1 ],
2455- true);
2488+ LogicalTapeRewindForWrite (state -> tapeset , state -> tp_tapenum [state -> tapeRange - 1 ]);
24562489 state -> tp_runs [state -> tapeRange - 1 ] = 0 ;
24572490
24582491 /*
@@ -2818,9 +2851,9 @@ rum_tuplesort_rescan(Tuplesortstate *state)
28182851 state -> markpos_eof = false;
28192852 break ;
28202853 case TSS_SORTEDONTAPE :
2821- LogicalTapeRewind (state -> tapeset ,
2822- state -> result_tape ,
2823- false );
2854+ LogicalTapeRewindForRead (state -> tapeset ,
2855+ state -> result_tape ,
2856+ state -> read_buffer_size );
28242857 state -> eof_reached = false;
28252858 state -> markpos_block = 0L ;
28262859 state -> markpos_offset = 0 ;
@@ -2883,11 +2916,18 @@ rum_tuplesort_restorepos(Tuplesortstate *state)
28832916 state -> eof_reached = state -> markpos_eof ;
28842917 break ;
28852918 case TSS_SORTEDONTAPE :
2919+ #if PG_VERSION_NUM < 100000
28862920 if (!LogicalTapeSeek (state -> tapeset ,
28872921 state -> result_tape ,
28882922 state -> markpos_block ,
28892923 state -> markpos_offset ))
28902924 elog (ERROR , "rum_tuplesort_restorepos failed" );
2925+ #else
2926+ LogicalTapeSeek (state -> tapeset ,
2927+ state -> result_tape ,
2928+ state -> markpos_block ,
2929+ state -> markpos_offset );
2930+ #endif
28912931 state -> eof_reached = state -> markpos_eof ;
28922932 break ;
28932933 default :
0 commit comments