Skip to content

Commit 461d238

Browse files
authored
Merge pull request #1862 from CortexFoundation/dev
core/rawdb: implement size reporting for live items in freezer_table …
2 parents f471720 + 858c1e3 commit 461d238

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

core/rawdb/freezer_table.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
471485
func (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) {
680694
func (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.
875890
func (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

core/rawdb/freezer_table_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,13 @@ func TestFreezerOffset(t *testing.T) {
658658
}
659659
}
660660

661+
func assertTableSize(t *testing.T, f *freezerTable, size int) {
662+
t.Helper()
663+
if got, err := f.size(); got != uint64(size) {
664+
t.Fatalf("expected size of %d bytes, got %d, err: %v", size, got, err)
665+
}
666+
}
667+
661668
func TestTruncateTail(t *testing.T) {
662669
t.Parallel()
663670
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
@@ -692,6 +699,9 @@ func TestTruncateTail(t *testing.T) {
692699
5: getChunk(20, 0xaa),
693700
6: getChunk(20, 0x11),
694701
})
702+
// maxFileSize*fileCount + headBytes + indexFileSize - hiddenBytes
703+
expected := 20*7 + 48 - 0
704+
assertTableSize(t, f, expected)
695705

696706
// truncate single element( item 0 ), deletion is only supported at file level
697707
f.truncateTail(1)
@@ -707,6 +717,8 @@ func TestTruncateTail(t *testing.T) {
707717
5: getChunk(20, 0xaa),
708718
6: getChunk(20, 0x11),
709719
})
720+
expected = 20*7 + 48 - 20
721+
assertTableSize(t, f, expected)
710722

711723
// Reopen the table, the deletion information should be persisted as well
712724
f.Close()
@@ -739,6 +751,8 @@ func TestTruncateTail(t *testing.T) {
739751
5: getChunk(20, 0xaa),
740752
6: getChunk(20, 0x11),
741753
})
754+
expected = 20*5 + 36 - 0
755+
assertTableSize(t, f, expected)
742756

743757
// Reopen the table, the above testing should still pass
744758
f.Close()
@@ -760,6 +774,23 @@ func TestTruncateTail(t *testing.T) {
760774
6: getChunk(20, 0x11),
761775
})
762776

777+
// truncate 3 more elements( item 2, 3, 4), the file 1 should be deleted
778+
// file 2 should only contain item 5
779+
f.truncateTail(5)
780+
checkRetrieveError(t, f, map[uint64]error{
781+
0: errOutOfBounds,
782+
1: errOutOfBounds,
783+
2: errOutOfBounds,
784+
3: errOutOfBounds,
785+
4: errOutOfBounds,
786+
})
787+
checkRetrieve(t, f, map[uint64][]byte{
788+
5: getChunk(20, 0xaa),
789+
6: getChunk(20, 0x11),
790+
})
791+
expected = 20*3 + 24 - 20
792+
assertTableSize(t, f, expected)
793+
763794
// truncate all, the entire freezer should be deleted
764795
f.truncateTail(7)
765796
checkRetrieveError(t, f, map[uint64]error{
@@ -771,6 +802,8 @@ func TestTruncateTail(t *testing.T) {
771802
5: errOutOfBounds,
772803
6: errOutOfBounds,
773804
})
805+
expected = 12
806+
assertTableSize(t, f, expected)
774807
}
775808

776809
func TestTruncateHead(t *testing.T) {

0 commit comments

Comments
 (0)