@@ -154,6 +154,11 @@ bool trace_sort = false;
154
154
bool optimize_bounded_sort = true;
155
155
#endif
156
156
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
157
162
158
163
/*
159
164
* The objects we actually sort are SortTuple structs. These contain
@@ -300,6 +305,9 @@ struct Tuplesortstate
300
305
int memtupsize ; /* allocated length of memtuples array */
301
306
bool growmemtuples ; /* memtuples' growth still underway? */
302
307
308
+ /* Buffer size to use for reading input tapes, during merge. */
309
+ size_t read_buffer_size ;
310
+
303
311
/*
304
312
* While building initial runs, this is the current output run number
305
313
* (starting at 0). Afterwards, it is the number of initial runs we made.
@@ -2364,6 +2372,8 @@ mergeruns(Tuplesortstate *state)
2364
2372
svTape ,
2365
2373
svRuns ,
2366
2374
svDummy ;
2375
+ int numTapes ;
2376
+ int numInputTapes ;
2367
2377
2368
2378
Assert (state -> status == TSS_BUILDRUNS );
2369
2379
Assert (state -> memtupcount == 0 );
@@ -2383,9 +2393,33 @@ mergeruns(Tuplesortstate *state)
2383
2393
return ;
2384
2394
}
2385
2395
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
+
2386
2420
/* End of step D2: rewind all output tapes to prepare for merging */
2387
2421
for (tapenum = 0 ; tapenum < state -> tapeRange ; tapenum ++ )
2388
- LogicalTapeRewind (state -> tapeset , tapenum , false );
2422
+ LogicalTapeRewindForRead (state -> tapeset , tapenum , state -> read_buffer_size );
2389
2423
2390
2424
for (;;)
2391
2425
{
@@ -2448,11 +2482,10 @@ mergeruns(Tuplesortstate *state)
2448
2482
if (-- state -> Level == 0 )
2449
2483
break ;
2450
2484
/* 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 );
2453
2487
/* 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 ]);
2456
2489
state -> tp_runs [state -> tapeRange - 1 ] = 0 ;
2457
2490
2458
2491
/*
@@ -2818,9 +2851,9 @@ rum_tuplesort_rescan(Tuplesortstate *state)
2818
2851
state -> markpos_eof = false;
2819
2852
break ;
2820
2853
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 );
2824
2857
state -> eof_reached = false;
2825
2858
state -> markpos_block = 0L ;
2826
2859
state -> markpos_offset = 0 ;
@@ -2883,11 +2916,18 @@ rum_tuplesort_restorepos(Tuplesortstate *state)
2883
2916
state -> eof_reached = state -> markpos_eof ;
2884
2917
break ;
2885
2918
case TSS_SORTEDONTAPE :
2919
+ #if PG_VERSION_NUM < 100000
2886
2920
if (!LogicalTapeSeek (state -> tapeset ,
2887
2921
state -> result_tape ,
2888
2922
state -> markpos_block ,
2889
2923
state -> markpos_offset ))
2890
2924
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
2891
2931
state -> eof_reached = state -> markpos_eof ;
2892
2932
break ;
2893
2933
default :
0 commit comments