├── .gitignore
├── LICENSE
├── README.md
├── core
├── admin
│ ├── admin.go
│ └── config.go
├── basic
│ ├── command.go
│ ├── command_own.go
│ ├── command_term.go
│ ├── command_termack.go
│ ├── command_termreq.go
│ ├── cond.go
│ ├── object.go
│ ├── object_test.go
│ ├── objectlocalstorage.go
│ ├── objectmonitor.go
│ ├── options.go
│ └── sinker.go
├── build.go
├── build_darwin.go
├── build_linux.go
├── build_windows.go
├── buildall.bat
├── builtin
│ ├── action
│ │ ├── packetslices.go
│ │ ├── txctrlcmd.go
│ │ ├── txresult.go
│ │ └── txstart.go
│ ├── filter
│ │ ├── authentication.go
│ │ ├── blacklist.go
│ │ ├── connectionthrottle.go
│ │ ├── keepalive.go
│ │ └── trace.go
│ ├── gen_cpp.bat
│ ├── gen_go.bat
│ └── protocol
│ │ ├── corepacketid.pb.go
│ │ ├── corepacketid.proto
│ │ ├── keepalive.pb.go
│ │ ├── keepalive.proto
│ │ ├── sessionauth.pb.go
│ │ ├── sessionauth.proto
│ │ ├── slices.pb.go
│ │ ├── slices.proto
│ │ ├── transact.pb.go
│ │ └── transact.proto
├── cmdline
│ ├── cmdline.go
│ ├── cmdline_exit.go
│ ├── cmdline_help.go
│ ├── command_cmdline.go
│ └── config.go
├── config.go
├── container
│ ├── doc.go
│ ├── queue
│ │ ├── queue.go
│ │ ├── queue_chan.go
│ │ ├── queue_sync.go
│ │ └── queue_test.go
│ ├── recycler
│ │ ├── recycler.go
│ │ ├── recycler_bytebuf.go
│ │ ├── recycler_mgr.go
│ │ ├── recycler_test.go
│ │ └── recycler_timer.go
│ ├── synchronizedlist.go
│ └── synchronizedmap.go
├── ctx.go
├── doc.go
├── i18n
│ ├── config.go
│ └── i18n.go
├── ids.go
├── loader.go
├── logger
│ ├── ilogger.go
│ └── log.go
├── module
│ ├── config.go
│ ├── module.go
│ ├── modulemgr.go
│ └── preload.go
├── mongo
│ └── config.go
├── netlib
│ ├── acceptor.go
│ ├── action.go
│ ├── command_start_ioservice.go
│ ├── config.go
│ ├── connector.go
│ ├── connectormgr.go
│ ├── decoder.go
│ ├── defaultprotocol.go
│ ├── enc-binary.go
│ ├── enc-gbp.go
│ ├── enc-gob.go
│ ├── enc-nill.go
│ ├── encoder.go
│ ├── encoder_test.go
│ ├── encoding.go
│ ├── error.go
│ ├── errorpackethandler.go
│ ├── ioservice.go
│ ├── netengine.go
│ ├── packetfactory.go
│ ├── packethandler.go
│ ├── packetpool.go
│ ├── recycler_action.go
│ ├── recycler_rwbuf.go
│ ├── session.go
│ ├── sessionfilter.go
│ ├── sessionhandler.go
│ ├── tcp_acceptor.go
│ ├── tcp_connector.go
│ ├── tcp_session.go
│ ├── tcpkeepalive
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── keepalive.go
│ │ ├── keepalive_bsd.go
│ │ ├── keepalive_darwin.go
│ │ ├── keepalive_linux.go
│ │ ├── keepalive_solaris.go
│ │ └── keepalive_windows.go
│ ├── test.go
│ ├── udp_acceptor.go
│ ├── udp_connector.go
│ ├── udp_session.go
│ ├── ws_acceptor.go
│ ├── ws_connector.go
│ └── ws_session.go
├── profile
│ ├── config.go
│ ├── recycler_watcher.go
│ ├── statistics.go
│ └── timewatcher.go
├── schedule
│ ├── task.go
│ └── task_test.go
├── signal
│ ├── config.go
│ ├── interrupt_handler.go
│ ├── kill_handler.go
│ └── signal.go
├── task
│ ├── command_task_exe.go
│ ├── command_task_req.go
│ ├── command_task_res.go
│ ├── config.go
│ ├── executor.go
│ ├── task.go
│ └── worker.go
├── timer
│ ├── command_start_timer.go
│ ├── command_stop_timer.go
│ ├── command_timeout_timer.go
│ ├── config.go
│ ├── timer.go
│ ├── timer_action.go
│ ├── timer_queue.go
│ └── timer_queue_test.go
├── transact
│ ├── command_trans_resume.go
│ ├── command_trans_yield.go
│ ├── config.go
│ ├── doc.go
│ ├── transcommitpolicy.go
│ ├── transcommskeleton.go
│ ├── transcoordinator.go
│ ├── transctx.go
│ ├── transfactory.go
│ ├── transhandler.go
│ ├── transnode.go
│ ├── transtimeouthandler.go
│ └── transtype.go
├── utils
│ ├── atomicidgen.go
│ ├── clone.go
│ ├── clone_test.go
│ ├── debug.go
│ ├── debug_test.go
│ ├── healthcheck.go
│ ├── idgen.go
│ ├── panic.go
│ ├── profile.go
│ ├── profile_test.go
│ ├── rand.go
│ ├── slices.go
│ ├── utils.go
│ └── waitor.go
└── zk
│ ├── zk.go
│ └── zk_test.go
├── doc.go
├── examples
├── echoclient
│ ├── config.json
│ ├── logger.xml
│ ├── main.go
│ ├── pressure.go
│ ├── scpacketponghandler.go
│ └── serversessionfilter.go
├── echoserver
│ ├── config.json
│ ├── logger.xml
│ ├── main.go
│ └── scpacketponghandler.go
├── gen_go.bat
├── other
│ ├── config.json
│ ├── logger.xml
│ ├── main.go
│ ├── task.go
│ └── timer.go
├── protocol
│ ├── packetid.pb.go
│ ├── packetid.proto
│ ├── pingpong.pb.go
│ ├── pingpong.proto
│ ├── txtype.go
│ └── txuserdata.go
├── txserver1
│ ├── config.json
│ ├── dependent.go
│ ├── logger.xml
│ ├── main.go
│ └── tx_trace.go
└── txserver2
│ ├── config.json
│ ├── dependent.go
│ ├── logger.xml
│ ├── main.go
│ └── tx_trace.go
├── mmo
├── accountsrv
│ ├── config.json
│ ├── doc.go
│ ├── logger.xml
│ └── main.go
├── balancesrv
│ ├── clientsessionhandler.go
│ ├── config.json
│ ├── doc.go
│ ├── logger.xml
│ └── main.go
├── build.bat
├── clean.bat
├── client
│ ├── config.json
│ ├── logger.xml
│ ├── main.go
│ └── packet_scgateinfo.go
├── close.bat
├── clrlogs.bat
├── gamesrv
│ ├── config.json
│ ├── doc.go
│ ├── logger.xml
│ └── main.go
├── gatesrv
│ ├── broadcasthandler.go
│ ├── bundlemgr.go
│ ├── clientsessionload.go
│ ├── config.json
│ ├── doc.go
│ ├── dupfilter.go
│ ├── logger.xml
│ ├── main.go
│ ├── multicasthandler.go
│ └── packetdispatchhandler.go
├── gen_go.bat
├── imports.go
├── mgrsrv
│ ├── config.json
│ ├── doc.go
│ ├── logger.xml
│ └── main.go
├── protocol
│ ├── gateinfo.pb.go
│ ├── gateinfo.proto
│ ├── packetid.pb.go
│ ├── packetid.proto
│ ├── serverload.pb.go
│ └── serverload.proto
├── startup.bat
└── worldsrv
│ ├── config.json
│ ├── doc.go
│ ├── logger.xml
│ └── main.go
└── srvlib
├── action
├── redirecthandler.go
└── transithandler.go
├── clientsessionmgr.go
├── const.go
├── gen_go.bat
├── handler.go
├── handler
├── clientsessionregiste.go
├── serverserviceregiste.go
└── serversessionregiste.go
├── protocol
├── broadcast.pb.go
├── broadcast.proto
├── multicast.pb.go
├── multicast.proto
├── packetid.pb.go
├── packetid.proto
├── redirect.pb.go
├── redirect.proto
├── serviceinfo.pb.go
├── serviceinfo.proto
├── srvregiste.pb.go
├── srvregiste.proto
├── transit.pb.go
└── transit.proto
├── serversessionmgr.go
├── servicemgr.go
├── sessionid.go
├── srvertable.go
└── txcommskeleton.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## goserver
2 |
3 | goserver 旨在做一个传统的CS结构的服务器框架
4 | 目前主要用于游戏服务器开发
5 | 框架还在不断努力完善中,如果你对它感兴趣,请关注它的动态或者参与进来
6 |
7 | ## Features
8 |
9 | * 组件通过package的概念统一管理(可以理解为win32下的dll),由config来配置各个组件的特性参数
10 | * goroutine通过Object进行包装以树型结构组织,Object间的通信通过command(内部是chan),主要是为了预防chan滥用、失控,从而造成各种死锁问题
11 | * 提供了时间,任务,事务,计划工作,网络通讯,模块管理的内置组件
12 | * 提供一套传统的游戏服务器架构(制作中...)
13 |
14 | ## 模块说明
15 | * +core 核心模块
16 | * admin : http管理接口,主要提供一种外部可以操控进程的可能
17 | * basic : 基础的线程对象,封装对象间内部通讯;避免chan环锁现象,树形管理object
18 | * bulletin: 框架内建元素,提供通讯层的一些基础过滤器和通讯协议
19 | * cmdline: 自建命令行,给控制台进程提供一种命令模式
20 | * container: 框架用到的一些容器,队列,回收器,线程安全list,线程安全map
21 | * i18n: 国际化配置
22 | * logger: 日志接口
23 | * module: 业务模块管理,提供统一的心跳管理,模块通过注册挂载到管理器
24 | * mongo: mogodb相关配置
25 | * netlib: 通讯模块,支持TCP和WebSocket两种通讯方式
26 | * profile: 性能统计相关,用于辅助查找性能热点
27 | * schedule: 定时任务调度模块,用于周期job处理,如:每日凌晨4:00进行日志清理
28 | * signal: 信号管理模块,hook操作系统的信号进行回调处理,如:kill -2 PID
29 | * task: 线程模块,提供线程池、实名线程和独立线程多种模式
30 | * timer: 定时器,有别于go内置的timer;主要用于确保线程安全问题
31 | * transact: 分布式事务,基于二段提交实现,协调多节点配合完成一件原子性操作
32 | * utils: 工具接口
33 | * zk: zookeeper接口,用于分布式协调
34 | * +srvlib core/netlib的扩展封装,提供常用的客户端session和服务端service管理,以及服务发现;进一步封装,使框架层达到拆箱即用
35 | * action 内置常用的包重定向和中转操作
36 | * handler 提供基本的session和service管理
37 | * protocol 内置协议定义
38 | * +examples 示例程序
39 | * echoclient 回声客户端程序
40 | * echoserver 回声服务端程序
41 | * other timer和task使用示例
42 | * txserver1 分布式事务节点1
43 | * txserver2 分布式事务节点2
44 | * +mmo 提供一套基本的服务器架构模板
--------------------------------------------------------------------------------
/core/admin/config.go:
--------------------------------------------------------------------------------
1 | package admin
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | )
6 |
7 | var Config = Configuration{}
8 |
9 | type Configuration struct {
10 | SupportAdmin bool
11 | AdminHttpAddr string
12 | AdminHttpPort int
13 | WhiteHttpAddr []string
14 | }
15 |
16 | func (c *Configuration) Name() string {
17 | return "admin"
18 | }
19 |
20 | func (c *Configuration) Init() error {
21 | if c.SupportAdmin {
22 | MyAdminApp.Start(c.AdminHttpAddr, c.AdminHttpPort)
23 | }
24 | return nil
25 | }
26 |
27 | func (c *Configuration) Close() error {
28 | return nil
29 | }
30 |
31 | func init() {
32 | core.RegistePackage(&Config)
33 | }
34 |
--------------------------------------------------------------------------------
/core/basic/command.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | // Object to process the command.
4 |
5 | type Command interface {
6 | Done(*Object) error
7 | }
8 |
9 | type CommandWrapper func(*Object) error
10 |
11 | func (cw CommandWrapper) Done(o *Object) error {
12 | return cw(o)
13 | }
14 |
--------------------------------------------------------------------------------
/core/basic/command_own.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | import "github.com/idealeak/goserver/core/container"
4 |
5 | type ownCommand struct {
6 | c *Object
7 | }
8 |
9 | func (oc *ownCommand) Done(o *Object) error {
10 |
11 | defer o.ProcessSeqnum()
12 |
13 | // If the object is already being shut down, new owned objects are
14 | // immediately asked to terminate. Note that linger is set to zero.
15 | if o.terminating {
16 | o.termAcks++
17 | SendTerm(oc.c)
18 | return nil
19 | }
20 |
21 | // Store the reference to the owned object.
22 | if o.childs == nil {
23 | o.childs = container.NewSynchronizedMap()
24 | }
25 | o.childs.Set(oc.c.Id, oc.c)
26 |
27 | return nil
28 | }
29 |
30 | func SendOwn(p *Object, c *Object) bool {
31 | return p.SendCommand(&ownCommand{c: c}, true)
32 | }
33 |
--------------------------------------------------------------------------------
/core/basic/command_term.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | var termCmd = &termCommand{}
4 |
5 | type termCommand struct {
6 | }
7 |
8 | func (tc *termCommand) Done(o *Object) error {
9 | if o == nil {
10 | return nil
11 | }
12 |
13 | // Double termination should never happen.
14 | o.processTerm()
15 |
16 | return nil
17 | }
18 |
19 | func SendTerm(o *Object) bool {
20 | return o.SendCommand(termCmd, false)
21 | }
22 |
--------------------------------------------------------------------------------
/core/basic/command_termack.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | var termAckCmd = &termAckCommand{}
4 |
5 | type termAckCommand struct {
6 | }
7 |
8 | func (tac *termAckCommand) Done(o *Object) error {
9 | if o == nil {
10 | return nil
11 | }
12 |
13 | if o.termAcks > 0 {
14 | o.termAcks--
15 |
16 | // This may be a last ack we are waiting for before termination...
17 | o.checkTermAcks()
18 | }
19 |
20 | return nil
21 | }
22 |
23 | func SendTermAck(p *Object) bool {
24 | return p.SendCommand(termAckCmd, false)
25 | }
26 |
--------------------------------------------------------------------------------
/core/basic/command_termreq.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | type termReqCommand struct {
4 | c *Object
5 | }
6 |
7 | func (trc *termReqCommand) Done(o *Object) error {
8 | if o == nil {
9 | return nil
10 | }
11 |
12 | // When shutting down we can ignore termination requests from owned
13 | // objects. The termination request was already sent to the object.
14 | if o.terminating {
15 | return nil
16 | }
17 |
18 | // If I/O object is well and alive let's ask it to terminate.
19 | if o.childs.IsExist(trc.c.Id) {
20 | o.termAcks++
21 | // Note that this object is the root of the (partial shutdown) thus, its
22 | // value of linger is used, rather than the value stored by the children.
23 | SendTerm(trc.c)
24 | // Remove child
25 | o.childs.Delete(trc.c.Id)
26 | }
27 |
28 | return nil
29 | }
30 |
31 | func SendTermReq(p *Object, c *Object) bool {
32 | return p.SendCommand(&termReqCommand{c: c}, false)
33 | }
34 |
--------------------------------------------------------------------------------
/core/basic/cond.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | import (
4 | "sync/atomic"
5 | "time"
6 | )
7 |
8 | type Cond struct {
9 | notify chan struct{}
10 | countor int32
11 | }
12 |
13 | func NewCond(waitor int) *Cond {
14 | return &Cond{notify: make(chan struct{}, waitor)}
15 | }
16 |
17 | func (c *Cond) Wait() {
18 | atomic.AddInt32(&c.countor, 1)
19 | defer atomic.AddInt32(&c.countor, -1)
20 |
21 | select {
22 | case <-c.notify:
23 | }
24 | }
25 |
26 | func (c *Cond) WaitForTimeout(dura time.Duration) bool {
27 | atomic.AddInt32(&c.countor, 1)
28 | defer atomic.AddInt32(&c.countor, -1)
29 |
30 | select {
31 | case <-c.notify:
32 | case <-time.Tick(dura):
33 | return true
34 | }
35 | return false
36 | }
37 |
38 | func (c *Cond) WaitForTick(ticker *time.Ticker) bool {
39 | atomic.AddInt32(&c.countor, 1)
40 | defer atomic.AddInt32(&c.countor, -1)
41 |
42 | select {
43 | case <-c.notify:
44 | case <-ticker.C:
45 | return true
46 | }
47 | return false
48 | }
49 |
50 | func (c *Cond) Signal() {
51 | select {
52 | case c.notify <- struct{}{}:
53 | default:
54 | return
55 | }
56 | }
57 |
58 | func (c *Cond) Drain() {
59 | for {
60 | select {
61 | case <-c.notify:
62 | default:
63 | return
64 | }
65 | }
66 | }
67 |
68 | func (c *Cond) Broadcast() {
69 | for atomic.LoadInt32(&c.countor) > 0 {
70 | c.notify <- struct{}{}
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/core/basic/object_test.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | import (
4 | "fmt"
5 | "runtime"
6 | "testing"
7 | "time"
8 | )
9 |
10 | func TestSendCommand(t *testing.T) {
11 | n := 5
12 | opt := Options{
13 | Interval: time.Second,
14 | MaxDone: n,
15 | }
16 | c := make(chan int)
17 | o := NewObject(1, "test1", opt, nil)
18 | o.Active()
19 | for i := 0; i < n*2; i++ {
20 | go func(tag int) {
21 | o.SendCommand(CommandWrapper(func(*Object) error {
22 | c <- tag
23 | return nil
24 | }), true)
25 | }(i)
26 | }
27 |
28 | go func() {
29 | i := 0
30 | for {
31 | i++
32 | if i%1000 == 0 {
33 | runtime.Gosched()
34 | }
35 | }
36 | }()
37 |
38 | slice := make([]int, 0, n*2)
39 | for i := 0; i < n*2; i++ {
40 | tag := <-c
41 | slice = append(slice, tag)
42 | }
43 | if len(slice) != n*2 {
44 | t.Fatal("Command be droped")
45 | }
46 | fmt.Println("TestSendCommand", slice)
47 | }
48 |
49 | func TestSendCommandLoop(t *testing.T) {
50 | n := 5
51 | m := n * 2
52 | opt := Options{
53 | Interval: time.Second,
54 | MaxDone: n,
55 | }
56 | c := make(chan int)
57 | o := NewObject(1, "test1", opt, nil)
58 | o.Active()
59 | for i := 0; i < n; i++ {
60 | go func(tag int) {
61 | o.SendCommand(CommandWrapper(func(oo *Object) error {
62 | for j := 0; j < m; j++ {
63 | func(tag2 int) {
64 | oo.SendCommand(CommandWrapper(func(*Object) error {
65 | c <- tag*1000 + tag2
66 | return nil
67 | }), true)
68 | }(j)
69 | }
70 | return nil
71 | }), true)
72 | }(i)
73 | }
74 | go func() {
75 | i := 0
76 | for {
77 | i++
78 | if i%1000 == 0 {
79 | runtime.Gosched()
80 | }
81 | }
82 | }()
83 | slice := make([]int, 0, n*m)
84 | for i := 0; i < n*m; i++ {
85 | tag := <-c
86 | slice = append(slice, tag)
87 | }
88 | if len(slice) != n*m {
89 | t.Fatal("Command be droped")
90 | }
91 | fmt.Println("TestSendCommandLoop", slice, len(slice))
92 | }
93 |
--------------------------------------------------------------------------------
/core/basic/objectlocalstorage.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | import (
4 | "math"
5 | "sync"
6 |
7 | "github.com/idealeak/goserver/core/container"
8 | )
9 |
10 | // Be similar to (Windows, Thread Local Storage)
11 |
12 | const OLS_MAX_SLOT uint = 64
13 | const OLS_INVALID_SLOT = math.MaxUint32
14 |
15 | type OlsSlotCleanHandler func(interface{})
16 |
17 | var objSlotFlag uint64
18 | var objSlotLock sync.Mutex
19 | var objSlotCleanHandler [OLS_MAX_SLOT]OlsSlotCleanHandler
20 | var objSlotHolder = container.NewSynchronizedMap()
21 |
22 | func OlsAlloc() uint {
23 | objSlotLock.Lock()
24 | for i := uint(0); i < 64; i++ {
25 | if ((1 << i) & objSlotFlag) == 0 {
26 | objSlotFlag |= (1 << i)
27 | objSlotLock.Unlock()
28 | return i
29 | }
30 | }
31 | objSlotLock.Unlock()
32 | return OLS_INVALID_SLOT
33 | }
34 |
35 | func OlsFree(slot uint) {
36 | objSlotLock.Lock()
37 | defer objSlotLock.Unlock()
38 | if slot < OLS_MAX_SLOT {
39 | handler := objSlotCleanHandler[slot]
40 | flag := objSlotFlag & (1 << slot)
41 | if handler != nil && flag != 0 {
42 | objSlotFlag ^= (1 << slot)
43 | objSlotHolder.Foreach(func(k, v interface{}) {
44 | if o, ok := k.(*Object); ok && o != nil {
45 | v := o.ols[slot]
46 | if v != nil {
47 | o.ols[slot] = nil
48 | handler(v)
49 | }
50 | }
51 | })
52 | }
53 | }
54 | }
55 |
56 | func OlsInstallSlotCleanHandler(slot uint, handler OlsSlotCleanHandler) {
57 | if slot < OLS_MAX_SLOT {
58 | objSlotCleanHandler[slot] = handler
59 | }
60 | }
61 |
62 | func (o *Object) OlsGetValue(slot uint) interface{} {
63 | if slot < OLS_MAX_SLOT {
64 | return o.ols[slot]
65 | }
66 | return nil
67 | }
68 |
69 | func (o *Object) OlsSetValue(slot uint, val interface{}) {
70 | if slot < OLS_MAX_SLOT {
71 | old := o.ols[slot]
72 | o.ols[slot] = val
73 | if old != nil {
74 | handler := objSlotCleanHandler[slot]
75 | if handler != nil {
76 | handler(old)
77 | }
78 | }
79 | objSlotHolder.Set(o, struct{}{})
80 | }
81 | }
82 |
83 | func (o *Object) OlsClrValue() {
84 | for i := uint(0); i < OLS_MAX_SLOT; i++ {
85 | v := o.ols[i]
86 | if v != nil {
87 | handler := objSlotCleanHandler[i]
88 | if handler != nil {
89 | handler(v)
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/core/basic/objectmonitor.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | var StatsWatchMgr IStatsWatchMgr
4 |
5 | type ObjectMonitor struct {
6 | }
7 |
8 | func (om *ObjectMonitor) OnStart(o *Object) {
9 | }
10 |
11 | func (om *ObjectMonitor) OnTick(o *Object) {
12 | }
13 |
14 | func (om *ObjectMonitor) OnStop(o *Object) {
15 | }
16 |
17 | type IStatsWatchMgr interface {
18 | WatchStart(name string, elementype int) IStatsWatch
19 | }
20 |
21 | type IStatsWatch interface {
22 | Stop()
23 | }
24 |
25 | type CmdStats struct {
26 | PendingCnt int64
27 | SendCmdCnt int64
28 | RecvCmdCnt int64
29 | }
30 |
--------------------------------------------------------------------------------
/core/basic/options.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | const (
8 | QueueType_List int = iota
9 | QueueType_Chan
10 | )
11 |
12 | type Options struct {
13 | // HeartBeat interval
14 | Interval time.Duration
15 | // The maximum number of processing each heartbeat
16 | MaxDone int
17 | //
18 | QueueBacklog int
19 | }
20 |
--------------------------------------------------------------------------------
/core/basic/sinker.go:
--------------------------------------------------------------------------------
1 | package basic
2 |
3 | type Sinker interface {
4 | OnStart()
5 | OnTick()
6 | OnStop()
7 | }
8 |
--------------------------------------------------------------------------------
/core/build.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | func BuildTime() string {
4 | return "" //buildTime()
5 | }
6 |
--------------------------------------------------------------------------------
/core/build_darwin.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | /*
4 | const char* build_time(void)
5 | {
6 | static const char* psz_build_time = "["__DATE__ " " __TIME__ "]";
7 | return psz_build_time;
8 | }
9 | */
10 | import "C"
11 |
12 | var (
13 | _linux_buildTime = C.GoString(C.build_time())
14 | )
15 |
16 | func buildTime() string {
17 | return _linux_buildTime
18 | }
19 |
--------------------------------------------------------------------------------
/core/build_linux.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | /*
4 | const char* build_time(void)
5 | {
6 | static const char* psz_build_time = "["__DATE__ " " __TIME__ "]";
7 | return psz_build_time;
8 | }
9 | */
10 | import "C"
11 |
12 | var (
13 | _linux_buildTime = C.GoString(C.build_time())
14 | )
15 |
16 | func buildTime() string {
17 | return _linux_buildTime
18 | }
19 |
--------------------------------------------------------------------------------
/core/build_windows.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func buildTime() string {
9 | return fmt.Sprintf("[%s]", time.Now().String())
10 | }
11 |
--------------------------------------------------------------------------------
/core/buildall.bat:
--------------------------------------------------------------------------------
1 | go build
2 | cd admin
3 | go build
4 | cd ../basic
5 | go build
6 | cd ../builtin/action
7 | go build
8 | cd ../filter
9 | go build
10 | cd ../protocol
11 | go build
12 | cd ../../cmdline
13 | go build
14 | cd ../logger
15 | go build
16 | cd ../module
17 | go build
18 | cd ../netlib
19 | go build
20 | cd ../profile
21 | go build
22 | cd ../schedule
23 | go build
24 | cd ../signal
25 | go build
26 | cd ../task
27 | go build
28 | cd ../timer
29 | go build
30 | cd ../transact
31 | go build
32 | cd ../utils
33 | go build
34 | pause
35 |
--------------------------------------------------------------------------------
/core/builtin/action/txctrlcmd.go:
--------------------------------------------------------------------------------
1 | package action
2 |
3 | import (
4 | "errors"
5 | "strconv"
6 |
7 | "code.google.com/p/goprotobuf/proto"
8 | "github.com/idealeak/goserver/core/builtin/protocol"
9 | "github.com/idealeak/goserver/core/netlib"
10 | "github.com/idealeak/goserver/core/transact"
11 | )
12 |
13 | type TxCtrlCmdPacketFactory struct {
14 | }
15 |
16 | type TxCtrlCmdHandler struct {
17 | }
18 |
19 | func (this *TxCtrlCmdPacketFactory) CreatePacket() interface{} {
20 | pack := &protocol.TransactCtrlCmd{}
21 | return pack
22 | }
23 |
24 | func (this *TxCtrlCmdHandler) Process(session *netlib.Session, packetid int, data interface{}) error {
25 | //logger.Logger.Trace("TxCtrlCmdHandler.Process")
26 | if txcmd, ok := data.(*protocol.TransactCtrlCmd); ok {
27 | if !transact.ProcessTransCmd(transact.TransNodeID(txcmd.GetTId()), transact.TransCmd(txcmd.GetCmd())) {
28 | return errors.New("TxCtrlCmdHandler error, tid=" + strconv.FormatInt(txcmd.GetTId(), 16) + " cmd=" + strconv.Itoa(int(txcmd.GetCmd())))
29 | }
30 | }
31 | return nil
32 | }
33 |
34 | func init() {
35 | netlib.RegisterHandler(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_CMD), &TxCtrlCmdHandler{})
36 | netlib.RegisterFactory(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_CMD), &TxCtrlCmdPacketFactory{})
37 | }
38 |
39 | func ConstructTxCmdPacket(tnp *transact.TransNodeParam, cmd transact.TransCmd) proto.Message {
40 | packet := &protocol.TransactCtrlCmd{
41 | TId: proto.Int64(int64(tnp.TId)),
42 | Cmd: proto.Int32(int32(cmd)),
43 | }
44 | proto.SetDefaults(packet)
45 | return packet
46 | }
47 |
--------------------------------------------------------------------------------
/core/builtin/action/txresult.go:
--------------------------------------------------------------------------------
1 | package action
2 |
3 | import (
4 | "errors"
5 | "strconv"
6 |
7 | "code.google.com/p/goprotobuf/proto"
8 | "github.com/idealeak/goserver/core/builtin/protocol"
9 | "github.com/idealeak/goserver/core/logger"
10 | "github.com/idealeak/goserver/core/netlib"
11 | "github.com/idealeak/goserver/core/transact"
12 | )
13 |
14 | type TxResultPacketFactory struct {
15 | }
16 |
17 | type TxResultHandler struct {
18 | }
19 |
20 | func (this *TxResultPacketFactory) CreatePacket() interface{} {
21 | pack := &protocol.TransactResult{}
22 | return pack
23 | }
24 |
25 | func (this *TxResultHandler) Process(session *netlib.Session, packetid int, data interface{}) error {
26 | //logger.Logger.Trace("TxResultHandler.Process")
27 | if tr, ok := data.(*protocol.TransactResult); ok {
28 | if !transact.ProcessTransResult(transact.TransNodeID(tr.GetMyTId()), transact.TransNodeID(tr.GetChildTId()), int(tr.GetRetCode()), tr.GetCustomData()) {
29 | return errors.New("TxResultHandler error, tid=" + strconv.FormatInt(tr.GetMyTId(), 16))
30 | }
31 | }
32 | return nil
33 | }
34 |
35 | func init() {
36 | netlib.RegisterHandler(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_RESULT), &TxResultHandler{})
37 | netlib.RegisterFactory(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_RESULT), &TxResultPacketFactory{})
38 | }
39 |
40 | func ContructTxResultPacket(parent, me *transact.TransNodeParam, tr *transact.TransResult) proto.Message {
41 | packet := &protocol.TransactResult{
42 | MyTId: proto.Int64(int64(parent.TId)),
43 | ChildTId: proto.Int64(int64(me.TId)),
44 | RetCode: proto.Int32(int32(tr.RetCode)),
45 | }
46 | if tr.RetFiels != nil {
47 | b, err := netlib.MarshalPacketNoPackId(tr.RetFiels)
48 | if err != nil {
49 | logger.Logger.Warn("ContructTxResultPacket Marshal UserData error:", err)
50 | } else {
51 | packet.CustomData = b
52 | }
53 | }
54 | proto.SetDefaults(packet)
55 | return packet
56 | }
57 |
--------------------------------------------------------------------------------
/core/builtin/filter/connectionthrottle.go:
--------------------------------------------------------------------------------
1 | package filter
2 |
3 | import (
4 | "net"
5 | "time"
6 |
7 | "github.com/idealeak/goserver/core/container"
8 | "github.com/idealeak/goserver/core/netlib"
9 | )
10 |
11 | var (
12 | DefaultAllowedInterval = 500 //ms
13 | ConnectionThrottleFilterName = "session-filter-connectionthrottle"
14 | )
15 |
16 | type ConnectionThrottleFilter struct {
17 | clients *container.SynchronizedMap //need synchronize
18 | AllowedInterval int //ms
19 | }
20 |
21 | func (ctf *ConnectionThrottleFilter) GetName() string {
22 | return ConnectionThrottleFilterName
23 | }
24 |
25 | func (ctf *ConnectionThrottleFilter) GetInterestOps() uint {
26 | return 1 << netlib.InterestOps_Opened
27 | }
28 |
29 | func (ctf *ConnectionThrottleFilter) OnSessionOpened(s *netlib.Session) bool {
30 | if !ctf.isConnectionOk(s) {
31 | s.Close()
32 | return false
33 | }
34 | return true
35 | }
36 |
37 | func (ctf *ConnectionThrottleFilter) OnSessionClosed(s *netlib.Session) bool {
38 | return true
39 | }
40 |
41 | func (ctf *ConnectionThrottleFilter) OnSessionIdle(s *netlib.Session) bool {
42 | return true
43 | }
44 |
45 | func (ctf *ConnectionThrottleFilter) OnPacketReceived(s *netlib.Session, packetid int, logicNo uint32, packet interface{}) bool {
46 | return true
47 | }
48 |
49 | func (ctf *ConnectionThrottleFilter) OnPacketSent(s *netlib.Session, packetid int, logicNo uint32, data []byte) bool {
50 | return true
51 | }
52 |
53 | func (ctf *ConnectionThrottleFilter) isConnectionOk(s *netlib.Session) bool {
54 | host, _, err := net.SplitHostPort(s.RemoteAddr())
55 | if err != nil {
56 | return false
57 | }
58 |
59 | tNow := time.Now()
60 | value := ctf.clients.Get(host)
61 | if value != nil {
62 | tLast := value.(time.Time)
63 | if tNow.Sub(tLast) < time.Duration(ctf.AllowedInterval)*time.Millisecond {
64 | ctf.clients.Set(host, tNow)
65 | return false
66 | }
67 | }
68 |
69 | ctf.clients.Set(host, tNow)
70 | return true
71 | }
72 |
73 | func init() {
74 | netlib.RegisteSessionFilterCreator(ConnectionThrottleFilterName, func() netlib.SessionFilter {
75 | return &ConnectionThrottleFilter{clients: container.NewSynchronizedMap(), AllowedInterval: DefaultAllowedInterval}
76 | })
77 | }
78 |
--------------------------------------------------------------------------------
/core/builtin/filter/keepalive.go:
--------------------------------------------------------------------------------
1 | package filter
2 |
3 | import (
4 | "code.google.com/p/goprotobuf/proto"
5 | "github.com/idealeak/goserver/core/builtin/protocol"
6 | "github.com/idealeak/goserver/core/netlib"
7 | )
8 |
9 | var (
10 | KeepAliveFilterName = "session-filter-keepalive"
11 | )
12 |
13 | type KeepAliveFilter struct {
14 | }
15 |
16 | func (kf *KeepAliveFilter) GetName() string {
17 | return KeepAliveFilterName
18 | }
19 |
20 | func (kf *KeepAliveFilter) GetInterestOps() uint {
21 | return 1 << netlib.InterestOps_Idle
22 | }
23 |
24 | func (kf *KeepAliveFilter) OnSessionOpened(s *netlib.Session) bool {
25 | return true
26 | }
27 |
28 | func (kf *KeepAliveFilter) OnSessionClosed(s *netlib.Session) bool {
29 | return true
30 | }
31 |
32 | func (kf *KeepAliveFilter) OnSessionIdle(s *netlib.Session) bool {
33 | p := &protocol.SSPacketKeepAlive{Flag: proto.Int32(0)}
34 | proto.SetDefaults(p)
35 | s.Send(int(protocol.CoreBuiltinPacketID_PACKET_SS_KEEPALIVE), p)
36 | return true
37 | }
38 |
39 | func (kf *KeepAliveFilter) OnPacketReceived(s *netlib.Session, packetid int, logicNo uint32, packet interface{}) bool {
40 | return true
41 | }
42 |
43 | func (kf *KeepAliveFilter) OnPacketSent(s *netlib.Session, packetid int, logicNo uint32, data []byte) bool {
44 | return true
45 | }
46 |
47 | func init() {
48 | netlib.RegisterFactory(int(protocol.CoreBuiltinPacketID_PACKET_SS_KEEPALIVE), netlib.PacketFactoryWrapper(func() interface{} {
49 | return &protocol.SSPacketKeepAlive{}
50 | }))
51 | netlib.RegisteSessionFilterCreator(KeepAliveFilterName, func() netlib.SessionFilter {
52 | return &KeepAliveFilter{}
53 | })
54 | netlib.RegisterHandler(int(protocol.CoreBuiltinPacketID_PACKET_SS_KEEPALIVE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, data interface{}) error {
55 | if p, ok := data.(*protocol.SSPacketKeepAlive); ok {
56 | if p.GetFlag() == 0 {
57 | p.Flag = proto.Int32(1)
58 | s.Send(int(protocol.CoreBuiltinPacketID_PACKET_SS_KEEPALIVE), p)
59 | }
60 | }
61 | return nil
62 | }))
63 | }
64 |
--------------------------------------------------------------------------------
/core/builtin/gen_cpp.bat:
--------------------------------------------------------------------------------
1 | protoc --cpp_out=. protocol/*.proto
2 | pause
--------------------------------------------------------------------------------
/core/builtin/gen_go.bat:
--------------------------------------------------------------------------------
1 | protoc --go_out=. protocol/*.proto
2 | pause
--------------------------------------------------------------------------------
/core/builtin/protocol/corepacketid.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/corepacketid.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type CoreBuiltinPacketID int32
17 |
18 | const (
19 | CoreBuiltinPacketID_PACKET_SS_TX_START CoreBuiltinPacketID = -1000
20 | CoreBuiltinPacketID_PACKET_SS_TX_CMD CoreBuiltinPacketID = -1001
21 | CoreBuiltinPacketID_PACKET_SS_TX_RESULT CoreBuiltinPacketID = -1002
22 | CoreBuiltinPacketID_PACKET_SS_SLICES CoreBuiltinPacketID = -1003
23 | CoreBuiltinPacketID_PACKET_SS_AUTH CoreBuiltinPacketID = -1004
24 | CoreBuiltinPacketID_PACKET_SS_KEEPALIVE CoreBuiltinPacketID = -1005
25 | CoreBuiltinPacketID_PACKET_SS_AUTH_ACK CoreBuiltinPacketID = -1006
26 | )
27 |
28 | var CoreBuiltinPacketID_name = map[int32]string{
29 | -1000: "PACKET_SS_TX_START",
30 | -1001: "PACKET_SS_TX_CMD",
31 | -1002: "PACKET_SS_TX_RESULT",
32 | -1003: "PACKET_SS_SLICES",
33 | -1004: "PACKET_SS_AUTH",
34 | -1005: "PACKET_SS_KEEPALIVE",
35 | -1006: "PACKET_SS_AUTH_ACK",
36 | }
37 | var CoreBuiltinPacketID_value = map[string]int32{
38 | "PACKET_SS_TX_START": -1000,
39 | "PACKET_SS_TX_CMD": -1001,
40 | "PACKET_SS_TX_RESULT": -1002,
41 | "PACKET_SS_SLICES": -1003,
42 | "PACKET_SS_AUTH": -1004,
43 | "PACKET_SS_KEEPALIVE": -1005,
44 | "PACKET_SS_AUTH_ACK": -1006,
45 | }
46 |
47 | func (x CoreBuiltinPacketID) Enum() *CoreBuiltinPacketID {
48 | p := new(CoreBuiltinPacketID)
49 | *p = x
50 | return p
51 | }
52 | func (x CoreBuiltinPacketID) String() string {
53 | return proto.EnumName(CoreBuiltinPacketID_name, int32(x))
54 | }
55 | func (x CoreBuiltinPacketID) MarshalJSON() ([]byte, error) {
56 | return json.Marshal(x.String())
57 | }
58 | func (x *CoreBuiltinPacketID) UnmarshalJSON(data []byte) error {
59 | value, err := proto.UnmarshalJSONEnum(CoreBuiltinPacketID_value, data, "CoreBuiltinPacketID")
60 | if err != nil {
61 | return err
62 | }
63 | *x = CoreBuiltinPacketID(value)
64 | return nil
65 | }
66 |
67 | func init() {
68 | proto.RegisterEnum("protocol.CoreBuiltinPacketID", CoreBuiltinPacketID_name, CoreBuiltinPacketID_value)
69 | }
70 |
--------------------------------------------------------------------------------
/core/builtin/protocol/corepacketid.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | enum CoreBuiltinPacketID {
4 | PACKET_SS_TX_START = -1000;
5 | PACKET_SS_TX_CMD = -1001;
6 | PACKET_SS_TX_RESULT = -1002;
7 | PACKET_SS_SLICES = -1003;
8 | PACKET_SS_AUTH = -1004;
9 | PACKET_SS_KEEPALIVE = -1005;
10 | PACKET_SS_AUTH_ACK = -1006;
11 | }
--------------------------------------------------------------------------------
/core/builtin/protocol/keepalive.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/keepalive.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type SSPacketKeepAlive struct {
17 | Flag *int32 `protobuf:"varint,1,req" json:"Flag,omitempty"`
18 | XXX_unrecognized []byte `json:"-"`
19 | }
20 |
21 | func (m *SSPacketKeepAlive) Reset() { *m = SSPacketKeepAlive{} }
22 | func (m *SSPacketKeepAlive) String() string { return proto.CompactTextString(m) }
23 | func (*SSPacketKeepAlive) ProtoMessage() {}
24 |
25 | func (m *SSPacketKeepAlive) GetFlag() int32 {
26 | if m != nil && m.Flag != nil {
27 | return *m.Flag
28 | }
29 | return 0
30 | }
31 |
32 | func init() {
33 | }
34 |
--------------------------------------------------------------------------------
/core/builtin/protocol/keepalive.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message SSPacketKeepAlive {
4 | required int32 Flag = 1;
5 | }
--------------------------------------------------------------------------------
/core/builtin/protocol/sessionauth.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/sessionauth.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type SSPacketAuth struct {
17 | AuthKey *string `protobuf:"bytes,1,req" json:"AuthKey,omitempty"`
18 | Timestamp *int64 `protobuf:"varint,2,req" json:"Timestamp,omitempty"`
19 | XXX_unrecognized []byte `json:"-"`
20 | }
21 |
22 | func (m *SSPacketAuth) Reset() { *m = SSPacketAuth{} }
23 | func (m *SSPacketAuth) String() string { return proto.CompactTextString(m) }
24 | func (*SSPacketAuth) ProtoMessage() {}
25 |
26 | func (m *SSPacketAuth) GetAuthKey() string {
27 | if m != nil && m.AuthKey != nil {
28 | return *m.AuthKey
29 | }
30 | return ""
31 | }
32 |
33 | func (m *SSPacketAuth) GetTimestamp() int64 {
34 | if m != nil && m.Timestamp != nil {
35 | return *m.Timestamp
36 | }
37 | return 0
38 | }
39 |
40 | type SSPacketAuthAck struct {
41 | Msg *string `protobuf:"bytes,1,opt" json:"Msg,omitempty"`
42 | XXX_unrecognized []byte `json:"-"`
43 | }
44 |
45 | func (m *SSPacketAuthAck) Reset() { *m = SSPacketAuthAck{} }
46 | func (m *SSPacketAuthAck) String() string { return proto.CompactTextString(m) }
47 | func (*SSPacketAuthAck) ProtoMessage() {}
48 |
49 | func (m *SSPacketAuthAck) GetMsg() string {
50 | if m != nil && m.Msg != nil {
51 | return *m.Msg
52 | }
53 | return ""
54 | }
55 |
56 | func init() {
57 | }
58 |
--------------------------------------------------------------------------------
/core/builtin/protocol/sessionauth.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message SSPacketAuth {
4 | required string AuthKey = 1;
5 | required int64 Timestamp = 2;
6 | }
7 |
8 | message SSPacketAuthAck {
9 | optional string Msg = 1;
10 | }
--------------------------------------------------------------------------------
/core/builtin/protocol/slices.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/slices.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type SSPacketSlices struct {
17 | SeqNo *int32 `protobuf:"varint,1,req" json:"SeqNo,omitempty"`
18 | TotalSize *int32 `protobuf:"varint,2,req" json:"TotalSize,omitempty"`
19 | Offset *int32 `protobuf:"varint,3,req" json:"Offset,omitempty"`
20 | PacketData []byte `protobuf:"bytes,4,req" json:"PacketData,omitempty"`
21 | XXX_unrecognized []byte `json:"-"`
22 | }
23 |
24 | func (m *SSPacketSlices) Reset() { *m = SSPacketSlices{} }
25 | func (m *SSPacketSlices) String() string { return proto.CompactTextString(m) }
26 | func (*SSPacketSlices) ProtoMessage() {}
27 |
28 | func (m *SSPacketSlices) GetSeqNo() int32 {
29 | if m != nil && m.SeqNo != nil {
30 | return *m.SeqNo
31 | }
32 | return 0
33 | }
34 |
35 | func (m *SSPacketSlices) GetTotalSize() int32 {
36 | if m != nil && m.TotalSize != nil {
37 | return *m.TotalSize
38 | }
39 | return 0
40 | }
41 |
42 | func (m *SSPacketSlices) GetOffset() int32 {
43 | if m != nil && m.Offset != nil {
44 | return *m.Offset
45 | }
46 | return 0
47 | }
48 |
49 | func (m *SSPacketSlices) GetPacketData() []byte {
50 | if m != nil {
51 | return m.PacketData
52 | }
53 | return nil
54 | }
55 |
56 | func init() {
57 | }
58 |
--------------------------------------------------------------------------------
/core/builtin/protocol/slices.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message SSPacketSlices {
4 | required int32 SeqNo = 1;
5 | required int32 TotalSize = 2;
6 | required int32 Offset = 3;
7 | required bytes PacketData = 4;
8 | }
--------------------------------------------------------------------------------
/core/builtin/protocol/transact.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message TransactStart {
4 | required TransactParam MyTNP = 1;
5 | required TransactParam ParenTNP = 2;
6 | optional bytes CustomData = 3;
7 | }
8 |
9 | message TransactCtrlCmd {
10 | required int64 TId = 1;
11 | required int32 Cmd = 2;
12 | }
13 |
14 | message TransactResult {
15 | required int64 MyTId = 1;
16 | required int64 ChildTId = 2;
17 | required int32 RetCode = 3;
18 | optional bytes CustomData = 4;
19 | }
20 |
21 | message TransactParam {
22 | required int64 TransNodeID = 1;
23 | required int32 TransType = 2;
24 | required int32 OwnerType = 3;
25 | required int32 OwnerID = 4;
26 | required int32 SkeletonID = 5;
27 | required int32 LevelNo = 6;
28 | required int32 AreaID = 7;
29 | required int64 TimeOut = 8;
30 | required int32 TransCommitType = 9;
31 | }
--------------------------------------------------------------------------------
/core/cmdline/cmdline_exit.go:
--------------------------------------------------------------------------------
1 | package cmdline
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/idealeak/goserver/core/module"
7 | )
8 |
9 | type exitExecuter struct {
10 | }
11 |
12 | func (this exitExecuter) Execute(args []string) {
13 | module.Stop()
14 | }
15 |
16 | func (this exitExecuter) ShowUsage() {
17 | fmt.Println("usage: exit")
18 | }
19 |
20 | func init() {
21 | RegisteCmd("exit", &exitExecuter{})
22 | }
23 |
--------------------------------------------------------------------------------
/core/cmdline/cmdline_help.go:
--------------------------------------------------------------------------------
1 | package cmdline
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type helpExecuter struct {
8 | }
9 |
10 | func (this helpExecuter) Execute(args []string) {
11 | if len(args) > 0 {
12 | if cmde, exist := cmdpool[args[0]]; exist {
13 | cmde.ShowUsage()
14 | }
15 | } else {
16 | this.ShowUsage()
17 | fmt.Println("The commands are:")
18 | for k, _ := range cmdpool {
19 | if k != "help" {
20 | fmt.Println("\t", k)
21 | }
22 | }
23 | fmt.Println("Use \"help [command]\" for more information about a command.")
24 | }
25 | }
26 |
27 | func (this helpExecuter) ShowUsage() {
28 | fmt.Println("Help is a help command like window or linux shell's command")
29 | fmt.Println("Usage:")
30 | fmt.Println("\t", "help command")
31 | }
32 |
33 | func init() {
34 | RegisteCmd("help", &helpExecuter{})
35 | }
36 |
--------------------------------------------------------------------------------
/core/cmdline/command_cmdline.go:
--------------------------------------------------------------------------------
1 | package cmdline
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | )
6 |
7 | type cmdlineCommand struct {
8 | exec cmdExecuter
9 | args []string
10 | }
11 |
12 | func (cmd *cmdlineCommand) Done(o *basic.Object) error {
13 | defer o.ProcessSeqnum()
14 | cmd.exec.Execute(cmd.args)
15 | return nil
16 | }
17 |
18 | func PostCmd(p *basic.Object, exec cmdExecuter, args []string) bool {
19 | return p.SendCommand(&cmdlineCommand{exec: exec, args: args}, true)
20 | }
21 |
--------------------------------------------------------------------------------
/core/cmdline/config.go:
--------------------------------------------------------------------------------
1 | package cmdline
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | )
6 |
7 | var Config = Configuration{}
8 |
9 | type Configuration struct {
10 | SupportCmdLine bool
11 | }
12 |
13 | func (c *Configuration) Name() string {
14 | return "cmdline"
15 | }
16 |
17 | func (c *Configuration) Init() error {
18 | return nil
19 | }
20 |
21 | func (c *Configuration) Close() error {
22 | return nil
23 | }
24 |
25 | func init() {
26 | core.RegistePackage(&Config)
27 | }
28 |
--------------------------------------------------------------------------------
/core/config.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "runtime"
5 | )
6 |
7 | var Config = Configuration{}
8 |
9 | type Configuration struct {
10 | MaxProcs int
11 | Debug bool
12 | }
13 |
14 | func (c *Configuration) Name() string {
15 | return "core"
16 | }
17 |
18 | func (c *Configuration) Init() error {
19 | if c.MaxProcs <= 0 {
20 | c.MaxProcs = 1
21 | }
22 | runtime.GOMAXPROCS(c.MaxProcs)
23 | return nil
24 | }
25 |
26 | func (c *Configuration) Close() error {
27 | return nil
28 | }
29 |
30 | func init() {
31 | RegistePackage(&Config)
32 | }
33 |
--------------------------------------------------------------------------------
/core/container/doc.go:
--------------------------------------------------------------------------------
1 | package container
2 |
--------------------------------------------------------------------------------
/core/container/queue/queue.go:
--------------------------------------------------------------------------------
1 | // queue
2 | package queue
3 |
4 | import (
5 | "time"
6 | )
7 |
8 | type Queue interface {
9 | Len() int
10 | Enqueue(interface{}, time.Duration) bool
11 | Dequeue(time.Duration) (interface{}, bool)
12 | }
13 |
--------------------------------------------------------------------------------
/core/container/queue/queue_chan.go:
--------------------------------------------------------------------------------
1 | // queue
2 | package queue
3 |
4 | import "time"
5 |
6 | type queueC struct {
7 | c chan interface{}
8 | }
9 |
10 | func NewQueueC(backlog int) Queue {
11 | return &queueC{
12 | c: make(chan interface{}, backlog),
13 | }
14 | }
15 |
16 | func (q *queueC) Enqueue(i interface{}, timeout time.Duration) bool {
17 | if timeout > 0 {
18 | timer := time.NewTimer(timeout)
19 | select {
20 | case q.c <- i:
21 | case <-timer.C:
22 | return false
23 | }
24 | } else {
25 | q.c <- i
26 | }
27 |
28 | return true
29 | }
30 |
31 | func (q *queueC) Dequeue(timeout time.Duration) (i interface{}, ok bool) {
32 | if timeout > 0 {
33 | timer := time.NewTimer(timeout)
34 | select {
35 | case i, ok = <-q.c:
36 | return i, ok
37 | case <-timer.C:
38 | return nil, false
39 | }
40 | } else {
41 | select {
42 | case i, ok = <-q.c:
43 | return i, ok
44 | }
45 | }
46 | return nil, false
47 | }
48 |
49 | func (q *queueC) Len() int {
50 | return len(q.c)
51 | }
52 |
--------------------------------------------------------------------------------
/core/container/queue/queue_sync.go:
--------------------------------------------------------------------------------
1 | package queue
2 |
3 | import (
4 | "container/list"
5 | "sync"
6 | "time"
7 | )
8 |
9 | type queueS struct {
10 | fifo *list.List
11 | lock *sync.RWMutex
12 | }
13 |
14 | func NewQueueS() Queue {
15 | q := &queueS{
16 | fifo: list.New(),
17 | lock: new(sync.RWMutex),
18 | }
19 | return q
20 | }
21 |
22 | func (q *queueS) Enqueue(i interface{}, timeout time.Duration) bool {
23 | q.lock.Lock()
24 | q.fifo.PushBack(i)
25 | q.lock.Unlock()
26 | return true
27 | }
28 |
29 | func (q *queueS) Dequeue(timeout time.Duration) (interface{}, bool) {
30 | if q.fifo.Len() == 0 {
31 | return nil, false
32 | }
33 |
34 | q.lock.Lock()
35 | e := q.fifo.Front()
36 | if e != nil {
37 | q.fifo.Remove(e)
38 | q.lock.Unlock()
39 | return e.Value, true
40 | }
41 | q.lock.Unlock()
42 | return nil, false
43 | }
44 |
45 | func (q *queueS) Len() int {
46 | q.lock.RLock()
47 | l := q.fifo.Len()
48 | q.lock.RUnlock()
49 | return l
50 | }
51 |
--------------------------------------------------------------------------------
/core/container/queue/queue_test.go:
--------------------------------------------------------------------------------
1 | // queue_test
2 | package queue
3 |
4 | import (
5 | "testing"
6 | "time"
7 | )
8 |
9 | func TestSyncQueneEnqueue(t *testing.T) {
10 | const CNT int = 10
11 | q := NewQueueS()
12 | for i := 0; i < CNT; i++ {
13 | q.Enqueue(i, 0)
14 | }
15 | if q.Len() != CNT {
16 | t.Error("sync queue Enqueue error")
17 | }
18 | }
19 |
20 | func TestSyncQueneDequeue(t *testing.T) {
21 | const CNT int = 10
22 | q := NewQueueS()
23 | for i := 0; i < CNT; i++ {
24 | q.Enqueue(i, 0)
25 | }
26 |
27 | var (
28 | b bool = true
29 | d interface{}
30 | cnt int
31 | )
32 |
33 | for b {
34 | d, b = q.Dequeue(0)
35 | if b {
36 | cnt++
37 | t.Log("Dequeue data:", d)
38 | }
39 | }
40 | if cnt != CNT {
41 | t.Error("sync queue Dequeue error")
42 | }
43 | }
44 |
45 | func BenchmarkSyncQueneEnqueue(b *testing.B) {
46 | q := NewQueueS()
47 | b.StartTimer()
48 | for i := 0; i < b.N; i++ {
49 | q.Enqueue(i, 0)
50 | }
51 | b.StopTimer()
52 | }
53 |
54 | func BenchmarkSyncQueneDequeue(b *testing.B) {
55 | q := NewQueueS()
56 | for i := 0; i < b.N; i++ {
57 | q.Enqueue(i, 0)
58 | }
59 | b.StartTimer()
60 | for i := 0; i < b.N; i++ {
61 | q.Dequeue(0)
62 | }
63 | b.StopTimer()
64 | }
65 |
66 | func BenchmarkChanQueneEnqueue(b *testing.B) {
67 | q := NewQueueC(b.N)
68 | b.StartTimer()
69 | for i := 0; i < b.N; i++ {
70 | q.Enqueue(i, time.Millisecond)
71 | }
72 | b.StopTimer()
73 | }
74 |
75 | func BenchmarkChanQueneDequeue(b *testing.B) {
76 | q := NewQueueC(b.N)
77 | for i := 0; i < b.N; i++ {
78 | q.Enqueue(i, 0)
79 | }
80 | b.StartTimer()
81 | for i := 0; i < b.N; i++ {
82 | q.Dequeue(0)
83 | }
84 | b.StopTimer()
85 | }
86 |
--------------------------------------------------------------------------------
/core/container/recycler/recycler.go:
--------------------------------------------------------------------------------
1 | // recycler
2 | package recycler
3 |
4 | import (
5 | "container/list"
6 | "time"
7 | )
8 |
9 | var RecyclerBacklogDefault int = 5
10 |
11 | type element struct {
12 | when time.Time
13 | data interface{}
14 | }
15 |
16 | type Recycler struct {
17 | get chan interface{}
18 | give chan interface{}
19 | ocf func() interface{}
20 | que *list.List
21 | timeout *time.Timer
22 | makecnt int
23 | name string
24 | running bool
25 | }
26 |
27 | func NewRecycler(backlog int, ocf func() interface{}, name string) *Recycler {
28 | r := &Recycler{
29 | get: make(chan interface{}, backlog),
30 | give: make(chan interface{}, backlog),
31 | ocf: ocf,
32 | que: list.New(),
33 | timeout: time.NewTimer(time.Minute),
34 | name: name,
35 | running: true,
36 | }
37 |
38 | go r.run()
39 | return r
40 | }
41 |
42 | func (this *Recycler) run() {
43 | RecyclerMgr.registe(this)
44 | defer RecyclerMgr.unregiste(this)
45 |
46 | for this.running {
47 | if this.que.Len() == 0 {
48 | this.que.PushFront(element{when: time.Now(), data: this.ocf()})
49 | this.makecnt++
50 | }
51 |
52 | this.timeout.Reset(time.Minute)
53 | e := this.que.Front()
54 | select {
55 | case d := <-this.give:
56 | this.timeout.Stop()
57 | this.que.PushFront(element{when: time.Now(), data: d})
58 | case this.get <- e.Value.(element).data:
59 | this.timeout.Stop()
60 | this.que.Remove(e)
61 | case <-this.timeout.C:
62 | e := this.que.Front()
63 | for e != nil {
64 | n := e.Next()
65 | if time.Since(e.Value.(element).when) > time.Minute {
66 | this.que.Remove(e)
67 | e.Value = nil
68 | this.makecnt--
69 | }
70 | e = n
71 | }
72 | }
73 | }
74 | }
75 |
76 | func (this *Recycler) Get() interface{} {
77 | i := <-this.get
78 | return i
79 | }
80 |
81 | func (this *Recycler) Give(i interface{}) {
82 | this.give <- i
83 | }
84 |
85 | func (this *Recycler) Close() {
86 | this.running = false
87 | }
88 |
--------------------------------------------------------------------------------
/core/container/recycler/recycler_bytebuf.go:
--------------------------------------------------------------------------------
1 | package recycler
2 |
3 | import (
4 | "bytes"
5 | )
6 |
7 | const (
8 | BytebufRecyclerBacklog int = 128
9 | )
10 |
11 | var BytebufRecycler = NewRecycler(
12 | BytebufRecyclerBacklog,
13 | func() interface{} {
14 | return bytes.NewBuffer(nil)
15 | },
16 | "bytebuf_recycler",
17 | )
18 |
19 | func AllocBytebuf() *bytes.Buffer {
20 | b := BytebufRecycler.Get()
21 | buf := b.(*bytes.Buffer)
22 | buf.Reset()
23 | return buf
24 | }
25 |
26 | func FreeBytebuf(buf *bytes.Buffer) {
27 | BytebufRecycler.Give(buf)
28 | }
29 |
--------------------------------------------------------------------------------
/core/container/recycler/recycler_mgr.go:
--------------------------------------------------------------------------------
1 | package recycler
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "sync"
7 | )
8 |
9 | var RecyclerMgr = &recyclerMgr{
10 | recyclers: make(map[interface{}]*Recycler),
11 | lock: new(sync.Mutex),
12 | }
13 |
14 | type recyclerMgr struct {
15 | recyclers map[interface{}]*Recycler
16 | lock *sync.Mutex
17 | }
18 |
19 | func (this *recyclerMgr) registe(r *Recycler) {
20 | this.lock.Lock()
21 | this.recyclers[r] = r
22 | this.lock.Unlock()
23 | }
24 |
25 | func (this *recyclerMgr) unregiste(r *Recycler) {
26 | this.lock.Lock()
27 | delete(this.recyclers, r)
28 | this.lock.Unlock()
29 | }
30 |
31 | func (this *recyclerMgr) CloseAll() {
32 | this.lock.Lock()
33 | defer this.lock.Unlock()
34 | for _, r := range this.recyclers {
35 | r.Close()
36 | }
37 | }
38 |
39 | func (this *recyclerMgr) Dump(w io.Writer) {
40 | this.lock.Lock()
41 | for _, r := range this.recyclers {
42 | w.Write([]byte(fmt.Sprintf("(%s) alloc object (%d)", r.name, r.makecnt)))
43 | }
44 | this.lock.Unlock()
45 | }
46 |
--------------------------------------------------------------------------------
/core/container/recycler/recycler_test.go:
--------------------------------------------------------------------------------
1 | // recycler_test
2 | package recycler
3 |
4 | import (
5 | "runtime"
6 | "testing"
7 | )
8 |
9 | func makeBuffer() interface{} {
10 | buf := make([]byte, 0, 1024)
11 | return buf
12 | }
13 |
14 | var MyRecycler = NewRecycler(RecyclerBacklogDefault, makeBuffer, "test")
15 |
16 | func TestGet(t *testing.T) {
17 | MyRecycler.Get()
18 | }
19 |
20 | func TestGive(t *testing.T) {
21 | MyRecycler.Give(nil)
22 | }
23 |
24 | func BenchmarkGet(b *testing.B) {
25 | b.StartTimer()
26 | for i := 0; i < b.N; i++ {
27 | MyRecycler.Get()
28 | }
29 | b.StopTimer()
30 | }
31 |
--------------------------------------------------------------------------------
/core/container/recycler/recycler_timer.go:
--------------------------------------------------------------------------------
1 | package recycler
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | const (
8 | NewTimerDefaultDuration time.Duration = time.Minute
9 | TimerRecyclerBacklog int = 128
10 | )
11 |
12 | var TimerRecycler = NewRecycler(
13 | TimerRecyclerBacklog,
14 | func() interface{} {
15 | return time.NewTimer(NewTimerDefaultDuration)
16 | },
17 | "timer_recycler",
18 | )
19 |
20 | func GetTimer(timeout time.Duration) *time.Timer {
21 | t := TimerRecycler.Get()
22 | timer := t.(*time.Timer)
23 | timer.Reset(timeout)
24 | return timer
25 | }
26 |
27 | func GiveTimer(t *time.Timer) {
28 | TimerRecycler.Give(t)
29 | }
30 |
--------------------------------------------------------------------------------
/core/container/synchronizedlist.go:
--------------------------------------------------------------------------------
1 | package container
2 |
3 | import (
4 | "container/list"
5 | "sync"
6 | )
7 |
8 | type SynchronizedList struct {
9 | list *list.List
10 | lock *sync.Mutex
11 | }
12 |
13 | func NewSynchronizedList() *SynchronizedList {
14 | sl := &SynchronizedList{
15 | list: list.New(),
16 | lock: new(sync.Mutex),
17 | }
18 | return sl
19 | }
20 |
21 | func (sl *SynchronizedList) PushFront(v interface{}) {
22 | sl.lock.Lock()
23 | sl.list.PushFront(v)
24 | sl.lock.Unlock()
25 | }
26 |
27 | func (sl *SynchronizedList) PopFront() (v interface{}) {
28 | sl.lock.Lock()
29 | e := sl.list.Front()
30 | if e != nil {
31 | v = e.Value
32 | sl.list.Remove(e)
33 | }
34 | sl.lock.Unlock()
35 | return v
36 | }
37 |
38 | func (sl *SynchronizedList) PushBack(v interface{}) {
39 | sl.lock.Lock()
40 | sl.list.PushBack(v)
41 | sl.lock.Unlock()
42 | }
43 |
44 | func (sl *SynchronizedList) PopBack() (v interface{}) {
45 | sl.lock.Lock()
46 | e := sl.list.Back()
47 | if e != nil {
48 | v = e.Value
49 | sl.list.Remove(e)
50 | }
51 | sl.lock.Unlock()
52 | return v
53 | }
54 |
55 | func (sl *SynchronizedList) Len() (n int) {
56 | sl.lock.Lock()
57 | n = sl.list.Len()
58 | sl.lock.Unlock()
59 | return
60 | }
61 |
--------------------------------------------------------------------------------
/core/container/synchronizedmap.go:
--------------------------------------------------------------------------------
1 | package container
2 |
3 | import (
4 | "sync"
5 | )
6 |
7 | type SynchronizedMap struct {
8 | lock *sync.RWMutex
9 | m map[interface{}]interface{}
10 | }
11 |
12 | // NewSynchronizedMap return new SynchronizedMap
13 | func NewSynchronizedMap() *SynchronizedMap {
14 | return &SynchronizedMap{
15 | lock: new(sync.RWMutex),
16 | m: make(map[interface{}]interface{}),
17 | }
18 | }
19 |
20 | // Get from maps return the k's value
21 | func (m *SynchronizedMap) Get(k interface{}) interface{} {
22 | m.lock.RLock()
23 | if val, ok := m.m[k]; ok {
24 | m.lock.RUnlock()
25 | return val
26 | }
27 | m.lock.RUnlock()
28 | return nil
29 | }
30 |
31 | // Maps the given key and value. Returns false
32 | // if the key is already in the map and changes nothing.
33 | func (m *SynchronizedMap) Set(k interface{}, v interface{}) bool {
34 | m.lock.Lock()
35 | if val, ok := m.m[k]; !ok {
36 | m.m[k] = v
37 | } else if val != v {
38 | m.m[k] = v
39 | } else {
40 | m.lock.Unlock()
41 | return false
42 | }
43 | m.lock.Unlock()
44 | return true
45 | }
46 |
47 | // Returns true if k is exist in the map.
48 | func (m *SynchronizedMap) IsExist(k interface{}) bool {
49 | m.lock.RLock()
50 | if _, ok := m.m[k]; !ok {
51 | m.lock.RUnlock()
52 | return false
53 | }
54 | m.lock.RUnlock()
55 | return true
56 | }
57 |
58 | // Delete the given key and value.
59 | func (m *SynchronizedMap) Delete(k interface{}) {
60 | m.lock.Lock()
61 | delete(m.m, k)
62 | m.lock.Unlock()
63 | }
64 |
65 | // Items returns all items in SynchronizedMap.
66 | func (m *SynchronizedMap) Items() map[interface{}]interface{} {
67 | mm := make(map[interface{}]interface{})
68 | m.lock.RLock()
69 | for k, v := range m.m {
70 | mm[k] = v
71 | }
72 | m.lock.RUnlock()
73 | return mm
74 | }
75 |
76 | func (m *SynchronizedMap) Foreach(cb func(k, v interface{})) {
77 | m.lock.Lock()
78 | defer m.lock.Unlock()
79 | for k, v := range m.m {
80 | cb(k, v)
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/core/ctx.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "path/filepath"
7 |
8 | "github.com/idealeak/goserver/core/basic"
9 | "github.com/idealeak/goserver/core/utils"
10 | )
11 |
12 | const (
13 | HOOK_BEFORE_START int = iota
14 | HOOK_AFTER_STOP
15 | HOOK_MAX
16 | )
17 |
18 | var (
19 | AppCtx *Ctx = newCtx()
20 | hooks [HOOK_MAX][]hookfunc
21 | )
22 |
23 | type hookfunc func() error
24 |
25 | type Ctx struct {
26 | *basic.Object
27 | CoreObj *basic.Object
28 | }
29 |
30 | func newCtx() *Ctx {
31 | ctx := &Ctx{}
32 | ctx.init()
33 | return ctx
34 | }
35 |
36 | func (ctx *Ctx) init() {
37 | ctx.Object = basic.NewObject(ObjId_RootId,
38 | "root",
39 | basic.Options{
40 | MaxDone: 1024,
41 | QueueBacklog: 1024,
42 | },
43 | nil)
44 | ctx.Object.Waitor = utils.NewWaitor("core.Ctx")
45 | ctx.UserData = ctx
46 | ctx.Active()
47 | }
48 |
49 | func LaunchChild(o *basic.Object) {
50 | AppCtx.LaunchChild(o)
51 | }
52 |
53 | func Terminate(o *basic.Object) {
54 | AppCtx.Terminate(o)
55 | }
56 |
57 | func CoreObject() *basic.Object {
58 | //return AppCtx.GetChildById(ObjId_CoreId)
59 | return AppCtx.CoreObj
60 | }
61 |
62 | func RegisteHook(hookpos int, f hookfunc) {
63 | if hookpos < 0 || hookpos > HOOK_MAX {
64 | return
65 | }
66 | hooks[hookpos] = append(hooks[hookpos], f)
67 | }
68 |
69 | func ExecuteHook(hookpos int) error {
70 | if hookpos < 0 || hookpos > HOOK_MAX {
71 | return nil
72 | }
73 | var err error
74 | for _, h := range hooks[hookpos] {
75 | err = h()
76 | if err != nil {
77 | return err
78 | }
79 | }
80 | return nil
81 | }
82 |
83 | func WritePid() {
84 | if len(os.Args) > 0 {
85 | baseName := filepath.Base(os.Args[0])
86 | f, err := os.OpenFile(baseName+".pid", os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.ModePerm)
87 | if err != nil {
88 | panic(fmt.Sprintf("%s had running", os.Args[0]))
89 | return
90 | }
91 |
92 | f.WriteString(fmt.Sprintf("%v", os.Getpid()))
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/core/doc.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | /*
4 |
5 | core struct
6 |
7 | AppCtx---------------------------------------------
8 | | | | |
9 | | TimerMgr TaskExecutor Profile
10 | |
11 | AppModules--------------------------------------
12 | | | |
13 | | | XXX_UserCustomModule
14 | | |
15 | | TransactModule
16 | |
17 | |
18 | NetModule------------------------
19 | | |
20 | | Connector-----------------
21 | | | |
22 | | Session Socket Connect
23 | |
24 | Acceptor---------------------
25 | | |
26 | Session0 Session1..n
27 | */
28 |
--------------------------------------------------------------------------------
/core/ids.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | const (
4 | ObjId_RootId int = iota
5 | ObjId_CoreId
6 | ObjId_ExecutorId
7 | ObjId_TimerId
8 | ObjId_ProfileId
9 | )
10 |
--------------------------------------------------------------------------------
/core/logger/ilogger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | type ILogger interface {
4 | Tracef(format string, params ...interface{})
5 | Debugf(format string, params ...interface{})
6 | Infof(format string, params ...interface{})
7 | Warnf(format string, params ...interface{}) error
8 | Errorf(format string, params ...interface{}) error
9 | Criticalf(format string, params ...interface{}) error
10 |
11 | Trace(v ...interface{})
12 | Debug(v ...interface{})
13 | Info(v ...interface{})
14 | Warn(v ...interface{}) error
15 | Error(v ...interface{}) error
16 | Critical(v ...interface{}) error
17 |
18 | Close()
19 | Flush()
20 | Closed() bool
21 | }
22 |
--------------------------------------------------------------------------------
/core/logger/log.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/cihub/seelog"
7 | )
8 |
9 | var (
10 | Logger seelog.LoggerInterface
11 | )
12 |
13 | func init() {
14 | Logger, _ = seelog.LoggerFromConfigAsFile("logger.xml")
15 | seelog.ReplaceLogger(Logger)
16 | }
17 |
18 | func Reload(fileName string) error {
19 | newLogger, err := seelog.LoggerFromConfigAsFile(fileName)
20 | if err != nil {
21 | return err
22 | }
23 | if newLogger != nil {
24 | Logger = newLogger
25 | seelog.ReplaceLogger(Logger)
26 | fmt.Println("Reload success")
27 | }
28 | return nil
29 | }
30 |
31 | func Tracef(format string, params ...interface{}) {
32 | if Logger != nil {
33 | Logger.Tracef(format, params...)
34 | }
35 | }
36 |
37 | func Debugf(format string, params ...interface{}) {
38 | if Logger != nil {
39 | Logger.Debugf(format, params...)
40 | }
41 | }
42 |
43 | func Infof(format string, params ...interface{}) {
44 | if Logger != nil {
45 | Logger.Infof(format, params...)
46 | }
47 | }
48 |
49 | func Warnf(format string, params ...interface{}) error {
50 | if Logger != nil {
51 | return Logger.Warnf(format, params...)
52 | }
53 | return nil
54 | }
55 |
56 | func Errorf(format string, params ...interface{}) error {
57 | if Logger != nil {
58 | return Logger.Errorf(format, params...)
59 | }
60 | return nil
61 | }
62 |
63 | func Criticalf(format string, params ...interface{}) error {
64 | if Logger != nil {
65 | return Logger.Criticalf(format, params...)
66 | }
67 | return nil
68 | }
69 |
70 | func Trace(v ...interface{}) {
71 | if Logger != nil {
72 | Logger.Trace(v...)
73 | }
74 | }
75 |
76 | func Debug(v ...interface{}) {
77 | if Logger != nil {
78 | Logger.Debug(v...)
79 | }
80 | }
81 |
82 | func Info(v ...interface{}) {
83 | if Logger != nil {
84 | Logger.Info(v...)
85 | }
86 | }
87 |
88 | func Warn(v ...interface{}) error {
89 | if Logger != nil {
90 | return Logger.Warn(v...)
91 | }
92 | return nil
93 | }
94 |
95 | func Error(v ...interface{}) error {
96 | if Logger != nil {
97 | return Logger.Error(v...)
98 | }
99 | return nil
100 | }
101 |
102 | func Critical(v ...interface{}) error {
103 | if Logger != nil {
104 | return Logger.Critical(v...)
105 | }
106 | return nil
107 | }
108 |
--------------------------------------------------------------------------------
/core/module/config.go:
--------------------------------------------------------------------------------
1 | package module
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/basic"
8 | )
9 |
10 | var Config = Configuration{}
11 |
12 | type Configuration struct {
13 | Options basic.Options
14 | }
15 |
16 | func (c *Configuration) Name() string {
17 | return "module"
18 | }
19 |
20 | func (c *Configuration) Init() error {
21 | if c.Options.QueueBacklog <= 0 {
22 | c.Options.QueueBacklog = 1024
23 | }
24 | if c.Options.MaxDone <= 0 {
25 | c.Options.MaxDone = 1024
26 | }
27 | if c.Options.Interval <= 0 {
28 | c.Options.Interval = time.Millisecond * 10
29 | } else {
30 | c.Options.Interval = time.Millisecond * c.Options.Interval
31 | }
32 |
33 | return nil
34 | }
35 |
36 | func (c *Configuration) Close() error {
37 | return nil
38 | }
39 |
40 | func init() {
41 | core.RegistePackage(&Config)
42 | }
43 |
--------------------------------------------------------------------------------
/core/module/module.go:
--------------------------------------------------------------------------------
1 | package module
2 |
3 | const (
4 | ModuleName_Net string = "net-module"
5 | ModuleName_Transact = "dtc-module"
6 | )
7 |
8 | type Module interface {
9 | ModuleName() string
10 | Init()
11 | Update()
12 | Shutdown()
13 | }
14 |
--------------------------------------------------------------------------------
/core/module/preload.go:
--------------------------------------------------------------------------------
1 | package module
2 |
3 | type PreloadModule interface {
4 | Start()
5 | }
6 |
--------------------------------------------------------------------------------
/core/netlib/acceptor.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import "net"
4 |
5 | type Acceptor interface {
6 | ioService
7 | GetSessionConfig() *SessionConfig
8 | Addr() net.Addr
9 | }
10 |
--------------------------------------------------------------------------------
/core/netlib/action.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 |
7 | "github.com/idealeak/goserver/core/logger"
8 | "github.com/idealeak/goserver/core/profile"
9 | "github.com/idealeak/goserver/core/utils"
10 | )
11 |
12 | type action struct {
13 | s *Session
14 | p interface{}
15 | n string
16 | packid int
17 | logicNo uint32
18 | next *action
19 | }
20 |
21 | func (this *action) do() {
22 | watch := profile.TimeStatisticMgr.WatchStart(fmt.Sprintf("/action/%v", this.n), profile.TIME_ELEMENT_ACTION)
23 | defer func() {
24 | FreeAction(this)
25 | if watch != nil {
26 | watch.Stop()
27 | }
28 | utils.DumpStackIfPanic(fmt.Sprintf("netlib.session.task.do exe error, packet type:%v", reflect.TypeOf(this.p)))
29 | }()
30 |
31 | h := GetHandler(this.packid)
32 | if h != nil {
33 | err := h.Process(this.s, this.packid, this.p)
34 | if err != nil {
35 | logger.Logger.Infof("%v process error %v", this.n, err)
36 | }
37 | } else {
38 | logger.Logger.Infof("%v not registe handler", this.n)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/netlib/command_start_ioservice.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | "github.com/idealeak/goserver/core/basic"
6 | )
7 |
8 | type startIoService struct {
9 | sc *SessionConfig
10 | }
11 |
12 | func (sis *startIoService) Done(o *basic.Object) error {
13 |
14 | s := NetModule.newIoService(sis.sc)
15 | if s != nil {
16 | NetModule.pool[sis.sc.Id] = s
17 | s.start()
18 | }
19 |
20 | return nil
21 | }
22 |
23 | func SendStartNetIoService(sc *SessionConfig) bool {
24 | return core.CoreObject().SendCommand(&startIoService{sc: sc}, false)
25 | }
26 |
--------------------------------------------------------------------------------
/core/netlib/connector.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import "time"
4 |
5 | const (
6 | ReconnectInterval time.Duration = 5 * time.Second
7 | )
8 |
9 | type Connector interface {
10 | ioService
11 | GetSessionConfig() *SessionConfig
12 | }
13 |
--------------------------------------------------------------------------------
/core/netlib/connectormgr.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | )
7 |
8 | var (
9 | ConnectorMgr = &connectorMgr{
10 | pool: make(map[string]Connector),
11 | }
12 | )
13 |
14 | type connectorMgr struct {
15 | pool map[string]Connector
16 | lock sync.Mutex
17 | }
18 |
19 | func (cm *connectorMgr) IsConnecting(sc *SessionConfig) bool {
20 | strKey := fmt.Sprintf("%v:%v", sc.Ip, sc.Port)
21 | cm.lock.Lock()
22 | defer cm.lock.Unlock()
23 | if _, exist := cm.pool[strKey]; exist {
24 | return true
25 | }
26 | return false
27 | }
28 |
29 | func (cm *connectorMgr) registeConnector(c Connector) {
30 | sc := c.GetSessionConfig()
31 | strKey := fmt.Sprintf("%v:%v", sc.Ip, sc.Port)
32 | cm.lock.Lock()
33 | defer cm.lock.Unlock()
34 | cm.pool[strKey] = c
35 | }
36 |
37 | func (cm *connectorMgr) unregisteConnector(c Connector) {
38 | cm.lock.Lock()
39 | defer cm.lock.Unlock()
40 | for k, v := range cm.pool {
41 | if v == c {
42 | delete(cm.pool, k)
43 | return
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/core/netlib/defaultprotocol.go:
--------------------------------------------------------------------------------
1 | // protocol
2 | package netlib
3 |
4 | import (
5 | "encoding/binary"
6 | "fmt"
7 | )
8 |
9 | var (
10 | LenOfPacketHeader int
11 | LenOfProtoHeader int
12 | MaxPacketSize int = 64 * 1024
13 | )
14 |
15 | type ProtoHeader struct {
16 | Len uint16 //包长度
17 | Seq uint16 //包序号
18 | LogicNo uint32 //逻辑号
19 | }
20 |
21 | type PacketHeader struct {
22 | EncodeType int16
23 | PacketId int16
24 | }
25 |
26 | type RWBuffer struct {
27 | pheader ProtoHeader
28 | seq uint16
29 | buf []byte
30 | }
31 |
32 | func (rwb *RWBuffer) Init() {
33 | rwb.seq = 0
34 | }
35 |
36 | func init() {
37 | LenOfPacketHeader = binary.Size(&PacketHeader{})
38 | LenOfProtoHeader = binary.Size(&ProtoHeader{})
39 | fmt.Println("sizeof(PacketHeader)=", LenOfPacketHeader, " sizeof(ProtoHeader)=", LenOfProtoHeader)
40 | }
41 |
--------------------------------------------------------------------------------
/core/netlib/enc-binary.go:
--------------------------------------------------------------------------------
1 | // binary
2 | package netlib
3 |
4 | import (
5 | "bytes"
6 | "encoding/binary"
7 | )
8 |
9 | var Bcd = &BinaryEncDecoder{}
10 |
11 | type BinaryEncDecoder struct {
12 | }
13 |
14 | func (this *BinaryEncDecoder) Unmarshal(buf []byte, pack interface{}) error {
15 | return binary.Read(bytes.NewReader(buf), binary.LittleEndian, pack)
16 | }
17 |
18 | func (this *BinaryEncDecoder) Marshal(pack interface{}) ([]byte, error) {
19 | writer := bytes.NewBuffer(nil)
20 | err := binary.Write(writer, binary.LittleEndian, pack)
21 | return writer.Bytes(), err
22 | }
23 |
24 | func init() {
25 | RegisteEncoding(EncodingTypeBinary, Bcd, func(pack interface{}) int {
26 | if _, ok := pack.([]byte); ok {
27 | return EncodingTypeBinary
28 | }
29 | return -1
30 | })
31 | }
32 |
--------------------------------------------------------------------------------
/core/netlib/enc-gbp.go:
--------------------------------------------------------------------------------
1 | // Gbp
2 | package netlib
3 |
4 | import (
5 | "errors"
6 |
7 | "code.google.com/p/goprotobuf/proto"
8 | )
9 |
10 | var ErrorTypeNotFit = errors.New("packet not proto.Message type")
11 |
12 | var Gpb = &GbpEncDecoder{}
13 |
14 | type GbpEncDecoder struct {
15 | }
16 |
17 | func (this *GbpEncDecoder) Unmarshal(buf []byte, pack interface{}) error {
18 | if protomsg, ok := pack.(proto.Message); ok {
19 | err := proto.Unmarshal(buf, protomsg)
20 | if err != nil {
21 | return err
22 | } else {
23 | return nil
24 | }
25 | }
26 |
27 | return ErrorTypeNotFit
28 | }
29 |
30 | func (this *GbpEncDecoder) Marshal(pack interface{}) ([]byte, error) {
31 | if protomsg, ok := pack.(proto.Message); ok {
32 | return proto.Marshal(protomsg)
33 | }
34 |
35 | return nil, ErrorTypeNotFit
36 | }
37 |
38 | func init() {
39 | RegisteEncoding(EncodingTypeGPB, Gpb, func(pack interface{}) int {
40 | if _, ok := pack.(proto.Message); ok {
41 | return EncodingTypeGPB
42 | }
43 | return -1
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/core/netlib/enc-gob.go:
--------------------------------------------------------------------------------
1 | // Gob
2 | package netlib
3 |
4 | import (
5 | "bytes"
6 | "encoding/gob"
7 | )
8 |
9 | var Gob = &GobEncDecoder{}
10 |
11 | type GobEncDecoder struct {
12 | }
13 |
14 | func (this *GobEncDecoder) Unmarshal(buf []byte, pack interface{}) error {
15 | network := bytes.NewBuffer(buf)
16 | // Create a decoder and receive a value.
17 | dec := gob.NewDecoder(network)
18 | err := dec.Decode(pack)
19 | if err != nil {
20 | return err
21 | }
22 |
23 | return nil
24 | }
25 |
26 | func (this *GobEncDecoder) Marshal(pack interface{}) ([]byte, error) {
27 | var network bytes.Buffer // Stand-in for the network.
28 |
29 | // Create an encoder and send a value.
30 | enc := gob.NewEncoder(&network)
31 | err := enc.Encode(pack)
32 | if err != nil {
33 | return nil, err
34 | }
35 |
36 | return network.Bytes(), nil
37 | }
38 |
39 | func init() {
40 | RegisteEncoding(EncodingTypeGob, Gob, func(pack interface{}) int {
41 | return EncodingTypeGob
42 | })
43 | }
44 |
--------------------------------------------------------------------------------
/core/netlib/enc-nill.go:
--------------------------------------------------------------------------------
1 | // nil
2 | package netlib
3 |
4 | var Nil = &NilEncDecoder{}
5 |
6 | type NilEncDecoder struct {
7 | }
8 |
9 | func (this *NilEncDecoder) Unmarshal(buf []byte, pack interface{}) error {
10 | return nil
11 | }
12 |
13 | func (this *NilEncDecoder) Marshal(pack interface{}) ([]byte, error) {
14 | if binarymsg, ok := pack.([]byte); ok {
15 | return binarymsg, nil
16 | }
17 |
18 | return nil, ErrorTypeNotFit
19 | }
20 |
21 | func init() {
22 | RegisteEncoding(EncodingTypeNil, Nil, nil)
23 | }
24 |
--------------------------------------------------------------------------------
/core/netlib/error.go:
--------------------------------------------------------------------------------
1 | // error
2 | package netlib
3 |
4 | type NetLibParamError struct {
5 | Src string
6 | Param string
7 | }
8 |
9 | func (self *NetLibParamError) Error() string {
10 | return "Invalid Parameter: " + self.Src + self.Param
11 | }
12 |
13 | func newNetLibParamError(src, param string) *NetLibParamError {
14 | return &NetLibParamError{Src: src, Param: param}
15 | }
16 |
--------------------------------------------------------------------------------
/core/netlib/errorpackethandler.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | var (
4 | errorPacketHandlerCreatorPool = make(map[string]ErrorPacketHandlerCreator)
5 | )
6 |
7 | type ErrorPacketHandlerCreator func() ErrorPacketHandler
8 |
9 | type ErrorPacketHandler interface {
10 | OnErrorPacket(s *Session, packetid int, logicNo uint32, data []byte) bool //run in session receive goroutine
11 | }
12 |
13 | type ErrorPacketHandlerWrapper func(session *Session, packetid int, logicNo uint32, data []byte) bool
14 |
15 | func (hw ErrorPacketHandlerWrapper) OnErrorPacket(session *Session, packetid int, logicNo uint32, data []byte) bool {
16 | return hw(session, packetid, logicNo, data)
17 | }
18 |
19 | func RegisteErrorPacketHandlerCreator(name string, ephc ErrorPacketHandlerCreator) {
20 | if ephc == nil {
21 | return
22 | }
23 | if _, exist := errorPacketHandlerCreatorPool[name]; exist {
24 | panic("repeate registe ErrorPacketHandler:" + name)
25 | }
26 |
27 | errorPacketHandlerCreatorPool[name] = ephc
28 | }
29 |
30 | func GetErrorPacketHandlerCreator(name string) ErrorPacketHandlerCreator {
31 | if ephc, exist := errorPacketHandlerCreatorPool[name]; exist {
32 | return ephc
33 | }
34 | return nil
35 | }
36 |
--------------------------------------------------------------------------------
/core/netlib/ioservice.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | type SessionStats struct {
4 | Id int
5 | GroupId int
6 | RunningTime int64
7 | SendedBytes int64
8 | RecvedBytes int64
9 | SendedPack int64
10 | RecvedPack int64
11 | PendSendPack int
12 | PendRecvPack int
13 | RemoteAddr string
14 | }
15 |
16 | type ServiceStats struct {
17 | Id int
18 | Type int
19 | Name string
20 | Addr string
21 | MaxActive int
22 | MaxDone int
23 | RunningTime int64
24 | SessionStats []SessionStats
25 | }
26 |
27 | type ioService interface {
28 | start() error
29 | update()
30 | shutdown()
31 | dump()
32 | stats() ServiceStats
33 | }
34 |
--------------------------------------------------------------------------------
/core/netlib/packetfactory.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | )
7 |
8 | var factories = make(map[int]PacketFactory)
9 | var packetQuickMap = make(map[reflect.Type]packetInfo)
10 |
11 | type packetInfo struct {
12 | ptype int
13 | pid int
14 | }
15 |
16 | type PacketFactory interface {
17 | CreatePacket() interface{}
18 | }
19 |
20 | type PacketFactoryWrapper func() interface{}
21 |
22 | func (pfw PacketFactoryWrapper) CreatePacket() interface{} {
23 | return pfw()
24 | }
25 |
26 | func RegisterFactory(packetId int, factory PacketFactory) {
27 | if _, ok := factories[packetId]; ok {
28 | panic(fmt.Sprintf("repeate register packet factory: %v", packetId))
29 | }
30 |
31 | factories[packetId] = factory
32 | tp := factory.CreatePacket()
33 | if tp != nil {
34 | pt := typetest(tp)
35 | packetQuickMap[reflect.TypeOf(tp)] = packetInfo{ptype: pt, pid: packetId}
36 | }
37 | }
38 |
39 | func CreatePacket(packetId int) interface{} {
40 | if v, ok := factories[packetId]; ok {
41 | return v.CreatePacket()
42 | }
43 | return nil
44 | }
45 |
46 | func GetPacketTypeAndId(pack interface{}) (int, int) {
47 | t := reflect.TypeOf(pack)
48 | if tp, exist := packetQuickMap[t]; exist {
49 | return tp.ptype, tp.pid
50 | }
51 | return 0, 0
52 | }
53 |
--------------------------------------------------------------------------------
/core/netlib/packethandler.go:
--------------------------------------------------------------------------------
1 | // handler
2 | package netlib
3 |
4 | import (
5 | "fmt"
6 | "reflect"
7 | )
8 |
9 | var handlers = make(map[int]Handler)
10 |
11 | type Handler interface {
12 | Process(session *Session, packetid int, data interface{}) error
13 | }
14 |
15 | type HandlerWrapper func(session *Session, packetid int, data interface{}) error
16 |
17 | func (hw HandlerWrapper) Process(session *Session, packetid int, data interface{}) error {
18 | return hw(session, packetid, data)
19 | }
20 |
21 | func RegisterHandler(packetId int, h Handler) {
22 | if _, ok := handlers[packetId]; ok {
23 | panic(fmt.Sprintf("repeate register handler: %v Handler type=%v", packetId, reflect.TypeOf(h)))
24 | }
25 |
26 | handlers[packetId] = h
27 | }
28 |
29 | func Register1ToMHandler(h Handler, packetIds ...int) {
30 | for _, packetId := range packetIds {
31 | RegisterHandler(packetId, h)
32 | }
33 | }
34 |
35 | func RegisterRangeHandler(start, end int, h Handler) {
36 | for ; start <= end; start++ {
37 | RegisterHandler(start, h)
38 | }
39 | }
40 |
41 | func GetHandler(packetId int) Handler {
42 | if h, ok := handlers[packetId]; ok {
43 | return h
44 | }
45 |
46 | return nil
47 | }
48 |
--------------------------------------------------------------------------------
/core/netlib/packetpool.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import "sync"
4 |
5 | var pp = NewPacketPool(10240)
6 |
7 | func AllocPacket() *packet {
8 | return pp.Get()
9 | }
10 |
11 | func FreePacket(p *packet) {
12 | pp.Give(p)
13 | }
14 |
15 | type PacketPool struct {
16 | free *packet
17 | lock *sync.Mutex
18 | num int
19 | allocNum int
20 | remainNum int
21 | }
22 |
23 | func NewPacketPool(num int) *PacketPool {
24 | pp := &PacketPool{
25 | lock: new(sync.Mutex),
26 | num: num,
27 | }
28 | return pp
29 | }
30 |
31 | func (pp *PacketPool) grow() {
32 | var (
33 | i int
34 | p *packet
35 | ps = make([]packet, pp.num)
36 | )
37 | pp.free = &(ps[0])
38 | p = pp.free
39 | for i = 1; i < pp.num; i++ {
40 | p.next = &(ps[i])
41 | p = p.next
42 | }
43 | p.next = nil
44 | pp.allocNum += pp.num
45 | pp.remainNum += pp.num
46 | return
47 | }
48 |
49 | func (pp *PacketPool) Get() (p *packet) {
50 | pp.lock.Lock()
51 | if p = pp.free; p == nil {
52 | pp.grow()
53 | p = pp.free
54 | }
55 | pp.free = p.next
56 | p.next = nil
57 | pp.remainNum--
58 | pp.lock.Unlock()
59 | return
60 | }
61 |
62 | func (pp *PacketPool) Give(p *packet) {
63 | if p.next != nil {
64 | return
65 | }
66 | pp.lock.Lock()
67 | p.next = pp.free
68 | pp.free = p
69 | pp.remainNum++
70 | pp.lock.Unlock()
71 | }
72 |
--------------------------------------------------------------------------------
/core/netlib/recycler_action.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import "sync"
4 |
5 | var ap = NewActionPool(1024)
6 |
7 | func AllocAction() *action {
8 | return ap.Get()
9 | }
10 |
11 | func FreeAction(a *action) {
12 | ap.Give(a)
13 | }
14 |
15 | type ActionPool struct {
16 | free *action
17 | lock *sync.Mutex
18 | num int
19 | allocNum int
20 | remainNum int
21 | }
22 |
23 | func NewActionPool(num int) *ActionPool {
24 | ap := &ActionPool{
25 | lock: new(sync.Mutex),
26 | num: num,
27 | }
28 | return ap
29 | }
30 |
31 | func (ap *ActionPool) grow() {
32 | var (
33 | i int
34 | a *action
35 | as = make([]action, ap.num)
36 | )
37 | ap.free = &(as[0])
38 | a = ap.free
39 | for i = 1; i < ap.num; i++ {
40 | a.next = &(as[i])
41 | a = a.next
42 | }
43 | a.next = nil
44 | ap.allocNum += ap.num
45 | ap.remainNum += ap.num
46 | return
47 | }
48 |
49 | func (ap *ActionPool) Get() (a *action) {
50 | ap.lock.Lock()
51 | if a = ap.free; a == nil {
52 | ap.grow()
53 | a = ap.free
54 | }
55 | ap.free = a.next
56 | a.next = nil
57 | ap.remainNum--
58 | ap.lock.Unlock()
59 | return
60 | }
61 |
62 | func (ap *ActionPool) Give(a *action) {
63 | ap.lock.Lock()
64 | a.next = ap.free
65 | ap.free = a
66 | ap.remainNum++
67 | ap.lock.Unlock()
68 | }
69 |
--------------------------------------------------------------------------------
/core/netlib/recycler_rwbuf.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/container/recycler"
5 | )
6 |
7 | const (
8 | RWBufRecyclerBacklog int = 128
9 | )
10 |
11 | var RWRecycler = recycler.NewRecycler(
12 | RWBufRecyclerBacklog,
13 | func() interface{} {
14 | rb := &RWBuffer{
15 | buf: make([]byte, 0, MaxPacketSize),
16 | }
17 |
18 | return rb
19 | },
20 | "rwbuf_recycler",
21 | )
22 |
23 | func AllocRWBuf() *RWBuffer {
24 | b := RWRecycler.Get()
25 | rb := b.(*RWBuffer)
26 | rb.Init()
27 | return rb
28 | }
29 |
30 | func FreeRWBuf(buf *RWBuffer) {
31 | RWRecycler.Give(buf)
32 | }
33 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Felix Geisendörfer (felix@debuggable.com) and contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/README.md:
--------------------------------------------------------------------------------
1 | # tcpkeepalive
2 |
3 | **Known Issues:** Some problems with the implementation were [reported](https://groups.google.com/d/msg/golang-nuts/rRu6ibLNdeI/TIzShZCmbzwJ), I'll try to fix them when I get a chance, or if somebody sends a PR.
4 |
5 | Package tcpkeepalive implements additional TCP keepalive control beyond what is
6 | currently offered by the net pkg.
7 |
8 | Only Linux \>= 2.4, DragonFly, FreeBSD, NetBSD and OS X \>= 10.8 are supported
9 | at this point, but patches for additional platforms are welcome.
10 |
11 | See also: http://felixge.de/2014/08/26/tcp-keepalive-with-golang.html
12 |
13 | **License:** MIT
14 |
15 | **Docs:** http://godoc.org/github.com/felixge/tcpkeepalive
16 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/keepalive_bsd.go:
--------------------------------------------------------------------------------
1 | // +build dragonfly freebsd netbsd
2 |
3 | package tcpkeepalive
4 |
5 | import (
6 | "os"
7 | "syscall"
8 | )
9 |
10 | func setIdle(fd int, secs int) error {
11 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
12 | }
13 |
14 | func setCount(fd int, n int) error {
15 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, n))
16 | }
17 |
18 | func setInterval(fd int, secs int) error {
19 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
20 | }
21 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/keepalive_darwin.go:
--------------------------------------------------------------------------------
1 | package tcpkeepalive
2 |
3 | import (
4 | "os"
5 | "syscall"
6 | )
7 |
8 | // from netinet/tcp.h (OS X 10.9.4)
9 | const (
10 | _TCP_KEEPINTVL = 0x101 /* interval between keepalives */
11 | _TCP_KEEPCNT = 0x102 /* number of keepalives before close */
12 | )
13 |
14 | func setIdle(fd int, secs int) error {
15 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs))
16 | }
17 |
18 | func setCount(fd int, n int) error {
19 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPCNT, n))
20 | }
21 |
22 | func setInterval(fd int, secs int) error {
23 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPINTVL, secs))
24 | }
25 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/keepalive_linux.go:
--------------------------------------------------------------------------------
1 | package tcpkeepalive
2 |
3 | import (
4 | "os"
5 | "syscall"
6 | )
7 |
8 | func setIdle(fd int, secs int) error {
9 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
10 | }
11 |
12 | func setCount(fd int, n int) error {
13 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, n))
14 | }
15 |
16 | func setInterval(fd int, secs int) error {
17 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
18 | }
19 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/keepalive_solaris.go:
--------------------------------------------------------------------------------
1 | package tcpkeepalive
2 |
3 | import (
4 | "os"
5 | "syscall"
6 | )
7 |
8 | func setIdle(fd int, secs int) error {
9 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
10 | }
11 |
12 | func setCount(fd int, n int) error {
13 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, n))
14 | }
15 |
16 | func setInterval(fd int, secs int) error {
17 | return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
18 | }
19 |
--------------------------------------------------------------------------------
/core/netlib/tcpkeepalive/keepalive_windows.go:
--------------------------------------------------------------------------------
1 | package tcpkeepalive
2 |
3 | func setIdle(fd int, secs int) error {
4 | return nil
5 | }
6 |
7 | func setCount(fd int, n int) error {
8 | return nil
9 | }
10 |
11 | func setInterval(fd int, secs int) error {
12 | return nil
13 | }
14 |
--------------------------------------------------------------------------------
/core/netlib/test.go:
--------------------------------------------------------------------------------
1 | package netlib
2 |
3 | import "testing"
4 |
5 | func TestAllocAction(t *testing.T) {
6 | AllocAction()
7 | }
8 |
9 | func TestFreeAction(t *testing.T) {
10 | a := AllocAction()
11 | FreeAction(a)
12 | }
13 |
14 | func BenchmarkAllocAction(b *testing.B) {
15 | tt := make([]*action, 0, b.N)
16 | b.StartTimer()
17 | for i := 0; i < b.N; i++ {
18 | tt = append(tt, AllocAction())
19 | }
20 | b.StopTimer()
21 | }
22 |
--------------------------------------------------------------------------------
/core/profile/config.go:
--------------------------------------------------------------------------------
1 | package profile
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | )
6 |
7 | var Config = Configuration{}
8 |
9 | type Configuration struct {
10 | SlowMS int
11 | }
12 |
13 | func (c *Configuration) Name() string {
14 | return "profile"
15 | }
16 |
17 | func (c *Configuration) Init() error {
18 | if c.SlowMS <= 0 {
19 | c.SlowMS = 1000
20 | }
21 | return nil
22 | }
23 |
24 | func (c *Configuration) Close() error {
25 | return nil
26 | }
27 |
28 | func init() {
29 | core.RegistePackage(&Config)
30 | }
31 |
--------------------------------------------------------------------------------
/core/profile/recycler_watcher.go:
--------------------------------------------------------------------------------
1 | package profile
2 |
3 | import "sync"
4 |
5 | var wp = NewWatcherPool(1024)
6 |
7 | func AllocWatcher() *TimeWatcher {
8 | return wp.Get()
9 | }
10 |
11 | func FreeWatcher(t *TimeWatcher) {
12 | wp.Give(t)
13 | }
14 |
15 | type WatcherPool struct {
16 | free *TimeWatcher
17 | lock *sync.Mutex
18 | num int
19 | allocNum int
20 | remainNum int
21 | }
22 |
23 | func NewWatcherPool(num int) *WatcherPool {
24 | wp := &WatcherPool{
25 | lock: new(sync.Mutex),
26 | num: num,
27 | }
28 | return wp
29 | }
30 |
31 | func (wp *WatcherPool) grow() {
32 | var (
33 | i int
34 | t *TimeWatcher
35 | ts = make([]TimeWatcher, wp.num)
36 | )
37 | wp.free = &(ts[0])
38 | t = wp.free
39 | for i = 1; i < wp.num; i++ {
40 | t.next = &(ts[i])
41 | t = t.next
42 | }
43 | t.next = nil
44 | wp.allocNum += wp.num
45 | wp.remainNum += wp.num
46 | return
47 | }
48 |
49 | func (wp *WatcherPool) Get() (t *TimeWatcher) {
50 | wp.lock.Lock()
51 | if t = wp.free; t == nil {
52 | wp.grow()
53 | t = wp.free
54 | }
55 | wp.free = t.next
56 | t.next = nil
57 | wp.remainNum--
58 | wp.lock.Unlock()
59 | return
60 | }
61 |
62 | func (wp *WatcherPool) Give(t *TimeWatcher) {
63 | wp.lock.Lock()
64 | t.next = wp.free
65 | wp.free = t
66 | wp.remainNum++
67 | wp.lock.Unlock()
68 | }
69 |
--------------------------------------------------------------------------------
/core/profile/timewatcher.go:
--------------------------------------------------------------------------------
1 | package profile
2 |
3 | import "time"
4 |
5 | type TimeWatcher struct {
6 | name string //模块名称
7 | elementype int //类型
8 | tStart time.Time //开始时间
9 | next *TimeWatcher
10 | }
11 |
12 | func newTimeWatcher(name string, elementype int) *TimeWatcher {
13 | w := AllocWatcher()
14 | w.name = name
15 | w.elementype = elementype
16 | w.tStart = time.Now()
17 | return w
18 | }
19 |
20 | func (this *TimeWatcher) Stop() {
21 | defer FreeWatcher(this)
22 | d := time.Now().Sub(this.tStart)
23 | TimeStatisticMgr.addStatistic(this.name, this.elementype, int64(d))
24 | }
25 |
--------------------------------------------------------------------------------
/core/schedule/task_test.go:
--------------------------------------------------------------------------------
1 | package schedule
2 |
3 | import (
4 | "fmt"
5 | "sync"
6 | "testing"
7 | "time"
8 | )
9 |
10 | func TestParse(t *testing.T) {
11 | tk := NewTask("taska", "0/30 * * * * *", func() error { fmt.Println("hello world"); return nil })
12 | err := tk.Run()
13 | if err != nil {
14 | t.Fatal(err)
15 | }
16 | AddTask("taska", tk)
17 | StartTask()
18 | time.Sleep(6 * time.Second)
19 | StopTask()
20 | }
21 |
22 | func TestSpec(t *testing.T) {
23 | wg := &sync.WaitGroup{}
24 | wg.Add(2)
25 | tk1 := NewTask("tk1", "0 12 * * * *", func() error { fmt.Println("tk1"); return nil })
26 | tk2 := NewTask("tk2", "0,10,20 * * * * *", func() error { fmt.Println("tk2"); wg.Done(); return nil })
27 | tk3 := NewTask("tk3", "0 10 * * * *", func() error { fmt.Println("tk3"); wg.Done(); return nil })
28 |
29 | AddTask("tk1", tk1)
30 | AddTask("tk2", tk2)
31 | AddTask("tk3", tk3)
32 | StartTask()
33 | defer StopTask()
34 |
35 | select {
36 | case <-time.After(200 * time.Second):
37 | t.FailNow()
38 | case <-wait(wg):
39 | }
40 | }
41 |
42 | func wait(wg *sync.WaitGroup) chan bool {
43 | ch := make(chan bool)
44 | go func() {
45 | wg.Wait()
46 | ch <- true
47 | }()
48 | return ch
49 | }
50 |
--------------------------------------------------------------------------------
/core/signal/config.go:
--------------------------------------------------------------------------------
1 | package signal
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | )
6 |
7 | var Config = Configuration{}
8 |
9 | type Configuration struct {
10 | SupportSignal bool
11 | }
12 |
13 | func (c *Configuration) Name() string {
14 | return "signal"
15 | }
16 |
17 | func (c *Configuration) Init() error {
18 | if c.SupportSignal {
19 | //demon goroutine
20 | go SignalHandlerModule.ProcessSignal()
21 | }
22 | return nil
23 | }
24 |
25 | func (c *Configuration) Close() error {
26 | return nil
27 | }
28 |
29 | func init() {
30 | core.RegistePackage(&Config)
31 | }
32 |
--------------------------------------------------------------------------------
/core/signal/interrupt_handler.go:
--------------------------------------------------------------------------------
1 | package signal
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/idealeak/goserver/core/logger"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | type InterruptSignalHandler struct {
11 | }
12 |
13 | func (ish *InterruptSignalHandler) Process(s os.Signal, ud interface{}) error {
14 | logger.Logger.Warn("Receive Interrupt signal, process start quit.")
15 | module.Stop()
16 | return nil
17 | }
18 |
19 | func init() {
20 | SignalHandlerModule.RegisteHandler(os.Interrupt, &InterruptSignalHandler{}, nil)
21 | }
22 |
--------------------------------------------------------------------------------
/core/signal/kill_handler.go:
--------------------------------------------------------------------------------
1 | package signal
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/idealeak/goserver/core/logger"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | type KillSignalHandler struct {
11 | }
12 |
13 | func (ish *KillSignalHandler) Process(s os.Signal, ud interface{}) error {
14 | logger.Logger.Warn("Receive Kill signal, process be close")
15 | module.Stop()
16 | return nil
17 | }
18 |
19 | func init() {
20 | SignalHandlerModule.RegisteHandler(os.Kill, &KillSignalHandler{}, nil)
21 | }
22 |
--------------------------------------------------------------------------------
/core/task/command_task_exe.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | "github.com/idealeak/goserver/core/utils"
6 | )
7 |
8 | type taskExeCommand struct {
9 | t *Task
10 | }
11 |
12 | func (ttc *taskExeCommand) Done(o *basic.Object) error {
13 | defer o.ProcessSeqnum()
14 | defer utils.DumpStackIfPanic("taskExeCommand")
15 | ttc.t.afterQueCnt = o.GetPendingCommandCnt()
16 | return ttc.t.run(o)
17 | }
18 |
19 | func SendTaskExe(o *basic.Object, t *Task) bool {
20 | t.beforeQueCnt = o.GetPendingCommandCnt()
21 | return o.SendCommand(&taskExeCommand{t: t}, true)
22 | }
23 |
--------------------------------------------------------------------------------
/core/task/command_task_res.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | "github.com/idealeak/goserver/core/utils"
6 | )
7 |
8 | type taskResCommand struct {
9 | t *Task
10 | }
11 |
12 | func (trc *taskResCommand) Done(o *basic.Object) error {
13 | defer o.ProcessSeqnum()
14 | defer utils.DumpStackIfPanic("taskExeCommand")
15 | trc.t.n.Done(<-trc.t.r, trc.t)
16 | return nil
17 | }
18 |
19 | func SendTaskRes(o *basic.Object, t *Task) bool {
20 | if o == nil {
21 | return false
22 | }
23 | return o.SendCommand(&taskResCommand{t: t}, true)
24 | }
25 |
--------------------------------------------------------------------------------
/core/task/config.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import (
4 | "github.com/idealeak/goserver/core"
5 | "github.com/idealeak/goserver/core/basic"
6 | )
7 |
8 | var Config = Configuration{}
9 |
10 | type WorkerConfig struct {
11 | Options basic.Options
12 | WorkerCnt int
13 | }
14 |
15 | type Configuration struct {
16 | Options basic.Options
17 | Worker WorkerConfig
18 | }
19 |
20 | func (c *Configuration) Name() string {
21 | return "executor"
22 | }
23 |
24 | func (c *Configuration) Init() error {
25 | if c.Options.QueueBacklog <= 0 {
26 | c.Options.QueueBacklog = 1024
27 | }
28 | if c.Options.MaxDone <= 0 {
29 | c.Options.MaxDone = 1024
30 | }
31 | if c.Worker.Options.QueueBacklog <= 0 {
32 | c.Worker.Options.QueueBacklog = 1024
33 | }
34 | if c.Worker.Options.MaxDone <= 0 {
35 | c.Worker.Options.MaxDone = 1024
36 | }
37 | if c.Worker.WorkerCnt <= 0 {
38 | c.Worker.WorkerCnt = 8
39 | }
40 | TaskExecutor.Start()
41 | return nil
42 | }
43 |
44 | func (c *Configuration) Close() error {
45 | return nil
46 | }
47 |
48 | func init() {
49 | core.RegistePackage(&Config)
50 | }
51 |
--------------------------------------------------------------------------------
/core/task/worker.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | )
6 |
7 | type Worker struct {
8 | *basic.Object
9 | }
10 |
--------------------------------------------------------------------------------
/core/timer/command_start_timer.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "container/heap"
5 | "time"
6 |
7 | "github.com/idealeak/goserver/core"
8 | "github.com/idealeak/goserver/core/basic"
9 | )
10 |
11 | type startTimerCommand struct {
12 | src *basic.Object
13 | ta TimerAction
14 | ud interface{}
15 | interval time.Duration
16 | times int
17 | h TimerHandle
18 | }
19 |
20 | func (stc *startTimerCommand) Done(o *basic.Object) error {
21 | defer o.ProcessSeqnum()
22 |
23 | te := &TimerEntity{
24 | sink: stc.src,
25 | ud: stc.ud,
26 | ta: stc.ta,
27 | interval: stc.interval,
28 | times: stc.times,
29 | h: stc.h,
30 | next: time.Now().Add(stc.interval),
31 | }
32 |
33 | heap.Push(TimerModule.tq, te)
34 |
35 | return nil
36 | }
37 |
38 | // StartTimer only can be called in main module
39 | func StartTimer(ta TimerAction, ud interface{}, interval time.Duration, times int) (TimerHandle, bool) {
40 | return StartTimerByObject(core.CoreObject(), ta, ud, interval, times)
41 | }
42 | func AfterTimer(taw TimerActionWrapper, ud interface{}, interval time.Duration) (TimerHandle, bool) {
43 | var tac = &TimerActionCommon{
44 | Taw: taw,
45 | }
46 | return StartTimerByObject(core.CoreObject(), tac, ud, interval, 1)
47 | }
48 |
49 | func StartTimerByObject(src *basic.Object, ta TimerAction, ud interface{}, interval time.Duration, times int) (TimerHandle, bool) {
50 | h := generateTimerHandle()
51 | ret := TimerModule.SendCommand(
52 | &startTimerCommand{
53 | src: src,
54 | ta: ta,
55 | ud: ud,
56 | interval: interval,
57 | times: times,
58 | h: h,
59 | },
60 | true)
61 | return h, ret
62 | }
63 |
--------------------------------------------------------------------------------
/core/timer/command_stop_timer.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "container/heap"
5 |
6 | "github.com/idealeak/goserver/core/basic"
7 | )
8 |
9 | type stopTimerCommand struct {
10 | h TimerHandle
11 | }
12 |
13 | func (stc *stopTimerCommand) Done(o *basic.Object) error {
14 | defer o.ProcessSeqnum()
15 |
16 | if v, ok := TimerModule.tq.ref[stc.h]; ok {
17 | heap.Remove(TimerModule.tq, v)
18 | }
19 |
20 | return nil
21 | }
22 |
23 | func StopTimer(h TimerHandle) bool {
24 | return TimerModule.SendCommand(&stopTimerCommand{h: h}, true)
25 | }
26 |
--------------------------------------------------------------------------------
/core/timer/command_timeout_timer.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "fmt"
5 | "github.com/idealeak/goserver/core/basic"
6 | "github.com/idealeak/goserver/core/profile"
7 | "reflect"
8 | )
9 |
10 | type timeoutCommand struct {
11 | te *TimerEntity
12 | }
13 |
14 | func (tc *timeoutCommand) Done(o *basic.Object) error {
15 | tta := reflect.TypeOf(tc.te.ta)
16 | watch := profile.TimeStatisticMgr.WatchStart(fmt.Sprintf("/timer/%v/ontimer", tta.Name()), profile.TIME_ELEMENT_TIMER)
17 | defer func() {
18 | o.ProcessSeqnum()
19 | if watch != nil {
20 | watch.Stop()
21 | }
22 | }()
23 | if tc.te.stoped {
24 | return nil
25 | }
26 | if tc.te.ta.OnTimer(tc.te.h, tc.te.ud) == false {
27 | tc.te.stoped = true
28 | if tc.te.times < 0 {
29 | StopTimer(tc.te.h)
30 | }
31 | }
32 | return nil
33 | }
34 |
35 | func SendTimeout(te *TimerEntity) bool {
36 | if te.sink == nil {
37 | return false
38 | }
39 |
40 | return te.sink.SendCommand(&timeoutCommand{te: te}, true)
41 | }
42 |
--------------------------------------------------------------------------------
/core/timer/config.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/basic"
8 | )
9 |
10 | var Config = Configuration{}
11 |
12 | type Configuration struct {
13 | Options basic.Options
14 | }
15 |
16 | func (c *Configuration) Name() string {
17 | return "timer"
18 | }
19 |
20 | func (c *Configuration) Init() error {
21 | if c.Options.QueueBacklog <= 0 {
22 | c.Options.QueueBacklog = 1024
23 | }
24 | if c.Options.MaxDone <= 0 {
25 | c.Options.MaxDone = 1024
26 | }
27 | if c.Options.Interval <= 0 {
28 | c.Options.Interval = time.Millisecond * 10
29 | } else {
30 | c.Options.Interval = time.Millisecond * c.Options.Interval
31 | }
32 | TimerModule.Start()
33 | return nil
34 | }
35 |
36 | func (c *Configuration) Close() error {
37 | return nil
38 | }
39 |
40 | func init() {
41 | core.RegistePackage(&Config)
42 | }
43 |
--------------------------------------------------------------------------------
/core/timer/timer.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "container/heap"
5 | "time"
6 |
7 | "github.com/idealeak/goserver/core"
8 | "github.com/idealeak/goserver/core/basic"
9 | "github.com/idealeak/goserver/core/logger"
10 | )
11 |
12 | var (
13 | TimerHandleGenerator uint32 = 1
14 | InvalidTimerHandle TimerHandle = 0
15 | TimerModule *TimerMgr = NewTimerMgr()
16 | )
17 |
18 | type TimerMgr struct {
19 | *basic.Object
20 | tq *TimerQueue
21 | }
22 |
23 | func NewTimerMgr() *TimerMgr {
24 | tm := &TimerMgr{
25 | tq: NewTimerQueue(),
26 | }
27 |
28 | return tm
29 | }
30 |
31 | func (tm *TimerMgr) Start() {
32 | logger.Logger.Trace("Timer Start")
33 | defer logger.Logger.Trace("Timer Start [ok]")
34 |
35 | tm.Object = basic.NewObject(core.ObjId_TimerId,
36 | "timer",
37 | Config.Options,
38 | tm)
39 | tm.UserData = tm
40 |
41 | core.LaunchChild(TimerModule.Object)
42 | }
43 |
44 | func (tm *TimerMgr) TimerCount() int {
45 | return tm.tq.Len()
46 | }
47 |
48 | func (tm *TimerMgr) OnTick() {
49 | nowTime := time.Now()
50 | for {
51 | if tm.tq.Len() > 0 {
52 | t := heap.Pop(tm.tq)
53 | if te, ok := t.(*TimerEntity); ok {
54 | if !te.stoped && te.next.Before(nowTime) {
55 | if te.times > 0 {
56 | te.times--
57 | }
58 | //Avoid async stop timer failed
59 | if te.times != 0 {
60 | te.next = te.next.Add(te.interval)
61 | heap.Push(tm.tq, te)
62 | }
63 | if !SendTimeout(te) {
64 | if v, ok := tm.tq.ref[te.h]; ok {
65 | heap.Remove(tm.tq, v)
66 | }
67 | }
68 | } else {
69 | if !te.stoped {
70 | heap.Push(tm.tq, te)
71 | }
72 | return
73 | }
74 | }
75 | } else {
76 | return
77 | }
78 | }
79 | }
80 |
81 | func (tm *TimerMgr) OnStart() {}
82 |
83 | func (tm *TimerMgr) OnStop() {}
84 |
--------------------------------------------------------------------------------
/core/timer/timer_action.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | type TimerHandle uint32
4 |
5 | type TimerAction interface {
6 | OnTimer(h TimerHandle, ud interface{}) bool
7 | }
8 |
9 | type TimerActionWrapper func(h TimerHandle, ud interface{}) bool
10 |
11 | func (taw TimerActionWrapper) OnTimer(h TimerHandle, ud interface{}) bool {
12 | return taw(h, ud)
13 | }
14 |
15 | type TimerActionCommon struct {
16 | Taw TimerActionWrapper
17 | }
18 |
19 | func (this TimerActionCommon) OnTimer(h TimerHandle, ud interface{}) bool {
20 | return this.Taw(h, ud)
21 | }
22 |
--------------------------------------------------------------------------------
/core/timer/timer_queue.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "container/heap"
5 | "sync/atomic"
6 | "time"
7 |
8 | "github.com/idealeak/goserver/core/basic"
9 | )
10 |
11 | type TimerEntity struct {
12 | sink *basic.Object
13 | ud interface{}
14 | interval time.Duration
15 | next time.Time
16 | times int
17 | ta TimerAction
18 | h TimerHandle
19 | stoped bool
20 | }
21 |
22 | type TimerQueue struct {
23 | queue []*TimerEntity
24 | ref map[TimerHandle]int
25 | }
26 |
27 | func generateTimerHandle() TimerHandle {
28 | return TimerHandle(atomic.AddUint32(&TimerHandleGenerator, 1))
29 | }
30 |
31 | func NewTimerQueue() *TimerQueue {
32 | tq := &TimerQueue{
33 | ref: make(map[TimerHandle]int),
34 | }
35 | heap.Init(tq)
36 | return tq
37 | }
38 | func (tq TimerQueue) Len() int {
39 | return len(tq.queue)
40 | }
41 |
42 | func (tq TimerQueue) Less(i, j int) bool {
43 | return tq.queue[i].next.Before(tq.queue[j].next)
44 | }
45 |
46 | func (tq *TimerQueue) Swap(i, j int) {
47 | tq.queue[i], tq.queue[j] = tq.queue[j], tq.queue[i]
48 | tq.ref[tq.queue[i].h] = i
49 | tq.ref[tq.queue[j].h] = j
50 | }
51 |
52 | func (tq *TimerQueue) Push(x interface{}) {
53 | n := len(tq.queue)
54 | te := x.(*TimerEntity)
55 | tq.ref[te.h] = n
56 | tq.queue = append(tq.queue, te)
57 | }
58 |
59 | func (tq *TimerQueue) Pop() interface{} {
60 | old := tq.queue
61 | n := len(old)
62 | te := old[n-1]
63 | delete(tq.ref, te.h)
64 | tq.queue = old[0 : n-1]
65 | return te
66 | }
67 |
--------------------------------------------------------------------------------
/core/timer/timer_queue_test.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "container/heap"
5 | "testing"
6 | "time"
7 | )
8 |
9 | func TestTimerQueuePush(t *testing.T) {
10 | tq := NewTimerQueue()
11 | tNow := time.Now()
12 | te1 := &TimerEntity{
13 | ud: int(2),
14 | next: tNow.Add(time.Minute),
15 | }
16 | te2 := &TimerEntity{
17 | ud: int(1),
18 | next: tNow.Add(time.Second),
19 | }
20 | te3 := &TimerEntity{
21 | ud: int(3),
22 | next: tNow.Add(time.Hour),
23 | }
24 | heap.Push(tq, te2)
25 | heap.Push(tq, te1)
26 | heap.Push(tq, te3)
27 |
28 | if tq.Len() != 3 {
29 | t.Fatal("Timer Queue Size error")
30 | }
31 | var (
32 | tee interface{}
33 | te *TimerEntity
34 | ok bool
35 | )
36 | tee = heap.Pop(tq)
37 | if te, ok = tee.(*TimerEntity); ok {
38 | if te.ud.(int) != 1 {
39 | t.Fatal("First Must 1.")
40 | }
41 | }
42 |
43 | tee = heap.Pop(tq)
44 | if te, ok = tee.(*TimerEntity); ok {
45 | if te.ud.(int) != 2 {
46 | t.Fatal("Second Must 2.")
47 | }
48 | }
49 |
50 | tee = heap.Pop(tq)
51 | if te, ok = tee.(*TimerEntity); ok {
52 | if te.ud.(int) != 3 {
53 | t.Fatal("Third Must 3.")
54 | }
55 | }
56 | }
57 |
58 | func BenchmarkTimerQueuePush(b *testing.B) {
59 | tq := NewTimerQueue()
60 | b.StartTimer()
61 | for i := 0; i < b.N; i++ {
62 | h := generateTimerHandle()
63 | te := &TimerEntity{
64 | h: h,
65 | }
66 | tq.Push(te)
67 | }
68 | b.StopTimer()
69 | }
70 |
71 | func BenchmarkTimerQueuePop(b *testing.B) {
72 | tq := NewTimerQueue()
73 |
74 | for i := 0; i < b.N; i++ {
75 | h := generateTimerHandle()
76 | te := &TimerEntity{
77 | h: h,
78 | }
79 | tq.Push(te)
80 | }
81 |
82 | b.StartTimer()
83 | for i := 0; i < b.N; i++ {
84 | te := tq.Pop()
85 | tq.Push(te)
86 | }
87 | b.StopTimer()
88 | }
89 |
--------------------------------------------------------------------------------
/core/transact/command_trans_resume.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | )
6 |
7 | type transactResumeCommand struct {
8 | tnode *TransNode
9 | }
10 |
11 | func (trc *transactResumeCommand) Done(o *basic.Object) error {
12 | defer o.ProcessSeqnum()
13 | trc.tnode.checkExeOver()
14 | return nil
15 | }
16 |
17 | func SendTranscatResume(tnode *TransNode) bool {
18 | return tnode.ownerObj.SendCommand(&transactResumeCommand{tnode: tnode}, true)
19 | }
20 |
--------------------------------------------------------------------------------
/core/transact/command_trans_yield.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/basic"
5 | )
6 |
7 | type transactYieldCommand struct {
8 | tnode *TransNode
9 | }
10 |
11 | func (trc *transactYieldCommand) Done(o *basic.Object) error {
12 | defer o.ProcessSeqnum()
13 | trc.tnode.checkExeOver()
14 | return nil
15 | }
16 |
17 | func SendTranscatYield(tnode *TransNode) bool {
18 | return tnode.ownerObj.SendCommand(&transactYieldCommand{tnode: tnode}, true)
19 | }
20 |
--------------------------------------------------------------------------------
/core/transact/config.go:
--------------------------------------------------------------------------------
1 | // config
2 | package transact
3 |
4 | import (
5 | "github.com/idealeak/goserver/core"
6 | "github.com/idealeak/goserver/core/logger"
7 | )
8 |
9 | var Config = Configuration{}
10 |
11 | type Configuration struct {
12 | TxSkeletonName string
13 | tcs TransactCommSkeleton
14 | }
15 |
16 | func (this *Configuration) Name() string {
17 | return "tx"
18 | }
19 |
20 | func (this *Configuration) Init() error {
21 | if this.TxSkeletonName != "" {
22 | this.tcs = GetTxCommSkeleton(this.TxSkeletonName)
23 | if this.tcs == nil {
24 | logger.Logger.Warnf("%v TxSkeletonName not registed!!!", this.TxSkeletonName)
25 | }
26 | }
27 | return nil
28 | }
29 |
30 | func (this *Configuration) Close() error {
31 | return nil
32 | }
33 |
34 | func init() {
35 | core.RegistePackage(&Config)
36 | }
37 |
--------------------------------------------------------------------------------
/core/transact/doc.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | // 2pc
4 |
--------------------------------------------------------------------------------
/core/transact/transcommitpolicy.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | const (
4 | TransactCommitPolicy_SelfDecide TransactCommitPolicy = iota
5 | TransactCommitPolicy_TwoPhase
6 | )
7 |
8 | type TransactCommitPolicy int
9 |
--------------------------------------------------------------------------------
/core/transact/transcommskeleton.go:
--------------------------------------------------------------------------------
1 | // transcommskeleton
2 | package transact
3 |
4 | var txSkeletons = make(map[string]TransactCommSkeleton)
5 |
6 | type TransactCommSkeleton interface {
7 | SendTransResult(parent, me *TransNodeParam, tr *TransResult) bool
8 | SendTransStart(parent, me *TransNodeParam, ud interface{}) bool
9 | SendCmdToTransNode(tnp *TransNodeParam, cmd TransCmd) bool
10 | GetSkeletonID() int
11 | GetAreaID() int
12 | }
13 |
14 | func RegisteTxCommSkeleton(name string, tcs TransactCommSkeleton) {
15 | if _, exist := txSkeletons[name]; exist {
16 | panic("repeate registe TxCommSkeleton:" + name)
17 | }
18 | txSkeletons[name] = tcs
19 | }
20 |
21 | func GetTxCommSkeleton(name string) TransactCommSkeleton {
22 | if t, exist := txSkeletons[name]; exist {
23 | return t
24 | }
25 | return nil
26 | }
27 |
--------------------------------------------------------------------------------
/core/transact/transctx.go:
--------------------------------------------------------------------------------
1 | // transctx
2 | package transact
3 |
4 | import (
5 | "sync"
6 | )
7 |
8 | type TransCtx struct {
9 | fields map[interface{}]interface{}
10 | lock *sync.RWMutex
11 | }
12 |
13 | func NewTransCtx() *TransCtx {
14 | tc := &TransCtx{
15 | lock: new(sync.RWMutex),
16 | }
17 | return tc
18 | }
19 |
20 | func (this *TransCtx) SetField(k, v interface{}) {
21 | this.lock.Lock()
22 | if this.fields == nil {
23 | this.fields = make(map[interface{}]interface{})
24 | }
25 | this.fields[k] = v
26 | this.lock.Unlock()
27 | }
28 |
29 | func (this *TransCtx) GetField(k interface{}) interface{} {
30 | this.lock.RLock()
31 | if this.fields != nil {
32 | if v, exist := this.fields[k]; exist {
33 | this.lock.RUnlock()
34 | return v
35 | }
36 | }
37 | this.lock.RUnlock()
38 | return nil
39 | }
40 |
--------------------------------------------------------------------------------
/core/transact/transfactory.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/idealeak/goserver/core/logger"
7 | )
8 |
9 | var transactionHandlerPool = make(map[TransType]TransHandler)
10 |
11 | func GetHandler(tt TransType) TransHandler {
12 | if v, exist := transactionHandlerPool[tt]; exist {
13 | return v
14 | }
15 | return nil
16 | }
17 |
18 | func RegisteHandler(tt TransType, th TransHandler) {
19 | if _, exist := transactionHandlerPool[tt]; exist {
20 | panic(fmt.Sprintf("TransHandlerFactory repeate registe handler, type=%v", tt))
21 | return
22 | }
23 | logger.Logger.Trace("transact.RegisteHandler:", tt)
24 | transactionHandlerPool[tt] = th
25 | }
26 |
--------------------------------------------------------------------------------
/core/transact/transhandler.go:
--------------------------------------------------------------------------------
1 | // transhandler
2 | package transact
3 |
4 | type TransHandler interface {
5 | OnExcute(n *TransNode, ud interface{}) TransExeResult
6 | OnCommit(n *TransNode) TransExeResult
7 | OnRollBack(n *TransNode) TransExeResult
8 | OnChildTransRep(n *TransNode, hChild TransNodeID, retCode int, ud interface{}) TransExeResult
9 | }
10 |
11 | type OnExecuteWrapper func(n *TransNode, ud interface{}) TransExeResult
12 | type OnCommitWrapper func(n *TransNode) TransExeResult
13 | type OnRollBackWrapper func(n *TransNode) TransExeResult
14 | type OnChildRespWrapper func(n *TransNode, hChild TransNodeID, retCode int, ud interface{}) TransExeResult
15 |
16 | type TransHanderWrapper struct {
17 | OnExecuteWrapper
18 | OnCommitWrapper
19 | OnRollBackWrapper
20 | OnChildRespWrapper
21 | }
22 |
23 | func (wrapper *TransHanderWrapper) OnExcute(n *TransNode, ud interface{}) TransExeResult {
24 | if wrapper.OnExecuteWrapper != nil {
25 | return wrapper.OnExecuteWrapper(n, ud)
26 | }
27 | return TransExeResult_Success
28 | }
29 |
30 | func (wrapper *TransHanderWrapper) OnCommit(n *TransNode) TransExeResult {
31 | if wrapper.OnCommitWrapper != nil {
32 | return wrapper.OnCommitWrapper(n)
33 | }
34 | return TransExeResult_Success
35 | }
36 |
37 | func (wrapper *TransHanderWrapper) OnRollBack(n *TransNode) TransExeResult {
38 | if wrapper.OnRollBackWrapper != nil {
39 | return wrapper.OnRollBackWrapper(n)
40 | }
41 | return TransExeResult_Success
42 | }
43 |
44 | func (wrapper *TransHanderWrapper) OnChildTransRep(n *TransNode, hChild TransNodeID, retCode int, ud interface{}) TransExeResult {
45 | if wrapper.OnChildRespWrapper != nil {
46 | return wrapper.OnChildRespWrapper(n, hChild, retCode, ud)
47 | }
48 | return TransExeResult_Success
49 | }
50 |
--------------------------------------------------------------------------------
/core/transact/transtimeouthandler.go:
--------------------------------------------------------------------------------
1 | package transact
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/timer"
5 | )
6 |
7 | type transactTimerAction struct {
8 | }
9 |
10 | func (t transactTimerAction) OnTimer(h timer.TimerHandle, ud interface{}) bool {
11 | if trans, ok := ud.(*TransNode); ok {
12 | trans.timeout()
13 | return true
14 | }
15 | return false
16 | }
17 |
--------------------------------------------------------------------------------
/core/transact/transtype.go:
--------------------------------------------------------------------------------
1 | // transtype
2 | package transact
3 |
4 | type TransType int
5 |
--------------------------------------------------------------------------------
/core/utils/atomicidgen.go:
--------------------------------------------------------------------------------
1 | // AtomicIdGen
2 | package utils
3 |
4 | import (
5 | "sync/atomic"
6 | )
7 |
8 | type AtomicIdGen struct {
9 | cur uint32
10 | beg uint32
11 | }
12 |
13 | func (this *AtomicIdGen) NextId() uint32 {
14 | return atomic.AddUint32(&this.cur, 1)
15 | }
16 |
17 | func (this *AtomicIdGen) Reset() {
18 | atomic.StoreUint32(&this.cur, this.beg)
19 | }
20 |
21 | func (this *AtomicIdGen) SetStartPoint(startPoint uint32) {
22 | this.beg = startPoint
23 | this.Reset()
24 | }
25 |
26 | func (this *AtomicIdGen) CurrId() uint32 {
27 | return this.cur
28 | }
29 |
--------------------------------------------------------------------------------
/core/utils/clone_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "testing"
5 |
6 | "code.google.com/p/goprotobuf/proto"
7 | )
8 |
9 | type StructD struct {
10 | Int4 int
11 | }
12 |
13 | type StructC struct {
14 | Int3 int
15 | DMap map[int]*StructD
16 | DArr []StructD
17 | TMap map[int]struct{}
18 | }
19 |
20 | type StructB struct {
21 | StructC
22 | C *int32
23 | IntSlice []*int32
24 | Map map[int]string
25 | }
26 | type StructA struct {
27 | IntValue int
28 | StrValue string
29 | InnerValue *StructB
30 | }
31 |
32 | func TestClone(t *testing.T) {
33 | a := &StructA{IntValue: 1, StrValue: "test",
34 | InnerValue: &StructB{
35 | C: proto.Int(9),
36 | IntSlice: []*int32{proto.Int(1), proto.Int(2), proto.Int(3), proto.Int(4), proto.Int(5), proto.Int(6), proto.Int(7), proto.Int(8), proto.Int(9), proto.Int(0)},
37 | Map: map[int]string{1: "test", 2: "Hello"},
38 | StructC: StructC{Int3: 33, DMap: map[int]*StructD{1: &StructD{Int4: 44}}},
39 | },
40 | }
41 | b := Clone(a).(*StructA)
42 | //t.Trace(a, b)
43 |
44 | b.InnerValue.IntSlice[0] = proto.Int(99)
45 | b.InnerValue.IntSlice = b.InnerValue.IntSlice[:7]
46 | //t.Tracef("%#v %#v %#v\r\n", a, a.InnerValue.IntSlice, *a.InnerValue.C)
47 | //t.Tracef("%#v %#v %#v\r\n", b, b.InnerValue.IntSlice, *b.InnerValue.C)
48 | //t.Tracef("%#v\r\n", a.InnerValue.Map)
49 | //t.Tracef("%#v\r\n", b.InnerValue.Map)
50 | //t.Tracef("%#v\r\n", a.InnerValue.StructC)
51 | //t.Tracef("%#v\r\n", b.InnerValue.StructC)
52 | }
53 |
54 | func BenchmarkClone(b *testing.B) {
55 | a := &StructA{IntValue: 1, StrValue: "test",
56 | InnerValue: &StructB{
57 | C: proto.Int(9),
58 | IntSlice: []*int32{proto.Int(1), proto.Int(2), proto.Int(3), proto.Int(4), proto.Int(5), proto.Int(6), proto.Int(7), proto.Int(8), proto.Int(9), proto.Int(0)},
59 | Map: map[int]string{1: "test", 2: "Hello"},
60 | StructC: StructC{Int3: 33, DMap: map[int]*StructD{1: &StructD{Int4: 44}}},
61 | },
62 | }
63 |
64 | b.StartTimer()
65 | for i := 0; i < b.N; i++ {
66 | _ = Clone(a).(*StructA)
67 | }
68 | b.StopTimer()
69 | }
70 |
--------------------------------------------------------------------------------
/core/utils/debug_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | type mytype struct {
8 | next *mytype
9 | prev *mytype
10 | }
11 |
12 | func TestPrint(t *testing.T) {
13 | Display("v1", 1, "v2", 2, "v3", 3)
14 | }
15 |
16 | func TestPrintPoint(t *testing.T) {
17 | var v1 = new(mytype)
18 | var v2 = new(mytype)
19 |
20 | v1.prev = nil
21 | v1.next = v2
22 |
23 | v2.prev = v1
24 | v2.next = nil
25 |
26 | Display("v1", v1, "v2", v2)
27 | }
28 |
29 | func TestPrintString(t *testing.T) {
30 | str := GetDisplayString("v1", 1, "v2", 2)
31 | println(str)
32 | }
33 |
--------------------------------------------------------------------------------
/core/utils/healthcheck.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | //type DatabaseCheck struct {
4 | //}
5 |
6 | //func (dc *DatabaseCheck) Check() error {
7 | // if dc.isConnected() {
8 | // return nil
9 | // } else {
10 | // return errors.New("can't connect database")
11 | // }
12 | //}
13 |
14 | //AddHealthCheck("database",&DatabaseCheck{})
15 |
16 | var AdminCheckList map[string]HealthChecker
17 |
18 | type HealthChecker interface {
19 | Check() error
20 | }
21 |
22 | type HealthCheckerWrapper func() error
23 |
24 | func (hcw HealthCheckerWrapper) Check() error {
25 | return hcw()
26 | }
27 |
28 | func AddHealthCheck(name string, hc HealthChecker) {
29 | AdminCheckList[name] = hc
30 | }
31 |
32 | func init() {
33 | AdminCheckList = make(map[string]HealthChecker)
34 | }
35 |
--------------------------------------------------------------------------------
/core/utils/idgen.go:
--------------------------------------------------------------------------------
1 | // idgen
2 | package utils
3 |
4 | import (
5 | "sync/atomic"
6 | )
7 |
8 | type IdGen struct {
9 | beg int32
10 | seq int32
11 | }
12 |
13 | func (this *IdGen) NextId() int {
14 | seq := atomic.AddInt32(&this.seq, 1)
15 | return int(seq)
16 | }
17 |
18 | func (this *IdGen) Reset() {
19 | atomic.StoreInt32(&this.seq, this.beg)
20 | }
21 |
22 | func (this *IdGen) SetSeq(seq int) {
23 | atomic.StoreInt32(&this.seq, int32(seq))
24 | }
25 |
26 | func (this *IdGen) SetStartPoint(startPoint int) {
27 | atomic.StoreInt32(&this.beg, int32(startPoint))
28 | }
29 |
30 | func (this *IdGen) CurrId() int {
31 | return int(atomic.LoadInt32(&this.seq))
32 | }
33 |
--------------------------------------------------------------------------------
/core/utils/panic.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "runtime"
5 |
6 | "encoding/json"
7 | "fmt"
8 | "github.com/idealeak/goserver/core/logger"
9 | "sync"
10 | "sync/atomic"
11 | "time"
12 | )
13 |
14 | var _panicStackMgr = &PanicStackMgr{
15 | items: make(map[string]*PanicStackInfo),
16 | }
17 |
18 | type PanicStackMgr struct {
19 | sync.RWMutex
20 | items map[string]*PanicStackInfo
21 | }
22 |
23 | type PanicStackInfo struct {
24 | FirstTime time.Time
25 | LastTime time.Time
26 | Times int64
27 | ErrorMsg string
28 | StackBuf string
29 | }
30 |
31 | func DumpStackIfPanic(f string) {
32 | if err := recover(); err != nil {
33 | defer func() { //防止二次panic
34 | if err := recover(); err != nil {
35 | logger.Logger.Error(f, " panic.panic,error=", err)
36 | }
37 | }()
38 | logger.Logger.Error(f, " panic,error=", err)
39 | errMsg := fmt.Sprintf("%v", err)
40 | var buf [4096]byte
41 | n := runtime.Stack(buf[:], false)
42 | logger.Logger.Error("stack--->", string(buf[:n]))
43 | stk := make([]uintptr, 32)
44 | m := runtime.Callers(0, stk[:])
45 | stk = stk[:m]
46 | if len(stk) > 0 {
47 | d, err := json.Marshal(stk)
48 | if err == nil && len(d) > 0 {
49 | key := string(d)
50 | _panicStackMgr.Lock()
51 | defer _panicStackMgr.Unlock()
52 | tNow := time.Now()
53 | if ps, exist := _panicStackMgr.items[key]; exist {
54 | atomic.AddInt64(&ps.Times, 1)
55 | ps.LastTime = tNow
56 | } else {
57 | ps = &PanicStackInfo{
58 | ErrorMsg: errMsg,
59 | Times: 1,
60 | StackBuf: string(buf[:n]),
61 | FirstTime: tNow,
62 | LastTime: tNow,
63 | }
64 | _panicStackMgr.items[key] = ps
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
71 | func DumpStack(f string) {
72 | logger.Logger.Error(f)
73 | var buf [4096]byte
74 | len := runtime.Stack(buf[:], false)
75 | logger.Logger.Error("stack--->", string(buf[:len]))
76 | }
77 |
78 | func GetPanicStats() map[string]PanicStackInfo {
79 | stats := make(map[string]PanicStackInfo)
80 | _panicStackMgr.RLock()
81 | defer _panicStackMgr.RUnlock()
82 | for k, v := range _panicStackMgr.items {
83 | stats[k] = *v
84 | }
85 | return stats
86 | }
87 |
--------------------------------------------------------------------------------
/core/utils/profile_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "os"
5 | "testing"
6 | )
7 |
8 | func TestProcessInput(t *testing.T) {
9 | ProcessInput("lookup goroutine", os.Stdout)
10 | ProcessInput("lookup heap", os.Stdout)
11 | ProcessInput("lookup threadcreate", os.Stdout)
12 | ProcessInput("lookup block", os.Stdout)
13 | ProcessInput("gc summary", os.Stdout)
14 | }
15 |
--------------------------------------------------------------------------------
/core/utils/rand.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "errors"
5 | "math/rand"
6 | "strconv"
7 | "strings"
8 | "time"
9 | )
10 |
11 | var MinMaxError = errors.New("Min cannot be greater than max.")
12 | var Char_Buff = [26]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
13 | "t", "u", "v", "w", "x", "y", "z"}
14 |
15 | func RandChoice(choices []interface{}) (interface{}, error) {
16 | var winner interface{}
17 | length := len(choices)
18 | i, err := IntRange(0, length)
19 | if err != nil {
20 | return nil, err
21 | }
22 | winner = choices[i]
23 | return winner, nil
24 | }
25 |
26 | func IntRange(min, max int) (int, error) {
27 | var result int
28 | switch {
29 | case min > max:
30 | return result, MinMaxError
31 | case min == max:
32 | result = max
33 | case min < max:
34 | rand.Seed(time.Now().UnixNano())
35 | result = min + rand.Intn(max-min)
36 | }
37 | return result, nil
38 | }
39 |
40 | func RandCode(codelen int) string {
41 | if codelen == 0 {
42 | return ""
43 | }
44 | numLen := rand.Intn(codelen)
45 | charLen := codelen - numLen
46 | var buff string
47 | for i := 0; i < numLen; i++ {
48 | buff = buff + strconv.Itoa(rand.Intn(10))
49 | }
50 | for i := 0; i < charLen; i++ {
51 | buff = buff + Char_Buff[rand.Intn(26)]
52 | }
53 | var code string
54 | arr := rand.Perm(codelen)
55 | for i := 0; i < 6; i++ {
56 | code = code + string(buff[arr[i]])
57 | }
58 | return strings.ToUpper(code)
59 | }
60 | func RandNumCode(codelen int) string {
61 | if codelen == 0 {
62 | return ""
63 | }
64 | var buff string
65 | for i := 0; i < codelen; i++ {
66 | buff = buff + strconv.Itoa(rand.Intn(10))
67 | }
68 | return strings.ToUpper(buff)
69 | }
70 |
--------------------------------------------------------------------------------
/core/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "github.com/idealeak/goserver/core/logger"
6 | "runtime"
7 | "time"
8 | )
9 |
10 | func Avg(items []time.Duration) time.Duration {
11 | var sum time.Duration
12 | for _, item := range items {
13 | sum += item
14 | }
15 | return time.Duration(int64(sum) / int64(len(items)))
16 | }
17 |
18 | // human readable format
19 | func ToH(bytes uint64) string {
20 | switch {
21 | case bytes < 1024:
22 | return fmt.Sprintf("%dB", bytes)
23 | case bytes < 1024*1024:
24 | return fmt.Sprintf("%.2fK", float64(bytes)/1024)
25 | case bytes < 1024*1024*1024:
26 | return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024)
27 | default:
28 | return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024)
29 | }
30 | }
31 |
32 | // short string format
33 | func ToS(d time.Duration) string {
34 |
35 | u := uint64(d)
36 | if u < uint64(time.Second) {
37 | switch {
38 | case u == 0:
39 | return "0"
40 | case u < uint64(time.Microsecond):
41 | return fmt.Sprintf("%.2fns", float64(u))
42 | case u < uint64(time.Millisecond):
43 | return fmt.Sprintf("%.2fus", float64(u)/1000)
44 | default:
45 | return fmt.Sprintf("%.2fms", float64(u)/1000/1000)
46 | }
47 | } else {
48 | switch {
49 | case u < uint64(time.Minute):
50 | return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000)
51 | case u < uint64(time.Hour):
52 | return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60)
53 | default:
54 | return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60)
55 | }
56 | }
57 |
58 | }
59 |
60 | func CatchPanic(f func()) (err interface{}) {
61 | defer func() {
62 | err = recover()
63 | if err != nil {
64 | logger.Logger.Warnf("%s panic: %s", f, err)
65 | var buf [4096]byte
66 | n := runtime.Stack(buf[:], false)
67 | logger.Logger.Error("stack--->", string(buf[:n]))
68 | }
69 | }()
70 | f()
71 | return
72 | }
73 |
74 | func RunPanicless(f func()) (panicless bool) {
75 | defer func() {
76 | err := recover()
77 | panicless = err == nil
78 | if err != nil {
79 | logger.Logger.Warnf("%s panic: %s", f, err)
80 | var buf [4096]byte
81 | n := runtime.Stack(buf[:], false)
82 | logger.Logger.Error("stack--->", string(buf[:n]))
83 | }
84 | }()
85 |
86 | f()
87 | return
88 | }
89 |
90 | func RepeatUntilPanicless(f func()) {
91 | for !RunPanicless(f) {
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/core/utils/waitor.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "sync/atomic"
5 |
6 | "github.com/idealeak/goserver/core/logger"
7 | )
8 |
9 | type Waitor struct {
10 | name string
11 | counter int32
12 | waiters int32
13 | c chan string
14 | }
15 |
16 | func NewWaitor(name string) *Waitor {
17 | w := &Waitor{name: name, c: make(chan string, 16)}
18 | return w
19 | }
20 |
21 | func (w *Waitor) Add(name string, delta int) {
22 | v := atomic.AddInt32(&w.counter, int32(delta))
23 | if v < 0 {
24 | panic("negative Waitor counter")
25 | }
26 | cnt := atomic.LoadInt32(&w.counter)
27 | logger.Logger.Debugf("(w *Waitor)(%v:%p) Add(%v,%v) counter(%v)", w.name, w, name, delta, cnt)
28 | }
29 |
30 | func (w *Waitor) Wait(name string) {
31 | v := atomic.AddInt32(&w.waiters, 1)
32 | if v > 1 {
33 | panic("only support one waitor")
34 | }
35 | cnt := atomic.LoadInt32(&w.waiters)
36 | logger.Logger.Debugf("(w *Waitor)(%v:%p) Waiter(%v) waiters(%v)", w.name, w, name, cnt)
37 | for w.counter > 0 {
38 | dname := <-w.c
39 | v = atomic.AddInt32(&w.counter, -1)
40 | cnt = atomic.LoadInt32(&w.counter)
41 | logger.Logger.Debugf("(w *Waitor)(%v:%p) Waiter(%v) after(%v)done! counter(%v)", w.name, w, name, dname, cnt)
42 | }
43 | }
44 |
45 | func (w *Waitor) Done(name string) {
46 | w.c <- name
47 | logger.Logger.Debugf("(w *Waitor)(%v:%p) Done(%v)!!!", w.name, w, name)
48 | }
49 |
--------------------------------------------------------------------------------
/core/zk/zk_test.go:
--------------------------------------------------------------------------------
1 | package zk
2 |
3 | import (
4 | "testing"
5 | "time"
6 | )
7 |
8 | func TestZK(t *testing.T) {
9 | conn, err := Connect([]string{"10.33.21.152:2181"}, time.Second*30)
10 | if err != nil {
11 | t.Error(err)
12 | }
13 | defer conn.Close()
14 | err = Create(conn, "/test/test")
15 | if err != nil {
16 | t.Error(err)
17 | }
18 | // registertmp
19 | err = RegisterTemp(conn, "/test/test", "1")
20 | if err != nil {
21 | t.Error(err)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/doc.go:
--------------------------------------------------------------------------------
1 | package goserver
2 |
--------------------------------------------------------------------------------
/examples/echoclient/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":{
4 | "Name": "EchoClient",
5 | "Type": 1,
6 | "Id": 101,
7 | "AreaID": 1,
8 | "Banner": [
9 | "=================",
10 | "echo client",
11 | "================="
12 | ]
13 | },
14 |
15 | "IoServices": []
16 | },
17 |
18 | "module": {
19 | "Options": {
20 | "QueueBacklog": 1024,
21 | "MaxDone": 1024,
22 | "Interval": 100
23 | }
24 | },
25 |
26 | "executor": {
27 | "Options": {
28 | "QueueBacklog": 1024,
29 | "MaxDone": 1024,
30 | "Interval": 0
31 | },
32 | "Worker": {
33 | "WorkerCnt": 8,
34 | "Options": {
35 | "QueueBacklog": 1024,
36 | "MaxDone": 1024,
37 | "Interval": 0
38 | }
39 | }
40 | },
41 |
42 | "timer": {
43 | "Options": {
44 | "QueueBacklog": 1024,
45 | "MaxDone": 1024,
46 | "Interval": 100
47 | }
48 | },
49 |
50 | "core": {
51 | "MaxProcs": 4
52 | },
53 |
54 | "pressure": {
55 | "Count":1,
56 | "Connects": {
57 | "Id": 201,
58 | "Type": 2,
59 | "AreaID": 0,
60 | "Name": "EchoService",
61 | "Ip": "gt.doudoubei.com",
62 | "Port": 11111,
63 | "Protocol":"tcp",
64 | "Path":"/",
65 | "MaxDone": 20,
66 | "MaxPend": 20,
67 | "MaxPacket": 65535,
68 | "MaxConn": 8,
69 | "RcvBuff": 8192,
70 | "SndBuff": 8192,
71 | "WriteTimeout": 30,
72 | "ReadTimeout": 30,
73 | "NoDelay": true,
74 | "IsInnerLink": true,
75 | "IsClient": true,
76 | "IsAutoReconn": true,
77 | "AllowMultiConn": true,
78 | "SupportFragment": true,
79 | "AuthKey": "1234567890",
80 | "FilterChain": ["session-filter-trace","session-filter-auth","serversessionfilter"]
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/examples/echoclient/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/echoclient/main.go:
--------------------------------------------------------------------------------
1 | // main
2 | package main
3 |
4 | import (
5 | "github.com/idealeak/goserver/core"
6 | "github.com/idealeak/goserver/core/module"
7 | )
8 |
9 | func main() {
10 | defer core.ClosePackages()
11 | core.LoadPackages("config.json")
12 |
13 | waiter := module.Start()
14 | waiter.Wait("main")
15 | }
16 |
--------------------------------------------------------------------------------
/examples/echoclient/pressure.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/idealeak/goserver/core"
7 | _ "github.com/idealeak/goserver/core/builtin/action"
8 | _ "github.com/idealeak/goserver/core/builtin/filter"
9 | "github.com/idealeak/goserver/core/module"
10 | "github.com/idealeak/goserver/core/netlib"
11 | )
12 |
13 | var (
14 | Config = Configuration{}
15 | PressureModule = &PressureTest{}
16 | StartCnt = 0
17 | )
18 |
19 | type Configuration struct {
20 | Count int
21 | Connects netlib.SessionConfig
22 | }
23 |
24 | func (this *Configuration) Name() string {
25 | return "pressure"
26 | }
27 |
28 | func (this *Configuration) Init() error {
29 | this.Connects.Init()
30 | return nil
31 | }
32 |
33 | func (this *Configuration) Close() error {
34 | return nil
35 | }
36 |
37 | type PressureTest struct {
38 | }
39 |
40 | func (this PressureTest) ModuleName() string {
41 | return "pressure-module"
42 | }
43 |
44 | func (this *PressureTest) Init() {
45 | cfg := Config.Connects
46 | for i := 0; i < Config.Count; i++ {
47 | cfg.Id += i
48 | netlib.Connect(&cfg)
49 | }
50 | }
51 |
52 | func (this *PressureTest) Update() {
53 | return
54 | }
55 |
56 | func (this *PressureTest) Shutdown() {
57 | module.UnregisteModule(this)
58 | }
59 |
60 | func init() {
61 | core.RegistePackage(&Config)
62 | module.RegisteModule(PressureModule, time.Second*30, 50)
63 | }
64 |
--------------------------------------------------------------------------------
/examples/echoclient/scpacketponghandler.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 |
6 | "code.google.com/p/goprotobuf/proto"
7 | "github.com/idealeak/goserver/core/netlib"
8 | "github.com/idealeak/goserver/examples/protocol"
9 | )
10 |
11 | type SCPacketPongPacketFactory struct {
12 | }
13 |
14 | type SCPacketPongHandler struct {
15 | }
16 |
17 | func (this *SCPacketPongPacketFactory) CreatePacket() interface{} {
18 | pack := &protocol.SCPacketPong{}
19 | return pack
20 | }
21 |
22 | func (this *SCPacketPongHandler) Process(session *netlib.Session, packetid int, data interface{}) error {
23 | if pong, ok := data.(*protocol.SCPacketPong); ok {
24 | ping := &protocol.CSPacketPing{
25 | TimeStamb: proto.Int64(time.Now().Unix()),
26 | Message: pong.GetMessage(),
27 | }
28 | proto.SetDefaults(ping)
29 | session.Send(int(protocol.PacketID_PACKET_CS_PING), ping)
30 | }
31 | return nil
32 | }
33 |
34 | func init() {
35 | netlib.RegisterHandler(int(protocol.PacketID_PACKET_SC_PONG), &SCPacketPongHandler{})
36 | netlib.RegisterFactory(int(protocol.PacketID_PACKET_SC_PONG), &SCPacketPongPacketFactory{})
37 | }
38 |
--------------------------------------------------------------------------------
/examples/echoclient/serversessionfilter.go:
--------------------------------------------------------------------------------
1 | // serversessionfilter
2 | package main
3 |
4 | import (
5 | "time"
6 |
7 | "code.google.com/p/goprotobuf/proto"
8 | "github.com/idealeak/goserver/core/logger"
9 | "github.com/idealeak/goserver/core/netlib"
10 | "github.com/idealeak/goserver/examples/protocol"
11 | )
12 |
13 | var (
14 | ServerSessionFilterName = "serversessionfilter"
15 | )
16 |
17 | type ServerSessionFilter struct {
18 | netlib.BasicSessionFilter
19 | }
20 |
21 | func (ssf ServerSessionFilter) GetName() string {
22 | return ServerSessionFilterName
23 | }
24 |
25 | func (ssf *ServerSessionFilter) GetInterestOps() uint {
26 | return 1 << netlib.InterestOps_Opened
27 | }
28 |
29 | func (ssf *ServerSessionFilter) OnSessionOpened(s *netlib.Session) bool {
30 | logger.Logger.Trace("(ssf *ServerSessionFilter) OnSessionOpened")
31 | packet := &protocol.CSPacketPing{
32 | TimeStamb: proto.Int64(time.Now().Unix()),
33 | Message: []byte("=1234567890abcderghijklmnopqrstuvwxyz="),
34 | }
35 | //for i := 0; i < 1024*32; i++ {
36 | // packet.Message = append(packet.Message, byte('x'))
37 | //}
38 | proto.SetDefaults(packet)
39 | s.Send(int(protocol.PacketID_PACKET_CS_PING), packet)
40 | return true
41 | }
42 |
43 | func init() {
44 | netlib.RegisteSessionFilterCreator(ServerSessionFilterName, func() netlib.SessionFilter {
45 | return &ServerSessionFilter{}
46 | })
47 | }
48 |
--------------------------------------------------------------------------------
/examples/echoserver/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":{
4 | "Name": "EchoServer",
5 | "Type": 2,
6 | "Id": 201,
7 | "AreaID": 1,
8 | "Banner": [
9 | "=================",
10 | "echo server",
11 | "================="
12 | ]
13 | },
14 |
15 | "IoServices": [
16 | {
17 | "Id": 201,
18 | "Type": 2,
19 | "AreaId": 1,
20 | "Name": "EchoService",
21 | "Ip": "",
22 | "Port": 2345,
23 | "Protocol":"ws",
24 | "Path":"/",
25 | "MaxDone": 20,
26 | "MaxPend": 20,
27 | "MaxPacket": 65535,
28 | "MaxConn": 10000,
29 | "RcvBuff": 8192,
30 | "SndBuff": 8192,
31 | "WriteTimeout": 30,
32 | "ReadTimeout": 30,
33 | "IsInnerLink": true,
34 | "NoDelay": true,
35 | "SupportFragment": true,
36 | "AuthKey": "1234567890",
37 | "FilterChain": ["session-filter-trace","session-filter-auth"]
38 | }
39 | ]
40 | },
41 |
42 | "module": {
43 | "Options": {
44 | "QueueBacklog": 1024,
45 | "MaxDone": 1024,
46 | "Interval": 100
47 | }
48 | },
49 |
50 | "executor": {
51 | "Options": {
52 | "QueueBacklog": 1024,
53 | "MaxDone": 1024,
54 | "Interval": 0
55 | },
56 | "Worker": {
57 | "WorkerCnt": 8,
58 | "Options": {
59 | "QueueBacklog": 1024,
60 | "MaxDone": 1024,
61 | "Interval": 0
62 | }
63 | }
64 | },
65 |
66 | "timer": {
67 | "Options": {
68 | "QueueBacklog": 1024,
69 | "MaxDone": 1024,
70 | "Interval": 100
71 | }
72 | },
73 |
74 | "core": {
75 | "MaxProcs": 4
76 | },
77 |
78 | "cmdline": {
79 | "SupportCmdLine": true
80 | }
81 | }
--------------------------------------------------------------------------------
/examples/echoserver/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/echoserver/main.go:
--------------------------------------------------------------------------------
1 | // main
2 | package main
3 |
4 | import (
5 | "net/http"
6 | _ "net/http/pprof"
7 |
8 | "github.com/idealeak/goserver/core"
9 | _ "github.com/idealeak/goserver/core/builtin/filter"
10 | "github.com/idealeak/goserver/core/module"
11 | )
12 |
13 | func main() {
14 | defer core.ClosePackages()
15 | core.LoadPackages("config.json")
16 | //usage: go tool pprof http://localhost:6060/debug/pprof/heap
17 | go func() {
18 | http.ListenAndServe("localhost:6060", nil)
19 | }()
20 |
21 | waiter := module.Start()
22 | waiter.Wait("main")
23 | }
24 |
--------------------------------------------------------------------------------
/examples/echoserver/scpacketponghandler.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "code.google.com/p/goprotobuf/proto"
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/examples/protocol"
7 | )
8 |
9 | type CSPacketPingPacketFactory struct {
10 | }
11 |
12 | type CSPacketPingHandler struct {
13 | }
14 |
15 | func (this *CSPacketPingPacketFactory) CreatePacket() interface{} {
16 | pack := &protocol.CSPacketPing{}
17 | return pack
18 | }
19 |
20 | func (this *CSPacketPingHandler) Process(session *netlib.Session, packetid int, data interface{}) error {
21 | if ping, ok := data.(*protocol.CSPacketPing); ok {
22 | pong := &protocol.SCPacketPong{
23 | TimeStamb: proto.Int64(ping.GetTimeStamb()),
24 | Message: ping.GetMessage(),
25 | }
26 | proto.SetDefaults(pong)
27 | session.Send(int(protocol.PacketID_PACKET_SC_PONG), pong)
28 | }
29 | return nil
30 | }
31 |
32 | func init() {
33 | netlib.RegisterHandler(int(protocol.PacketID_PACKET_CS_PING), &CSPacketPingHandler{})
34 | netlib.RegisterFactory(int(protocol.PacketID_PACKET_CS_PING), &CSPacketPingPacketFactory{})
35 | }
36 |
--------------------------------------------------------------------------------
/examples/gen_go.bat:
--------------------------------------------------------------------------------
1 | protoc --go_out=. protocol/*.proto
2 | pause
--------------------------------------------------------------------------------
/examples/other/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":
4 | {
5 | "Name": "TimerServer",
6 | "Banner": [
7 | "=================",
8 | "timer server",
9 | "================="
10 | ]
11 | }
12 | },
13 |
14 | "core": {
15 | "MaxProcs": 4,
16 | "SupportCmdLine":true,
17 | "SupportSignal": true,
18 | "SupportAdmin": true,
19 | "SlowMS": 200,
20 | "Object": {
21 | "QueueBacklog": 1024,
22 | "MaxDone": 1024,
23 | "Interval": 100
24 | },
25 |
26 | "Executor": {
27 | "Object": {
28 | "QueueBacklog": 1024,
29 | "MaxDone": 1024,
30 | "Interval": 0
31 | },
32 | "Worker": {
33 | "WorkerCnt": 8,
34 | "Object": {
35 | "QueueBacklog": 1024,
36 | "MaxDone": 1024,
37 | "Interval": 0
38 | }
39 | }
40 | },
41 |
42 | "Timer": {
43 | "Object": {
44 | "QueueBacklog": 1024,
45 | "MaxDone": 1024,
46 | "Interval": 100
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/examples/other/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/other/main.go:
--------------------------------------------------------------------------------
1 | // main
2 | package main
3 |
4 | import (
5 | "github.com/idealeak/goserver/core"
6 | "github.com/idealeak/goserver/core/module"
7 | )
8 |
9 | func main() {
10 | defer core.ClosePackages()
11 | core.LoadPackages("config.json")
12 |
13 | waiter := module.Start()
14 | waiter.Wait("main")
15 | }
16 |
--------------------------------------------------------------------------------
/examples/other/task.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "github.com/idealeak/goserver/core/basic"
6 | "math/rand"
7 | "time"
8 |
9 | "github.com/idealeak/goserver/core/module"
10 | "github.com/idealeak/goserver/core/task"
11 | )
12 |
13 | var TaskExampleSington = &TaskExample{}
14 |
15 | type TaskExample struct {
16 | id int
17 | }
18 |
19 | //in task.Worker goroutine
20 | func (this *TaskExample) Call(o *basic.Object) interface{} {
21 | tNow := time.Now()
22 | fmt.Println("[", this.id, "]TaskExample execute start ")
23 | time.Sleep(time.Second * time.Duration(rand.Intn(10)))
24 | fmt.Println("[", this.id, "]TaskExample execute end, take ", time.Now().Sub(tNow))
25 | return nil
26 | }
27 |
28 | // in laucher goroutine
29 | func (this *TaskExample) Done(i interface{}, t *task.Task) {
30 | fmt.Println("TaskExample execute over")
31 | }
32 |
33 | ////////////////////////////////////////////////////////////////////
34 | /// Module Implement [beg]
35 | ////////////////////////////////////////////////////////////////////
36 | func (this *TaskExample) ModuleName() string {
37 | return "taskexample"
38 | }
39 |
40 | func (this *TaskExample) Init() {
41 | for i := 1; i < 100; i++ {
42 | th := &TaskExample{id: i}
43 | t := task.New(nil, th, th,"test")
44 | if b := t.StartByExecutor(fmt.Sprintf("%v", i)); !b {
45 | fmt.Println("[", i, "]task lauch failed")
46 | } else {
47 | fmt.Println("[", i, "]task lauch success")
48 | }
49 | }
50 |
51 | for i := 100; i < 200; i++ {
52 | th := &TaskExample{id: i}
53 | t := task.New(nil, th, th,"test")
54 | w := rand.Intn(100)
55 | go func(id, n int) {
56 | if b := t.StartByFixExecutor(fmt.Sprintf("test%v", n)); !b {
57 | fmt.Println("[", id, "]task lauch failed")
58 | } else {
59 | fmt.Println("[", id, "]task lauch success")
60 | }
61 | }(i, w)
62 | }
63 | }
64 |
65 | func (this *TaskExample) Update() {
66 | fmt.Println("TaskExample.Update")
67 | }
68 |
69 | func (this *TaskExample) Shutdown() {
70 | module.UnregisteModule(this)
71 | }
72 |
73 | ////////////////////////////////////////////////////////////////////
74 | /// Module Implement [end]
75 | ////////////////////////////////////////////////////////////////////
76 |
77 | func init() {
78 | module.RegisteModule(TaskExampleSington, time.Second, 0)
79 | }
80 |
--------------------------------------------------------------------------------
/examples/other/timer.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | "github.com/idealeak/goserver/core/module"
8 | "github.com/idealeak/goserver/core/timer"
9 | )
10 |
11 | var TimerExampleSington = &TimerExample{}
12 |
13 | type TimerExample struct {
14 | }
15 |
16 | ////////////////////////////////////////////////////////////////////
17 | /// Module Implement [beg]
18 | ////////////////////////////////////////////////////////////////////
19 | func (this *TimerExample) ModuleName() string {
20 | return "timerexample"
21 | }
22 |
23 | func (this *TimerExample) Init() {
24 | var i int
25 | h, b := timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
26 | i++
27 | fmt.Println(i, time.Now())
28 |
29 | if i > 5 {
30 | return false
31 | }
32 |
33 | return true
34 | }), nil, time.Second, 10)
35 | fmt.Println("timer lauch ", h, b)
36 | }
37 |
38 | func (this *TimerExample) Update() {
39 | fmt.Println("timer queue len=", timer.TimerModule.TimerCount())
40 | }
41 |
42 | func (this *TimerExample) Shutdown() {
43 | module.UnregisteModule(this)
44 | }
45 |
46 | ////////////////////////////////////////////////////////////////////
47 | /// Module Implement [end]
48 | ////////////////////////////////////////////////////////////////////
49 |
50 | func init() {
51 | module.RegisteModule(TimerExampleSington, time.Second, 0)
52 | }
53 |
--------------------------------------------------------------------------------
/examples/protocol/packetid.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/packetid.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type PacketID int32
17 |
18 | const (
19 | PacketID_PACKET_CS_PING PacketID = 1000
20 | PacketID_PACKET_SC_PONG PacketID = 1001
21 | )
22 |
23 | var PacketID_name = map[int32]string{
24 | 1000: "PACKET_CS_PING",
25 | 1001: "PACKET_SC_PONG",
26 | }
27 | var PacketID_value = map[string]int32{
28 | "PACKET_CS_PING": 1000,
29 | "PACKET_SC_PONG": 1001,
30 | }
31 |
32 | func (x PacketID) Enum() *PacketID {
33 | p := new(PacketID)
34 | *p = x
35 | return p
36 | }
37 | func (x PacketID) String() string {
38 | return proto.EnumName(PacketID_name, int32(x))
39 | }
40 | func (x PacketID) MarshalJSON() ([]byte, error) {
41 | return json.Marshal(x.String())
42 | }
43 | func (x *PacketID) UnmarshalJSON(data []byte) error {
44 | value, err := proto.UnmarshalJSONEnum(PacketID_value, data, "PacketID")
45 | if err != nil {
46 | return err
47 | }
48 | *x = PacketID(value)
49 | return nil
50 | }
51 |
52 | func init() {
53 | proto.RegisterEnum("protocol.PacketID", PacketID_name, PacketID_value)
54 | }
55 |
--------------------------------------------------------------------------------
/examples/protocol/packetid.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | enum PacketID {
4 | PACKET_CS_PING = 1000;
5 | PACKET_SC_PONG = 1001;
6 | }
--------------------------------------------------------------------------------
/examples/protocol/pingpong.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/pingpong.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type CSPacketPing struct {
17 | TimeStamb *int64 `protobuf:"varint,1,req" json:"TimeStamb,omitempty"`
18 | Message []byte `protobuf:"bytes,2,req" json:"Message,omitempty"`
19 | XXX_unrecognized []byte `json:"-"`
20 | }
21 |
22 | func (m *CSPacketPing) Reset() { *m = CSPacketPing{} }
23 | func (m *CSPacketPing) String() string { return proto.CompactTextString(m) }
24 | func (*CSPacketPing) ProtoMessage() {}
25 |
26 | func (m *CSPacketPing) GetTimeStamb() int64 {
27 | if m != nil && m.TimeStamb != nil {
28 | return *m.TimeStamb
29 | }
30 | return 0
31 | }
32 |
33 | func (m *CSPacketPing) GetMessage() []byte {
34 | if m != nil {
35 | return m.Message
36 | }
37 | return nil
38 | }
39 |
40 | type SCPacketPong struct {
41 | TimeStamb *int64 `protobuf:"varint,1,req" json:"TimeStamb,omitempty"`
42 | Message []byte `protobuf:"bytes,2,req" json:"Message,omitempty"`
43 | XXX_unrecognized []byte `json:"-"`
44 | }
45 |
46 | func (m *SCPacketPong) Reset() { *m = SCPacketPong{} }
47 | func (m *SCPacketPong) String() string { return proto.CompactTextString(m) }
48 | func (*SCPacketPong) ProtoMessage() {}
49 |
50 | func (m *SCPacketPong) GetTimeStamb() int64 {
51 | if m != nil && m.TimeStamb != nil {
52 | return *m.TimeStamb
53 | }
54 | return 0
55 | }
56 |
57 | func (m *SCPacketPong) GetMessage() []byte {
58 | if m != nil {
59 | return m.Message
60 | }
61 | return nil
62 | }
63 |
64 | func init() {
65 | }
66 |
--------------------------------------------------------------------------------
/examples/protocol/pingpong.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message CSPacketPing {
4 | required int64 TimeStamb = 1;
5 | required bytes Message = 2;
6 | }
7 |
8 | message SCPacketPong {
9 | required int64 TimeStamb = 1;
10 | required bytes Message = 2;
11 | }
--------------------------------------------------------------------------------
/examples/protocol/txtype.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/transact"
5 | )
6 |
7 | const (
8 | TxTrace transact.TransType = 1000
9 | )
10 |
--------------------------------------------------------------------------------
/examples/protocol/txuserdata.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | type StructA struct {
4 | X, Y, Z int
5 | P *int
6 | Desc string
7 | }
8 |
--------------------------------------------------------------------------------
/examples/txserver1/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":
4 | {
5 | "Name": "TxServer1",
6 | "Type": 2,
7 | "Id": 201,
8 | "AreaID": 1,
9 | "Banner": [
10 | "=================",
11 | "tx server 1",
12 | "================="
13 | ]
14 | },
15 |
16 | "IoServices": [
17 | {
18 | "Id": 201,
19 | "Type": 2,
20 | "AreaId": 1,
21 | "Name": "TxService1",
22 | "Ip": "127.0.0.1",
23 | "Port": 2346,
24 | "MaxDone": 20,
25 | "MaxPend": 20,
26 | "MaxPacket": 65535,
27 | "MaxConn": 10,
28 | "RcvBuff": 8192,
29 | "SndBuff": 8192,
30 | "WriteTimeout": 30,
31 | "ReadTimeout": 30,
32 | "IsInnerLink": true,
33 | "NoDelay": true,
34 | "SupportFragment": true,
35 | "AuthKey": "1234567890",
36 | "FilterChain": ["session-filter-trace","session-filter-auth","session-filter-keepalive"],
37 | "HandlerChain": ["session-srv-registe"]
38 | },
39 | {
40 | "Id": 202,
41 | "Type": 2,
42 | "AreaId": 1,
43 | "Name": "TxService2",
44 | "Ip": "127.0.0.1",
45 | "Port": 2347,
46 | "MaxDone": 20,
47 | "MaxPend": 20,
48 | "MaxPacket": 65535,
49 | "MaxConn": 10,
50 | "RcvBuff": 8192,
51 | "SndBuff": 8192,
52 | "WriteTimeout": 30,
53 | "ReadTimeout": 30,
54 | "IsInnerLink": true,
55 | "IsClient": true,
56 | "IsAutoReconn": true,
57 | "NoDelay": true,
58 | "SupportFragment": true,
59 | "AuthKey": "1234567890",
60 | "FilterChain": ["session-filter-trace","session-filter-auth","session-filter-keepalive"],
61 | "HandlerChain": ["session-srv-registe"]
62 | }
63 | ]
64 | },
65 |
66 | "tx": {
67 | "TxSkeletonName": "github.com/idealeak/goserver/srvlib/txcommskeleton"
68 | },
69 |
70 | "core": {
71 | "MaxProcs": 4
72 | }
73 | }
--------------------------------------------------------------------------------
/examples/txserver1/dependent.go:
--------------------------------------------------------------------------------
1 | // dummy
2 | package main
3 |
4 | import (
5 | _ "github.com/idealeak/goserver/core/builtin/action"
6 | _ "github.com/idealeak/goserver/core/builtin/filter"
7 | _ "github.com/idealeak/goserver/srvlib"
8 | _ "github.com/idealeak/goserver/srvlib/handler"
9 | )
10 |
--------------------------------------------------------------------------------
/examples/txserver1/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/txserver1/main.go:
--------------------------------------------------------------------------------
1 | // main
2 | package main
3 |
4 | import (
5 | "github.com/idealeak/goserver/core"
6 | "github.com/idealeak/goserver/core/module"
7 | )
8 |
9 | func main() {
10 | defer core.ClosePackages()
11 | core.LoadPackages("config.json")
12 |
13 | waiter := module.Start()
14 | waiter.Wait("main")
15 | }
16 |
--------------------------------------------------------------------------------
/examples/txserver1/tx_trace.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/logger"
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/core/transact"
7 | "github.com/idealeak/goserver/examples/protocol"
8 | "github.com/idealeak/goserver/srvlib"
9 | )
10 |
11 | type traceTransHandler struct {
12 | }
13 |
14 | func init() {
15 | transact.RegisteHandler(protocol.TxTrace, &traceTransHandler{})
16 | srvlib.ServerSessionMgrSington.AddListener(&MyServerSessionRegisteListener{})
17 | }
18 |
19 | func (this *traceTransHandler) OnExcute(tNode *transact.TransNode, ud interface{}) transact.TransExeResult {
20 | logger.Logger.Trace("traceTransHandler.OnExcute ")
21 | userData := &protocol.StructA{}
22 | err := netlib.UnmarshalPacketNoPackId(ud.([]byte), userData)
23 | if err == nil {
24 | logger.Logger.Tracef("==========%#v", userData)
25 | }
26 | return transact.TransExeResult_Success
27 | }
28 |
29 | func (this *traceTransHandler) OnCommit(tNode *transact.TransNode) transact.TransExeResult {
30 | logger.Logger.Trace("traceTransHandler.OnCommit ")
31 | return transact.TransExeResult_Success
32 | }
33 |
34 | func (this *traceTransHandler) OnRollBack(tNode *transact.TransNode) transact.TransExeResult {
35 | logger.Logger.Trace("traceTransHandler.OnRollBack ")
36 | return transact.TransExeResult_Success
37 | }
38 |
39 | func (this *traceTransHandler) OnChildTransRep(tNode *transact.TransNode, hChild transact.TransNodeID, retCode int, ud interface{}) transact.TransExeResult {
40 | logger.Logger.Trace("traceTransHandler.OnChildTransRep ")
41 | return transact.TransExeResult_Success
42 | }
43 |
44 | type MyServerSessionRegisteListener struct {
45 | }
46 |
47 | func (mssrl *MyServerSessionRegisteListener) OnRegiste(*netlib.Session) {
48 | logger.Logger.Trace("MyServerSessionRegisteListener.OnRegiste")
49 | }
50 |
51 | func (mssrl *MyServerSessionRegisteListener) OnUnregiste(*netlib.Session) {
52 | logger.Logger.Trace("MyServerSessionRegisteListener.OnUnregiste")
53 | }
54 |
--------------------------------------------------------------------------------
/examples/txserver2/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":
4 | {
5 | "Name": "TxServer2",
6 | "Type": 2,
7 | "Id": 202,
8 | "AreaID": 1,
9 | "Banner": [
10 | "=================",
11 | "tx server 2",
12 | "================="
13 | ]
14 | },
15 |
16 | "IoServices": [
17 | {
18 | "Id": 202,
19 | "Type": 2,
20 | "AreaId": 1,
21 | "Name": "TxService2",
22 | "Ip": "127.0.0.1",
23 | "Port": 2347,
24 | "MaxDone": 20,
25 | "MaxPend": 20,
26 | "MaxPacket": 65535,
27 | "MaxConn": 10,
28 | "RcvBuff": 8192,
29 | "SndBuff": 8192,
30 | "WriteTimeout": 30,
31 | "ReadTimeout": 30,
32 | "IsInnerLink": true,
33 | "NoDelay": true,
34 | "SupportFragment": true,
35 | "AuthKey": "1234567890",
36 | "FilterChain": ["session-filter-trace","session-filter-auth","session-filter-keepalive"],
37 | "HandlerChain": ["session-srv-registe"]
38 | }
39 | ]
40 | },
41 |
42 | "tx": {
43 | "TxSkeletonName": "github.com/idealeak/goserver/srvlib/txcommskeleton"
44 | },
45 |
46 | "core": {
47 | "MaxProcs": 4
48 | }
49 | }
--------------------------------------------------------------------------------
/examples/txserver2/dependent.go:
--------------------------------------------------------------------------------
1 | // dummy
2 | package main
3 |
4 | import (
5 | _ "github.com/idealeak/goserver/core/builtin/action"
6 | _ "github.com/idealeak/goserver/core/builtin/filter"
7 | _ "github.com/idealeak/goserver/srvlib"
8 | _ "github.com/idealeak/goserver/srvlib/handler"
9 | )
10 |
--------------------------------------------------------------------------------
/examples/txserver2/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/txserver2/main.go:
--------------------------------------------------------------------------------
1 | // main
2 | package main
3 |
4 | import (
5 | "github.com/idealeak/goserver/core"
6 | "github.com/idealeak/goserver/core/module"
7 | )
8 |
9 | func main() {
10 | defer core.ClosePackages()
11 | core.LoadPackages("config.json")
12 |
13 | waiter := module.Start()
14 | waiter.Wait("main")
15 | }
16 |
--------------------------------------------------------------------------------
/mmo/accountsrv/doc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // Account server.
4 | // Responsibilities:
5 | // 1:Responsible for account verification, login, logout.
6 |
--------------------------------------------------------------------------------
/mmo/accountsrv/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/accountsrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/balancesrv/doc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // Load balancing server in traditional sense.
4 | // Responsibilities:
5 | // 1:according to the load on each gatesrv, select the current load a minimum.
6 |
--------------------------------------------------------------------------------
/mmo/balancesrv/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/balancesrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/build.bat:
--------------------------------------------------------------------------------
1 | cd accountsrv
2 | go build
3 | cd ../balancesrv
4 | go build
5 | cd ../gamesrv
6 | go build
7 | cd ../gatesrv
8 | go build
9 | cd ../mgrsrv
10 | go build
11 | cd ../worldsrv
12 | go build
13 | pause
--------------------------------------------------------------------------------
/mmo/clean.bat:
--------------------------------------------------------------------------------
1 | del /F/S accountsrv\accountsrv.exe
2 | del /F/S balancesrv\balancesrv.exe
3 | del /F/S gamesrv\gamesrv.exe
4 | del /F/S gatesrv\gatesrv.exe
5 | del /F/S mgrsrv\mgrsrv.exe
6 | del /F/S worldsrv\worldsrv.exe
--------------------------------------------------------------------------------
/mmo/client/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":{
4 | "Name": "Client",
5 | "Type": 1,
6 | "Id": 1,
7 | "AreaID": 1,
8 | "Banner": [
9 | "=================",
10 | "client",
11 | "================="
12 | ]
13 | },
14 |
15 | "IoServices": [
16 | {
17 | "Id": 101,
18 | "Type": 1,
19 | "AreaId": 1,
20 | "Name": "ClientService",
21 | "Ip": "127.0.0.1",
22 | "Port": 11001,
23 | "MaxDone": 20,
24 | "MaxPend": 20,
25 | "MaxPacket": 1024,
26 | "MaxConn": 1,
27 | "RcvBuff": 1024,
28 | "SndBuff": 1024,
29 | "WriteTimeout": 30,
30 | "ReadTimeout": 30,
31 | "SoLinger": 10,
32 | "IsInnerLink": false,
33 | "IsClient": true,
34 | "NoDelay": true,
35 | "SupportFragment": true,
36 | "AuthKey": "1234567890",
37 | "FilterChain": ["session-filter-trace","session-filter-auth"],
38 | "HandlerChain": []
39 | }
40 | ]
41 | },
42 |
43 | "module": {
44 | "Options": {
45 | "QueueBacklog": 1024,
46 | "MaxDone": 1024,
47 | "Interval": 100
48 | }
49 | },
50 |
51 | "executor": {
52 | "Options": {
53 | "QueueBacklog": 1024,
54 | "MaxDone": 1024,
55 | "Interval": 0
56 | },
57 | "Worker": {
58 | "WorkerCnt": 8,
59 | "Options": {
60 | "QueueBacklog": 1024,
61 | "MaxDone": 1024,
62 | "Interval": 0
63 | }
64 | }
65 | },
66 |
67 | "timer": {
68 | "Options": {
69 | "QueueBacklog": 1024,
70 | "MaxDone": 1024,
71 | "Interval": 100
72 | }
73 | },
74 |
75 | "core": {
76 | "MaxProcs": 4
77 | },
78 |
79 | "cmdline": {
80 | "SupportCmdLine": true
81 | }
82 | }
--------------------------------------------------------------------------------
/mmo/client/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/client/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/client/packet_scgateinfo.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/logger"
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/mmo/protocol"
7 | )
8 |
9 | func init() {
10 | netlib.RegisterFactory(int(protocol.MmoPacketID_PACKET_SC_GATEINFO), netlib.PacketFactoryWrapper(func() interface{} {
11 | return &protocol.SCGateInfo{}
12 | }))
13 | netlib.RegisterHandler(int(protocol.MmoPacketID_PACKET_SC_GATEINFO), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
14 | logger.Logger.Trace("receive gateinfo==", pack)
15 | if sr, ok := pack.(*protocol.SCGateInfo); ok {
16 | sc := &netlib.SessionConfig{
17 | Id: int(sr.GetSrvId()),
18 | Type: int(sr.GetSrvType()),
19 | Ip: sr.GetIp(),
20 | Port: int(sr.GetPort()),
21 | AuthKey: sr.GetAuthKey(),
22 | WriteTimeout: 30,
23 | ReadTimeout: 30,
24 | IdleTimeout: 30,
25 | MaxDone: 20,
26 | MaxPend: 20,
27 | MaxPacket: 1024,
28 | RcvBuff: 1024,
29 | SndBuff: 1024,
30 | IsClient: true,
31 | NoDelay: true,
32 | FilterChain: []string{"session-filter-trace", "session-filter-auth"},
33 | }
34 | sc.Init()
35 | err := netlib.Connect(sc)
36 | if err != nil {
37 | logger.Logger.Warn("connect server failed err:", err)
38 | }
39 | }
40 | return nil
41 | }))
42 | }
43 |
--------------------------------------------------------------------------------
/mmo/close.bat:
--------------------------------------------------------------------------------
1 | TASKKILL /F /IM accountsrv.exe
2 | TASKKILL /F /IM balancesrv.exe
3 | TASKKILL /F /IM gamesrv.exe
4 | TASKKILL /F /IM gatesrv.exe
5 | TASKKILL /F /IM mgrsrv.exe
6 | TASKKILL /F /IM worldsrv.exe
--------------------------------------------------------------------------------
/mmo/clrlogs.bat:
--------------------------------------------------------------------------------
1 | del /F/S accountsrv\all.log
2 | del /F/S balancesrv\all.log
3 | del /F/S gamesrv\all.log
4 | del /F/S gatesrv\all.log
5 | del /F/S mgrsrv\all.log
6 | del /F/S worldsrv\all.log
--------------------------------------------------------------------------------
/mmo/gamesrv/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":{
4 | "Name": "GameServer",
5 | "Type": 7,
6 | "Id": 701,
7 | "AreaID": 1,
8 | "Banner": [
9 | "=================",
10 | "game server",
11 | "================="
12 | ]
13 | },
14 |
15 | "IoServices": [
16 | {
17 | "Id": 701,
18 | "Type": 7,
19 | "AreaId": 1,
20 | "Name": "GameService",
21 | "Ip": "127.0.0.1",
22 | "Port": 7001,
23 | "MaxDone": 20,
24 | "MaxPend": 20,
25 | "MaxPacket": 65535,
26 | "MaxConn": 10000,
27 | "RcvBuff": 8192,
28 | "SndBuff": 8192,
29 | "WriteTimeout": 30,
30 | "ReadTimeout": 30,
31 | "IsInnerLink": true,
32 | "NoDelay": true,
33 | "SupportFragment": true,
34 | "AuthKey": "1234567890",
35 | "FilterChain": ["session-filter-auth","session-filter-keepalive"],
36 | "HandlerChain": ["session-srv-registe"]
37 | },
38 | {
39 | "Id": 501,
40 | "Type": 5,
41 | "AreaId": 1,
42 | "Name": "ManagerService",
43 | "Ip": "127.0.0.1",
44 | "Port": 5555,
45 | "MaxDone": 20,
46 | "MaxPend": 20,
47 | "MaxPacket": 65535,
48 | "MaxConn": 10000,
49 | "RcvBuff": 8192,
50 | "SndBuff": 8192,
51 | "WriteTimeout": 30,
52 | "ReadTimeout": 30,
53 | "IsInnerLink": true,
54 | "NoDelay": true,
55 | "IsClient": true,
56 | "SupportFragment": true,
57 | "AuthKey": "1234567890",
58 | "FilterChain": ["session-filter-auth","session-filter-keepalive"],
59 | "HandlerChain": ["session-srv-registe","srv-service-handler"]
60 | }
61 | ]
62 | },
63 |
64 | "module": {
65 | "Options": {
66 | "QueueBacklog": 1024,
67 | "MaxDone": 1024,
68 | "Interval": 100
69 | }
70 | },
71 |
72 | "executor": {
73 | "Options": {
74 | "QueueBacklog": 1024,
75 | "MaxDone": 1024,
76 | "Interval": 0
77 | },
78 | "Worker": {
79 | "WorkerCnt": 8,
80 | "Options": {
81 | "QueueBacklog": 1024,
82 | "MaxDone": 1024,
83 | "Interval": 0
84 | }
85 | }
86 | },
87 |
88 | "timer": {
89 | "Options": {
90 | "QueueBacklog": 1024,
91 | "MaxDone": 1024,
92 | "Interval": 100
93 | }
94 | },
95 |
96 | "core": {
97 | "MaxProcs": 4
98 | },
99 |
100 | "cmdline": {
101 | "SupportCmdLine": true
102 | }
103 | }
--------------------------------------------------------------------------------
/mmo/gamesrv/doc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // Game logic server.
4 | // Responsibilities:
5 | // 1:The logic is mainly responsible for the game.
6 |
--------------------------------------------------------------------------------
/mmo/gamesrv/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/gamesrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/gatesrv/broadcasthandler.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "code.google.com/p/goprotobuf/proto"
5 | "github.com/idealeak/goserver/core/logger"
6 | "github.com/idealeak/goserver/core/netlib"
7 | "github.com/idealeak/goserver/srvlib"
8 | "github.com/idealeak/goserver/srvlib/protocol"
9 | )
10 |
11 | var (
12 | BroadcastMaker = &BroadcastPacketFactory{}
13 | )
14 |
15 | type BroadcastPacketFactory struct {
16 | }
17 |
18 | type BroadcastHandler struct {
19 | }
20 |
21 | func init() {
22 | netlib.RegisterHandler(int(protocol.SrvlibPacketID_PACKET_SS_BROADCAST), &BroadcastHandler{})
23 | netlib.RegisterFactory(int(protocol.SrvlibPacketID_PACKET_SS_BROADCAST), BroadcastMaker)
24 | }
25 |
26 | func (this *BroadcastPacketFactory) CreatePacket() interface{} {
27 | pack := &protocol.SSPacketBroadcast{}
28 | return pack
29 | }
30 |
31 | func (this *BroadcastPacketFactory) CreateBroadcastPacket(sp *protocol.BCSessionUnion, packetid int, data interface{}) (proto.Message, error) {
32 | pack := &protocol.SSPacketBroadcast{
33 | SessParam: sp,
34 | PacketId: proto.Int(packetid),
35 | }
36 | if byteData, ok := data.([]byte); ok {
37 | pack.Data = byteData
38 | } else {
39 | byteData, err := netlib.MarshalPacket(packetid, data)
40 | if err == nil {
41 | pack.Data = byteData
42 | } else {
43 | logger.Logger.Warn("BroadcastPacketFactory.CreateBroadcastPacket err:", err)
44 | return nil, err
45 | }
46 | }
47 | proto.SetDefaults(pack)
48 | return pack, nil
49 | }
50 |
51 | func (this *BroadcastHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
52 | if bp, ok := data.(*protocol.SSPacketBroadcast); ok {
53 | pd := bp.GetData()
54 | sp := bp.GetSessParam()
55 | if bcss := sp.GetBcss(); bcss != nil {
56 | srvlib.ServerSessionMgrSington.Broadcast(int(bp.GetPacketId()), pd, int(bcss.GetSArea()), int(bcss.GetSType()))
57 | } else {
58 | BundleMgrSington.Broadcast(int(bp.GetPacketId()), pd)
59 | }
60 | }
61 | return nil
62 | }
63 |
--------------------------------------------------------------------------------
/mmo/gatesrv/clientsessionload.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "code.google.com/p/goprotobuf/proto"
5 | "github.com/idealeak/goserver/core/logger"
6 | "github.com/idealeak/goserver/core/netlib"
7 | "github.com/idealeak/goserver/mmo/protocol"
8 | "github.com/idealeak/goserver/srvlib"
9 | )
10 |
11 | var (
12 | SessionHandlerClientLoadName = "handler-client-load"
13 | )
14 |
15 | type SessionHandlerClientLoad struct {
16 | netlib.BasicSessionHandler
17 | }
18 |
19 | func (sfcl SessionHandlerClientLoad) GetName() string {
20 | return SessionHandlerClientLoadName
21 | }
22 |
23 | func (sfcl *SessionHandlerClientLoad) GetInterestOps() uint {
24 | return 1<
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/gatesrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/gatesrv/multicasthandler.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "code.google.com/p/goprotobuf/proto"
5 | "github.com/idealeak/goserver/core/logger"
6 | "github.com/idealeak/goserver/core/netlib"
7 | "github.com/idealeak/goserver/srvlib"
8 | "github.com/idealeak/goserver/srvlib/protocol"
9 | )
10 |
11 | var (
12 | MulticastMaker = &MulticastPacketFactory{}
13 | )
14 |
15 | type MulticastPacketFactory struct {
16 | }
17 |
18 | type MulticastHandler struct {
19 | }
20 |
21 | func init() {
22 | netlib.RegisterHandler(int(protocol.SrvlibPacketID_PACKET_SS_MULTICAST), &MulticastHandler{})
23 | netlib.RegisterFactory(int(protocol.SrvlibPacketID_PACKET_SS_MULTICAST), MulticastMaker)
24 | }
25 |
26 | func (this *MulticastPacketFactory) CreatePacket() interface{} {
27 | pack := &protocol.SSPacketMulticast{}
28 | return pack
29 | }
30 |
31 | func (this *MulticastPacketFactory) CreateMulticastPacket(packetid int, data interface{}, sis ...*protocol.MCSessionUnion) (proto.Message, error) {
32 | pack := &protocol.SSPacketMulticast{
33 | Sessions: sis,
34 | PacketId: proto.Int(packetid),
35 | }
36 | if byteData, ok := data.([]byte); ok {
37 | pack.Data = byteData
38 | } else {
39 | byteData, err := netlib.MarshalPacket(packetid, data)
40 | if err == nil {
41 | pack.Data = byteData
42 | } else {
43 | logger.Logger.Info("MulticastPacketFactory.CreateMulticastPacket err:", err)
44 | return nil, err
45 | }
46 | }
47 | proto.SetDefaults(pack)
48 | return pack, nil
49 | }
50 |
51 | func (this *MulticastHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
52 | if mp, ok := data.(*protocol.SSPacketMulticast); ok {
53 | pd := mp.GetData()
54 | sis := mp.GetSessions()
55 | for _, si := range sis {
56 | cs := si.GetMccs()
57 | if cs != nil {
58 | sid := srvlib.SessionId(cs.GetSId())
59 | bundleId := sid.SeqId()
60 | bs := BundleMgrSington.GetBundleSession(uint16(bundleId))
61 | if bs != nil {
62 | bs.Send(int(mp.GetPacketId()), pd)
63 | }
64 | } else {
65 | ss := si.GetMcss()
66 | if ss != nil {
67 | ns := srvlib.ServerSessionMgrSington.GetSession(int(ss.GetSArea()), int(ss.GetSType()), int(ss.GetSId()))
68 | if ns != nil {
69 | ns.Send(int(mp.GetPacketId()), pd /*, s.GetSessionConfig().IsInnerLink*/)
70 | }
71 | }
72 | }
73 | }
74 | }
75 | return nil
76 | }
77 |
--------------------------------------------------------------------------------
/mmo/gatesrv/packetdispatchhandler.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "sync/atomic"
6 |
7 | "code.google.com/p/goprotobuf/proto"
8 | "games.jiexunjiayin.com/jxjyqp/protocol"
9 | "github.com/idealeak/goserver/core/builtin/filter"
10 | "github.com/idealeak/goserver/core/logger"
11 | "github.com/idealeak/goserver/core/netlib"
12 | )
13 |
14 | func init() {
15 | netlib.RegisteErrorPacketHandlerCreator("packetdispatchhandler", func() netlib.ErrorPacketHandler {
16 | return netlib.ErrorPacketHandlerWrapper(func(s *netlib.Session, packetid int, logicNo uint32, data []byte) bool {
17 | if s.GetAttribute(filter.SessionAttributeAuth) == nil {
18 | logger.Logger.Trace("packetdispatchhandler session not auth! ")
19 | return false
20 | }
21 |
22 | bs := BundleMgrSington.GetBundleSession(uint16(s.GroupId))
23 | if bs == nil {
24 | logger.Logger.Trace("packetdispatchhandler BundleSession is nil! ")
25 | return false
26 | }
27 |
28 | if atomic.CompareAndSwapUint32(&bs.rcvLogicNo, logicNo-1, logicNo) {
29 | var ss *netlib.Session
30 | if packetid >= 2000 && packetid < 3000 {
31 | ss = bs.worldsrvSession
32 | } else {
33 | ss = bs.gamesrvSession
34 | }
35 | if ss == nil {
36 | logger.Logger.Trace("packetdispatchhandler redirect server session is nil ", packetid)
37 | return true
38 | }
39 | //must copy
40 | buf := bytes.NewBuffer(nil)
41 | buf.Write(data)
42 | pack := &protocol.SSTransmit{
43 | SessionId: proto.Int64(s.Sid),
44 | PacketData: buf.Bytes(),
45 | }
46 | proto.SetDefaults(pack)
47 | ss.Send(int(protocol.MmoPacketID_PACKET_SS_PACKET_TRANSMIT), pack)
48 | return true
49 | }
50 |
51 | //丢掉
52 | return false
53 | })
54 | })
55 | }
56 |
--------------------------------------------------------------------------------
/mmo/gen_go.bat:
--------------------------------------------------------------------------------
1 | protoc --go_out=. protocol/*.proto
2 | pause
--------------------------------------------------------------------------------
/mmo/imports.go:
--------------------------------------------------------------------------------
1 | package mmo
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/core/builtin/action"
5 | _ "github.com/idealeak/goserver/core/builtin/filter"
6 | _ "github.com/idealeak/goserver/core/cmdline"
7 | _ "github.com/idealeak/goserver/core/netlib"
8 | _ "github.com/idealeak/goserver/core/signal"
9 | _ "github.com/idealeak/goserver/srvlib/action"
10 | _ "github.com/idealeak/goserver/srvlib/handler"
11 | )
12 |
--------------------------------------------------------------------------------
/mmo/mgrsrv/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "netlib": {
3 | "SrvInfo":{
4 | "Name": "ManagerServer",
5 | "Type": 5,
6 | "Id": 501,
7 | "AreaID": 1,
8 | "Banner": [
9 | "=================",
10 | "manager server",
11 | "================="
12 | ]
13 | },
14 |
15 | "IoServices": [
16 | {
17 | "Id": 501,
18 | "Type": 5,
19 | "AreaId": 1,
20 | "Name": "ManagerService",
21 | "Ip": "",
22 | "Port": 5555,
23 | "MaxDone": 20,
24 | "MaxPend": 20,
25 | "MaxPacket": 65535,
26 | "MaxConn": 10000,
27 | "RcvBuff": 8192,
28 | "SndBuff": 8192,
29 | "WriteTimeout": 30,
30 | "ReadTimeout": 30,
31 | "IsInnerLink": true,
32 | "NoDelay": true,
33 | "SupportFragment": true,
34 | "AuthKey": "1234567890",
35 | "FilterChain": ["session-filter-auth","session-filter-keepalive"],
36 | "HandlerChain": ["session-srv-registe","srv-service-handler"]
37 | }
38 | ]
39 | },
40 |
41 | "module": {
42 | "Options": {
43 | "QueueBacklog": 1024,
44 | "MaxDone": 1024,
45 | "Interval": 100
46 | }
47 | },
48 |
49 | "executor": {
50 | "Options": {
51 | "QueueBacklog": 1024,
52 | "MaxDone": 1024,
53 | "Interval": 0
54 | },
55 | "Worker": {
56 | "WorkerCnt": 8,
57 | "Options": {
58 | "QueueBacklog": 1024,
59 | "MaxDone": 1024,
60 | "Interval": 0
61 | }
62 | }
63 | },
64 |
65 | "timer": {
66 | "Options": {
67 | "QueueBacklog": 1024,
68 | "MaxDone": 1024,
69 | "Interval": 100
70 | }
71 | },
72 |
73 | "core": {
74 | "MaxProcs": 4
75 | },
76 |
77 | "cmdline": {
78 | "SupportCmdLine": true
79 | }
80 | }
--------------------------------------------------------------------------------
/mmo/mgrsrv/doc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // Responsibilities:
4 | // 1:responsible for managing the relationship between the server group.
5 | // 2:message forwarding.
6 |
--------------------------------------------------------------------------------
/mmo/mgrsrv/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/mgrsrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/mmo/protocol/gateinfo.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/gateinfo.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type SCGateInfo struct {
17 | SrvType *int32 `protobuf:"varint,1,opt" json:"SrvType,omitempty"`
18 | SrvId *int32 `protobuf:"varint,2,opt" json:"SrvId,omitempty"`
19 | AuthKey *string `protobuf:"bytes,3,opt" json:"AuthKey,omitempty"`
20 | Ip *string `protobuf:"bytes,4,opt" json:"Ip,omitempty"`
21 | Port *int32 `protobuf:"varint,5,opt" json:"Port,omitempty"`
22 | XXX_unrecognized []byte `json:"-"`
23 | }
24 |
25 | func (m *SCGateInfo) Reset() { *m = SCGateInfo{} }
26 | func (m *SCGateInfo) String() string { return proto.CompactTextString(m) }
27 | func (*SCGateInfo) ProtoMessage() {}
28 |
29 | func (m *SCGateInfo) GetSrvType() int32 {
30 | if m != nil && m.SrvType != nil {
31 | return *m.SrvType
32 | }
33 | return 0
34 | }
35 |
36 | func (m *SCGateInfo) GetSrvId() int32 {
37 | if m != nil && m.SrvId != nil {
38 | return *m.SrvId
39 | }
40 | return 0
41 | }
42 |
43 | func (m *SCGateInfo) GetAuthKey() string {
44 | if m != nil && m.AuthKey != nil {
45 | return *m.AuthKey
46 | }
47 | return ""
48 | }
49 |
50 | func (m *SCGateInfo) GetIp() string {
51 | if m != nil && m.Ip != nil {
52 | return *m.Ip
53 | }
54 | return ""
55 | }
56 |
57 | func (m *SCGateInfo) GetPort() int32 {
58 | if m != nil && m.Port != nil {
59 | return *m.Port
60 | }
61 | return 0
62 | }
63 |
64 | func init() {
65 | }
66 |
--------------------------------------------------------------------------------
/mmo/protocol/gateinfo.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 |
4 | message SCGateInfo {
5 | optional int32 SrvType = 1;
6 | optional int32 SrvId = 2;
7 | optional string AuthKey = 3;
8 | optional string Ip = 4;
9 | optional int32 Port = 5;
10 | }
11 |
12 | message CSSessionBundle {
13 | required string Key = 1;
14 | required int64 Ts = 2;
15 | }
16 |
17 | message CSSessionAck {
18 | required uint32 LogicNo = 1;
19 | }
--------------------------------------------------------------------------------
/mmo/protocol/packetid.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/packetid.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type MmoPacketID int32
17 |
18 | const (
19 | MmoPacketID_PACKET_GB_CUR_LOAD MmoPacketID = 1000
20 | MmoPacketID_PACKET_GB_STATE_SWITCH MmoPacketID = 1001
21 | MmoPacketID_PACKET_SC_GATEINFO MmoPacketID = 1002
22 | )
23 |
24 | var MmoPacketID_name = map[int32]string{
25 | 1000: "PACKET_GB_CUR_LOAD",
26 | 1001: "PACKET_GB_STATE_SWITCH",
27 | 1002: "PACKET_SC_GATEINFO",
28 | }
29 | var MmoPacketID_value = map[string]int32{
30 | "PACKET_GB_CUR_LOAD": 1000,
31 | "PACKET_GB_STATE_SWITCH": 1001,
32 | "PACKET_SC_GATEINFO": 1002,
33 | }
34 |
35 | func (x MmoPacketID) Enum() *MmoPacketID {
36 | p := new(MmoPacketID)
37 | *p = x
38 | return p
39 | }
40 | func (x MmoPacketID) String() string {
41 | return proto.EnumName(MmoPacketID_name, int32(x))
42 | }
43 | func (x MmoPacketID) MarshalJSON() ([]byte, error) {
44 | return json.Marshal(x.String())
45 | }
46 | func (x *MmoPacketID) UnmarshalJSON(data []byte) error {
47 | value, err := proto.UnmarshalJSONEnum(MmoPacketID_value, data, "MmoPacketID")
48 | if err != nil {
49 | return err
50 | }
51 | *x = MmoPacketID(value)
52 | return nil
53 | }
54 |
55 | func init() {
56 | proto.RegisterEnum("protocol.MmoPacketID", MmoPacketID_name, MmoPacketID_value)
57 | }
58 |
--------------------------------------------------------------------------------
/mmo/protocol/packetid.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | enum MmoPacketID {
4 | PACKET_GB_CUR_LOAD = 1000;
5 | PACKET_GB_STATE_SWITCH = 1001;
6 | PACKET_SC_GATEINFO = 1002;
7 | PACKET_CS_SESSIONBUNDLE = 1003;
8 | PACKET_CS_SESSIONACK = 1004;
9 | }
--------------------------------------------------------------------------------
/mmo/protocol/serverload.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: protocol/serverload.proto
3 | // DO NOT EDIT!
4 |
5 | package protocol
6 |
7 | import proto "code.google.com/p/goprotobuf/proto"
8 | import json "encoding/json"
9 | import math "math"
10 |
11 | // Reference proto, json, and math imports to suppress error if they are not otherwise used.
12 | var _ = proto.Marshal
13 | var _ = &json.SyntaxError{}
14 | var _ = math.Inf
15 |
16 | type ServerLoad struct {
17 | SrvType *int32 `protobuf:"varint,1,req" json:"SrvType,omitempty"`
18 | SrvId *int32 `protobuf:"varint,2,req" json:"SrvId,omitempty"`
19 | CurLoad *int32 `protobuf:"varint,3,req" json:"CurLoad,omitempty"`
20 | XXX_unrecognized []byte `json:"-"`
21 | }
22 |
23 | func (m *ServerLoad) Reset() { *m = ServerLoad{} }
24 | func (m *ServerLoad) String() string { return proto.CompactTextString(m) }
25 | func (*ServerLoad) ProtoMessage() {}
26 |
27 | func (m *ServerLoad) GetSrvType() int32 {
28 | if m != nil && m.SrvType != nil {
29 | return *m.SrvType
30 | }
31 | return 0
32 | }
33 |
34 | func (m *ServerLoad) GetSrvId() int32 {
35 | if m != nil && m.SrvId != nil {
36 | return *m.SrvId
37 | }
38 | return 0
39 | }
40 |
41 | func (m *ServerLoad) GetCurLoad() int32 {
42 | if m != nil && m.CurLoad != nil {
43 | return *m.CurLoad
44 | }
45 | return 0
46 | }
47 |
48 | type ServerStateSwitch struct {
49 | SrvType *int32 `protobuf:"varint,1,req" json:"SrvType,omitempty"`
50 | SrvId *int32 `protobuf:"varint,2,req" json:"SrvId,omitempty"`
51 | XXX_unrecognized []byte `json:"-"`
52 | }
53 |
54 | func (m *ServerStateSwitch) Reset() { *m = ServerStateSwitch{} }
55 | func (m *ServerStateSwitch) String() string { return proto.CompactTextString(m) }
56 | func (*ServerStateSwitch) ProtoMessage() {}
57 |
58 | func (m *ServerStateSwitch) GetSrvType() int32 {
59 | if m != nil && m.SrvType != nil {
60 | return *m.SrvType
61 | }
62 | return 0
63 | }
64 |
65 | func (m *ServerStateSwitch) GetSrvId() int32 {
66 | if m != nil && m.SrvId != nil {
67 | return *m.SrvId
68 | }
69 | return 0
70 | }
71 |
72 | func init() {
73 | }
74 |
--------------------------------------------------------------------------------
/mmo/protocol/serverload.proto:
--------------------------------------------------------------------------------
1 | package protocol;
2 |
3 | message ServerLoad {
4 | required int32 SrvType = 1;
5 | required int32 SrvId = 2;
6 | required int32 CurLoad = 3;
7 | }
8 |
9 | message ServerStateSwitch {
10 | required int32 SrvType = 1;
11 | required int32 SrvId = 2;
12 | }
--------------------------------------------------------------------------------
/mmo/startup.bat:
--------------------------------------------------------------------------------
1 | cd accountsrv
2 | start accountsrv
3 | cd ../balancesrv
4 | start balancesrv
5 | cd ../gamesrv
6 | start gamesrv
7 | cd ../gatesrv
8 | start gatesrv
9 | cd ../mgrsrv
10 | start mgrsrv
11 | cd ../worldsrv
12 | start worldsrv
--------------------------------------------------------------------------------
/mmo/worldsrv/doc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // Game world server(The whole world only).
4 | // Responsibilities:
5 | // 1:Responsible for the overall business in the game.
6 | // For example: social relations
7 |
--------------------------------------------------------------------------------
/mmo/worldsrv/logger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/mmo/worldsrv/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "github.com/idealeak/goserver/mmo"
5 |
6 | "github.com/idealeak/goserver/core"
7 | "github.com/idealeak/goserver/core/module"
8 | )
9 |
10 | func main() {
11 | defer core.ClosePackages()
12 | core.LoadPackages("config.json")
13 |
14 | waiter := module.Start()
15 | waiter.Wait("main")
16 | }
17 |
--------------------------------------------------------------------------------
/srvlib/action/redirecthandler.go:
--------------------------------------------------------------------------------
1 | package action
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/logger"
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/srvlib"
7 | "github.com/idealeak/goserver/srvlib/protocol"
8 | )
9 |
10 | type PacketRedirectPacketFactory struct {
11 | }
12 |
13 | type PacketRedirectHandler struct {
14 | }
15 |
16 | func init() {
17 | netlib.RegisterHandler(int(protocol.SrvlibPacketID_PACKET_SS_REDIRECT), &PacketRedirectHandler{})
18 | netlib.RegisterFactory(int(protocol.SrvlibPacketID_PACKET_SS_REDIRECT), &PacketRedirectPacketFactory{})
19 | }
20 |
21 | func (this *PacketRedirectPacketFactory) CreatePacket() interface{} {
22 | pack := &protocol.SSPacketRedirect{}
23 | return pack
24 | }
25 |
26 | func (this *PacketRedirectHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
27 | logger.Logger.Trace("PacketRedirectHandler.Process")
28 | if pr, ok := data.(*protocol.SSPacketRedirect); ok {
29 | packid, pack, err := netlib.UnmarshalPacket(pr.GetData())
30 | if err != nil {
31 | return err
32 | }
33 | h := srvlib.GetHandler(packid)
34 | if h != nil {
35 | return h.Process(s, packid, pack, pr.GetClientSid(), pr.GetSrvRoutes())
36 | } else {
37 | nh := netlib.GetHandler(packid)
38 | if nh != nil {
39 | return nh.Process(s, packid, pack)
40 | }
41 | }
42 | }
43 | return nil
44 | }
45 |
--------------------------------------------------------------------------------
/srvlib/action/transithandler.go:
--------------------------------------------------------------------------------
1 | package action
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/logger"
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/srvlib"
7 | "github.com/idealeak/goserver/srvlib/protocol"
8 | )
9 |
10 | type PacketTransitPacketFactory struct {
11 | }
12 |
13 | type PacketTransitHandler struct {
14 | }
15 |
16 | func init() {
17 | netlib.RegisterHandler(int(protocol.SrvlibPacketID_PACKET_SS_TRANSIT), &PacketTransitHandler{})
18 | netlib.RegisterFactory(int(protocol.SrvlibPacketID_PACKET_SS_TRANSIT), &PacketTransitPacketFactory{})
19 | }
20 |
21 | func (this *PacketTransitPacketFactory) CreatePacket() interface{} {
22 | pack := &protocol.SSPacketTransit{}
23 | return pack
24 | }
25 |
26 | func (this *PacketTransitHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
27 | logger.Logger.Trace("PacketTransitHandler.Process")
28 | if pr, ok := data.(*protocol.SSPacketTransit); ok {
29 | targetS := srvlib.ServerSessionMgrSington.GetSession(int(pr.GetSArea()), int(pr.GetSType()), int(pr.GetSId()))
30 | if targetS != nil {
31 | targetS.Send(int(pr.GetPacketId()), pr.GetData())
32 | }
33 | }
34 | return nil
35 | }
36 |
--------------------------------------------------------------------------------
/srvlib/clientsessionmgr.go:
--------------------------------------------------------------------------------
1 | package srvlib
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/logger"
5 | "github.com/idealeak/goserver/core/netlib"
6 | )
7 |
8 | var (
9 | SessionAttributeClientSession = &ClientSessionMgr{}
10 | ClientSessionMgrSington = &ClientSessionMgr{sessions: make(map[int64]*netlib.Session)}
11 | )
12 |
13 | type ClientSessionMgr struct {
14 | sessions map[int64]*netlib.Session //keys=>sessionid
15 | }
16 |
17 | func (csm *ClientSessionMgr) RegisteSession(s *netlib.Session) bool {
18 | attr := s.GetAttribute(SessionAttributeClientSession)
19 | if attr == nil {
20 | sid := NewSessionId(s)
21 | s.SetAttribute(SessionAttributeClientSession, sid)
22 | csm.sessions[sid.Get()] = s
23 | logger.Logger.Tracef("ClientSessionMgr(%p).RegisteSession client session %v registe", csm, sid.Get())
24 | }
25 | return true
26 | }
27 |
28 | func (csm *ClientSessionMgr) UnregisteSession(s *netlib.Session) bool {
29 | attr := s.GetAttribute(SessionAttributeClientSession)
30 | if attr != nil {
31 | if sid, ok := attr.(SessionId); ok {
32 | delete(csm.sessions, sid.Get())
33 | logger.Logger.Tracef("ClientSessionMgr(%p).UnregisteSession client session %v unregiste", csm, sid.Get())
34 | }
35 | }
36 | return true
37 | }
38 |
39 | func (csm *ClientSessionMgr) GetSession(srvId int64) *netlib.Session {
40 | if s, exist := csm.sessions[srvId]; exist {
41 | return s
42 | }
43 | return nil
44 | }
45 |
46 | func (csm *ClientSessionMgr) GetSessions() map[int64]*netlib.Session {
47 | return csm.sessions
48 | }
49 |
50 | func (csm *ClientSessionMgr) Broadcast(packetid int, pack interface{}) {
51 | for _, s := range csm.sessions {
52 | s.Send(packetid, pack)
53 | }
54 | }
55 |
56 | func (csm *ClientSessionMgr) Count() int {
57 | return len(csm.sessions)
58 | }
59 |
60 | func (csm *ClientSessionMgr) CloseAll() {
61 | logger.Logger.Tracef("ClientSessionMgr(%p).CloseAll!!!!!!!!!!!! session's cnt=%v", csm, len(csm.sessions))
62 | for _, s := range csm.sessions {
63 | s.Close()
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/srvlib/const.go:
--------------------------------------------------------------------------------
1 | package srvlib
2 |
3 | const (
4 | UnknowServiceType int = 0
5 | ClientServiceType = 1
6 | BalanceServiceType = 2
7 | AccountServiceType = 3
8 | GateServiceType = 4
9 | ManagerServiceType = 5
10 | WorldServiceType = 6
11 | GameServiceType = 7
12 | MaxServiceType = 8
13 | )
14 |
15 | const (
16 | UnknowServerType int = 0
17 | _
18 | BalanceServerType = 2
19 | AccountServerType = 3
20 | GateServerType = 4
21 | ManagerServerType = 5
22 | WorldServerType = 6
23 | GameServerType = 7
24 | MaxServerType = 8
25 | )
26 |
--------------------------------------------------------------------------------
/srvlib/gen_go.bat:
--------------------------------------------------------------------------------
1 | protoc --go_out=. protocol/*.proto
2 | pause
--------------------------------------------------------------------------------
/srvlib/handler.go:
--------------------------------------------------------------------------------
1 | package srvlib
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 |
7 | "github.com/idealeak/goserver/core/netlib"
8 | "github.com/idealeak/goserver/srvlib/protocol"
9 | )
10 |
11 | var handlers = make(map[int]Handler)
12 |
13 | type Handler interface {
14 | Process(s *netlib.Session, packetid int, data interface{}, sid int64, routes []*protocol.SrvInfo) error
15 | }
16 |
17 | type HandlerWrapper func(s *netlib.Session, packetid int, data interface{}, sid int64, routes []*protocol.SrvInfo) error
18 |
19 | func (hw HandlerWrapper) Process(s *netlib.Session, packetid int, data interface{}, sid int64, routes []*protocol.SrvInfo) error {
20 | return hw(s, packetid, data, sid, routes)
21 | }
22 |
23 | func RegisterHandler(packetId int, h Handler) {
24 | if _, ok := handlers[packetId]; ok {
25 | panic(fmt.Sprintf("repeate register handler: %v Handler type=%v", packetId, reflect.TypeOf(h)))
26 | }
27 |
28 | handlers[packetId] = h
29 | }
30 |
31 | func Register1ToMHandler(h Handler, packetIds ...int) {
32 | for _, packetId := range packetIds {
33 | RegisterHandler(packetId, h)
34 | }
35 | }
36 |
37 | func RegisterRangeHandler(start, end int, h Handler) {
38 | for ; start <= end; start++ {
39 | RegisterHandler(start, h)
40 | }
41 | }
42 |
43 | func GetHandler(packetId int) Handler {
44 | if h, ok := handlers[packetId]; ok {
45 | return h
46 | }
47 |
48 | return nil
49 | }
50 |
--------------------------------------------------------------------------------
/srvlib/handler/clientsessionregiste.go:
--------------------------------------------------------------------------------
1 | // SessionHandlerClientRegiste
2 | package handler
3 |
4 | import (
5 | "github.com/idealeak/goserver/core/netlib"
6 | "github.com/idealeak/goserver/srvlib"
7 | )
8 |
9 | var (
10 | SessionHandlerClientRegisteName = "session-client-registe"
11 | )
12 |
13 | type SessionHandlerClientRegiste struct {
14 | }
15 |
16 | func (sfcr SessionHandlerClientRegiste) GetName() string {
17 | return SessionHandlerClientRegisteName
18 | }
19 |
20 | func (sfl *SessionHandlerClientRegiste) GetInterestOps() uint {
21 | return 1<", sc.Name)
30 | /*报告自己的监听信息*/
31 | srvlib.ServiceMgr.ReportService(s)
32 | } else {
33 | s.SetAttribute(srvlib.SessionAttributeServiceFlag, 1)
34 | }
35 | }
36 |
37 | func (this *SessionHandlerServiceRegiste) OnSessionClosed(s *netlib.Session) {
38 | sc := s.GetSessionConfig()
39 | if !sc.IsClient {
40 | logger.Logger.Warn("SessionHandlerServiceRegiste:OnSessionClosed ClearServiceBySession")
41 | srvlib.ServiceMgr.ClearServiceBySession(s)
42 | }
43 | }
44 |
45 | func (this *SessionHandlerServiceRegiste) OnSessionIdle(s *netlib.Session) {
46 | }
47 |
48 | func (this *SessionHandlerServiceRegiste) OnPacketReceived(s *netlib.Session, packetid int, logicNo uint32, packet interface{}) {
49 | }
50 |
51 | func (this *SessionHandlerServiceRegiste) OnPacketSent(s *netlib.Session, packetid int, logicNo uint32, data []byte) {
52 | }
53 |
54 | func init() {
55 | netlib.RegisteSessionHandlerCreator(ServiceHandlerServiceRegisteName, func() netlib.SessionHandler {
56 | return &SessionHandlerServiceRegiste{}
57 | })
58 | }
59 |
--------------------------------------------------------------------------------
/srvlib/handler/serversessionregiste.go:
--------------------------------------------------------------------------------
1 | // SessionHandlerSrvRegiste
2 | package handler
3 |
4 | import (
5 | "code.google.com/p/goprotobuf/proto"
6 | "github.com/idealeak/goserver/core/netlib"
7 | "github.com/idealeak/goserver/srvlib"
8 | "github.com/idealeak/goserver/srvlib/protocol"
9 | )
10 |
11 | var (
12 | SessionHandlerSrvRegisteName = "session-srv-registe"
13 | )
14 |
15 | type SessionHandlerSrvRegiste struct {
16 | }
17 |
18 | func (sfl SessionHandlerSrvRegiste) GetName() string {
19 | return SessionHandlerSrvRegisteName
20 | }
21 |
22 | func (sfl *SessionHandlerSrvRegiste) GetInterestOps() uint {
23 | return 1<>SessionIdSrvAreaOffset) & SessionIdSrvAreaIdMask
48 | }
49 |
50 | func (id SessionId) SrvType() uint32 {
51 | return uint32(id>>SessionIdSrvTypeOffset) & SessionIdSrvTypeMask
52 | }
53 |
54 | func (id SessionId) SrvId() uint32 {
55 | return uint32(id>>SessionIdSrvIdOffset) & SessionIdSrvIdMask
56 | }
57 |
58 | func (id SessionId) SeqId() uint32 {
59 | return uint32(id) & SessionIdSeqIdMask
60 | }
61 |
--------------------------------------------------------------------------------
/srvlib/srvertable.go:
--------------------------------------------------------------------------------
1 | package srvlib
2 |
3 | var (
4 | sessionServiceERtable = make(map[int32][]int32)
5 | serviceSessionERtable = make(map[int32][]int32)
6 | )
7 |
8 | var arrER = [][]int32{
9 | {0, 0, 0, 0, 0, 0, 0, 0},
10 | {0, 0, 0, 0, 0, 0, 0, 0},
11 | {0, 0, 0, 0, 0, 0, 0, 0},
12 | {0, 0, 0, 0, 0, 0, 0, 0},
13 | {2, 3, 6, 7, 0, 0, 0, 0},
14 | {0, 0, 0, 0, 0, 0, 0, 0},
15 | {3, 0, 0, 0, 0, 0, 0, 0},
16 | {6, 0, 0, 0, 0, 0, 0, 0},
17 | }
18 |
19 | func init() {
20 | buildSessionTable()
21 | buildServiceTable()
22 | }
23 |
24 | func buildSessionTable() {
25 | for k1, v1 := range arrER {
26 | t := make([]int32, 0, MaxServerType)
27 | for _, v2 := range v1 {
28 | if v2 != 0 {
29 | t = append(t, int32(v2))
30 | }
31 | }
32 | sessionServiceERtable[int32(k1)] = t
33 | }
34 | }
35 |
36 | func buildServiceTable() {
37 | for k1, v1 := range sessionServiceERtable {
38 | for _, v2 := range v1 {
39 | if _, has := serviceSessionERtable[v2]; !has {
40 | serviceSessionERtable[v2] = make([]int32, 0, MaxServerType)
41 | }
42 |
43 | serviceSessionERtable[v2] = append(serviceSessionERtable[v2], k1)
44 | }
45 | }
46 | }
47 |
48 | func SessionCareService(sessionType, serviceType int32) bool {
49 | if v, has := sessionServiceERtable[sessionType]; has {
50 | for _, service := range v {
51 | if service == serviceType {
52 | return true
53 | }
54 | }
55 | }
56 |
57 | return false
58 | }
59 |
60 | func GetCareSessionsByService(serviceType int32) []int32 {
61 | if v, has := serviceSessionERtable[serviceType]; has {
62 | return v
63 | }
64 |
65 | return nil
66 | }
67 |
68 | func GetCareServicesBySession(sessionType int32) []int32 {
69 | if v, has := sessionServiceERtable[sessionType]; has {
70 | return v
71 | }
72 |
73 | return nil
74 | }
75 |
--------------------------------------------------------------------------------
/srvlib/txcommskeleton.go:
--------------------------------------------------------------------------------
1 | package srvlib
2 |
3 | import (
4 | "github.com/idealeak/goserver/core/builtin/action"
5 | "github.com/idealeak/goserver/core/builtin/protocol"
6 | "github.com/idealeak/goserver/core/logger"
7 | "github.com/idealeak/goserver/core/netlib"
8 | "github.com/idealeak/goserver/core/transact"
9 | )
10 |
11 | type TxCommSkeleton struct {
12 | }
13 |
14 | func (tcs *TxCommSkeleton) SendTransResult(parent, me *transact.TransNodeParam, tr *transact.TransResult) bool {
15 | //logger.Logger.Trace("TxCommSkeleton.SendTransResult")
16 | p := action.ContructTxResultPacket(parent, me, tr)
17 | if p == nil {
18 | return false
19 | }
20 | s := ServerSessionMgrSington.GetSession(parent.AreaID, int(parent.Ot), parent.Oid)
21 | if s == nil {
22 | logger.Logger.Trace("TxCommSkeleton.SendTransResult s=nil")
23 | return false
24 | }
25 |
26 | s.Send(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_RESULT), p)
27 | //logger.Logger.Trace("TxCommSkeleton.SendTransResult success")
28 | return true
29 | }
30 |
31 | func (tcs *TxCommSkeleton) SendTransStart(parent, me *transact.TransNodeParam, ud interface{}) bool {
32 | //logger.Logger.Trace("TxCommSkeleton.SendTransStart")
33 | p := action.ContructTxStartPacket(parent, me, ud)
34 | if p == nil {
35 | return false
36 | }
37 | s := ServerSessionMgrSington.GetSession(me.AreaID, int(me.Ot), me.Oid)
38 | if s == nil {
39 | logger.Logger.Trace("TxCommSkeleton.SendTransStart s=nil")
40 | return false
41 | }
42 |
43 | s.Send(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_START), p)
44 | return true
45 | }
46 |
47 | func (tcs *TxCommSkeleton) SendCmdToTransNode(tnp *transact.TransNodeParam, c transact.TransCmd) bool {
48 | //logger.Logger.Trace("TxCommSkeleton.SendCmdToTransNode")
49 | p := action.ConstructTxCmdPacket(tnp, c)
50 | if p == nil {
51 | return false
52 | }
53 | s := ServerSessionMgrSington.GetSession(tnp.AreaID, int(tnp.Ot), tnp.Oid)
54 | if s == nil {
55 | logger.Logger.Trace("TxCommSkeleton.SendCmdToTransNode s=nil")
56 | return false
57 | }
58 |
59 | s.Send(int(protocol.CoreBuiltinPacketID_PACKET_SS_TX_CMD), p)
60 | return true
61 | }
62 |
63 | func (tcs *TxCommSkeleton) GetSkeletonID() int {
64 | return netlib.Config.SrvInfo.Id
65 | }
66 |
67 | func (tcs *TxCommSkeleton) GetAreaID() int {
68 | return netlib.Config.SrvInfo.AreaID
69 | }
70 |
71 | func init() {
72 | transact.RegisteTxCommSkeleton("github.com/idealeak/goserver/srvlib/txcommskeleton", &TxCommSkeleton{})
73 | }
74 |
--------------------------------------------------------------------------------