oldschool-toontown/toontown/uberdog/DataStore.py

178 lines
6.5 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from pandac.PandaModules import ConfigVariableBool
from direct.task import Task
import pickle
import os
import sys
import dbm
import time
class DataStore:
QueryTypes = []
QueryTypes = dict(list(zip(QueryTypes, list(range(len(QueryTypes))))))
@classmethod
def addQueryTypes(cls, typeStrings):
superTypes = list(zip(list(cls.QueryTypes.values()), list(cls.QueryTypes.keys())))
superTypes.sort()
newTypes = [ item[1] for item in superTypes ] + typeStrings
newTypes = dict(list(zip(newTypes, list(range(1 + len(newTypes))))))
return newTypes
notify = DirectNotifyGlobal.directNotify.newCategory('DataStore')
wantAnyDbm = ConfigVariableBool('want-ds-anydbm', 1).getValue()
def __init__(self, filepath, writePeriod = 300, writeCountTrigger = 100):
self.filepath = filepath
self.writePeriod = writePeriod
self.writeCountTrigger = writeCountTrigger
self.writeCount = 0
self.data = None
self.className = self.__class__.__name__
if self.wantAnyDbm:
self.filepath += '-anydbm'
self.notify.debug('anydbm default module used: %s ' % dbm._defaultmod.__name__)
self.open()
return
def readDataFromFile(self):
if self.wantAnyDbm:
try:
if os.path.exists(self.filepath):
self.data = dbm.open(self.filepath, 'w')
self.notify.debug('Opening existing anydbm database at: %s.' % (self.filepath,))
else:
self.data = dbm.open(self.filepath, 'c')
self.notify.debug('Creating new anydbm database at: %s.' % (self.filepath,))
except dbm.error:
self.notify.warning('Cannot open anydbm database at: %s.' % (self.filepath,))
else:
try:
file = open(self.filepath + '.bu', 'r')
self.notify.debug('Opening backup pickle data file at %s.' % (self.filepath + '.bu',))
if os.path.exists(self.filepath):
os.remove(self.filepath)
except IOError:
try:
file = open(self.filepath, 'r')
self.notify.debug('Opening old pickle data file at %s..' % (self.filepath,))
except IOError:
file = None
self.notify.debug('New pickle data file will be written to %s.' % (self.filepath,))
if file:
data = pickle.load(file)
file.close()
self.data = data
else:
self.data = {}
return
def writeDataToFile(self):
if self.data is not None:
self.notify.debug('Data is now synced with disk at %s' % self.filepath)
if self.wantAnyDbm:
self.data.sync()
else:
try:
backuppath = self.filepath + '.bu'
if os.path.exists(self.filepath):
os.rename(self.filepath, backuppath)
outfile = open(self.filepath, 'w')
pickle.dump(self.data, outfile)
outfile.close()
if os.path.exists(backuppath):
os.remove(backuppath)
except EnvironmentError:
self.notify.warning(str(sys.exc_info()[1]))
else:
self.notify.warning('No data to write. Aborting sync.')
return
def syncTask(self, task):
task.timeElapsed += globalClock.getDt()
if task.timeElapsed > self.writePeriod:
if self.writeCount:
self.writeDataToFile()
self.resetWriteCount()
task.timeElapsed = 0.0
if self.writeCount > self.writeCountTrigger:
self.writeDataToFile()
self.resetWriteCount()
task.timeElapsed = 0.0
return Task.cont
def incrementWriteCount(self):
self.writeCount += 1
def resetWriteCount(self):
self.writeCount = 0
def close(self):
if self.data is not None:
self.writeDataToFile()
if self.wantAnyDbm:
self.data.close()
taskMgr.remove('%s-syncTask' % (self.className,))
self.data = None
return
def open(self):
self.close()
self.readDataFromFile()
self.resetWriteCount()
taskMgr.remove('%s-syncTask' % (self.className,))
t = taskMgr.add(self.syncTask, '%s-syncTask' % (self.className,))
t.timeElapsed = 0.0
def reset(self):
self.destroy()
self.open()
def destroy(self):
self.close()
if self.wantAnyDbm:
lt = time.asctime(time.localtime())
trans = ': '.maketrans('__')
t = lt.translate(trans)
head, tail = os.path.split(self.filepath)
newFileName = 'UDStoreBak' + t
if os.path.exists(self.filepath):
try:
os.rename(tail, newFileName)
uber.air.writeServerEvent('Uberdog data store Info', 0, 'Creating backup of file: %s saving as: %s' % (tail, newFileName))
except:
uber.air.writeServerEvent('Uberdog data store Info', 0, 'Unable to create backup of file: %s ' % tail)
else:
files = os.listdir(head)
for file in files:
if file.find(tail) > -1:
filename, ext = os.path.splitext(file)
try:
os.rename(file, newFileName + ext)
uber.air.writeServerEvent('Uberdog data store Info', 0, 'Creating backup of file: %s saving as: %s' % (file, newFileName + ext))
except:
uber.air.writeServerEvent('Uberdog data store Info', 0, 'Unable to create backup of file: %s ' % newFileName + ext)
else:
if os.path.exists(self.filepath + '.bu'):
os.remove(self.filepath + '.bu')
if os.path.exists(self.filepath):
os.remove(self.filepath)
def query(self, query):
if self.data is not None:
qData = pickle.loads(query)
results = self.handleQuery(qData)
qResults = pickle.dumps(results)
else:
results = None
qResults = pickle.dumps(results)
return qResults
def handleQuery(self, query):
results = None
return results