plugeth/core/rawdb/plugin_hooks.go
Austin Roberts 9f28e94d66 Fix memory leak in freezer implementation
It turns out we were only notifying plugins of freezer commits and
cleaning up our record when the block being processed was greater
than MAX_UINT64.

So, uh, never.
2022-01-07 11:36:30 -06:00

121 lines
3.0 KiB
Go

package rawdb
import (
"github.com/ethereum/go-ethereum/plugins"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"sync"
)
var (
freezerUpdates map[uint64]map[string]interface{}
lock sync.Mutex
)
func PluginTrackUpdate(num uint64, kind string, value interface{}) {
lock.Lock()
defer lock.Unlock()
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }
update, ok := freezerUpdates[num]
if !ok {
update = make(map[string]interface{})
freezerUpdates[num] = update
}
update[kind] = value
}
func pluginCommitUpdate(num uint64) {
if plugins.DefaultPluginLoader == nil {
log.Warn("Attempting CommitUpdate, but default PluginLoader has not been initialized")
return
}
PluginCommitUpdate(plugins.DefaultPluginLoader, num)
}
func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
lock.Lock()
defer lock.Unlock()
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }
min := ^uint64(0)
for i := range freezerUpdates{
if min > i { min = i }
}
for i := min ; i < num; i++ {
update, ok := freezerUpdates[i]
defer func() { delete(freezerUpdates, i) }()
if !ok {
log.Warn("Attempting to commit untracked block", "num", i)
continue
}
fnList := pl.Lookup("ModifyAncients", func(item interface{}) bool {
_, ok := item.(func(uint64, map[string]interface{}))
return ok
})
for _, fni := range fnList {
if fn, ok := fni.(func(uint64, map[string]interface{})); ok {
fn(i, update)
}
}
appendAncientFnList := pl.Lookup("AppendAncient", func(item interface{}) bool {
_, ok := item.(func(number uint64, hash, header, body, receipts, td []byte))
if ok { log.Warn("PlugEth's AppendAncient is deprecated. Please update to ModifyAncients.") }
return ok
})
if len(appendAncientFnList) > 0 {
var (
hash []byte
header []byte
body []byte
receipts []byte
td []byte
)
if hashi, ok := update[freezerHashTable]; ok {
switch v := hashi.(type) {
case []byte:
hash = v
default:
hash, _ = rlp.EncodeToBytes(v)
}
}
if headeri, ok := update[freezerHeaderTable]; ok {
switch v := headeri.(type) {
case []byte:
header = v
default:
header, _ = rlp.EncodeToBytes(v)
}
}
if bodyi, ok := update[freezerBodiesTable]; ok {
switch v := bodyi.(type) {
case []byte:
body = v
default:
body, _ = rlp.EncodeToBytes(v)
}
}
if receiptsi, ok := update[freezerReceiptTable]; ok {
switch v := receiptsi.(type) {
case []byte:
receipts = v
default:
receipts, _ = rlp.EncodeToBytes(v)
}
}
if tdi, ok := update[freezerDifficultyTable]; ok {
switch v := tdi.(type) {
case []byte:
td = v
default:
td, _ = rlp.EncodeToBytes(v)
}
}
for _, fni := range appendAncientFnList {
if fn, ok := fni.(func(number uint64, hash, header, body, receipts, td []byte)); ok {
fn(i, hash, header, body, receipts, td)
}
}
}
}
}