game_sync/mgrsrv/stop.go

170 lines
6.0 KiB
Go

package main
import (
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/module"
"mongo.games.com/goserver/core/signal"
"os"
"time"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/common"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/transact"
"mongo.games.com/goserver/srvlib"
)
const (
STOPAPI_TRANSACTE_UD int = iota
)
type StopAPIUserData struct {
wait chan struct{}
srvtype int
timeout time.Duration
}
type InterruptSignalHandler struct {
}
func (ish *InterruptSignalHandler) Process(s os.Signal, ud interface{}) error {
logger.Logger.Warn("Receive Interrupt signal, process be close!!!")
wait := make(chan struct{}, 1)
//wait all world server close
StopServer(wait, srvlib.WorldServerType, time.Minute*5)
//shutdown all server
ShutdownAllServer(wait, time.Minute*10)
//close self
core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error {
module.Stop()
return nil
}), false)
return nil
}
func StopServer(wait chan struct{}, srvtype int, timeout time.Duration) {
core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error {
logger.Logger.Infof("StopApi start transcate srvtype(%v) timeout(%v)", srvtype, timeout)
tnp := &transact.TransNodeParam{
Tt: common.TransType_StopServer,
Ot: transact.TransOwnerType(common.GetSelfSrvType()),
Oid: common.GetSelfSrvId(),
AreaID: common.GetSelfAreaId(),
}
tNode := transact.DTCModule.StartTrans(tnp, &StopAPIUserData{wait: wait, srvtype: srvtype, timeout: timeout}, timeout)
if tNode != nil {
tNode.Go(core.CoreObject())
}
return nil
}), false)
select {
case _ = <-wait:
logger.Logger.Infof("StopApi transcate srvtype(%v) all done!!!", srvtype)
case <-time.After(timeout):
logger.Logger.Infof("StopApi transcate srvtype(%v) timeout force stop!!!", srvtype)
}
}
func ShutdownAllServer(wait chan struct{}, timeout time.Duration) {
core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error {
logger.Logger.Infof("StopApi start shutdown all server")
ctrlPacket := &server.ServerCtrl{
CtrlCode: proto.Int32(common.SrvCtrlCloseCode),
}
proto.SetDefaults(ctrlPacket)
srvlib.ServerSessionMgrSington.Broadcast(int(server.SSPacketID_PACKET_MS_SRVCTRL), ctrlPacket, common.GetSelfAreaId(), srvlib.GameServerType)
srvlib.ServerSessionMgrSington.Broadcast(int(server.SSPacketID_PACKET_MS_SRVCTRL), ctrlPacket, common.GetSelfAreaId(), srvlib.GateServerType)
srvlib.ServerSessionMgrSington.Broadcast(int(server.SSPacketID_PACKET_MS_SRVCTRL), ctrlPacket, common.GetSelfAreaId(), srvlib.WorldServerType)
//启动定时器检测
timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
gameId := srvlib.ServerSessionMgrSington.GetServerId(common.GetSelfAreaId(), srvlib.GameServerType)
if gameId != -1 {
logger.Logger.Infof("StopApi start shutdown all server gameId:%v", gameId)
return true
}
gateId := srvlib.ServerSessionMgrSington.GetServerId(common.GetSelfAreaId(), srvlib.GateServerType)
if gateId != -1 {
logger.Logger.Infof("StopApi start shutdown all server gateId:%v", gateId)
return true
}
worldId := srvlib.ServerSessionMgrSington.GetServerId(common.GetSelfAreaId(), srvlib.WorldServerType)
if worldId != -1 {
logger.Logger.Infof("StopApi start shutdown all server worldId:%v", worldId)
return true
}
wait <- struct{}{}
timer.StopTimer(h)
return true
}), nil, time.Second, -1)
return nil
}), false)
select {
case _ = <-wait:
logger.Logger.Info("StopApi ShutdownAllServer all done!!!")
case <-time.After(timeout):
logger.Logger.Info("StopApi ShutdownAllServer timeout force stop!!!")
}
}
func init() {
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
signal.SignalHandlerModule.ClearHandler(os.Interrupt)
signal.SignalHandlerModule.RegisteHandler(os.Interrupt, &InterruptSignalHandler{}, nil)
return nil
})
transact.RegisteHandler(common.TransType_StopServer, &transact.TransHanderWrapper{
OnExecuteWrapper: transact.OnExecuteWrapper(func(tNode *transact.TransNode, ud interface{}) transact.TransExeResult {
logger.Logger.Info("StopApi start TransType_StopServer OnExecuteWrapper ")
if stopUD, ok := ud.(*StopAPIUserData); ok {
tNode.TransEnv.SetField(STOPAPI_TRANSACTE_UD, ud)
ids := srvlib.ServerSessionMgrSington.GetServerIds(common.GetSelfAreaId(), stopUD.srvtype)
for _, id := range ids {
tnp := &transact.TransNodeParam{
Tt: common.TransType_StopServer,
Ot: transact.TransOwnerType(stopUD.srvtype),
Oid: id,
AreaID: common.GetSelfAreaId(),
Tct: transact.TransactCommitPolicy_TwoPhase,
}
tNode.StartChildTrans(tnp, nil, stopUD.timeout)
}
return transact.TransExeResult_Success
}
return transact.TransExeResult_Failed
}),
OnCommitWrapper: transact.OnCommitWrapper(func(tNode *transact.TransNode) transact.TransExeResult {
logger.Logger.Info("StopApi start TransType_StopServer OnCommitWrapper")
field := tNode.TransEnv.GetField(STOPAPI_TRANSACTE_UD)
if field != nil {
if ud, ok := field.(*StopAPIUserData); ok {
ud.wait <- struct{}{}
}
}
return transact.TransExeResult_Success
}),
OnRollBackWrapper: transact.OnRollBackWrapper(func(tNode *transact.TransNode) transact.TransExeResult {
logger.Logger.Info("StopApi start TransType_StopServer OnRollBackWrapper")
field := tNode.TransEnv.GetField(STOPAPI_TRANSACTE_UD)
if field != nil {
if ud, ok := field.(*StopAPIUserData); ok {
ud.wait <- struct{}{}
}
}
return transact.TransExeResult_Success
}),
OnChildRespWrapper: transact.OnChildRespWrapper(func(tNode *transact.TransNode, hChild transact.TransNodeID, retCode int, ud interface{}) transact.TransExeResult {
logger.Logger.Infof("StopApi start TransType_StopServer OnChildRespWrapper ret:%v childid:%x", retCode, hChild)
return transact.TransExeResult(retCode)
}),
})
}