#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package Script.DB.DBDataMgr # # @todo:DBÊý¾Ý¹ÜÀíÆ÷ # @author hxp # @date 2025-05-09 # @version 1.0 # # ÏêϸÃèÊö: DBÊý¾Ý¹ÜÀíÆ÷ # #------------------------------------------------------------------------------- #"""Version = 2025-05-09 12:20""" #------------------------------------------------------------------------------- import CommFunc import DBStruct import ChConfig import GameWorld import PyGameData import PyMongoMain import DBPlayerViewCache import DBEventTrig import DBBillboard import DBFuncTeam import DBGameRec import DBFamily import DBMail import time import os BakRoot = "C:\ServerRealTimeBackup" BakFileType = ".rtb" BackupCopyMax = 5 # ±£ÁôÀúÊ·±¸µµÎļþÊý BackupInterval = 30 # ±¸µµÆµÂÊ£¬·ÖÖÓ£¬Ôݶ¨Ã¿30·ÖÖÓ def OnServerStart(): ##Æô¶¯·þÎñÆ÷Êý¾Ý´¦Àí GameWorld.DebugLog("µØÍ¼·þÎñÆ÷Æô¶¯") if not LoadGameWorldDataFromBackup(): LoadGameWorldDataFromDB() return def OnServerClose(): ##¹Ø·þ·þÎñÆ÷Êý¾Ý´¦Àí SaveGameWorldDataToDB() return def OnMinute(curTime): if PyGameData.g_serverClosing: return DBFamily.OnMinute() DBBillboard.OnMinute() #±¸µµ¡¢Èë¿â·Å×îºó£¬µÈÊý¾Ý¶¼´¦ÀíÍêºóÔÙ±£´æ£¬Ã¿Ìì [[ʱ,·Ö], ...]£¬¾¡Á¿²í¿ªÕûµã¡¢5·Ö if [curTime.hour, curTime.minute] in [[3, 6]]: BackupGameWorldData(True) else: BackupGameWorldData(False) return #------------------------------------------- ±¸µµ --------------------------------------------------- def GetBakFileSortList(bakPath): ## °´±¸µµÊ±¼äµ¹ÐòÅÅÐò·µ»Ø [[bakTime, Êý¾Ý°æ±¾ºÅ, filePath], ...] bakFileList = [] for parent, _, filenames in os.walk(bakPath): for filename in filenames: if not filename.endswith(BakFileType): continue fullPath = os.path.join(parent, filename) bakInfo = filename[:filename.index(".")].split("_") if len(bakInfo) != 3: continue dataVersionNO = GameWorld.ToIntDef(bakInfo[1]) # Êý¾Ý°æ±¾ºÅ bakTime = GameWorld.ToIntDef(bakInfo[2]) # yyyyMMddhhmmss bakFileList.append([bakTime, dataVersionNO, fullPath]) bakFileList.sort(reverse=True) return bakFileList def LoadGameWorldDataFromBackup(): ## ±¸µµ¼ÓÔØ·þÎñÆ÷¹«¹²Êý¾Ý # @return: ÊÇ·ñ´æÔÚ±¸µµ³É¹¦¼ÓÔØ serverID = GameWorld.GetGameWorld().GetServerID() serverName = "S%s" % serverID BakDir = os.path.join(BakRoot, serverName) GameWorld.Log("¼ÓÔØ±¸µµ: %s" % BakDir) bakFileList = GetBakFileSortList(BakDir) if not bakFileList: GameWorld.Log("²»´æÔÚ±¸µµ!") return finalBakInfo = bakFileList[0] # ÅÅÐòºóµÄµÚÒ»¸öΪ×îб¸µµÊý¾Ý bakVersionNO = finalBakInfo[1] bakFilePath = finalBakInfo[2] if bakVersionNO != DBStruct.GAMEWORLD_DATA_VERSION_NO: GameWorld.ErrLog("±¸µµÊý¾Ý°æ±¾ºÅУÑéʧ°Ü£¬ÇëʹÓÃÕýÈ·°æ±¾·þÎñÆ÷Æô¶¯ÖØÐµ¼ÈëÊý¾Ý! bakVersionNO=%s, GAMEWORLD_DATA_VERSION_NO=%s" % (bakVersionNO, DBStruct.GAMEWORLD_DATA_VERSION_NO)) raise GameWorld.Log("¶ÁÈ¡±¸µµ: %s" % bakFilePath) f = open(bakFilePath, 'rb') compressed_data = f.read() f.close() saveData = CommFunc.Decompress(compressed_data) if not saveData: raise LoadPyGameData(saveData, 0) SaveGameWorldDataToDB(saveData) # Èç¹ûÊÇ´Ó±¸µµ¶ÁÈ¡µÄÔòÖ±½ÓÈë¿â return True def BackupGameWorldData(saveToDB=False): ## ·þÎñÆ÷¹«¹²Êý¾Ý¶¨Ê±±¸µµ£¬ÔÝʱֱ½Ó´æÅÌ # @param saveToDB: ÊÇ·ñ¸½´øÈë¿â£¬ÎªÈ·±£±¸µµÊý¾Ý´æÔÚʱһ¶¨ÓÅÓÚdb¿âÊý¾Ý£¬¹Ê³£¹æÈë¿âʱ±ØÐ븽´øÏȱ¸µµÒ»´Î if PyGameData.g_serverClosing: return if not PyGameData.g_loadDataOK: GameWorld.Log("¼ÓÔØÊý¾ÝδÍê³É£¬²»´æ´¢±¸µµ") return curTime = int(time.time()) if saveToDB: if curTime - PyGameData.g_lastRTBTime < BackupInterval * 60: GameWorld.Log("±¸µµÀäÈ´ÖÐ!") return serverID = GameWorld.GetGameWorld().GetServerID() serverName = "S%s" % serverID BakDir = os.path.join(BakRoot, serverName) GameWorld.Log("·þÎñÆ÷±¸µµ: %s" % serverName) if not os.path.exists(BakDir): os.makedirs(BakDir) dataVersionNO = DBStruct.GAMEWORLD_DATA_VERSION_NO bakTiemStr = GameWorld.ChangeTimeNumToStr(curTime, ChConfig.TYPE_Time_Format_YmdHMS) bakFilePath = os.path.join(BakDir, "%s_%s_%s%s" % (serverName, dataVersionNO, bakTiemStr, BakFileType)) saveData = GetSavePyData() GameWorld.Log("Bak:%s, len=%s, %s" % (serverName, len(saveData), bakFilePath)) compressed_data = CommFunc.Compress(saveData) # ±¸µµÊý¾Ý²Å½øÐÐѹËõ if not compressed_data: GameWorld.SendGameError("ServerDataBackupError") return GameWorld.Log("compress len=%s" % len(compressed_data)) try: fp = open(bakFilePath, "wb") fp.write(compressed_data) fp.close() except: return PyGameData.g_lastRTBTime = curTime bakFileList = GetBakFileSortList(BakDir) # ɾ³ý¶àÓ౸µµ for bakInfo in bakFileList[BackupCopyMax:]: filePath = bakInfo[-1] os.remove(filePath) GameWorld.Log("ɾ³ý¶àÓ౸µµÎļþ: %s" % filePath) if saveToDB: SaveGameWorldDataToDB(saveData) return def ClearBackupFile(): ## Çå¿Õ±¸µµÎļþ serverID = GameWorld.GetGameWorld().GetServerID() serverName = "S%s" % serverID BakDir = os.path.join(BakRoot, serverName) GameWorld.Log("Çå¿Õ±¸µµ: %s" % BakDir) CommFunc.DelFolder(BakDir, True) return #-------------------------------------------------------------------------------------------------- def LoadGameWorldDataFromDB(): ## Ö±½Ó´Ódb¶ÁÈ¡¹«¹²Êý¾Ý GameWorld.Log("ûÓб¸µµÊý¾Ý£¬Ö±½Ó´Ódb¼ÓÔØÊý¾Ý!") serverData = PyMongoMain.GetUserCtrlDB().readGameWorldData() LoadPyGameData(serverData, 0) return def SaveGameWorldDataToDB(saveData=""): ## ¹«¹²Êý¾ÝÈë¿â if not saveData: saveData = GetSavePyData() PyMongoMain.GetUserCtrlDB().saveGameWorldData(saveData) return def GetSavePyData(): #´æ´¢Êý¾Ýǰ£¬Ò»Ð©¹¦ÄÜÒµÎñÊý¾ÝÏÈת»¯Îª´æµµÊý¾Ý #... pyGameDataMgr = GetDBDataMgr() result = pyGameDataMgr.GetSaveData() GameWorld.Log("GetSavePyData!! id = %s-%s"%(id(pyGameDataMgr), len(result))) return result def LoadPyGameData(gameBuffer, pos): pyGameDataMgr = GetDBDataMgr() GameWorld.Log("LoadPyGameData!!id = %s %s"%(id(pyGameDataMgr), len(gameBuffer))) pos = pyGameDataMgr.LoadGameData(gameBuffer, pos) #¼ÓÔØÊý¾Ýºó£¬Ò»Ð©¹¦ÄÜת»¯Îª¹¦ÄÜÒµÎñÊý¾Ý #... #·Å×îºó PyGameData.g_loadDataOK = True return pos class PyGameDataManager(object): def __init__(self): self.EventTrigMgr = DBEventTrig.EventTrigMgr() self.PlayerViewCacheMgr = DBPlayerViewCache.PlayerViewCacheMgr() self.BillboardMgr = DBBillboard.BillboardMgr() self.MailMgr = DBMail.MailMgr() self.FamilyMgr = DBFamily.FamilyMgr() self.GameRecMgr = DBGameRec.GameRecMgr() self.FuncTeamMgr = DBFuncTeam.FuncTeamMgr() return def GetSaveData(self): buff = "" buff += self.EventTrigMgr.GetSaveData() buff += self.PlayerViewCacheMgr.GetSaveData() buff += self.BillboardMgr.GetSaveData() buff += self.MailMgr.GetSaveData() buff += self.FamilyMgr.GetSaveData() buff += self.GameRecMgr.GetSaveData() buff += self.FuncTeamMgr.GetSaveData() return buff def LoadGameData(self, gameBuffer, pos): dataslen = len(gameBuffer) pos = self.EventTrigMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.PlayerViewCacheMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.BillboardMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.MailMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.FamilyMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.GameRecMgr.LoadPyGameData(gameBuffer, pos, dataslen) pos = self.FuncTeamMgr.LoadPyGameData(gameBuffer, pos, dataslen) return pos def GetDBDataMgr(): ## pyÊý¾Ý¿â±íÊý¾Ý¹ÜÀíÆ÷ pyGameDataMgr = PyGameData.g_pyGameDataManager if not pyGameDataMgr: pyGameDataMgr = PyGameDataManager() PyGameData.g_pyGameDataManager = pyGameDataMgr return pyGameDataMgr def GetEventTrigMgr(): ## ʼþÖµ¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.EventTrigMgr def GetPlayerViewCacheMgr(): ## Íæ¼Ò²é¿´»º´æÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.PlayerViewCacheMgr def GetFamilyMgr(): ## ¼Ò×åÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.FamilyMgr def GetFamilyActionMgr(): ## ¼Ò×åActionÊý¾Ý¹ÜÀíÆ÷ return GetFamilyMgr().GetFamilyActionMgr() def GetMailMgr(): ## ÓʼþÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.MailMgr def GetBillboardMgr(): ## ÅÅÐаñÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.BillboardMgr def GetGameRecMgr(): ## ͨÓüǼÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.GameRecMgr def GetFuncTeamMgr(): ## ¹¦ÄܶÓÎéÊý¾Ý¹ÜÀíÆ÷ dbDataMgr = GetDBDataMgr() return dbDataMgr.FuncTeamMgr