@@ -467,6 +467,31 @@ func (t *freezerTable) truncateHead(items uint64) error {
467
467
return nil
468
468
}
469
469
470
+ // readIndexEntry reads the index entry at the given index.
471
+ func (t * freezerTable ) readIndexEntry (index uint64 ) (entry indexEntry , err error ) {
472
+ buffer := make ([]byte , indexEntrySize )
473
+ if _ , err := t .index .ReadAt (buffer , int64 (index * indexEntrySize )); err != nil {
474
+ return indexEntry {}, err
475
+ }
476
+ entry .unmarshalBinary (buffer )
477
+ return entry , nil
478
+ }
479
+
480
+ // hiddenBytes calculates the current size of hidden items in bytes
481
+ func (t * freezerTable ) hiddenBytes () (uint32 , error ) {
482
+ itemHidden := t .itemHidden .Load ()
483
+ itemOffset := t .itemOffset .Load ()
484
+ // no hidden items if the two markers are the same
485
+ if itemHidden == itemOffset {
486
+ return 0 , nil
487
+ }
488
+ itemHiddenIndexEntry , errHidden := t .readIndexEntry (itemHidden - itemOffset )
489
+ if errHidden != nil {
490
+ return 0 , fmt .Errorf ("failed to read index entry, itemHidden: %d, err: %v" , itemHidden , errHidden )
491
+ }
492
+ return itemHiddenIndexEntry .offset , nil
493
+ }
494
+
470
495
// truncateTail discards any recent data before the provided threshold number.
471
496
func (t * freezerTable ) truncateTail (items uint64 ) error {
472
497
t .lock .Lock ()
@@ -495,6 +520,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
495
520
newTail .unmarshalBinary (buffer )
496
521
newTailId = newTail .filenum
497
522
}
523
+ // Save the old size for metrics tracking. This needs to be done
524
+ // before any updates to either itemHidden or itemOffset.
525
+ oldSize , err := t .sizeNolock ()
526
+ if err != nil {
527
+ return err
528
+ }
498
529
// Update the virtual tail marker and hidden these entries in table.
499
530
t .itemHidden .Store (items )
500
531
if err := writeMetadata (t .meta , newMetadata (items )); err != nil {
@@ -509,18 +540,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
509
540
if t .tailId > newTailId {
510
541
return fmt .Errorf ("invalid index, tail-file %d, item-file %d" , t .tailId , newTailId )
511
542
}
512
- // Hidden items exceed the current tail file, drop the relevant
513
- // data files. We need to truncate, save the old size for metrics
514
- // tracking.
515
- oldSize , err := t .sizeNolock ()
516
- if err != nil {
517
- return err
518
- }
519
543
// Count how many items can be deleted from the file.
520
544
var (
521
545
newDeleted = items
522
546
deleted = t .itemOffset .Load ()
523
547
)
548
+ // Hidden items exceed the current tail file, drop the relevant data files.
524
549
for current := items - 1 ; current >= deleted ; current -= 1 {
525
550
if _ , err := t .index .ReadAt (buffer , int64 ((current - deleted + 1 )* indexEntrySize )); err != nil {
526
551
return err
@@ -877,7 +902,11 @@ func (t *freezerTable) sizeNolock() (uint64, error) {
877
902
if err != nil {
878
903
return 0 , err
879
904
}
880
- total := uint64 (t .maxFileSize )* uint64 (t .headId - t .tailId ) + uint64 (t .headBytes ) + uint64 (stat .Size ())
905
+ hiddenBytes , err := t .hiddenBytes ()
906
+ if err != nil {
907
+ return 0 , err
908
+ }
909
+ total := uint64 (t .maxFileSize )* uint64 (t .headId - t .tailId ) + uint64 (t .headBytes ) + uint64 (stat .Size ()) - uint64 (hiddenBytes )
881
910
return total , nil
882
911
}
883
912
0 commit comments