/
init.go
110 lines (99 loc) · 2.32 KB
/
init.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
package kernel
import (
"github.com/liangmanlin/gootp/kernel/kct"
)
const initServerName = "init"
var initServerPid *Pid = nil
var isStop = false
var stopCB func() = nil
// 停止整个服务
func InitStop() {
ErrorLog("system going to init stop")
if !isStop && stopCB != nil {
stopCB()
}
// 先停止各种app
CallTimeOut(appPid, &initStop{}, 600)
CallTimeOut(initServerPid, &initStop{}, 600)
}
type initStop struct {
reply bool
callID int64
recCh chan interface{}
}
type initState struct {
started *kct.BMap
}
var initActor = &Actor{
Init: func(context *Context, pid *Pid, args ...interface{}) interface{} {
ErrorLog("%s %s started", initServerName, pid)
initServerPid = pid
addToKernelMap(pid)
return &initState{started: kct.NewBMap()}
},
HandleCast: func(context *Context, msg interface{}) {
state := context.State.(*initState)
switch m := msg.(type) {
case *Pid:
state.started.Insert(m.id, m)
case *PidExit:
state.started.Delete(m.Pid.id)
}
},
HandleCall: func(context *Context, request interface{}) interface{} {
state := context.State.(*initState)
switch r := request.(type) {
case *initStop:
if !isStop {
isStop = true
initStopF(state, context)
}
return nil
case stopFunc:
stopCB = r
}
return nil
},
Terminate: func(context *Context, reason *Terminate) {
},
ErrorHandler: func(context *Context, err interface{}) bool {
return true
},
}
func initStopF(state *initState, context *Context) {
f := func(e interface{}) {
pid := e.(*Pid)
if _, ok := kernelPid[pid.id]; !ok && pid.IsAlive() {
callID := makeCallID()
iStop := &initStop{callID: callID, recCh: context.self.callResult}
Cast(pid, &actorOP{iStop})
for rl := true; rl; {
succ, rs := context.recResult(callID, context.self.callResult, 3)
if succ {
rl = false
} else {
switch r := rs.(type) {
case *CallError:
// 应该只有数据库持久进程会超时
if r.ErrType == CallErrorTypeTimeOut && pid.IsAlive() {
if name := TryGetName(pid); name != "" {
ErrorLog("stop %s timeout", name)
}
} else {
rl = false
}
default:
rl = false
}
}
}
}
}
state.started.Foreach(f)
ErrorLog("kernel going to stop")
kernelStop()
}
func initRegister(pid *Pid) *Pid {
Cast(initServerPid, pid)
return initServerPid
}