mirror of
https://github.com/status-im/simulation.git
synced 2025-02-22 20:08:07 +00:00
Add server
This commit is contained in:
parent
c82b8d22af
commit
2e30599707
1028
cmd/propagation_simulator/data_test.go
Normal file
1028
cmd/propagation_simulator/data_test.go
Normal file
File diff suppressed because it is too large
Load Diff
37
cmd/propagation_simulator/handler.go
Normal file
37
cmd/propagation_simulator/handler.go
Normal file
@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/divan/graphx/formats"
|
||||
)
|
||||
|
||||
// simulationHandler serves request to start simulation. It expectes network graph
|
||||
// in the request body, syncronously runs a new simulation on this network and
|
||||
// sends back simulation log in JSON format.
|
||||
//
|
||||
// TODO(divan): in the future, simulation will probably take longer, so it'll have to upgrade
|
||||
// connection to Websocket and talk to frontend this way.
|
||||
func simulationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := formats.FromD3JSONReader(r.Body)
|
||||
if err != nil {
|
||||
log.Println("[ERROR] Bad payload:", err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
log.Printf("Loaded graph with %d nodes", len(data.Nodes()))
|
||||
sim := NewSimulation(data)
|
||||
sim.Start()
|
||||
defer sim.Stop()
|
||||
|
||||
log.Println("Sending propagation log")
|
||||
sim.WriteOutput(w)
|
||||
}
|
35
cmd/propagation_simulator/handler_test.go
Normal file
35
cmd/propagation_simulator/handler_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandler(t *testing.T) {
|
||||
payload := bytes.NewBuffer(testdataJSON)
|
||||
req, err := http.NewRequest("POST", "/", payload)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(simulationHandler)
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, http.StatusOK)
|
||||
}
|
||||
|
||||
// Check the response body size (it should be reasonably big)
|
||||
// We can't compare output as it's non-deterministic (each simulation
|
||||
// produce different results).
|
||||
// TODO(divan): decode response and compare data sizes fields, at least.
|
||||
if len(rr.Body.String()) < 100 {
|
||||
t.Errorf("handler returned unexpected body: got %v",
|
||||
rr.Body.String())
|
||||
}
|
||||
}
|
@ -1,70 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/divan/graphx/formats"
|
||||
gethlog "github.com/ethereum/go-ethereum/log"
|
||||
"github.com/status-im/simulation/propagation"
|
||||
"github.com/status-im/simulation/propagation/naivep2p"
|
||||
"github.com/status-im/simulation/propagation/whisperv6"
|
||||
"github.com/status-im/simulation/stats"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
simType = flag.String("type", "whisperv6", "Type of simulators (naivep2p, whisperv6)")
|
||||
ttl = flag.Int("ttl", 10, "Message TTL for simulation")
|
||||
naiveP2PN = flag.Int("naivep2p.N", 3, "Number of peers to propagate (0..N of peers)")
|
||||
naiveP2PDelay = flag.Duration("naivep2p.delay", 10*time.Millisecond, "Delay for each step")
|
||||
input = flag.String("i", "network.json", "Input filename for pregenerated data to be used with simulation")
|
||||
output = flag.String("o", "propagation.json", "Output filename for p2p sending data")
|
||||
gethlogLevel = flag.String("loglevel", "crit", "Geth log level for whisper simulator (crti, error, warn, info, debug, trace)")
|
||||
input = flag.String("i", "network.json", "Input filename for pregenerated data to be used with simulation")
|
||||
output = flag.String("o", "propagation.json", "Output filename for p2p sending data")
|
||||
gethlogLevel = flag.String("loglevel", "crit", "Geth log level for whisper simulator (crti, error, warn, info, debug, trace)")
|
||||
server = flag.Bool("server", false, "Start as server to be used with whisperviz")
|
||||
serverAddr = flag.String("h", "localhost:8084", "Address to bind to in server mode")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
setGethLogLevel(*gethlogLevel)
|
||||
|
||||
if *server {
|
||||
log.Println("Starting simulator server on", *serverAddr)
|
||||
http.HandleFunc("/", simulationHandler)
|
||||
log.Fatal(http.ListenAndServe(*serverAddr, nil))
|
||||
return
|
||||
}
|
||||
|
||||
data, err := formats.FromD3JSON(*input)
|
||||
if err != nil {
|
||||
log.Fatal("Opening input file failed: ", err)
|
||||
}
|
||||
|
||||
fd, err := os.Create(*output)
|
||||
if err != nil {
|
||||
log.Fatal("Opening output file failed: ", err)
|
||||
}
|
||||
defer fd.Close()
|
||||
sim := NewSimulation(data)
|
||||
log.Printf("Starting message sending simulation for graph with %d nodes...", len(data.Nodes()))
|
||||
sim.Start()
|
||||
defer sim.Stop()
|
||||
sim.WriteOutputToFile(*output)
|
||||
|
||||
var sim propagation.Simulator
|
||||
switch *simType {
|
||||
case "naivep2p":
|
||||
sim = naivep2p.NewSimulator(data, *naiveP2PN, *naiveP2PDelay)
|
||||
case "whisperv6":
|
||||
lvl, err := gethlog.LvlFromString(*gethlogLevel)
|
||||
if err != nil {
|
||||
lvl = gethlog.LvlCrit
|
||||
}
|
||||
gethlog.Root().SetHandler(gethlog.LvlFilterHandler(lvl, gethlog.StreamHandler(os.Stderr, gethlog.TerminalFormat(true))))
|
||||
sim = whisperv6.NewSimulator(data)
|
||||
default:
|
||||
log.Fatal("Unknown simulation type: ", *simType)
|
||||
}
|
||||
defer sim.Stop()
|
||||
|
||||
// Start simulation by sending single message
|
||||
log.Printf("Starting message sending %s simulation for graph with %d nodes...", *simType, len(data.Nodes()))
|
||||
plog := sim.SendMessage(0, *ttl)
|
||||
|
||||
// stats
|
||||
ss := stats.Analyze(data, plog)
|
||||
ss := stats.Analyze(data, sim.plog)
|
||||
ss.PrintVerbose()
|
||||
|
||||
err = json.NewEncoder(fd).Encode(plog)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Written %s propagation data into %s", *simType, *output)
|
||||
log.Printf("Written propagation data into %s", *output)
|
||||
}
|
||||
|
||||
func setGethLogLevel(level string) {
|
||||
lvl, err := gethlog.LvlFromString(level)
|
||||
if err != nil {
|
||||
lvl = gethlog.LvlCrit
|
||||
}
|
||||
gethlog.Root().SetHandler(gethlog.LvlFilterHandler(lvl, gethlog.StreamHandler(os.Stderr, gethlog.TerminalFormat(true))))
|
||||
}
|
||||
|
55
cmd/propagation_simulator/simulation.go
Normal file
55
cmd/propagation_simulator/simulation.go
Normal file
@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/divan/graphx/graph"
|
||||
"github.com/status-im/simulation/propagation"
|
||||
"github.com/status-im/simulation/propagation/whisperv6"
|
||||
)
|
||||
|
||||
// Simulation represents single simulation.
|
||||
type Simulation struct {
|
||||
network *graph.Graph
|
||||
sim propagation.Simulator
|
||||
plog *propagation.Log
|
||||
}
|
||||
|
||||
// NewSimulation creates Simulation for the given network.
|
||||
func NewSimulation(network *graph.Graph) *Simulation {
|
||||
sim := whisperv6.NewSimulator(network)
|
||||
|
||||
return &Simulation{
|
||||
network: network,
|
||||
sim: sim,
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts simulation, creating network and preparing it for message sending.
|
||||
func (s *Simulation) Start() {
|
||||
s.plog = s.sim.SendMessage(0, 10)
|
||||
}
|
||||
|
||||
// Stop stops simulation and shuts down network.
|
||||
func (s *Simulation) Stop() error {
|
||||
return s.sim.Stop()
|
||||
}
|
||||
|
||||
// WriteOutput writes propagation log to the given io.Writer.
|
||||
func (s *Simulation) WriteOutput(w io.Writer) error {
|
||||
return json.NewEncoder(w).Encode(s.plog)
|
||||
}
|
||||
|
||||
// WriteOutputToFile writes propagation log to the given io.Writer.
|
||||
func (s *Simulation) WriteOutputToFile(path string) error {
|
||||
fd, err := os.Create(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create output file: %v", err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
return s.WriteOutput(fd)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user