// Create the bloom filter to track known trie nodes
bloom,err:=bloomfilter.New(memory*1024*1024*8,4)
iferr!=nil{
panic(fmt.Sprintf("failed to create bloom: %v",err))
}
log.Info("Allocated fast sync bloom","size",common.StorageSize(memory*1024*1024))
// Assemble the fast sync bloom and init it from previous sessions
b:=&SyncBloom{
bloom:bloom,
closeCh:make(chanstruct{}),
}
b.pend.Add(2)
gofunc(){
deferb.pend.Done()
b.init(database)
}()
gofunc(){
deferb.pend.Done()
b.meter()
}()
returnb
}
// init iterates over the database, pushing every trie hash into the bloom filter.
func(b*SyncBloom)init(databaseethdb.Iteratee){
// Iterate over the database, but restart every now and again to avoid holding
// a persistent snapshot since fast sync can push a ton of data concurrently,
// bloating the disk.
//
// Note, this is fine, because everything inserted into leveldb by fast sync is
// also pushed into the bloom directly, so we're not missing anything when the
// iterator is swapped out for a new one.
it:=database.NewIterator(nil,nil)
var(
start=time.Now()
swap=time.Now()
)
forit.Next()&&atomic.LoadUint32(&b.closed)==0{
// If the database entry is a trie node, add it to the bloom
key:=it.Key()
iflen(key)==common.HashLength{
b.bloom.AddHash(binary.BigEndian.Uint64(key))
bloomLoadMeter.Mark(1)
}elseifok,hash:=rawdb.IsCodeKey(key);ok{
// If the database entry is a contract code, add it to the bloom
b.bloom.AddHash(binary.BigEndian.Uint64(hash))
bloomLoadMeter.Mark(1)
}
// If enough time elapsed since the last iterator swap, restart
iftime.Since(swap)>8*time.Second{
key:=common.CopyBytes(it.Key())
it.Release()
it=database.NewIterator(nil,key)
log.Info("Initializing state bloom","items",b.bloom.N(),"errorrate",b.bloom.FalsePosititveProbability(),"elapsed",common.PrettyDuration(time.Since(start)))
swap=time.Now()
}
}
it.Release()
// Mark the bloom filter inited and return
log.Info("Initialized state bloom","items",b.bloom.N(),"errorrate",b.bloom.FalsePosititveProbability(),"elapsed",common.PrettyDuration(time.Since(start)))
atomic.StoreUint32(&b.inited,1)
}
// meter periodically recalculates the false positive error rate of the bloom
// filter and reports it in a metric.
func(b*SyncBloom)meter(){
// check every second
tick:=time.NewTicker(1*time.Second)
defertick.Stop()
for{
select{
case<-tick.C:
// Report the current error ration. No floats, lame, scale it up.