64
64
* Portions Copyright (c) 1994, Regents of the University of California
65
65
*
66
66
* IDENTIFICATION
67
- * $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.17 2005/10/18 22:59:37 tgl Exp $
67
+ * $PostgreSQL: pgsql/src/backend/utils/sort/logtape.c,v 1.18 2006/02/19 05:58:36 tgl Exp $
68
68
*
69
69
*-------------------------------------------------------------------------
70
70
*/
@@ -124,10 +124,10 @@ typedef struct LogicalTape
124
124
* we do need the relative block number so we can detect end-of-tape while
125
125
* reading.
126
126
*/
127
+ char * buffer ; /* physical buffer (separately palloc'd) */
127
128
long curBlockNumber ; /* this block's logical blk# within tape */
128
129
int pos ; /* next read/write position in buffer */
129
130
int nbytes ; /* total # of valid bytes in buffer */
130
- char buffer [BLCKSZ ];
131
131
} LogicalTape ;
132
132
133
133
/*
@@ -156,7 +156,7 @@ struct LogicalTapeSet
156
156
* is of length nTapes.
157
157
*/
158
158
int nTapes ; /* # of logical tapes in set */
159
- LogicalTape * tapes [1 ]; /* must be last in struct! */
159
+ LogicalTape tapes [1 ]; /* must be last in struct! */
160
160
};
161
161
162
162
static void ltsWriteBlock (LogicalTapeSet * lts , long blocknum , void * buffer );
@@ -327,6 +327,10 @@ ltsRewindIndirectBlock(LogicalTapeSet *lts,
327
327
IndirectBlock * indirect ,
328
328
bool freezing )
329
329
{
330
+ /* Handle case of never-written-to tape */
331
+ if (indirect == NULL )
332
+ return -1L ;
333
+
330
334
/* Insert sentinel if block is not full */
331
335
if (indirect -> nextSlot < BLOCKS_PER_INDIR_BLOCK )
332
336
indirect -> ptrs [indirect -> nextSlot ] = -1L ;
@@ -366,6 +370,10 @@ static long
366
370
ltsRewindFrozenIndirectBlock (LogicalTapeSet * lts ,
367
371
IndirectBlock * indirect )
368
372
{
373
+ /* Handle case of never-written-to tape */
374
+ if (indirect == NULL )
375
+ return -1L ;
376
+
369
377
/*
370
378
* If block is not topmost, recurse to obtain address of first block in
371
379
* this hierarchy level. Read that one in.
@@ -399,6 +407,10 @@ ltsRecallNextBlockNum(LogicalTapeSet *lts,
399
407
IndirectBlock * indirect ,
400
408
bool frozen )
401
409
{
410
+ /* Handle case of never-written-to tape */
411
+ if (indirect == NULL )
412
+ return -1L ;
413
+
402
414
if (indirect -> nextSlot >= BLOCKS_PER_INDIR_BLOCK ||
403
415
indirect -> ptrs [indirect -> nextSlot ] == -1L )
404
416
{
@@ -432,6 +444,10 @@ static long
432
444
ltsRecallPrevBlockNum (LogicalTapeSet * lts ,
433
445
IndirectBlock * indirect )
434
446
{
447
+ /* Handle case of never-written-to tape */
448
+ if (indirect == NULL )
449
+ return -1L ;
450
+
435
451
if (indirect -> nextSlot <= 1 )
436
452
{
437
453
long indirblock ;
@@ -467,12 +483,12 @@ LogicalTapeSetCreate(int ntapes)
467
483
int i ;
468
484
469
485
/*
470
- * Create top-level struct. First LogicalTape pointer is already counted
471
- * in sizeof(LogicalTapeSet).
486
+ * Create top-level struct including per-tape LogicalTape structs.
487
+ * First LogicalTape struct is already counted in sizeof(LogicalTapeSet).
472
488
*/
473
489
Assert (ntapes > 0 );
474
490
lts = (LogicalTapeSet * ) palloc (sizeof (LogicalTapeSet ) +
475
- (ntapes - 1 ) * sizeof (LogicalTape * ));
491
+ (ntapes - 1 ) * sizeof (LogicalTape ));
476
492
lts -> pfile = BufFileCreateTemp (false);
477
493
lts -> nFileBlocks = 0L ;
478
494
lts -> freeBlocksLen = 32 ; /* reasonable initial guess */
@@ -481,20 +497,21 @@ LogicalTapeSetCreate(int ntapes)
481
497
lts -> nTapes = ntapes ;
482
498
483
499
/*
484
- * Create per-tape structs, including first-level indirect blocks.
500
+ * Initialize per-tape structs. Note we allocate the I/O buffer and
501
+ * first-level indirect block for a tape only when it is first actually
502
+ * written to. This avoids wasting memory space when tuplesort.c
503
+ * overestimates the number of tapes needed.
485
504
*/
486
505
for (i = 0 ; i < ntapes ; i ++ )
487
506
{
488
- lt = (LogicalTape * ) palloc (sizeof (LogicalTape ));
489
- lts -> tapes [i ] = lt ;
490
- lt -> indirect = (IndirectBlock * ) palloc (sizeof (IndirectBlock ));
491
- lt -> indirect -> nextSlot = 0 ;
492
- lt -> indirect -> nextup = NULL ;
507
+ lt = & lts -> tapes [i ];
508
+ lt -> indirect = NULL ;
493
509
lt -> writing = true;
494
510
lt -> frozen = false;
495
511
lt -> dirty = false;
496
512
lt -> numFullBlocks = 0L ;
497
513
lt -> lastBlockBytes = 0 ;
514
+ lt -> buffer = NULL ;
498
515
lt -> curBlockNumber = 0L ;
499
516
lt -> pos = 0 ;
500
517
lt -> nbytes = 0 ;
@@ -516,13 +533,14 @@ LogicalTapeSetClose(LogicalTapeSet *lts)
516
533
BufFileClose (lts -> pfile );
517
534
for (i = 0 ; i < lts -> nTapes ; i ++ )
518
535
{
519
- lt = lts -> tapes [i ];
536
+ lt = & lts -> tapes [i ];
520
537
for (ib = lt -> indirect ; ib != NULL ; ib = nextib )
521
538
{
522
539
nextib = ib -> nextup ;
523
540
pfree (ib );
524
541
}
525
- pfree (lt );
542
+ if (lt -> buffer )
543
+ pfree (lt -> buffer );
526
544
}
527
545
pfree (lts -> freeBlocks );
528
546
pfree (lts );
@@ -556,9 +574,19 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
556
574
size_t nthistime ;
557
575
558
576
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
559
- lt = lts -> tapes [tapenum ];
577
+ lt = & lts -> tapes [tapenum ];
560
578
Assert (lt -> writing );
561
579
580
+ /* Allocate data buffer and first indirect block on first write */
581
+ if (lt -> buffer == NULL )
582
+ lt -> buffer = (char * ) palloc (BLCKSZ );
583
+ if (lt -> indirect == NULL )
584
+ {
585
+ lt -> indirect = (IndirectBlock * ) palloc (sizeof (IndirectBlock ));
586
+ lt -> indirect -> nextSlot = 0 ;
587
+ lt -> indirect -> nextup = NULL ;
588
+ }
589
+
562
590
while (size > 0 )
563
591
{
564
592
if (lt -> pos >= BLCKSZ )
@@ -606,7 +634,7 @@ LogicalTapeRewind(LogicalTapeSet *lts, int tapenum, bool forWrite)
606
634
long datablocknum ;
607
635
608
636
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
609
- lt = lts -> tapes [tapenum ];
637
+ lt = & lts -> tapes [tapenum ];
610
638
611
639
if (!forWrite )
612
640
{
@@ -660,13 +688,16 @@ LogicalTapeRewind(LogicalTapeSet *lts, int tapenum, bool forWrite)
660
688
661
689
Assert (!lt -> writing && !lt -> frozen );
662
690
/* Must truncate the indirect-block hierarchy down to one level. */
663
- for ( ib = lt -> indirect -> nextup ; ib != NULL ; ib = nextib )
691
+ if ( lt -> indirect )
664
692
{
665
- nextib = ib -> nextup ;
666
- pfree (ib );
693
+ for (ib = lt -> indirect -> nextup ; ib != NULL ; ib = nextib )
694
+ {
695
+ nextib = ib -> nextup ;
696
+ pfree (ib );
697
+ }
698
+ lt -> indirect -> nextSlot = 0 ;
699
+ lt -> indirect -> nextup = NULL ;
667
700
}
668
- lt -> indirect -> nextSlot = 0 ;
669
- lt -> indirect -> nextup = NULL ;
670
701
lt -> writing = true;
671
702
lt -> dirty = false;
672
703
lt -> numFullBlocks = 0L ;
@@ -691,7 +722,7 @@ LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
691
722
size_t nthistime ;
692
723
693
724
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
694
- lt = lts -> tapes [tapenum ];
725
+ lt = & lts -> tapes [tapenum ];
695
726
Assert (!lt -> writing );
696
727
697
728
while (size > 0 )
@@ -749,7 +780,7 @@ LogicalTapeFreeze(LogicalTapeSet *lts, int tapenum)
749
780
long datablocknum ;
750
781
751
782
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
752
- lt = lts -> tapes [tapenum ];
783
+ lt = & lts -> tapes [tapenum ];
753
784
Assert (lt -> writing );
754
785
755
786
/*
@@ -793,7 +824,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
793
824
int newpos ;
794
825
795
826
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
796
- lt = lts -> tapes [tapenum ];
827
+ lt = & lts -> tapes [tapenum ];
797
828
Assert (lt -> frozen );
798
829
799
830
/*
@@ -858,7 +889,7 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
858
889
LogicalTape * lt ;
859
890
860
891
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
861
- lt = lts -> tapes [tapenum ];
892
+ lt = & lts -> tapes [tapenum ];
862
893
Assert (lt -> frozen );
863
894
Assert (offset >= 0 && offset <= BLCKSZ );
864
895
@@ -921,7 +952,7 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
921
952
LogicalTape * lt ;
922
953
923
954
Assert (tapenum >= 0 && tapenum < lts -> nTapes );
924
- lt = lts -> tapes [tapenum ];
955
+ lt = & lts -> tapes [tapenum ];
925
956
* blocknum = lt -> curBlockNumber ;
926
957
* offset = lt -> pos ;
927
958
}
0 commit comments