kopia lustrzana https://github.com/cyoung/stratux
160 wiersze
3.6 KiB
Go
160 wiersze
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var uatDone bool
|
|
var esDone bool
|
|
|
|
func uatReplay(f *os.File, replaySpeed uint64) {
|
|
rdr := bufio.NewReader(f)
|
|
curTick := int64(0)
|
|
for {
|
|
buf, err := rdr.ReadString('\n')
|
|
if err != nil {
|
|
break
|
|
}
|
|
linesplit := strings.Split(buf, ",")
|
|
if len(linesplit) < 2 { // Blank line or invalid.
|
|
continue
|
|
}
|
|
if linesplit[0] == "START" { // Reset ticker, new start.
|
|
curTick = 0
|
|
} else { // If it's not "START", then it's a tick count.
|
|
i, err := strconv.ParseInt(linesplit[0], 10, 64)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "invalid tick: '%s'\n", linesplit[0])
|
|
continue
|
|
}
|
|
thisWait := (i - curTick) / int64(replaySpeed)
|
|
|
|
if thisWait >= 120000000000 { // More than 2 minutes wait, skip ahead.
|
|
fmt.Fprintf(os.Stderr, "UAT skipahead - %d seconds.\n", thisWait/1000000000)
|
|
} else {
|
|
time.Sleep(time.Duration(thisWait) * time.Nanosecond) // Just in case the units change.
|
|
}
|
|
|
|
p := strings.Trim(linesplit[1], " ;\r\n")
|
|
fmt.Printf("%s;\n", p)
|
|
curTick = i
|
|
}
|
|
}
|
|
uatDone = true
|
|
}
|
|
|
|
var connections map[string]net.Conn
|
|
|
|
func sendToClients(msg string) {
|
|
for addrStr, conn := range connections {
|
|
_, err := conn.Write([]byte(msg))
|
|
if err != nil {
|
|
delete(connections, addrStr)
|
|
fmt.Fprintf(os.Stderr, "disconnected: %s\n", addrStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func esListener(l net.Listener) {
|
|
defer l.Close()
|
|
connections = make(map[string]net.Conn)
|
|
for {
|
|
conn, err := l.Accept()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error accepting: %s\n", err.Error())
|
|
continue
|
|
}
|
|
fmt.Fprintf(os.Stderr, "new connection: %s\n", conn.RemoteAddr().String())
|
|
connections[conn.RemoteAddr().String()] = conn
|
|
}
|
|
}
|
|
|
|
func esReplay(f *os.File, replaySpeed uint64) {
|
|
l, err := net.Listen("tcp", "0.0.0.0:30003")
|
|
if err != nil {
|
|
esDone = true
|
|
fmt.Fprintf(os.Stderr, "couldn't open :30003: %s\n", err.Error())
|
|
return
|
|
}
|
|
|
|
go esListener(l)
|
|
|
|
rdr := bufio.NewReader(f)
|
|
curTick := int64(0)
|
|
for {
|
|
buf, err := rdr.ReadString('\n')
|
|
if err != nil {
|
|
break
|
|
}
|
|
buf = strings.Trim(buf, "\r\n")
|
|
linesplit := strings.Split(buf, ",")
|
|
if len(linesplit) < 2 { // Blank line or invalid.
|
|
continue
|
|
}
|
|
if linesplit[0] == "START" { // Reset ticker, new start.
|
|
curTick = 0
|
|
} else { // If it's not "START", then it's a tick count.
|
|
i, err := strconv.ParseInt(linesplit[0], 10, 64)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "invalid tick: '%s'\n", linesplit[0])
|
|
continue
|
|
}
|
|
thisWait := (i - curTick) / int64(replaySpeed)
|
|
|
|
if thisWait >= 120000000000 { // More than 2 minutes wait, skip ahead.
|
|
fmt.Fprintf(os.Stderr, "ES skipahead - %d seconds.\n", thisWait/1000000000)
|
|
} else {
|
|
time.Sleep(time.Duration(thisWait) * time.Nanosecond) // Just in case the units change.
|
|
}
|
|
|
|
p := strings.Join(linesplit[1:], ",")
|
|
p = p + "\n"
|
|
sendToClients(p)
|
|
|
|
curTick = i
|
|
}
|
|
}
|
|
esDone = true
|
|
}
|
|
|
|
func openFile(fn string) *os.File {
|
|
f, err := os.Open(fn)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "error opening '%s': %s\n", fn, err.Error())
|
|
os.Exit(1)
|
|
return nil
|
|
}
|
|
return f
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) < 3 {
|
|
fmt.Fprintf(os.Stderr, "%s <uat replay log> <es replay log> [speed multiplier]\n", os.Args[0])
|
|
return
|
|
}
|
|
f := openFile(os.Args[1])
|
|
f2 := openFile(os.Args[2])
|
|
replaySpeed := uint64(1)
|
|
if len(os.Args) >= 4 {
|
|
i, err := strconv.ParseUint(os.Args[3], 10, 64)
|
|
if err == nil {
|
|
replaySpeed = i
|
|
}
|
|
}
|
|
fmt.Fprintf(os.Stderr, "Replay speed: %dx\n", replaySpeed)
|
|
go uatReplay(f, replaySpeed)
|
|
go esReplay(f2, replaySpeed)
|
|
for {
|
|
time.Sleep(1 * time.Second)
|
|
if uatDone && esDone {
|
|
return
|
|
}
|
|
}
|
|
}
|