@@ -467,6 +467,20 @@ func (t *freezerTable) truncateHead(items uint64) error {
467
467
return nil
468
468
}
469
469
470
+ // sizeHidden returns the total data size of hidden items in the freezer table.
471
+ // This function assumes the lock is already held.
472
+ func (t * freezerTable ) sizeHidden () (uint64 , error ) {
473
+ hidden , offset := t .itemHidden .Load (), t .itemOffset .Load ()
474
+ if hidden <= offset {
475
+ return 0 , nil
476
+ }
477
+ indices , err := t .getIndices (hidden - 1 , 1 )
478
+ if err != nil {
479
+ return 0 , err
480
+ }
481
+ return uint64 (indices [1 ].offset ), nil
482
+ }
483
+
470
484
// truncateTail discards any recent data before the provided threshold number.
471
485
func (t * freezerTable ) truncateTail (items uint64 ) error {
472
486
t .lock .Lock ()
@@ -495,6 +509,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
495
509
newTail .unmarshalBinary (buffer )
496
510
newTailId = newTail .filenum
497
511
}
512
+ // Save the old size for metrics tracking. This needs to be done
513
+ // before any updates to either itemHidden or itemOffset.
514
+ oldSize , err := t .sizeNolock ()
515
+ if err != nil {
516
+ return err
517
+ }
498
518
// Update the virtual tail marker and hidden these entries in table.
499
519
t .itemHidden .Store (items )
500
520
if err := writeMetadata (t .meta , newMetadata (items )); err != nil {
@@ -509,18 +529,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
509
529
if t .tailId > newTailId {
510
530
return fmt .Errorf ("invalid index, tail-file %d, item-file %d" , t .tailId , newTailId )
511
531
}
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
532
// Count how many items can be deleted from the file.
520
533
var (
521
534
newDeleted = items
522
535
deleted = t .itemOffset .Load ()
523
536
)
537
+ // Hidden items exceed the current tail file, drop the relevant data files.
524
538
for current := items - 1 ; current >= deleted ; current -= 1 {
525
539
if _ , err := t .index .ReadAt (buffer , int64 ((current - deleted + 1 )* indexEntrySize )); err != nil {
526
540
return err
@@ -680,6 +694,7 @@ func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) {
680
694
func (t * freezerTable ) getIndices (from , count uint64 ) ([]* indexEntry , error ) {
681
695
// Apply the table-offset
682
696
from = from - t .itemOffset .Load ()
697
+
683
698
// For reading N items, we need N+1 indices.
684
699
buffer := make ([]byte , (count + 1 )* indexEntrySize )
685
700
if _ , err := t .index .ReadAt (buffer , int64 (from * indexEntrySize )); err != nil {
@@ -870,14 +885,18 @@ func (t *freezerTable) size() (uint64, error) {
870
885
return t .sizeNolock ()
871
886
}
872
887
873
- // sizeNolock returns the total data size in the freezer table without obtaining
874
- // the mutex first .
888
+ // sizeNolock returns the total data size in the freezer table. This function
889
+ // assumes the lock is already held .
875
890
func (t * freezerTable ) sizeNolock () (uint64 , error ) {
876
891
stat , err := t .index .Stat ()
877
892
if err != nil {
878
893
return 0 , err
879
894
}
880
- total := uint64 (t .maxFileSize )* uint64 (t .headId - t .tailId ) + uint64 (t .headBytes ) + uint64 (stat .Size ())
895
+ hidden , err := t .sizeHidden ()
896
+ if err != nil {
897
+ return 0 , err
898
+ }
899
+ total := uint64 (t .maxFileSize )* uint64 (t .headId - t .tailId ) + uint64 (t .headBytes ) + uint64 (stat .Size ()) - hidden
881
900
return total , nil
882
901
}
883
902
0 commit comments