@@ -36,6 +36,7 @@ import (
3636
3737 "github.com/erigontech/erigon/common"
3838 "github.com/erigontech/erigon/common/assert"
39+ "github.com/erigontech/erigon/common/background"
3940 "github.com/erigontech/erigon/common/dir"
4041 "github.com/erigontech/erigon/common/log/v3"
4142 "github.com/erigontech/erigon/common/mmap"
@@ -164,6 +165,8 @@ type RecSplit struct {
164165
165166 noFsync bool // fsync is enabled by default, but tests can manually disable
166167 timings Timings
168+
169+ progress * background.Progress // If set, tracks 0-100%: add-keys fills 0-50%, build fills 50-100%
167170}
168171
169172type RecSplitArgs struct {
@@ -395,6 +398,9 @@ func (rs *RecSplit) ResetNextSalt() {
395398 rs .collision = false
396399 rs .keysAdded = 0
397400 rs .salt ++
401+ if rs .progress != nil {
402+ rs .progress .Processed .Store (0 )
403+ }
398404 if rs .bucketCollector != nil {
399405 rs .bucketCollector .Close ()
400406 }
@@ -519,6 +525,9 @@ func (rs *RecSplit) AddKey(key []byte, offset uint64) error {
519525
520526 rs .keysAdded ++
521527 rs .prevOffset = offset
528+ if rs .progress != nil && rs .keysAdded % 1024 == 0 {
529+ rs .progress .Processed .Add (1024 )
530+ }
522531 return nil
523532}
524533
@@ -790,6 +799,10 @@ func (rs *RecSplit) loadFuncBucket(k, v []byte, _ etl.CurrentTableReader, _ etl.
790799 if err := rs .recsplitCurrentBucket (); err != nil {
791800 return err
792801 }
802+ if rs .progress != nil {
803+ // Build phase fills the 50–100% half: each bucket ≈ bucketSize keys worth.
804+ rs .progress .Processed .Add (uint64 (rs .bucketSize ))
805+ }
793806 }
794807 rs .currentBucketIdx = bucketIdx
795808 }
@@ -820,6 +833,26 @@ func (rs *RecSplit) buildOffsetEf() error {
820833 return nil
821834}
822835
836+ // KeyCount returns the number of keys added to the RecSplit.
837+ func (rs * RecSplit ) KeyCount () uint64 { return rs .keysAdded }
838+
839+ // BucketCount returns the number of buckets.
840+ func (rs * RecSplit ) BucketCount () uint64 { return rs .bucketCount }
841+
842+ // SetProgress wires a single progress tracker covering the full build lifecycle.
843+ // Total = 2*keyExpectedCount; AddKey fills 0→keyExpectedCount (0–50%) and
844+ // the bucket-building phase fills keyExpectedCount→2*keyExpectedCount (50–100%).
845+ // Progress is automatically reset on ResetNextSalt (collision retry).
846+ func (rs * RecSplit ) SetProgress (p * background.Progress ) {
847+ if p == nil {
848+ return
849+ }
850+ p .Name .Store (& rs .fileName )
851+ p .Processed .Store (0 )
852+ p .Total .Store (2 * rs .keyExpectedCount )
853+ rs .progress = p
854+ }
855+
823856// Build has to be called after all the keys have been added, and it initiates the process
824857// of building the perfect hash function and writing index into a file
825858func (rs * RecSplit ) Build (ctx context.Context ) error {
0 commit comments