Skip to content

Commit e50e3be

Browse files
committed
Merge pull request #2235 from fjl/chaindb-api-and-console-fixes
eth: add chaindbProperty to debug API (+ console fixes)
2 parents b34b130 + bea56d8 commit e50e3be

File tree

7 files changed

+78
-14
lines changed

7 files changed

+78
-14
lines changed

eth/api.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"math/big"
2727
"os"
2828
"runtime"
29+
"strings"
2930
"sync"
3031
"time"
3132

@@ -46,6 +47,7 @@ import (
4647
"github.com/ethereum/go-ethereum/p2p"
4748
"github.com/ethereum/go-ethereum/rlp"
4849
"github.com/ethereum/go-ethereum/rpc"
50+
"github.com/syndtr/goleveldb/leveldb"
4951
"golang.org/x/net/context"
5052
)
5153

@@ -1566,6 +1568,22 @@ func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAP
15661568
return &PrivateDebugAPI{config: config, eth: eth}
15671569
}
15681570

1571+
// ChaindbProperty returns leveldb properties of the chain database.
1572+
func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) {
1573+
ldb, ok := api.eth.chainDb.(interface {
1574+
LDB() *leveldb.DB
1575+
})
1576+
if !ok {
1577+
return "", fmt.Errorf("chaindbProperty does not work for memory databases")
1578+
}
1579+
if property == "" {
1580+
property = "leveldb.stats"
1581+
} else if !strings.HasPrefix(property, "leveldb.") {
1582+
property = "leveldb." + property
1583+
}
1584+
return ldb.LDB().GetProperty(property)
1585+
}
1586+
15691587
// BlockTraceResults is the returned value when replaying a block to check for
15701588
// consensus results and full VM trace logs for all included transactions.
15711589
type BlockTraceResult struct {

internal/debug/api.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"os/user"
2828
"path/filepath"
2929
"runtime"
30+
"runtime/debug"
3031
"runtime/pprof"
3132
"strings"
3233
"sync"
@@ -69,6 +70,20 @@ func (*HandlerT) BacktraceAt(location string) error {
6970
return glog.GetTraceLocation().Set(location)
7071
}
7172

73+
// MemStats returns detailed runtime memory statistics.
74+
func (*HandlerT) MemStats() *runtime.MemStats {
75+
s := new(runtime.MemStats)
76+
runtime.ReadMemStats(s)
77+
return s
78+
}
79+
80+
// GcStats returns GC statistics.
81+
func (*HandlerT) GcStats() *debug.GCStats {
82+
s := new(debug.GCStats)
83+
debug.ReadGCStats(s)
84+
return s
85+
}
86+
7287
// CpuProfile turns on CPU profiling for nsec seconds and writes
7388
// profile data to file.
7489
func (h *HandlerT) CpuProfile(file string, nsec uint) error {

jsre/completion.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
// evaluated, callers need to make sure that evaluating line does not have side effects.
2828
func (jsre *JSRE) CompleteKeywords(line string) []string {
2929
var results []string
30-
jsre.do(func(vm *otto.Otto) { results = getCompletions(vm, line) })
30+
jsre.Do(func(vm *otto.Otto) {
31+
results = getCompletions(vm, line)
32+
})
3133
return results
3234
}
3335

@@ -53,9 +55,18 @@ func getCompletions(vm *otto.Otto, line string) (results []string) {
5355
}
5456
}
5557
})
56-
// e.g. web3<tab><tab> append dot since its an object
57-
if obj, _ = vm.Object(line); obj != nil {
58-
results = append(results, line+".")
58+
59+
// Append opening parenthesis (for functions) or dot (for objects)
60+
// if the line itself is the only completion.
61+
if len(results) == 1 && results[0] == line {
62+
obj, _ := vm.Object(line)
63+
if obj != nil {
64+
if obj.Class() == "Function" {
65+
results[0] += "("
66+
} else {
67+
results[0] += "."
68+
}
69+
}
5970
}
6071

6172
sort.Strings(results)

jsre/completion_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ func TestCompleteKeywords(t *testing.T) {
4040
}{
4141
{
4242
input: "x",
43-
want: []string{"x", "x."},
43+
want: []string{"x."},
44+
},
45+
{
46+
input: "x.someMethod",
47+
want: []string{"x.someMethod("},
4448
},
4549
{
4650
input: "x.",

jsre/jsre.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ loop:
214214
self.loopWg.Done()
215215
}
216216

217-
// do schedules the given function on the event loop.
218-
func (self *JSRE) do(fn func(*otto.Otto)) {
217+
// Do executes the given function on the JS event loop.
218+
func (self *JSRE) Do(fn func(*otto.Otto)) {
219219
done := make(chan bool)
220220
req := &evalReq{fn, done}
221221
self.evalQueue <- req
@@ -235,7 +235,7 @@ func (self *JSRE) Exec(file string) error {
235235
if err != nil {
236236
return err
237237
}
238-
self.do(func(vm *otto.Otto) { _, err = vm.Run(code) })
238+
self.Do(func(vm *otto.Otto) { _, err = vm.Run(code) })
239239
return err
240240
}
241241

@@ -247,19 +247,19 @@ func (self *JSRE) Bind(name string, v interface{}) error {
247247

248248
// Run runs a piece of JS code.
249249
func (self *JSRE) Run(code string) (v otto.Value, err error) {
250-
self.do(func(vm *otto.Otto) { v, err = vm.Run(code) })
250+
self.Do(func(vm *otto.Otto) { v, err = vm.Run(code) })
251251
return v, err
252252
}
253253

254254
// Get returns the value of a variable in the JS environment.
255255
func (self *JSRE) Get(ns string) (v otto.Value, err error) {
256-
self.do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
256+
self.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
257257
return v, err
258258
}
259259

260260
// Set assigns value v to a variable in the JS environment.
261261
func (self *JSRE) Set(ns string, v interface{}) (err error) {
262-
self.do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
262+
self.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
263263
return err
264264
}
265265

@@ -288,7 +288,7 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
288288
// EvalAndPrettyPrint evaluates code and pretty prints the result to
289289
// standard output.
290290
func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
291-
self.do(func(vm *otto.Otto) {
291+
self.Do(func(vm *otto.Otto) {
292292
var val otto.Value
293293
val, err = vm.Run(code)
294294
if err != nil {
@@ -302,7 +302,7 @@ func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
302302

303303
// Compile compiles and then runs a piece of JS code.
304304
func (self *JSRE) Compile(filename string, src interface{}) (err error) {
305-
self.do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
305+
self.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
306306
return err
307307
}
308308

jsre/pretty.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func (ctx ppctx) fields(obj *otto.Object) []string {
177177
seen = make(map[string]bool)
178178
)
179179
add := func(k string) {
180-
if seen[k] || boringKeys[k] {
180+
if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") {
181181
return
182182
}
183183
seen[k] = true

rpc/javascript.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ web3._extend({
295295
call: 'debug_dumpBlock',
296296
params: 1
297297
}),
298+
new web3._extend.Method({
299+
name: 'chaindbProperty',
300+
call: 'debug_chaindbProperty',
301+
params: 1,
302+
outputFormatter: console.log
303+
}),
298304
new web3._extend.Method({
299305
name: 'metrics',
300306
call: 'debug_metrics',
@@ -321,6 +327,16 @@ web3._extend({
321327
params: 0,
322328
outputFormatter: console.log
323329
}),
330+
new web3._extend.Method({
331+
name: 'memStats',
332+
call: 'debug_memStats',
333+
params: 0,
334+
}),
335+
new web3._extend.Method({
336+
name: 'gcStats',
337+
call: 'debug_gcStats',
338+
params: 0,
339+
}),
324340
new web3._extend.Method({
325341
name: 'cpuProfile',
326342
call: 'debug_cpuProfile',

0 commit comments

Comments
 (0)