221 lines
4.2 KiB
Go
221 lines
4.2 KiB
Go
package f5
|
|
|
|
import (
|
|
"flag"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
"os"
|
|
"q5"
|
|
)
|
|
|
|
type F5App interface {
|
|
GetPkgName() string
|
|
}
|
|
|
|
type UserApp interface {
|
|
GetPkgName() string
|
|
Init()
|
|
Update()
|
|
UnInit()
|
|
}
|
|
|
|
type app struct {
|
|
nodeId int
|
|
instanceId int
|
|
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(int16, 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() uint32 {
|
|
return uint32(this.instanceId)
|
|
}
|
|
|
|
func (this *app) GetNodeId() uint32 {
|
|
return uint32(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 int16, 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 int16, handle func(int16,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
|
|
}
|
|
})
|
|
}
|