Commit 8aaf28ddf943150f5ba4f972303f6d78ad112419

Authored by zhangqijia
1 parent 92131fd9

fix: 修复gm系统修改role数据带来的数据竞争

cmd/gameserver/action/GmAction.go
1 package action 1 package action
2 2
3 import ( 3 import (
4 - "pro2d/common"  
5 "pro2d/common/components" 4 "pro2d/common/components"
6 "pro2d/common/logger" 5 "pro2d/common/logger"
7 "pro2d/models" 6 "pro2d/models"
@@ -11,23 +10,9 @@ import ( @@ -11,23 +10,9 @@ import (
11 type GmAction struct { 10 type GmAction struct {
12 } 11 }
13 12
14 -func (gm *GmAction) AddExp(properties map[string]interface{}) int {  
15 - r := properties[common.Role_]  
16 - c := properties[common.Conn_]  
17 -  
18 - role := r.(*models.RoleModel)  
19 - var conn components.IConnection  
20 - if c == nil {  
21 - conn = nil  
22 - } else {  
23 - conn = c.(components.IConnection)  
24 - }  
25 - 13 +func (gm *GmAction) AddExp(conn components.IConnection, role *models.RoleModel, properties map[string]interface{}) int {
26 logger.Debug(properties) 14 logger.Debug(properties)
27 exp, _ := strconv.Atoi(properties["exp"].(string)) 15 exp, _ := strconv.Atoi(properties["exp"].(string))
28 - logger.Debug("update before id: %s, exp: %d", role.Role.Id, role.Role.Exp)  
29 - role.Role.Exp += int64(exp)  
30 - role.UpdateProperty(conn, "exp", role.Role.Exp, true)  
31 - logger.Debug("update after id: %s, exp: %d", role.Role.Id, role.Role.Exp) 16 + role.IncrPropertyChan(conn, "exp", int64(exp))
32 return 0 17 return 0
33 } 18 }
cmd/gameserver/service/gm.go
@@ -65,13 +65,9 @@ func (s *GmServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc { @@ -65,13 +65,9 @@ func (s *GmServer) HandlerFuncObj(tvl, obj reflect.Value) gin.HandlerFunc {
65 role.LoadAll() 65 role.LoadAll()
66 } 66 }
67 67
68 - properties["_conn"] = conn  
69 - properties["_role"] = role  
70 -  
71 //func start 68 //func start
72 - v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(properties)})  
73 -  
74 - role.SaveRoleData(0) 69 + v := tvl.Call([]reflect.Value{obj, reflect.ValueOf(conn), reflect.ValueOf(role), reflect.ValueOf(properties)})
  70 + role.SaveRoleDataChan(conn, 0)
75 71
76 if len(v) != 1 { 72 if len(v) != 1 {
77 c.JSON(http.StatusNotFound, gin.H{"code": -100, "message": "request param len is error"}) 73 c.JSON(http.StatusNotFound, gin.H{"code": -100, "message": "request param len is error"})
common/components/conn.go
@@ -17,12 +17,13 @@ type Connection struct { @@ -17,12 +17,13 @@ type Connection struct {
17 splitter ISplitter 17 splitter ISplitter
18 Id uint32 18 Id uint32
19 19
20 - scanner *bufio.Scanner  
21 - writer *bufio.Writer  
22 - WBuffer chan []byte  
23 - Quit chan *Connection  
24 - readFunc chan func()  
25 - timerFunc chan func() 20 + scanner *bufio.Scanner
  21 + writer *bufio.Writer
  22 + WBuffer chan []byte
  23 + Quit chan *Connection
  24 + readFunc chan func()
  25 + timerFunc chan func()
  26 + customizeFunc chan func()
26 27
27 messageCallback MessageCallback 28 messageCallback MessageCallback
28 connectionCallback ConnectionCallback 29 connectionCallback ConnectionCallback
@@ -66,6 +67,9 @@ func (c *Connection) reset() { @@ -66,6 +67,9 @@ func (c *Connection) reset() {
66 if c.timerFunc == nil { 67 if c.timerFunc == nil {
67 c.timerFunc = make(chan func(), 10) 68 c.timerFunc = make(chan func(), 10)
68 } 69 }
  70 + if c.customizeFunc == nil {
  71 + c.customizeFunc = make(chan func(), 10)
  72 + }
69 73
70 //c.connectionCallback = c.defaultConnectionCallback 74 //c.connectionCallback = c.defaultConnectionCallback
71 //c.messageCallback = c.defaultMessageCallback 75 //c.messageCallback = c.defaultMessageCallback
@@ -136,6 +140,10 @@ func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error { @@ -136,6 +140,10 @@ func (c *Connection) Send(errCode int32, cmd uint32, data []byte) error {
136 } 140 }
137 } 141 }
138 142
  143 +func (c *Connection) CustomChan() chan<- func() {
  144 + return c.customizeFunc
  145 +}
  146 +
139 func (c *Connection) defaultConnectionCallback(conn IConnection) { 147 func (c *Connection) defaultConnectionCallback(conn IConnection) {
140 } 148 }
141 149
@@ -206,6 +214,8 @@ func (c *Connection) listen() { @@ -206,6 +214,8 @@ func (c *Connection) listen() {
206 timerFunc() 214 timerFunc()
207 case readFunc := <-c.readFunc: 215 case readFunc := <-c.readFunc:
208 readFunc() 216 readFunc()
  217 + case customizeFunc := <-c.customizeFunc:
  218 + customizeFunc()
209 case <-c.Quit: 219 case <-c.Quit:
210 return 220 return
211 } 221 }
common/components/icompontents.go
@@ -51,6 +51,7 @@ type ( @@ -51,6 +51,7 @@ type (
51 Start() 51 Start()
52 Stop() 52 Stop()
53 Send(errCode int32, cmd uint32, b []byte) error 53 Send(errCode int32, cmd uint32, b []byte) error
  54 + CustomChan() chan<- func()
54 55
55 SetConnectionCallback(ConnectionCallback) 56 SetConnectionCallback(ConnectionCallback)
56 SetMessageCallback(MessageCallback) 57 SetMessageCallback(MessageCallback)
@@ -149,6 +150,7 @@ type ( @@ -149,6 +150,7 @@ type (
149 150
150 SetProperty(key string, val interface{}) 151 SetProperty(key string, val interface{})
151 SetProperties(properties map[string]interface{}) 152 SetProperties(properties map[string]interface{})
  153 + IncrProperty(key string, val int64)
152 ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 154 ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32
153 } 155 }
154 ) 156 )
@@ -23,7 +23,7 @@ type RoleModel struct { @@ -23,7 +23,7 @@ type RoleModel struct {
23 func RoleExistByUid(uid string) *RoleModel { 23 func RoleExistByUid(uid string) *RoleModel {
24 data := &pb.Role{Uid: uid} 24 data := &pb.Role{Uid: uid}
25 25
26 - if err := mongoproxy.FindOne(mongoproxy.GetBsonM("uid", uid), data); err != nil { 26 + if err := mongoproxy.FindOne(mongoproxy.GetCollName(data), mongoproxy.GetBsonM("uid", uid), data); err != nil {
27 logger.Error("Role not exist err: %v", err) 27 logger.Error("Role not exist err: %v", err)
28 return nil 28 return nil
29 } 29 }
@@ -231,3 +231,35 @@ func (m *RoleModel) SaveRoleData(now int64) { @@ -231,3 +231,35 @@ func (m *RoleModel) SaveRoleData(now int64) {
231 } 231 }
232 } 232 }
233 } 233 }
  234 +
  235 +func (m *RoleModel) IncrPropertyChan(conn components.IConnection, key string, val int64) {
  236 + if conn != nil {
  237 + conn.CustomChan() <- func() {
  238 + m.IncrProperty(key, val)
  239 + }
  240 + } else {
  241 + m.IncrProperty(key, val)
  242 + }
  243 +
  244 +}
  245 +
  246 +func (m *RoleModel) UpdatePropertyChan(conn components.IConnection, key string, val interface{}, notify bool) {
  247 + if conn != nil {
  248 + conn.CustomChan() <- func() {
  249 + m.UpdateProperties(conn, map[string]interface{}{key: val}, notify)
  250 + }
  251 + } else {
  252 + m.UpdateProperties(conn, map[string]interface{}{key: val}, notify)
  253 + }
  254 +}
  255 +
  256 +func (m *RoleModel) SaveRoleDataChan(conn components.IConnection, now int64) {
  257 + if conn != nil {
  258 + conn.CustomChan() <- func() {
  259 + m.SaveRoleData(now)
  260 + }
  261 + } else {
  262 + m.SaveRoleData(now)
  263 + }
  264 +
  265 +}
@@ -153,6 +153,22 @@ func (s *Schema) SetProperties(properties map[string]interface{}) { @@ -153,6 +153,22 @@ func (s *Schema) SetProperties(properties map[string]interface{}) {
153 } 153 }
154 } 154 }
155 155
  156 +func (s *Schema) IncrProperty(key string, val int64) {
  157 + idx, ok := s.reflectIndex[strings.ToLower(key)]
  158 + if !ok {
  159 + return
  160 + }
  161 + field := s.reflectValue.Field(idx)
  162 + var v int64
  163 + switch field.Kind() {
  164 + case reflect.Int64:
  165 + v = field.Int() + val
  166 + case reflect.Int:
  167 + v = field.Int() + val
  168 + }
  169 + s.SetProperty(key, v)
  170 +}
  171 +
156 func (s *Schema) ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 { 172 func (s *Schema) ParseFields(message protoreflect.Message, properties map[string]interface{}) []int32 {
157 ids := make([]int32, 0, len(properties)) 173 ids := make([]int32, 0, len(properties))
158 for k, v := range properties { 174 for k, v := range properties {