mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd/swarm/global-store: add chunk explorer
This commit is contained in:
parent
f606f57cea
commit
a26d3e07e6
3 changed files with 118 additions and 16 deletions
66
cmd/swarm/global-store/explorer.go
Normal file
66
cmd/swarm/global-store/explorer.go
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of go-ethereum.
|
||||||
|
//
|
||||||
|
// go-ethereum is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// go-ethereum is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage/mock"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage/mock/explorer"
|
||||||
|
cli "gopkg.in/urfave/cli.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// serveChunkExplorer starts an http server in background with chunk explorer handler
|
||||||
|
// using the provided global store. Server is started if the returned shutdown function
|
||||||
|
// is not nil.
|
||||||
|
func serveChunkExplorer(ctx *cli.Context, globalStore mock.GlobalStorer) (shutdown func(), err error) {
|
||||||
|
if !ctx.IsSet("explorer-address") {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
corsOrigins := ctx.StringSlice("explorer-cors-origin")
|
||||||
|
server := &http.Server{
|
||||||
|
Handler: explorer.NewHandler(globalStore, corsOrigins),
|
||||||
|
IdleTimeout: 30 * time.Minute,
|
||||||
|
ReadTimeout: 2 * time.Minute,
|
||||||
|
WriteTimeout: 2 * time.Minute,
|
||||||
|
}
|
||||||
|
listener, err := net.Listen("tcp", ctx.String("explorer-address"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("explorer: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("chunk explorer http", "address", listener.Addr().String(), "origins", corsOrigins)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := server.Serve(listener); err != nil {
|
||||||
|
log.Error("chunk explorer", "err", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := server.Shutdown(ctx); err != nil {
|
||||||
|
log.Error("chunk explorer: shutdown", "err", err)
|
||||||
|
}
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -66,7 +67,7 @@ func startWS(ctx *cli.Context) (err error) {
|
||||||
return http.Serve(listener, server.WebsocketHandler(origins))
|
return http.Serve(listener, server.WebsocketHandler(origins))
|
||||||
}
|
}
|
||||||
|
|
||||||
// newServer creates a global store and returns its RPC server.
|
// newServer creates a global store and starts a chunk explorer server if configured.
|
||||||
// Returned cleanup function should be called only if err is nil.
|
// Returned cleanup function should be called only if err is nil.
|
||||||
func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error) {
|
func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error) {
|
||||||
log.PrintOrigins(true)
|
log.PrintOrigins(true)
|
||||||
|
|
@ -81,7 +82,9 @@ func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
cleanup = func() {
|
cleanup = func() {
|
||||||
dbStore.Close()
|
if err := dbStore.Close(); err != nil {
|
||||||
|
log.Error("global store: close", "err", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
globalStore = dbStore
|
globalStore = dbStore
|
||||||
log.Info("database global store", "dir", dir)
|
log.Info("database global store", "dir", dir)
|
||||||
|
|
@ -96,5 +99,22 @@ func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shutdown, err := serveChunkExplorer(ctx, globalStore)
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if shutdown != nil {
|
||||||
|
cleanup = func() {
|
||||||
|
shutdown()
|
||||||
|
|
||||||
|
if c, ok := globalStore.(io.Closer); ok {
|
||||||
|
if err := c.Close(); err != nil {
|
||||||
|
log.Error("global store: close", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return server, cleanup, nil
|
return server, cleanup, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
cli "gopkg.in/urfave/cli.v1"
|
cli "gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
|
var (
|
||||||
|
version = "0.1"
|
||||||
|
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := newApp().Run(os.Args)
|
err := newApp().Run(os.Args)
|
||||||
|
|
@ -37,16 +39,30 @@ func main() {
|
||||||
// newApp construct a new instance of Swarm Global Store.
|
// newApp construct a new instance of Swarm Global Store.
|
||||||
// Method Run is called on it in the main function and in tests.
|
// Method Run is called on it in the main function and in tests.
|
||||||
func newApp() (app *cli.App) {
|
func newApp() (app *cli.App) {
|
||||||
app = utils.NewApp(gitCommit, "Swarm Global Store")
|
app = cli.NewApp()
|
||||||
|
|
||||||
app.Name = "global-store"
|
app.Name = "global-store"
|
||||||
|
app.Version = version
|
||||||
|
if len(gitCommit) >= 8 {
|
||||||
|
app.Version += "-" + gitCommit[:8]
|
||||||
|
}
|
||||||
|
app.Usage = "Swarm Global Store"
|
||||||
|
|
||||||
// app flags (for all commands)
|
// app flags (for all commands)
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
Value: 3,
|
Value: 3,
|
||||||
Usage: "verbosity level",
|
Usage: "Verbosity level.",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "explorer-address",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Chunk explorer HTTP listener address.",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "explorer-cors-origin",
|
||||||
|
Value: nil,
|
||||||
|
Usage: "Chunk explorer CORS origin (can be specified multiple times).",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +70,7 @@ func newApp() (app *cli.App) {
|
||||||
{
|
{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
Aliases: []string{"h"},
|
Aliases: []string{"h"},
|
||||||
Usage: "start swarm global store with http server",
|
Usage: "Start swarm global store with HTTP server.",
|
||||||
Action: startHTTP,
|
Action: startHTTP,
|
||||||
// Flags only for "start" command.
|
// Flags only for "start" command.
|
||||||
// Allow app flags to be specified after the
|
// Allow app flags to be specified after the
|
||||||
|
|
@ -63,19 +79,19 @@ func newApp() (app *cli.App) {
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "dir",
|
Name: "dir",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "data directory",
|
Usage: "Data directory.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "addr",
|
Name: "addr",
|
||||||
Value: "0.0.0.0:3033",
|
Value: "0.0.0.0:3033",
|
||||||
Usage: "address to listen for http connection",
|
Usage: "Address to listen for HTTP connections.",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "websocket",
|
Name: "websocket",
|
||||||
Aliases: []string{"ws"},
|
Aliases: []string{"ws"},
|
||||||
Usage: "start swarm global store with websocket server",
|
Usage: "Start swarm global store with WebSocket server.",
|
||||||
Action: startWS,
|
Action: startWS,
|
||||||
// Flags only for "start" command.
|
// Flags only for "start" command.
|
||||||
// Allow app flags to be specified after the
|
// Allow app flags to be specified after the
|
||||||
|
|
@ -84,17 +100,17 @@ func newApp() (app *cli.App) {
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "dir",
|
Name: "dir",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "data directory",
|
Usage: "Data directory.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "addr",
|
Name: "addr",
|
||||||
Value: "0.0.0.0:3033",
|
Value: "0.0.0.0:3033",
|
||||||
Usage: "address to listen for websocket connection",
|
Usage: "Address to listen for WebSocket connections.",
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
Name: "origins",
|
Name: "origin",
|
||||||
Value: &cli.StringSlice{"*"},
|
Value: nil,
|
||||||
Usage: "websocket origins",
|
Usage: "WebSocket CORS origin (can be specified multiple times).",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue