aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2016-04-13 19:05:29 +0800
committerFelix Lange <fjl@twurst.com>2016-04-13 19:05:29 +0800
commite50e3bea495d96de9e67d4e9ab6fd9a9de7ba551 (patch)
tree37f57b694f59b2de2541e69a96ae80edfaa4e263
parentb34b130fb5f8de8bc875c4ddadff044a41c074b4 (diff)
parentbea56d84e53c255febaad5cb26d30122d87d02d9 (diff)
downloadgo-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar.gz
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar.bz2
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar.lz
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar.xz
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.tar.zst
go-tangerine-e50e3bea495d96de9e67d4e9ab6fd9a9de7ba551.zip
Merge pull request #2235 from fjl/chaindb-api-and-console-fixes
eth: add chaindbProperty to debug API (+ console fixes)
-rw-r--r--eth/api.go18
-rw-r--r--internal/debug/api.go15
-rw-r--r--jsre/completion.go19
-rw-r--r--jsre/completion_test.go6
-rw-r--r--jsre/jsre.go16
-rw-r--r--jsre/pretty.go2
-rw-r--r--rpc/javascript.go16
7 files changed, 78 insertions, 14 deletions
diff --git a/eth/api.go b/eth/api.go
index 508070646..105886752 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -26,6 +26,7 @@ import (
"math/big"
"os"
"runtime"
+ "strings"
"sync"
"time"
@@ -46,6 +47,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/syndtr/goleveldb/leveldb"
"golang.org/x/net/context"
)
@@ -1566,6 +1568,22 @@ func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAP
return &PrivateDebugAPI{config: config, eth: eth}
}
+// ChaindbProperty returns leveldb properties of the chain database.
+func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) {
+ ldb, ok := api.eth.chainDb.(interface {
+ LDB() *leveldb.DB
+ })
+ if !ok {
+ return "", fmt.Errorf("chaindbProperty does not work for memory databases")
+ }
+ if property == "" {
+ property = "leveldb.stats"
+ } else if !strings.HasPrefix(property, "leveldb.") {
+ property = "leveldb." + property
+ }
+ return ldb.LDB().GetProperty(property)
+}
+
// BlockTraceResults is the returned value when replaying a block to check for
// consensus results and full VM trace logs for all included transactions.
type BlockTraceResult struct {
diff --git a/internal/debug/api.go b/internal/debug/api.go
index 83857eb2e..2cb264040 100644
--- a/internal/debug/api.go
+++ b/internal/debug/api.go
@@ -27,6 +27,7 @@ import (
"os/user"
"path/filepath"
"runtime"
+ "runtime/debug"
"runtime/pprof"
"strings"
"sync"
@@ -69,6 +70,20 @@ func (*HandlerT) BacktraceAt(location string) error {
return glog.GetTraceLocation().Set(location)
}
+// MemStats returns detailed runtime memory statistics.
+func (*HandlerT) MemStats() *runtime.MemStats {
+ s := new(runtime.MemStats)
+ runtime.ReadMemStats(s)
+ return s
+}
+
+// GcStats returns GC statistics.
+func (*HandlerT) GcStats() *debug.GCStats {
+ s := new(debug.GCStats)
+ debug.ReadGCStats(s)
+ return s
+}
+
// CpuProfile turns on CPU profiling for nsec seconds and writes
// profile data to file.
func (h *HandlerT) CpuProfile(file string, nsec uint) error {
diff --git a/jsre/completion.go b/jsre/completion.go
index e84a5b75c..7f94dabfc 100644
--- a/jsre/completion.go
+++ b/jsre/completion.go
@@ -27,7 +27,9 @@ import (
// evaluated, callers need to make sure that evaluating line does not have side effects.
func (jsre *JSRE) CompleteKeywords(line string) []string {
var results []string
- jsre.do(func(vm *otto.Otto) { results = getCompletions(vm, line) })
+ jsre.Do(func(vm *otto.Otto) {
+ results = getCompletions(vm, line)
+ })
return results
}
@@ -53,9 +55,18 @@ func getCompletions(vm *otto.Otto, line string) (results []string) {
}
}
})
- // e.g. web3<tab><tab> append dot since its an object
- if obj, _ = vm.Object(line); obj != nil {
- results = append(results, line+".")
+
+ // Append opening parenthesis (for functions) or dot (for objects)
+ // if the line itself is the only completion.
+ if len(results) == 1 && results[0] == line {
+ obj, _ := vm.Object(line)
+ if obj != nil {
+ if obj.Class() == "Function" {
+ results[0] += "("
+ } else {
+ results[0] += "."
+ }
+ }
}
sort.Strings(results)
diff --git a/jsre/completion_test.go b/jsre/completion_test.go
index 6d42b2bd1..8765281e5 100644
--- a/jsre/completion_test.go
+++ b/jsre/completion_test.go
@@ -40,7 +40,11 @@ func TestCompleteKeywords(t *testing.T) {
}{
{
input: "x",
- want: []string{"x", "x."},
+ want: []string{"x."},
+ },
+ {
+ input: "x.someMethod",
+ want: []string{"x.someMethod("},
},
{
input: "x.",
diff --git a/jsre/jsre.go b/jsre/jsre.go
index f4464910d..7df022cb1 100644
--- a/jsre/jsre.go
+++ b/jsre/jsre.go
@@ -214,8 +214,8 @@ loop:
self.loopWg.Done()
}
-// do schedules the given function on the event loop.
-func (self *JSRE) do(fn func(*otto.Otto)) {
+// Do executes the given function on the JS event loop.
+func (self *JSRE) Do(fn func(*otto.Otto)) {
done := make(chan bool)
req := &evalReq{fn, done}
self.evalQueue <- req
@@ -235,7 +235,7 @@ func (self *JSRE) Exec(file string) error {
if err != nil {
return err
}
- self.do(func(vm *otto.Otto) { _, err = vm.Run(code) })
+ self.Do(func(vm *otto.Otto) { _, err = vm.Run(code) })
return err
}
@@ -247,19 +247,19 @@ func (self *JSRE) Bind(name string, v interface{}) error {
// Run runs a piece of JS code.
func (self *JSRE) Run(code string) (v otto.Value, err error) {
- self.do(func(vm *otto.Otto) { v, err = vm.Run(code) })
+ self.Do(func(vm *otto.Otto) { v, err = vm.Run(code) })
return v, err
}
// Get returns the value of a variable in the JS environment.
func (self *JSRE) Get(ns string) (v otto.Value, err error) {
- self.do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
+ self.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
return v, err
}
// Set assigns value v to a variable in the JS environment.
func (self *JSRE) Set(ns string, v interface{}) (err error) {
- self.do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
+ self.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
return err
}
@@ -288,7 +288,7 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
// EvalAndPrettyPrint evaluates code and pretty prints the result to
// standard output.
func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
- self.do(func(vm *otto.Otto) {
+ self.Do(func(vm *otto.Otto) {
var val otto.Value
val, err = vm.Run(code)
if err != nil {
@@ -302,7 +302,7 @@ func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
// Compile compiles and then runs a piece of JS code.
func (self *JSRE) Compile(filename string, src interface{}) (err error) {
- self.do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
+ self.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
return err
}
diff --git a/jsre/pretty.go b/jsre/pretty.go
index 8b2b35e8e..cd7fa5232 100644
--- a/jsre/pretty.go
+++ b/jsre/pretty.go
@@ -177,7 +177,7 @@ func (ctx ppctx) fields(obj *otto.Object) []string {
seen = make(map[string]bool)
)
add := func(k string) {
- if seen[k] || boringKeys[k] {
+ if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") {
return
}
seen[k] = true
diff --git a/rpc/javascript.go b/rpc/javascript.go
index d6ffcdf22..475691a87 100644
--- a/rpc/javascript.go
+++ b/rpc/javascript.go
@@ -296,6 +296,12 @@ web3._extend({
params: 1
}),
new web3._extend.Method({
+ name: 'chaindbProperty',
+ call: 'debug_chaindbProperty',
+ params: 1,
+ outputFormatter: console.log
+ }),
+ new web3._extend.Method({
name: 'metrics',
call: 'debug_metrics',
params: 1
@@ -322,6 +328,16 @@ web3._extend({
outputFormatter: console.log
}),
new web3._extend.Method({
+ name: 'memStats',
+ call: 'debug_memStats',
+ params: 0,
+ }),
+ new web3._extend.Method({
+ name: 'gcStats',
+ call: 'debug_gcStats',
+ params: 0,
+ }),
+ new web3._extend.Method({
name: 'cpuProfile',
call: 'debug_cpuProfile',
params: 2