package handler import ( "bet24.com/log" "bet24.com/servers/common" cash "bet24.com/servers/micros/money/proto" game_client "bet24.com/servers/micros/privateroom/game/client" pb "bet24.com/servers/micros/privateroom/proto" rule_status "bet24.com/servers/micros/privateroom/status/client" "encoding/json" "fmt" "sort" "sync" "time" ) type servermgr struct { lock *sync.RWMutex serverList map[string]*serverInfo recvMgr *receiverMgr } var s_mgr *servermgr func getServerManager() *servermgr { if s_mgr == nil { s_mgr = new(servermgr) s_mgr.ctor() } return s_mgr } func (sm *servermgr) ctor() { sm.lock = &sync.RWMutex{} sm.serverList = make(map[string]*serverInfo) sm.recvMgr = newReceiverMgr() } func (sm *servermgr) run() { go sm.checkTimeout() } func (sm *servermgr) checkTimeout() { time.AfterFunc(5*time.Second, sm.checkTimeout) var toRemove []string sm.lock.RLock() for _, v := range sm.serverList { if v.isTimeout() { toRemove = append(toRemove, v.Addr) } } sm.lock.RUnlock() if len(toRemove) <= 0 { return } log.Debug("servermgr.checkTimeout removing servers %v", toRemove) for _, v := range toRemove { sm.removeServer(v, true) } } func (sm *servermgr) getServer(addr string) *serverInfo { sm.lock.RLock() defer sm.lock.RUnlock() ret, ok := sm.serverList[addr] if !ok { return nil } return ret } func (sm *servermgr) addServer(addr string, gameId int, gameName string, rules []gameRule) bool { if sm.getServer(addr) != nil { log.Release("servermgr.addServer server[%s] exists", addr) return false } s := &serverInfo{ GameId: gameId, GameName: gameName, Addr: addr, OnlineUser: 0, lastPing: time.Now().Unix(), GameRules: rules, isOnline: true, } for i := 0; i < len(s.GameRules); i++ { s.GameRules[i].queryOptions() } sm.lock.Lock() sm.serverList[addr] = s sm.lock.Unlock() return true } func (sm *servermgr) addGameRule(addr string, gameId int, gameName string, ruleName, ruleDesc, ruleData string) { //log.Debug("servermgr.addGameRule %s", ruleData) s := sm.getServer(addr) if s == nil { sm.addServer(addr, gameId, gameName, []gameRule{{Name: ruleName, Desc: ruleDesc, Data: ruleData}}) s = sm.getServer(addr) } else { s.addGameRule(ruleName, ruleDesc, ruleData) } rule := s.getRule(ruleName) if rule == nil { log.Release("servermgr.addGameRule ruleName[%s] not found", ruleName) return } receivers := sm.recvMgr.getActiveReceivers() for _, v := range receivers { ok := rule_status.OnGameRuleRegistered(v, gameId, ruleName, ruleDesc, rule.Options.TargetOptions, rule.Options.UserCountOptions, rule.Options.PlayTimeOptions) if !ok { log.Debug("failed to send messsage to %s", v) //sm.receivers = append(sm.receivers[:i], sm.receivers[i+1:]...) sm.recvMgr.setReceiver(v, false) } } } func (sm *servermgr) updateServerOnline(addr string, online int) { s := sm.getServer(addr) if s == nil { log.Release("servermgr.updateServerOnline server %s not exist", addr) return } s.updateOnline(online) } func (sm *servermgr) removeServer(addr string, removeRoom bool) { s := sm.getServer(addr) if s == nil { return } // 删除房间 if removeRoom { getRoomManager().removeRoomsByServerAddr(addr) } sm.lock.Lock() delete(sm.serverList, addr) sm.lock.Unlock() if !removeRoom { return } // 判断是否需要广播删除规则 var toRemoveRules []string for _, v := range s.GameRules { toRemoveRules = append(toRemoveRules, v.Name) } for i := 0; i < len(toRemoveRules); { if sm.isGameRuleExist(s.GameId, toRemoveRules[i]) { toRemoveRules = append(toRemoveRules[:i], toRemoveRules[i+1:]...) } else { i++ } } if len(toRemoveRules) == 0 { return } receivers := sm.recvMgr.getActiveReceivers() for _, v := range receivers { ok := true for _, rule := range toRemoveRules { ok = rule_status.OnGameRuleDeregistered(v, s.GameId, rule) if !ok { break } } if !ok { log.Debug("failed to send messsage(OnGameRuleDeregistered) to %s", v) sm.recvMgr.setReceiver(v, false) } } } func (sm *servermgr) isGameRuleExist(gameId int, ruleName string) bool { sm.lock.RLock() defer sm.lock.RUnlock() for _, v := range sm.serverList { if v.GameId != gameId { continue } if v.getRule(ruleName) != nil { return true } } return false } func (sm *servermgr) getAServerAddr(gameId int, ruleName string) (addr string, rule *gameRule) { addr = "" rule = nil var ret []*serverInfo sm.lock.RLock() for _, v := range sm.serverList { if v.GameId == gameId { ret = append(ret, v) } } sm.lock.RUnlock() if len(ret) == 0 { return } if len(ret) > 1 { sort.Slice(ret, func(i, j int) bool { return ret[i].OnlineUser < ret[j].OnlineUser }) } for _, v := range ret { rule = v.getRule(ruleName) if rule != nil { addr = v.Addr return } } return } func (sm *servermgr) dump(param string) { log.Release("-------------------------------") log.Release("privateroom.servermgr.dump") defer func() { log.Release("+++++++++++++++++++++++++++++++") log.Release("") }() if param == "receiver" { sm.recvMgr.dump() return } sm.lock.RLock() for _, v := range sm.serverList { v.dump() } sm.lock.RUnlock() } func (sm *servermgr) getRules(gameId int) string { var ret []gameRule usedGameRules := make(map[string]int) sm.lock.RLock() defer sm.lock.RUnlock() for _, v := range sm.serverList { if gameId != 0 && v.GameId != gameId { continue } for _, rule := range v.GameRules { if usedGameRules[rule.Name] > 0 { continue } usedGameRules[rule.Name] = 1 ret = append(ret, rule) } } d, _ := json.Marshal(ret) return string(d) } func (sm *servermgr) createRoom(userId int, gameId int, ruleName string, target int, userCount int, fee int, prize int, roomType string, playTimeout int, isPublic bool, extraInfo string,yyfUid int) (roomNo int, errMsg string) { roomNo = 0 errMsg = "ok" if roomType != pb.RoomType_Normal { isPublic = false } // 找出有此规则的server addr, rule := sm.getAServerAddr(gameId, ruleName) if addr == "" { errMsg = fmt.Sprintf("server not found [%d:%s]", gameId, ruleName) log.Release("createRoom failed %s", errMsg) return } if rule == nil { errMsg = fmt.Sprintf("game rule not found [%d:%s]", gameId, ruleName) log.Release("createRoom failed %s", errMsg) return } // 检查创建参数是否存在 if !rule.isOptionValid(target, userCount, playTimeout, fee, roomType) { errMsg = fmt.Sprintf("invalid option parameter [%d:%d:%d]", target, userCount, playTimeout) log.Release("createRoom failed %s options[%v]", errMsg, rule.Options) return } createFee := prize if createFee > 0 && !cash.ReduceMoney2(userId, createFee, common.LOGTYPE_PRIVATEROOM_OWNER, "privateroom", "create", "",yyfUid) { //if createFee > 0 && !cash.ReduceMoney(userId, createFee, common.LOGTYPE_PRIVATEROOM_OWNER, "privateroom", "create", "") { errMsg = fmt.Sprintf("not enough cash for create room[%d]", createFee) log.Release("createRoom failed %s", errMsg) return } // 连接服务器 roomNo = game_client.CreatePrivateRoom(addr, game_client.Request_Create{ Creator: userId, GameRule: rule.Data, Target: target, UserCount: userCount, PlayTimeout: playTimeout, }) if roomNo == 0 { errMsg = "sever error,please try agrain" log.Release("servermgr.createRoom roomNo = 0, gameId = %d,ruleName = %s,userId = %d", gameId, ruleName, userId) // 加回去 if createFee > 0 { cash.GiveMoney2(userId, createFee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "create return", "",yyfUid) //cash.GiveMoney(userId, createFee, common.LOGTYPE_PRIVATEROOM_ENTER, "privateroom", "create return", "") } return } // 设置房间的userCount,ruleName和fee getRoomManager().setRoomExtra(roomNo, ruleName, rule.Data, userCount, target, fee, addr, createFee, rule.isDual(userCount), prize, roomType, isPublic, playTimeout, extraInfo) return } func (sm *servermgr) isGameRuleValid(gameId int, gameRule string, target int, userCount, playTime int) bool { _, rule := sm.getAServerAddr(gameId, gameRule) if rule == nil { log.Release("privateroom.servermgr.isGameRuleValid %d:%s not found", gameId, gameRule) return false } return rule.isOptionValid(target, userCount, playTime, 0, pb.RoomType_SimpleMatch) } func (sm *servermgr) registerServerStatus(addr string) { sm.recvMgr.setReceiver(addr, true) }