148 lines
5.6 KiB
Python
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) |