f5/app.go
2023-08-13 10:56:23 +08:00

236 lines
4.5 KiB
Go

package f5
import (
"flag"
"sync"
"sync/atomic"
"time"
"os"
"q5"
)
type App interface {
GetPkgName() string
NewUuid() int64
GetInstanceId() int32
GetNodeId() int32
GetZoneId() int32
HasFlag(int32) bool
AddIMMsg(uint16, q5.Args)
RegisterIMMsgHandle(uint16, func(uint16,q5.Args))
NotifyLoopCond()
NowUnix() int64
NowUnixMilli() int64
}
type UserApp interface {
GetPkgName() string
Init()
Update()
UnInit()
}
type app struct {
zoneId int32
nodeId int32
instanceId int32
terminated bool
pkgName string
flags map[int32]int32
servicing bool
contextHash map[int32]q5.Args
loopCond *sync.Cond
imTopNode *IMMsgNode
imBotNode *IMMsgNode
imWorkNode *IMMsgNode
imMsgMutex sync.RWMutex
chGoLoopTimerExit chan int
chGoLoopWait chan int64
nowTime time.Time
nowUnixNano int64
imMsgHandlers [1024]func(uint16, q5.Args)
maxRunDelay int64
maxScheduleTime int64
userApp UserApp
}
func (this *app) init(userApp UserApp) {
this.userApp = userApp
this.nowTime = time.Now()
atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano())
_Timer = &q5.XTimer{}
_Timer.Init(
func (context interface{}) int64 {
return q5.GetTickCount()
},
nil,
1000 * 60,
5000)
_SysLog = new(SysLog_)
_SysLog.Init()
_TgLog = new(TGLog_)
_TgLog.Init()
//flag.IntVar(&this.nodeId, "n", 0, "node id")
//flag.IntVar(&this.instanceId, "i", 0, "instance id")
flag.Parse()
this.loopCond = sync.NewCond(new(sync.Mutex))
this.chGoLoopTimerExit = make(chan int)
this.chGoLoopWait = make(chan int64)
this.outputRuningLog()
SysLog().Info("node_id:%d instance_id:%d pid:%d",
this.nodeId,
this.instanceId,
os.Getpid())
this.installTimer()
go this.goLoopTimer()
this.userApp.Init()
}
func (this *app) unInit() {
this.chGoLoopTimerExit <- 1
_Timer.UnInit()
_Timer = nil
this.userApp.UnInit()
}
func (this *app) run() {
for !this.terminated {
this.nowTime = time.Now()
atomic.StoreInt64(&this.nowUnixNano, this.nowTime.UnixNano())
beginTick := q5.GetTickCount()
_Timer.Update()
this.dispatchIMMsg()
this.userApp.Update()
this.schedule()
endTick := q5.GetTickCount()
if this.maxRunDelay < endTick - beginTick {
this.maxRunDelay = endTick - beginTick
}
}
}
func (this *app) NewUuid() int64 {
return 0
}
func (this *app) GetInstanceId() int32 {
return this.instanceId
}
func (this *app) GetNodeId() int32 {
return this.nodeId
}
func (this *app) GetZoneId() int32 {
return this.nodeId
}
func (this *app) GetPkgName() string {
return this.pkgName
}
func (this *app) setPkgName(pkgName string) {
this.pkgName = pkgName
}
func (this *app) HasFlag(flag int32) bool {
_, ok := this.flags[flag]
return ok
}
func (this *app) AddIMMsg(msgId uint16, params q5.Args) {
p := new(IMMsgNode)
p.msgId = msgId
p.params = params
this.imMsgMutex.Lock()
if this.imBotNode != nil {
this.imBotNode.next = p
this.imBotNode = p
} else {
this.imTopNode = p
this.imBotNode = p
}
this.imMsgMutex.Unlock()
this.loopCond.Broadcast()
}
func (this *app) RegisterIMMsgHandle(msgId uint16, handle func(uint16,q5.Args)) {
this.imMsgHandlers[msgId] = handle
}
func (this *app) goLoopTimer() {
var waitMs int64 = 1000 * 10
for {
select {
case <-this.chGoLoopTimerExit:
return
case waitMs = <-this.chGoLoopWait:
if waitMs < 1 {
waitMs = 1
}
case <-time.After(time.Millisecond * time.Duration(waitMs)):
waitMs = 1000 * 10
this.loopCond.Broadcast()
}
}
}
func (this *app) schedule() {
this.chGoLoopWait <- Timer().GetIdleTime()
this.loopCond.L.Lock()
this.loopCond.Wait()
this.loopCond.L.Unlock()
}
func (this *app) NotifyLoopCond() {
this.loopCond.Broadcast()
}
func (this *app) NowUnix() int64 {
return this.nowUnixNano / int64(time.Second)
}
func (this *app) NowUnixMilli() int64 {
return this.nowUnixNano / int64(time.Millisecond)
}
func (this *app) NowUnixNano() int64 {
return this.nowUnixNano
}
func (this *app) outputRuningLog() {
}
func (this *app) dispatchIMMsg() {
this.imMsgMutex.Lock()
this.imWorkNode = this.imTopNode
this.imTopNode = nil
this.imBotNode = nil
this.imMsgMutex.Unlock()
for this.imWorkNode != nil {
currNode := this.imWorkNode
this.imWorkNode = this.imWorkNode.next
if this.imMsgHandlers[currNode.msgId] != nil {
this.imMsgHandlers[currNode.msgId](currNode.msgId, currNode.params)
}
}
}
func (this *app) installTimer() {
Timer().SetInterval(1000 * 60,
func (ev int32, params *q5.Args) {
if ev == q5.TIMER_EXEC_EVENT {
SysLog().Info("max_run_delay:%d max_schedule_time:%d",
_app.maxRunDelay,
_app.maxScheduleTime)
_app.maxRunDelay = 0
_app.maxScheduleTime = 0
}
})
}