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