#!/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 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() 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() 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) 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