2
"""Persistence support for Pottery
4
For now, this defines a service which holds a reference to the game's
5
realm instance. Periodically, the realm is pickled and written to
6
disk. When the service is created, if an existing pickled realm
7
exists on disk, it is loaded and used instead of the realm passed in.
12
import cPickle as pickle
14
from twisted.application import service
15
from twisted.internet import task
16
from twisted.python import log
18
class PersistenceService(service.Service):
19
def __init__(self, fname, realm):
21
if os.path.exists(fname):
22
realm = self._unpersist()
25
def startService(self):
26
self.loop = task.LoopingCall(self._persist)
27
self.loop.start(60).addErrback(log.err)
29
def stopService(self):
34
# Try to reap the previous persistence child.
36
os.waitpid(-1, os.WNOHANG)
38
if e.errno != errno.ECHILD:
41
# Fork and continue normal execution in the parent. In the child,
42
# try to acquire the persist lock. If it cannot be acquired,
43
# return. Otherwise, pickle game state to a new file, move the
44
# entire result over the existing game state file, and release the
50
os.mkdir(self.fname + '.lock')
52
if e.errno != errno.EEXIST:
56
fObj = file(self.fname + '.tmp', 'wb')
57
fObj.write(pickle.dumps(self.realm))
59
os.rename(self.fname + '.tmp', self.fname)
61
os.rmdir(self.fname + '.lock')
66
fObj = file(self.fname, 'rb')
67
return pickle.loads(fObj.read())