/
start.go
126 lines (108 loc) · 3.2 KB
/
start.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
"github.com/xiaonanln/goworld/engine/config"
"github.com/xiaonanln/goworld/engine/consts"
)
func start(sid ServerID) {
err := os.Chdir(env.GoWorldRoot)
checkErrorOrQuit(err, "chdir to goworld directory failed")
ss := detectServerStatus()
if ss.NumDispatcherRunning > 0 || ss.NumGatesRunning > 0 {
status()
showMsgAndQuit("server is already running, can not start multiple servers")
}
startDispatchers()
startGames(sid, false)
startGates()
}
func startDispatchers() {
showMsg("start dispatchers ...")
dispatcherIds := config.GetDispatcherIDs()
showMsg("dispatcher ids: %v", dispatcherIds)
for _, dispid := range dispatcherIds {
startDispatcher(dispid)
}
}
func startDispatcher(dispid uint16) {
cfg := config.GetDispatcher(dispid)
args := []string{"-dispid", strconv.Itoa(int(dispid))}
if arguments.runInDaemonMode {
args = append(args, "-d")
}
cmd := exec.Command(env.GetDispatcherBinary(), args...)
err := runCmdUntilTag(cmd, cfg.LogFile, consts.DISPATCHER_STARTED_TAG, time.Second*10)
checkErrorOrQuit(err, "start dispatcher failed, see dispatcher.log for error")
}
func startGames(sid ServerID, isRestore bool) {
showMsg("start games ...")
gameIds := config.GetGameIDs()
showMsg("game ids: %v", gameIds)
for _, gameid := range gameIds {
startGame(sid, gameid, isRestore)
}
}
func startGame(sid ServerID, gameid uint16, isRestore bool) {
showMsg("start game %d ...", gameid)
gameExePath := filepath.Join(sid.Path(), sid.Name()+BinaryExtension)
args := []string{"-gid", strconv.Itoa(int(gameid))}
if isRestore {
args = append(args, "-restore")
}
if arguments.runInDaemonMode {
args = append(args, "-d")
}
cmd := exec.Command(gameExePath, args...)
err := runCmdUntilTag(cmd, config.GetGame(gameid).LogFile, consts.GAME_STARTED_TAG, time.Second*600)
checkErrorOrQuit(err, "start game failed, see game.log for error")
}
func startGates() {
showMsg("start gates ...")
gateIds := config.GetGateIDs()
showMsg("gate ids: %v", gateIds)
for _, gateid := range gateIds {
startGate(gateid)
}
}
func startGate(gateid uint16) {
showMsg("start gate %d ...", gateid)
args := []string{"-gid", strconv.Itoa(int(gateid))}
if arguments.runInDaemonMode {
args = append(args, "-d")
}
cmd := exec.Command(env.GetGateBinary(), args...)
err := runCmdUntilTag(cmd, config.GetGate(gateid).LogFile, consts.GATE_STARTED_TAG, time.Second*10)
checkErrorOrQuit(err, "start gate failed, see gate.log for error")
}
func runCmdUntilTag(cmd *exec.Cmd, logFile string, tag string, timeout time.Duration) (err error) {
clearLogFile(logFile)
err = cmd.Start()
if err != nil {
return
}
timeoutTime := time.Now().Add(timeout)
for time.Now().Before(timeoutTime) {
time.Sleep(time.Millisecond * 200)
if isTagInFile(logFile, tag) {
cmd.Process.Release()
return
}
}
err = errors.Errorf("wait started tag timeout")
return
}
func clearLogFile(logFile string) {
ioutil.WriteFile(logFile, []byte{}, 0644)
}
func isTagInFile(filename string, tag string) bool {
data, err := ioutil.ReadFile(filename)
checkErrorOrQuit(err, "read file error")
return strings.Contains(string(data), tag)
}