From a9aaed8d153245070152f696a3c90d6a10be28b9 Mon Sep 17 00:00:00 2001 From: Darren Ranalli Date: Thu, 16 Oct 2003 00:36:22 +0000 Subject: [PATCH] simpler spec autosave/backup --- direct/src/level/DistributedLevelAI.py | 49 ++++++++++++---------- direct/src/level/LevelSpec.py | 58 ++++++++++++++------------ 2 files changed, 60 insertions(+), 47 deletions(-) diff --git a/direct/src/level/DistributedLevelAI.py b/direct/src/level/DistributedLevelAI.py index c98d6819f4..93579b7f0c 100755 --- a/direct/src/level/DistributedLevelAI.py +++ b/direct/src/level/DistributedLevelAI.py @@ -20,7 +20,6 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI, self.zoneId = zoneId if __debug__: self.modified = 0 - self.makeBackup = 1 def generate(self, levelSpec): self.notify.debug('generate') @@ -41,7 +40,7 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI, def delete(self): self.notify.debug('delete') if __debug__: - self.saveSpec() + self.removeBackupTask() self.destroyLevel() DistributedObjectAI.DistributedObjectAI.delete(self) @@ -103,35 +102,43 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI, self.levelSpec.setAttribChange(entId, attribName, value, username) self.modified = 1 - self.scheduleSave() + self.scheduleAutosave() - SavePeriod = simbase.config.GetInt('factory-save-period', 10) - BackupPeriod = simbase.config.GetInt('factory-backup-period-minutes',5) + # backups are made every N minutes, starting from the time that + # the first edit is made + AutosavePeriod = simbase.config.GetFloat( + 'level-autosave-period-minutes', 5) - def scheduleSave(self): - if hasattr(self, 'saveTask'): + def scheduleAutosave(self): + if hasattr(self, 'autosaveTask'): return - self.saveTask = taskMgr.doMethodLater( - DistributedLevelAI.SavePeriod, - self.saveSpec, - self.uniqueName('saveSpec')) + self.autosaveTaskName = self.uniqueName('saveSpec') + self.autosaveTask = taskMgr.doMethodLater( + DistributedLevelAI.AutosavePeriod * 60, + 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): DistributedLevelAI.notify.info('saving spec') - if hasattr(self, 'saveTask'): - del self.saveTask + self.removeAutosaveTask() if not self.modified: DistributedLevelAI.notify.info('no changes to save') return - self.levelSpec.saveToDisk(createBackup=self.makeBackup) + self.levelSpec.saveToDisk() 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): senderId = self.air.msgSender diff --git a/direct/src/level/LevelSpec.py b/direct/src/level/LevelSpec.py index 47d13bfa88..87baf61ff2 100755 --- a/direct/src/level/LevelSpec.py +++ b/direct/src/level/LevelSpec.py @@ -3,6 +3,8 @@ import DirectNotifyGlobal from PythonUtil import list2dict, uniqueElements import string +if __debug__: + import os class LevelSpec: """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 return 'SpecImports' - def saveToDisk(self, filename=None, createBackup=1): - """returns zero on failure""" - import os + def getFilename(self): + return self.filename + def privGetBackupFilename(self): + return '%s.bak' % self.getFilename() + + def saveToDisk(self, filename=None, makeBackup=1): + """returns zero on failure""" if filename is None: filename = self.filename - if createBackup: + if makeBackup and self.privFileExists(filename): # create a backup try: - # does the file exist? - exists = 0 - try: - 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)) + backupFilename = self.privGetBackupFilename() + self.privRemoveFile(backupFilename) + os.rename(filename, backupFilename) except OSError, e: LevelSpec.notify.warning( '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 # wb to create a UNIX-format file f = file(filename, 'wb') @@ -184,6 +176,20 @@ class LevelSpec: f.close() 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): """Returns a string that contains the spec data, nicely formatted. This should be used when writing the spec out to file."""