@@ -467,6 +467,20 @@ func (t *freezerTable) truncateHead(items uint64) error {
467467 return nil
468468}
469469
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+
470484// truncateTail discards any recent data before the provided threshold number.
471485func (t * freezerTable ) truncateTail (items uint64 ) error {
472486 t .lock .Lock ()
@@ -495,6 +509,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
495509 newTail .unmarshalBinary (buffer )
496510 newTailId = newTail .filenum
497511 }
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+ }
498518 // Update the virtual tail marker and hidden these entries in table.
499519 t .itemHidden .Store (items )
500520 if err := writeMetadata (t .meta , newMetadata (items )); err != nil {
@@ -509,18 +529,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
509529 if t .tailId > newTailId {
510530 return fmt .Errorf ("invalid index, tail-file %d, item-file %d" , t .tailId , newTailId )
511531 }
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- }
519532 // Count how many items can be deleted from the file.
520533 var (
521534 newDeleted = items
522535 deleted = t .itemOffset .Load ()
523536 )
537+ // Hidden items exceed the current tail file, drop the relevant data files.
524538 for current := items - 1 ; current >= deleted ; current -= 1 {
525539 if _ , err := t .index .ReadAt (buffer , int64 ((current - deleted + 1 )* indexEntrySize )); err != nil {
526540 return err
@@ -680,6 +694,7 @@ func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) {
680694func (t * freezerTable ) getIndices (from , count uint64 ) ([]* indexEntry , error ) {
681695 // Apply the table-offset
682696 from = from - t .itemOffset .Load ()
697+
683698 // For reading N items, we need N+1 indices.
684699 buffer := make ([]byte , (count + 1 )* indexEntrySize )
685700 if _ , err := t .index .ReadAt (buffer , int64 (from * indexEntrySize )); err != nil {
@@ -870,14 +885,18 @@ func (t *freezerTable) size() (uint64, error) {
870885 return t .sizeNolock ()
871886}
872887
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 .
875890func (t * freezerTable ) sizeNolock () (uint64 , error ) {
876891 stat , err := t .index .Stat ()
877892 if err != nil {
878893 return 0 , err
879894 }
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
881900 return total , nil
882901}
883902
0 commit comments