80ae5b46d4
We had been assuming that the `item` returned from batch.commit() was the item committed, but it's actually the next item to be added to the freezer, and multiple items can be committed in a single batch. This commit finds the smallest item in the freezer and iterates from that to the number returned by commit(), passing any tracked blocks in that range to plugins.
121 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|