Skip to content

Commit 5670032

Browse files
committed
feat: rawdb.InspectDatabaseOption
1 parent d08d0f0 commit 5670032

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed

core/rawdb/database.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/ava-labs/libevm/ethdb/leveldb"
3232
"github.com/ava-labs/libevm/ethdb/memorydb"
3333
"github.com/ava-labs/libevm/ethdb/pebble"
34+
"github.com/ava-labs/libevm/libevm/options"
3435
"github.com/ava-labs/libevm/log"
3536
"github.com/olekukonko/tablewriter"
3637
)
@@ -451,7 +452,8 @@ func (s *stat) Count() string {
451452

452453
// InspectDatabase traverses the entire database and checks the size
453454
// of all different categories of data.
454-
func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
455+
func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte, opts ...InspectDatabaseOption) error {
456+
libevmConfig := options.As[inspectDatabaseConfig](opts...)
455457
it := db.NewIterator(keyPrefix, keyStart)
456458
defer it.Release()
457459

@@ -549,6 +551,9 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
549551
bytes.HasPrefix(key, BloomTrieIndexPrefix) ||
550552
bytes.HasPrefix(key, BloomTriePrefix): // Bloomtrie sub
551553
bloomTrieNodes.Add(size)
554+
case libevmConfig.recordStat(key, size):
555+
case libevmConfig.isMetadata(key):
556+
metadata.Add(size)
552557
default:
553558
var accounted bool
554559
for _, meta := range [][]byte{
@@ -617,7 +622,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
617622
table := tablewriter.NewWriter(os.Stdout)
618623
table.SetHeader([]string{"Database", "Category", "Size", "Items"})
619624
table.SetFooter([]string{"", "Total", total.String(), " "})
620-
table.AppendBulk(stats)
625+
table.AppendBulk(libevmConfig.transformStats(stats))
621626
table.Render()
622627

623628
if unaccounted.size > 0 {

core/rawdb/database.libevm.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2025 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
package rawdb
18+
19+
import (
20+
"github.com/ava-labs/libevm/common"
21+
"github.com/ava-labs/libevm/libevm/options"
22+
)
23+
24+
// An InspectDatabaseOption configures the behaviour of [InspectDatabase]. For
25+
// each type of option, only one instance can be used in the same call to
26+
// InspectDatabase().
27+
type InspectDatabaseOption = options.Option[inspectDatabaseConfig]
28+
29+
type inspectDatabaseConfig struct {
30+
statRecorder func([]byte, common.StorageSize) bool
31+
isMeta func([]byte) bool
32+
statsTransformer func([][]string) [][]string
33+
}
34+
35+
func (c inspectDatabaseConfig) recordStat(key []byte, size common.StorageSize) bool {
36+
if r := c.statRecorder; r != nil {
37+
return r(key, size)
38+
}
39+
return false
40+
}
41+
42+
func (c inspectDatabaseConfig) isMetadata(key []byte) bool {
43+
if m := c.isMeta; m != nil {
44+
return m(key)
45+
}
46+
return false
47+
}
48+
49+
func (c inspectDatabaseConfig) transformStats(stats [][]string) [][]string {
50+
if f := c.statsTransformer; f != nil {
51+
return f(stats)
52+
}
53+
return stats
54+
}
55+
56+
func newInspectOpt(fn func(*inspectDatabaseConfig)) InspectDatabaseOption {
57+
return options.Func[inspectDatabaseConfig](fn)
58+
}
59+
60+
// WithDatabaseStatRecorder returns an option that results in `rec` being called
61+
// for every `key` not otherwise matched by the [InspectDatabase] iterator loop.
62+
// The returned boolean signals whether the recorder matches the key, thus
63+
// stopping further matches.
64+
func WithDatabaseStatRecorder(rec func(key []byte, _ common.StorageSize) bool) InspectDatabaseOption {
65+
return newInspectOpt(func(c *inspectDatabaseConfig) {
66+
c.statRecorder = rec
67+
})
68+
}
69+
70+
// A DatabaseStat stores total size and counts for a parameter measured by
71+
// [InspectDatabase]. It is exported for use with [WithDatabaseStatRecorder].
72+
type DatabaseStat = stat
73+
74+
// WithDatabaseMetadataKeys returns an option that results in the `key` size
75+
// being counted with the metadata statistic i.f.f. the function returns true.
76+
func WithDatabaseMetadataKeys(isMetadata func(key []byte) bool) InspectDatabaseOption {
77+
return newInspectOpt(func(c *inspectDatabaseConfig) {
78+
c.isMeta = isMetadata
79+
})
80+
}
81+
82+
// WithDatabaseStatsTransformer returns an option that causes all statistics to
83+
// be passed to the provided function, with its return value being printed
84+
// instead of the original values.
85+
func WithDatabaseStatsTransformer(transform func([][]string) [][]string) InspectDatabaseOption {
86+
return newInspectOpt(func(c *inspectDatabaseConfig) {
87+
c.statsTransformer = transform
88+
})
89+
}

core/rawdb/database.libevm_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2025 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
package rawdb_test
18+
19+
import (
20+
"github.com/ava-labs/libevm/common"
21+
// To ensure that all methods are available to importing packages, this test
22+
// is defined in package `rawdb_test` instead of `rawdb`.
23+
"github.com/ava-labs/libevm/core/rawdb"
24+
)
25+
26+
// ExampleDatabaseStat demonstrates the method signatures of DatabaseStat, which
27+
// exposes an otherwise unexported type that won't have its methods documented.
28+
func ExampleDatabaseStat() {
29+
var (
30+
stat rawdb.DatabaseStat
31+
size common.StorageSize
32+
)
33+
34+
stat.Add(size)
35+
36+
var (
37+
_ string = stat.Size() // sum of all values passed to Add()
38+
_ string = stat.Count() // number of calls to Add()
39+
)
40+
}

0 commit comments

Comments
 (0)