Ejemplo n.º 1
0
//实现了Module接口的Run方法并提供了:
//1.ChanRPC(用于模块间交互)
//2.Command ChanRPC(用于提供命令服务)
//3.Go(避免操作阻塞当前goroutine)
//4.timer(用于定时器)
func (s *Skeleton) Run(closeSig chan bool) {
	for { //死循环
		select {
		case <-closeSig: //读取关闭信号
			s.commandServer.Close() //关闭命令rpc服务器
			s.server.Close()        //关闭rpc服务器
			s.g.Close()             //关闭Go
			return
		case ci := <-s.server.ChanCall: //从rpc服务器读取调用信息
			err := s.server.Exec(ci) //执行调用
			if err != nil {
				log.Error("%v", err)
			}
		case ci := <-s.commandServer.ChanCall: //从命令rpc服务器读取调用信息
			err := s.commandServer.Exec(ci) //执行命令调用
			if err != nil {
				log.Error("%v", err)
			}
		case cb := <-s.g.ChanCb: //从Go的回调管道中读取回调函数
			s.g.Cb(cb) //执行回调函数(不用自己写 d.Cb(<-d.ChanCb)了 )
		case t := <-s.dispatcher.ChanTimer: //从分发器中读取到时定时器
			t.Cb() //执行定时器回调
		}
	}
}
Ejemplo n.º 2
0
func execCb(ri *RetInfo) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	// execute
	switch ri.cb.(type) {
	case func(error):
		ri.cb.(func(error))(ri.err)
	case func(interface{}, error):
		ri.cb.(func(interface{}, error))(ri.ret, ri.err)
	case func([]interface{}, error):
		ri.cb.(func([]interface{}, error))(assert(ri.ret), ri.err)
	default:
		panic("bug")
	}
	return
}
Ejemplo n.º 3
0
func (s *Skeleton) Run(closeSig chan bool) {
	for {
		select {
		case <-closeSig:
			s.commandServer.Close()
			s.server.Close()
			s.g.Close()
			return
		case ci := <-s.server.ChanCall:
			err := s.server.Exec(ci)
			if err != nil {
				log.Error("%v", err)
			}
		case ci := <-s.commandServer.ChanCall:
			err := s.commandServer.Exec(ci)
			if err != nil {
				log.Error("%v", err)
			}
		case cb := <-s.g.ChanCb:
			s.g.Cb(cb)
		case t := <-s.dispatcher.ChanTimer:
			t.Cb()
		}
	}
}
Ejemplo n.º 4
0
Archivo: go.go Proyecto: name5566/leaf
func (c *LinearContext) Go(f func(), cb func()) {
	c.g.pendingGo++

	c.mutexLinearGo.Lock()
	c.linearGo.PushBack(&LinearGo{f: f, cb: cb})
	c.mutexLinearGo.Unlock()

	go func() {
		c.mutexExecution.Lock()
		defer c.mutexExecution.Unlock()

		c.mutexLinearGo.Lock()
		e := c.linearGo.Remove(c.linearGo.Front()).(*LinearGo)
		c.mutexLinearGo.Unlock()

		defer func() {
			c.g.ChanCb <- e.cb
			if r := recover(); r != nil {
				if conf.LenStackBuf > 0 {
					buf := make([]byte, conf.LenStackBuf)
					l := runtime.Stack(buf, false)
					log.Error("%v: %s", r, buf[:l])
				} else {
					log.Error("%v", r)
				}
			}
		}()

		e.f()
	}()
}
Ejemplo n.º 5
0
//线性上下文的Go函数
func (c *LinearContext) Go(f func(), cb func()) {
	c.g.pendingGo++ //增加待处理回调函数计数器

	c.mutexLinearGo.Lock()                       //链表加锁
	c.linearGo.PushBack(&LinearGo{f: f, cb: cb}) //向链表添加元素
	c.mutexLinearGo.Unlock()                     //链表解锁

	go func() { //在新的goroutine中执行
		c.mutexExecution.Lock()         //执行加锁,后来的Go将会阻塞在这里,直到该Go执行完成
		defer c.mutexExecution.Unlock() //延迟 执行解锁

		c.mutexLinearGo.Lock()                                 //链表加锁
		e := c.linearGo.Remove(c.linearGo.Front()).(*LinearGo) //从表头移出一个元素
		c.mutexLinearGo.Unlock()                               //链表解锁

		defer func() {
			c.g.ChanCb <- e.cb //当f执行完成后,将回调发送到回调管道中
			//捕获异常
			if r := recover(); r != nil {
				if conf.LenStackBuf > 0 {
					buf := make([]byte, conf.LenStackBuf)
					l := runtime.Stack(buf, false)
					log.Error("%v: %s", r, buf[:l])
				} else {
					log.Error("%v", r)
				}
			}
		}()

		e.f() //执行函数
	}()
}
Ejemplo n.º 6
0
Archivo: gate.go Proyecto: haoqoo/leaf
func (a *agent) WriteMsg(msg interface{}) {
	if a.gate.JSONProcessor != nil {
		// json
		data, err := a.gate.JSONProcessor.Marshal(msg)
		if err != nil {
			log.Error("marshal json %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		if a.wsConn != nil {
			a.wsConn.WriteMsg(data)
		} else if a.tcpConn != nil {
			a.tcpConn.WriteMsg(data)
		}
	} else if a.gate.ProtobufProcessor != nil {
		// protobuf
		id, data, err := a.gate.ProtobufProcessor.Marshal(msg.(proto.Message))
		if err != nil {
			log.Error("marshal protobuf %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		if a.wsConn != nil {
			b := make([]byte, len(id)+len(data))
			copy(b, id)
			copy(b[len(id):], data)
			a.wsConn.WriteMsg(b)
		} else if a.tcpConn != nil {
			a.tcpConn.WriteMsg(id, data)
		}
	}
}
Ejemplo n.º 7
0
func (a *agent) WriteMsg(msg interface{}) {
	if a.gate.Processor != nil {
		data, err := a.gate.Processor.Marshal(msg)
		if err != nil {
			log.Error("marshal message %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		err = a.conn.WriteMsg(data...)
		if err != nil {
			log.Error("write message %v error: %v", reflect.TypeOf(msg), err)
		}
	}
}
Ejemplo n.º 8
0
func (user *User) login(accID string) {
	userData := new(UserData)
	skeleton.Go(func() {
		db := mongoDB.Ref()
		defer mongoDB.UnRef(db)

		// load
		err := db.DB("game").C("users").
			Find(bson.M{"accid": accID}).One(userData)
		if err != nil {
			// unknown error
			if err != mgo.ErrNotFound {
				log.Error("load acc %v data error: %v", accID, err)
				userData = nil
				user.WriteMsg(&msg.S2C_Close{Err: msg.S2C_Close_InnerError})
				user.Close()
				return
			}

			// new
			err := userData.initValue(accID)
			if err != nil {
				log.Error("init acc %v data error: %v", accID, err)
				userData = nil
				user.WriteMsg(&msg.S2C_Close{Err: msg.S2C_Close_InnerError})
				user.Close()
				return
			}
		}
	}, func() {
		// network closed
		if user.state == userLogout {
			user.logout(accID)
			return
		}

		// db error
		user.state = userGame
		if userData == nil {
			return
		}

		// ok
		user.data = userData
		users[userData.UserID] = user
		user.UserData().(*AgentInfo).userID = userData.UserID
		user.onLogin()
		user.autoSaveDB()
	})
}
Ejemplo n.º 9
0
func (session *Session) login(accID int64) {
	userData := new(UserData)
	skeleton.Go(func() {

		user := new(model.User)
		user.AccId = accID
		has, err := model.Engine.Get(user)

		if err != nil {
			log.Error("load acc %v data error: %v", accID, err)
			userData = nil
			m := &msg.ClosePush{Code: msg.ClosePush_INNER.Enum()}
			session.WriteMsg(m)
			session.Close()
			return
		}
		if has {
			userData.User = user
		} else {
			err := userData.initValue(accID)
			if err != nil {
				log.Error("init acc %v data error: %v", accID, err)
				userData = nil
				m := &msg.ClosePush{Code: msg.ClosePush_INNER.Enum()}
				session.WriteMsg(m)
				session.Close()
				return
			}
		}
	}, func() {
		// network closed
		if session.state == Session_Logout {
			session.logout(accID)
			return
		}

		// db error
		session.state = Session_InGame
		if userData == nil {
			return
		}

		// ok
		session.data = userData
		userIDSessions[userData.User.Id] = session
		session.UserData().(*AgentInfo).userID = userData.User.Id
		session.onLogin()
		session.autoSaveDB()
	})
}
Ejemplo n.º 10
0
func destroy(m *module) {
	defer func() {
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	m.mi.OnDestroy()
}
Ejemplo n.º 11
0
//销毁模块
func destroy(m *module) {
	defer func() { //延迟执行
		if r := recover(); r != nil { //捕获异常
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf) //创建一个字节切片用于存储格式化后的stack trace
				l := runtime.Stack(buf, false)        //格式化调用Stack函数的goroutine的stack trace
				log.Error("%v: %s", r, buf[:l])       //打印错误消息和stack trace
			} else {
				log.Error("%v", r) //只打印错误消息
			}
		}
	}()

	m.mi.OnDestroy() //先调用模块的销毁函数,再执行上面的延迟函数
}
Ejemplo n.º 12
0
func (session *Session) logout(accID int64) {
	if session.data != nil {
		session.saveDBTimer.Stop()
		session.onLogout()
		delete(userIDSessions, session.data.User.Id)
	}

	// save
	data := util.DeepClone(session.data)
	session.Go(func() {
		if data != nil {
			//db := mongoDB.Ref()
			//defer mongoDB.UnRef(db)
			// userID := data.(*UserData).UserID
			// _, err := db.DB("game").C("users").
			// 	UpsertId(userID, data)

			//err := data.(*UserData).saveDB()
			err := session.data.saveDB()

			if err != nil {
				log.Error("save user %v data error: %v", session.data.User.Id, err)
			}
		}
	}, func() {
		delete(accIDSessions, accID)
	})
}
Ejemplo n.º 13
0
func (a *TCPAgent) OnClose() {
	if a.gate.AgentChanRPC != nil {
		err := a.gate.AgentChanRPC.Open(0).Call0("CloseAgent", a)
		if err != nil {
			log.Error("chanrpc error: %v", err)
		}
	}
}
Ejemplo n.º 14
0
Archivo: go.go Proyecto: name5566/leaf
func (g *Go) Cb(cb func()) {
	defer func() {
		g.pendingGo--
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	if cb != nil {
		cb()
	}
}
Ejemplo n.º 15
0
func (t *Timer) Cb() {
	defer func() {
		t.cb = nil
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	if t.cb != nil {
		t.cb()
	}
}
Ejemplo n.º 16
0
//执行回调函数
func (g *Go) Cb(cb func()) {
	defer func() {
		g.pendingGo-- //处理完一个,减少待处理回调函数计数器
		//异常处理
		if r := recover(); r != nil {
			if conf.LenStackBuf > 0 {
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r)
			}
		}
	}()

	if cb != nil { //如果回调函数不为空
		cb() //执行回调函数
	}
}
Ejemplo n.º 17
0
//调用定时器的回调函数
func (t *Timer) Cb() {
	defer func() { //延迟执行
		t.cb = nil                    //置空回调
		if r := recover(); r != nil { //捕获异常
			if conf.LenStackBuf > 0 { //堆栈buf长度大于0
				//打印堆栈信息
				buf := make([]byte, conf.LenStackBuf)
				l := runtime.Stack(buf, false)
				log.Error("%v: %s", r, buf[:l])
			} else {
				log.Error("%v", r) //打印异常
			}
		}
	}()
	//回调不为空
	if t.cb != nil {
		t.cb() //调用回调
	}
}
Ejemplo n.º 18
0
//实现代理接口(gate.Agent)WriteMsg函数
//发送消息
func (a *TCPAgent) WriteMsg(msg interface{}) {
	if a.gate.JSONProcessor != nil { //使用JSON处理器
		// json
		data, err := a.gate.JSONProcessor.Marshal(msg) //编码JSON消息。消息id存储在data内,直接发送就好了
		if err != nil {
			log.Error("marshal json %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		a.conn.WriteMsg(data) //发送消息
	} else if a.gate.ProtobufProcessor != nil { //使用protobuf处理器
		// protobuf
		id, data, err := a.gate.ProtobufProcessor.Marshal(msg.(proto.Message)) //编码protobuf消息。消息id是返回的,需要和data一起发送到客户端
		if err != nil {
			log.Error("marshal protobuf %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		a.conn.WriteMsg(id, data) //发送消息
	}
}
Ejemplo n.º 19
0
// goroutine safe
func (c *DialContext) Close() {
	c.Lock()
	for _, s := range c.sessions {
		s.Close()
		if s.ref != 0 {
			log.Error("session ref = %v", s.ref)
		}
	}
	c.Unlock()
}
Ejemplo n.º 20
0
func (a *TCPAgent) WriteMsg(msg interface{}) {
	if a.gate.JSONProcessor != nil {
		// json
		data, err := a.gate.JSONProcessor.Marshal(msg)
		if err != nil {
			log.Error("marshal json %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		a.conn.WriteMsg(data)
	} else if a.gate.ProtobufProcessor != nil {
		// protobuf
		id, data, err := a.gate.ProtobufProcessor.Marshal(msg.(proto.Message))
		if err != nil {
			log.Error("marshal protobuf %v error: %v", reflect.TypeOf(msg), err)
			return
		}
		a.conn.WriteMsg(id, data)
	}
}
Ejemplo n.º 21
0
Archivo: go.go Proyecto: name5566/leaf
func (g *Go) Go(f func(), cb func()) {
	g.pendingGo++

	go func() {
		defer func() {
			g.ChanCb <- cb
			if r := recover(); r != nil {
				if conf.LenStackBuf > 0 {
					buf := make([]byte, conf.LenStackBuf)
					l := runtime.Stack(buf, false)
					log.Error("%v: %s", r, buf[:l])
				} else {
					log.Error("%v", r)
				}
			}
		}()

		f()
	}()
}
Ejemplo n.º 22
0
//一般的Go函数
//执行一个比较耗时的操作,并在执行完成后,将回调函数通过回调管道发送回原goroutine执行
func (g *Go) Go(f func(), cb func()) {
	g.pendingGo++ //增加待处理回调函数计数器

	go func() { //在一个新的goroutine内执行
		defer func() { //在f执行完后执行
			g.ChanCb <- cb //发送回调函数到回调管道中
			//异常处理
			if r := recover(); r != nil {
				if conf.LenStackBuf > 0 {
					buf := make([]byte, conf.LenStackBuf)
					l := runtime.Stack(buf, false)
					log.Error("%v: %s", r, buf[:l])
				} else {
					log.Error("%v", r)
				}
			}
		}()

		f() //在新的gouroutine执行f(比如一个很耗时的操作)
	}()
}
Ejemplo n.º 23
0
func (p *RoomManager) Leave(id int, name string) error {
	room, err := p.whereAmI(name)

	if err != nil {
		return errors.New("you are not in any room")
	}
	if room.id != id {
		return errors.New("you are not in this room")
	}
	p.Lock()
	defer p.Unlock()
	room.players.Remove(name)
	log.Error("player %s removed", name)
	return nil
}
Ejemplo n.º 24
0
func (data *UserData) saveDB() error {
	//save User

	id := data.User.Id
	affected, err := model.Engine.Id(id).AllCols().Omit("Id", "AccId").Update(data.User)
	if err != nil {
		return fmt.Errorf("save db error: %v", err)
	}
	if affected != 1 {
		log.Error("%v", "save db no affect,may be an error")
	} else {
		log.Release("%v", "save db ok")
	}
	return nil
}
Ejemplo n.º 25
0
//运行TCP服务器
func (server *TCPServer) run() {
	for { //死循环
		conn, err := server.ln.Accept() //接受一个连接
		if err != nil {                 //如果有错(如果调用了server.Close,再Accept,那么就会出错)
			if server.closeFlag { //服务器关闭标志为true 因为关闭了TCP服务器导致的出错
				return //结束循环
			} else {
				log.Error("accept error: %v", err) //日志记录接受连接出错
				continue                           //继续循环
			}
		}

		server.mutexConns.Lock()                    //加锁,为什么要加锁,因为会从不同的goroutine中访问server.conns,比如从外部goroutine中调用server.Close或者在新的goroutine中运行代理执行清理工作的时候或者当前for循环所在goroutine中增加连接记录
		if len(server.conns) >= server.MaxConnNum { //如果当前连接数超过上限
			server.mutexConns.Unlock()        //解锁
			conn.Close()                      //关闭新来的连接
			log.Debug("too many connections") //日志记录:太多连接了
			continue                          //继续循环
		}
		//增加连接记录
		server.conns[conn] = struct{}{} //struct{}为类型,第二个{}为初始化,只不过是空值而已
		server.mutexConns.Unlock()      //解锁

		server.wg.Add(1) //等待组+1

		tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser) //创建一个TCP连接(原有net.Conn的封装)
		agent := server.NewAgent(tcpConn)                                     //调用注册的创建代理函数创建代理
		go func() {                                                           //此处形成闭包
			agent.Run() //在一个新的goroutine中运行代理,一个客户端一个agent
			//执行到这里时agent.Run for循环结束
			// cleanup
			//清理工作
			tcpConn.Close()            //关闭连接(封装层)
			server.mutexConns.Lock()   //加锁
			delete(server.conns, conn) //从连接集合中删除连接
			server.mutexConns.Unlock() //解锁
			agent.OnClose()            //关闭代理

			server.wg.Done() //等待组-1
		}()
	}
}
Ejemplo n.º 26
0
func (user *User) autoSaveDB() {
	const duration = 5 * time.Minute

	// save
	user.saveDBTimer = skeleton.AfterFunc(duration, func() {
		data := util.DeepClone(user.data)
		user.Go(func() {
			db := mongoDB.Ref()
			defer mongoDB.UnRef(db)
			userID := data.(*UserData).UserID
			_, err := db.DB("game").C("users").
				UpsertId(userID, data)
			if err != nil {
				log.Error("save user %v data error: %v", userID, err)
			}
		}, func() {
			user.autoSaveDB()
		})
	})
}
Ejemplo n.º 27
0
func (session *Session) autoSaveDB() {
	const duration = 5 * time.Minute

	// save
	session.saveDBTimer = skeleton.AfterFunc(duration, func() {
		data := util.DeepClone(session.data)
		session.Go(func() {
			//db := mongoDB.Ref()
			//defer mongoDB.UnRef(db)
			// userID := data.(*UserData).UserID
			// _, err := db.DB("game").C("users").
			// 	UpsertId(userID, data)
			err := data.(*UserData).saveDB()
			if err != nil {
				log.Error("save user %v data error: %v", session.data.User.Id, err)
			}
		}, func() {
			session.autoSaveDB()
		})
	})
}
Ejemplo n.º 28
0
func handleRegister(args []interface{}) {
	m := args[0].(*msg.RegisterReq)
	a := args[1].(gate.Agent)
	log.Debug("%v", m, a)
	account := new(model.Account)
	account.Name = m.GetName()
	account.Password = m.GetPassword()
	affected, err := model.Engine.Insert(account)
	if err != nil {
		//所有错误都返回用户名已存在
		log.Error("%v", err)
		a.WriteMsg(&msg.RegisterRes{Code: msg.RegisterRes_EXIST.Enum()})
		return
	}
	log.Debug("%v", affected)
	if affected == 1 {
		a.WriteMsg(&msg.RegisterRes{Code: msg.RegisterRes_YES.Enum()})
	} else {
		a.WriteMsg(&msg.RegisterRes{Code: msg.RegisterRes_NO.Enum()})
	}
}
Ejemplo n.º 29
0
func (server *TCPServer) run() {
	for {
		conn, err := server.ln.Accept()
		if err != nil {
			if server.closeFlag {
				return
			} else {
				log.Error("accept error: %v", err)
				continue
			}
		}

		server.mutexConns.Lock()
		if len(server.conns) >= server.MaxConnNum {
			server.mutexConns.Unlock()
			conn.Close()
			log.Debug("too many connections")
			continue
		}
		server.conns[conn] = struct{}{}
		server.mutexConns.Unlock()

		server.wg.Add(1)

		tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser)
		agent := server.NewAgent(tcpConn)
		go func() {
			agent.Run()

			// cleanup
			tcpConn.Close()
			server.mutexConns.Lock()
			delete(server.conns, conn)
			server.mutexConns.Unlock()
			agent.OnClose()

			server.wg.Done()
		}()
	}
}
Ejemplo n.º 30
0
func Example() {
	name := "Leaf"

	log.Debug("My name is %v", name)
	log.Release("My name is %v", name)
	log.Error("My name is %v", name)
	// log.Fatal("My name is %v", name)

	logger, err := log.New("release", "")
	if err != nil {
		return
	}
	defer logger.Close()

	logger.Debug("will not print")
	logger.Release("My name is %v", name)

	log.Export(logger)

	log.Debug("will not print")
	log.Release("My name is %v", name)
}