open-toontown/toontown/uberdog/DistributedDataStoreManager...

148 lines
5.6 KiB
Python

from otp.ai.AIBaseGlobal import *
from pandac.PandaModules import *
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD
from toontown.uberdog import DataStoreGlobals
import time
import os
class DistributedDataStoreManagerUD(DistributedObjectGlobalUD):
"""
This is UD gateway to all DataStores. It receives queries
from various AIs, locates the desired store, runs the query, and sends
back a response(if specified).
It looks for two config variables:
'server-data-folder' is a string that specifies the directory in
which each of the Stores will write their data. It defaults to '.'.
'enable-destroy-data-stores' controls whether the DataStore can be
destroyed by calling destroy(). If not, destroy() has no effect.
It defaults to 'False'.
"""
notify = directNotify.newCategory('DistributedDataStoreManagerUD')
serverDataFolder = simbase.config.GetString('server-data-folder', '.')
enableDestroyStore = simbase.config.GetBool('enable-destroy-data-stores', True)
def __init__(self,air):
DistributedObjectGlobalUD.__init__(self,air)
self.stores = {}
def __getFilePath(self,storeId):
#import pdb; pdb.set_trace()
return '%s/TUDS-%s'%(self.serverDataFolder,
repr(storeId))
def __str__(self):
outStr = self.__class__.__name__ + ' - ' + repr(len(self.stores)) + ' Stores\n'
outStr += '-'*40 + '\n'
for id in list(self.stores.keys()):
outStr += repr(id) + '\t: ' + self.stores[id].className + '\n'
return outStr
# From AI
def startStore(self,storeId):
"""
Starts a store corresponding to the id as specified
in DataStoreGlobals.
If the store is already present, it has no effect.
"""
storeClass = DataStoreGlobals.getStoreClass(storeId)
if not self.stores.get(storeId,None):
if storeClass is not None:
store = storeClass(self.__getFilePath(storeId))
if store:
self.stores[storeId] = store
else:
self.notify.debug('DataStore type \'%d\' not found DataStoreGlobals. Store not started.' % \
(storeId,))
else:
self.notify.debug('%s already present on uberdog.' % \
(storeClass.__name__,))
def stopStore(self,storeId):
"""
Closes the store corresponding to the id as specified
in DataStoreGlobals if the config variable
'enable-destroy-data-stores' is True. Otherwise
it just closes it, leaving the data on disk
intact.
If the store is not present, it has no effect.
"""
# import pdb; pdb.set_trace()
store = self.stores.pop(storeId,None)
if store:
if self.enableDestroyStore:
self.notify.debug('Destroying %s.' % repr(DataStoreGlobals.getStoreClass(storeId)))
store.destroy()
else:
self.notify.debug('Closing %s.' % repr(DataStoreGlobals.getStoreClass(storeId)))
store.close()
else:
self.notify.debug('%s not present on uberdog.' % repr(DataStoreGlobals.getStoreClass(storeId)))
def queryStore(self,storeId,query,retry = False):
"""
Pass a query on to the specified store and
respond with any results. If the store is
not present, return an error message to let
the client know.
'retry' is to let us know that this call is
an attempt to re-send a query that failed
because the desired store was not yet active.
We will try to start the store here and send
the query again. We only do this once per
query, otherwise we could get into an
infinite loop if the store cannot be started.
"""
store = self.stores.get(storeId,None)
if store:
result = store.query(query)
self.respondToQuery(storeId,result)
else:
if retry:
result = 'Store not found'
self.respondToQuery(storeId,result)
storeClass = DataStoreGlobals.getStoreClass(storeId)
if storeClass:
self.notify.debug('%s not present on uberdog. Query dropped.' % \
(storeClass.__name__,))
else:
self.notify.debug('Store of typeId %s not defined in DataStoreGlobals. Query dropped.' % \
(storeId,))
else:
self.startStore(storeId)
self.queryStore(storeId,query,True)
# To AI
def respondToQuery(self,storeId,data):
"""
Sends a message back to the querying AI with
the results of its query.
"""
replyToChannel = self.air.getSenderReturnChannel()
self.sendUpdateToChannel(
replyToChannel, 'receiveResults', [storeId,data])
def deleteBackupStores(self):
"""
Delete any backed up stores from previous year's
"""
year = time.localtime()[0]
for file in os.listdir(self.serverDataFolder):
if file.find('UDStoreBak')>-1 and file.find(str(year))==-1:
os.remove(file)
uber.air.writeServerEvent('Uberdog data store Info', 0 \
, 'Removing backup file: %s ' %file)