simpler spec autosave/backup

This commit is contained in:
Darren Ranalli 2003-10-16 00:36:22 +00:00
parent 8326fd6198
commit a9aaed8d15
2 changed files with 60 additions and 47 deletions

View File

@ -20,7 +20,6 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
self.zoneId = zoneId self.zoneId = zoneId
if __debug__: if __debug__:
self.modified = 0 self.modified = 0
self.makeBackup = 1
def generate(self, levelSpec): def generate(self, levelSpec):
self.notify.debug('generate') self.notify.debug('generate')
@ -41,7 +40,7 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
def delete(self): def delete(self):
self.notify.debug('delete') self.notify.debug('delete')
if __debug__: if __debug__:
self.saveSpec() self.removeBackupTask()
self.destroyLevel() self.destroyLevel()
DistributedObjectAI.DistributedObjectAI.delete(self) DistributedObjectAI.DistributedObjectAI.delete(self)
@ -103,35 +102,43 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
self.levelSpec.setAttribChange(entId, attribName, value, username) self.levelSpec.setAttribChange(entId, attribName, value, username)
self.modified = 1 self.modified = 1
self.scheduleSave() self.scheduleAutosave()
SavePeriod = simbase.config.GetInt('factory-save-period', 10) # backups are made every N minutes, starting from the time that
BackupPeriod = simbase.config.GetInt('factory-backup-period-minutes',5) # the first edit is made
AutosavePeriod = simbase.config.GetFloat(
'level-autosave-period-minutes', 5)
def scheduleSave(self): def scheduleAutosave(self):
if hasattr(self, 'saveTask'): if hasattr(self, 'autosaveTask'):
return return
self.saveTask = taskMgr.doMethodLater( self.autosaveTaskName = self.uniqueName('saveSpec')
DistributedLevelAI.SavePeriod, self.autosaveTask = taskMgr.doMethodLater(
self.saveSpec, DistributedLevelAI.AutosavePeriod * 60,
self.uniqueName('saveSpec')) self.autosaveSpec,
self.autosaveTaskName)
def removeAutosaveTask(self):
if hasattr(self, 'autosaveTask'):
taskMgr.remove(self.autosaveTaskName)
del self.autosaveTask
def autosaveSpec(self, task=None):
self.removeAutosaveTask()
if self.modified:
DistributedLevelAI.notify.info('autosaving spec')
filename = self.levelSpec.getFilename()
filename = '%s.autosave' % filename
self.levelSpec.saveToDisk(filename, makeBackup=0)
def saveSpec(self, task=None): def saveSpec(self, task=None):
DistributedLevelAI.notify.info('saving spec') DistributedLevelAI.notify.info('saving spec')
if hasattr(self, 'saveTask'): self.removeAutosaveTask()
del self.saveTask
if not self.modified: if not self.modified:
DistributedLevelAI.notify.info('no changes to save') DistributedLevelAI.notify.info('no changes to save')
return return
self.levelSpec.saveToDisk(createBackup=self.makeBackup) self.levelSpec.saveToDisk()
self.modified = 0 self.modified = 0
self.makeBackup = 0
def setMakeBackup(task, self=self):
self.makeBackup = 1
self.backupTask = taskMgr.doMethodLater(
DistributedLevelAI.BackupPeriod * 60,
setMakeBackup,
self.uniqueName('setMakeBackup'))
def requestCurrentLevelSpec(self, specHash, entTypeRegHash): def requestCurrentLevelSpec(self, specHash, entTypeRegHash):
senderId = self.air.msgSender senderId = self.air.msgSender

View File

@ -3,6 +3,8 @@
import DirectNotifyGlobal import DirectNotifyGlobal
from PythonUtil import list2dict, uniqueElements from PythonUtil import list2dict, uniqueElements
import string import string
if __debug__:
import os
class LevelSpec: class LevelSpec:
"""contains spec data for a level, is responsible for handing the data """contains spec data for a level, is responsible for handing the data
@ -138,42 +140,32 @@ class LevelSpec:
# name of module that should be imported by spec py file # name of module that should be imported by spec py file
return 'SpecImports' return 'SpecImports'
def saveToDisk(self, filename=None, createBackup=1): def getFilename(self):
"""returns zero on failure""" return self.filename
import os
def privGetBackupFilename(self):
return '%s.bak' % self.getFilename()
def saveToDisk(self, filename=None, makeBackup=1):
"""returns zero on failure"""
if filename is None: if filename is None:
filename = self.filename filename = self.filename
if createBackup: if makeBackup and self.privFileExists(filename):
# create a backup # create a backup
try: try:
# does the file exist? backupFilename = self.privGetBackupFilename()
exists = 0 self.privRemoveFile(backupFilename)
try: os.rename(filename, backupFilename)
os.stat(filename)
exists = 1
except OSError:
pass
if exists:
def getBackupFilename(num, filename=filename):
return '%s.%03i' % (filename, num)
numBackups = 200
try:
os.unlink(getBackupFilename(numBackups-1))
except OSError:
pass
for i in range(numBackups-1,0,-1):
try:
os.rename(getBackupFilename(i-1),
getBackupFilename(i))
except OSError:
pass
os.rename(filename, getBackupFilename(0))
except OSError, e: except OSError, e:
LevelSpec.notify.warning( LevelSpec.notify.warning(
'error during backup: %s' % str(e)) 'error during backup: %s' % str(e))
self.privRemoveFile(filename)
self.privSaveToDisk(filename)
def privSaveToDisk(self, filename):
"""internal. saves spec to file. returns zero on failure"""
retval = 1 retval = 1
# wb to create a UNIX-format file # wb to create a UNIX-format file
f = file(filename, 'wb') f = file(filename, 'wb')
@ -184,6 +176,20 @@ class LevelSpec:
f.close() f.close()
return retval return retval
def privFileExists(self, filename):
try:
os.stat(filename)
return 1
except OSError:
return 0
def privRemoveFile(self, filename):
try:
os.remove(filename)
return 1
except OSError:
return 0
def getPrettyString(self): def getPrettyString(self):
"""Returns a string that contains the spec data, nicely formatted. """Returns a string that contains the spec data, nicely formatted.
This should be used when writing the spec out to file.""" This should be used when writing the spec out to file."""