class Session(object): """ Representation of the game state. """ _persistent_attributes = ('scheduler', 'started', 'lastroom', 'universe', 'characters', 'player', 'debugging') # default values scheduler = None # Scheduler instance started = False # Is game started yet? (I.e. have player turns/actions begun) lastroom = None # Used to determine auto-placement of items universe = None # Top level container object (provides storage for entire game state) characters = () # List of character agents (references into universe) player = () # List of player character agents (normally only 1 in PUB) debugging = False # Debugging mode is for use during game development def __init__(self, storagefile="default.sav"): self.storage = Connection(FileStorage(storagefile)) self.root = self.storage.get_root() self.running = False def __setattr__(self, name, value): if name in self._persistent_attributes: self.root[name] = value else: object.__setattr__(self, name, value) def __getattribute__(self, name): persistent_attributes = object.__getattribute__( self, '_persistent_attributes') if name in persistent_attributes: try: return self.root[name] except KeyError: return getattr(self.__class__, name) else: return object.__getattribute__(self, name) def new_game(self): """ Start up a new game (clear the storage instance). """ self.scheduler = None self.started = True self.lastroom = None self.universe = None self.characters = None self.player = None self.debugging = False self.commit() self.pack() def commit(self): self.storage.commit() def abort(self): self.storage.abort() def pack(self): self.storage.pack()
def _scenario(self): c1 = Connection(self._get_storage()) c2 = Connection(self._get_storage()) c1.get_root()['A'] = Persistent() c1.get_root()['B'] = Persistent() c1.get_root()['A'].a = 1 c1.commit() c2.abort() c1.cache.recent_objects.discard(c1.get_root()['A']) # Imagine c1 has been running for a while, and # cache management, for example, has caused the # cache reference to be weak. return c1, c2
def _scenario(self): c1 = Connection(self._get_storage()) c2 = Connection(self._get_storage()) c1.get_root()['A'] = Persistent() c1.get_root()['B'] = Persistent() c1.get_root()['A'].a = 1 c1.commit() c2.abort() c1.cache.recent_objects.discard(c1.get_root()['A']) # Imagine c1 has been running for a while, and # cache management, for example, has caused the # cache reference to be weak. return c1, c2
def check_oid_reuse(self): # Requires ShelfStorage oid reuse pack semantics s1 = ClientStorage(address=self.address) s1.oid_pool_size = 1 c1 = Connection(s1) r1 = c1.get_root() s2 = ClientStorage(address=self.address) s2.oid_pool_size = 1 c2 = Connection(s2) r2 = c2.get_root() r1['a'] = PersistentDict() r1['b'] = PersistentDict() c1.commit() c2.abort() a_oid = r1['a']._p_oid assert 'a' in r1 and 'b' in r1 and len(r1['b']) == 0 assert 'a' in r2 and 'b' in r2 and len(r2['b']) == 0 del r2['a'] # remove only reference to a c2.commit() c2.pack() # force relinquished oid back into availability sleep(0.5) # Give time for pack to complete c2.abort() assert c2.get(a_oid) is None c1.abort() assert c1.get(a_oid)._p_is_ghost() r2['b']['new'] = Persistent() r2['b']['new'].bogus = 1 c2.commit() assert c2.get(a_oid) is r2['b']['new'] c1.abort() assert c1.get(a_oid).__class__ == PersistentDict r1['b']['new'].bogus assert c1.get(a_oid).__class__ == Persistent s1.close()
def check_conflict(self): b = Connection(self._get_storage()) c = Connection(self._get_storage()) rootb = b.get(int8_to_str(0)) rootb['b'] = Persistent() rootc = c.get(int8_to_str(0)) rootc['c'] = Persistent() c.commit() raises(ConflictError, b.commit) raises(KeyError, rootb.__getitem__, 'c') transaction_serial = b.transaction_serial b.abort() assert b.get_transaction_serial() > transaction_serial assert rootb._p_is_ghost() rootc['d'] = Persistent() c.commit() rootb['d']
def check_conflict(self): b = Connection(self._get_storage()) c = Connection(self._get_storage()) rootb = b.get(int8_to_str(0)) rootb['b'] = Persistent() rootc = c.get(int8_to_str(0)) rootc['c'] = Persistent() c.commit() raises(ConflictError, b.commit) raises(KeyError, rootb.__getitem__, 'c') transaction_serial = b.transaction_serial b.abort() assert b.get_transaction_serial() > transaction_serial assert rootb._p_is_ghost() rootc['d'] = Persistent() c.commit() rootb['d']
def check_more(self): storage = TempFileStorage() connection = Connection(storage) root=connection.get_root() assert not root._p_is_ghost() root['a'] = 1 assert root._p_is_unsaved() del root['a'] connection.abort() assert root._p_is_ghost() raises(AttributeError, getattr, root, 'a') root._p_set_status_saved() assert root._p_is_saved() root._p_set_status_unsaved() assert root._p_is_unsaved() root._p_set_status_ghost() assert root._p_is_ghost() root._p_set_status_unsaved()
def check_more(self): storage = TempFileStorage() connection = Connection(storage) root=connection.get_root() assert not root._p_is_ghost() root['a'] = 1 assert root._p_is_unsaved() del root['a'] connection.abort() assert root._p_is_ghost() raises(AttributeError, getattr, root, 'a') root._p_set_status_saved() assert root._p_is_saved() root._p_set_status_unsaved() assert root._p_is_unsaved() root._p_set_status_ghost() assert root._p_is_ghost() root._p_set_status_unsaved()
def b(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oid = r['a9']._p_oid del r['a9'] c.commit() c.pack() c.abort() assert len([repr(oid) for oid, record in s.gen_oid_record()]) == 10 new_oid = s.new_oid() assert new_oid == deleted_oid new_oid = s.new_oid() assert new_oid == int8_to_str(11)
def b(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oid = r['a9']._p_oid del r['a9'] c.commit() c.pack() c.abort() assert len([repr(oid) for oid, record in s.gen_oid_record()]) == 10 new_oid = s.new_oid() assert new_oid == deleted_oid new_oid = s.new_oid() assert new_oid == int8_to_str(11)
def a(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oids = [ r['a0']._p_oid, r['a2']._p_oid, r['a7']._p_oid, r['a8']._p_oid ] del r['a0'] del r['a2'] del r['a7'] del r['a8'] c.commit() c.pack() c.abort() assert c.get(deleted_oids[0])._p_is_ghost() assert c.get(deleted_oids[1])._p_is_ghost() raises(KeyError, getattr, c.get(deleted_oids[0]), 'a') assert len([repr(oid) for oid, record in s.gen_oid_record()]) == 7 c.commit() c.pack() new_oid = s.new_oid() assert new_oid == deleted_oids[-1], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-2], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-3], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-4], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == int8_to_str(11), repr(new_oid) new_oid = s.new_oid() assert new_oid == int8_to_str(12), repr(new_oid)
def c(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oid = r['a9']._p_oid del r['a9'] c.commit() c.pack() c.abort() r.clear() c.commit() c.pack() c.abort() new_oid = s.new_oid() assert new_oid == int8_to_str(1), repr(new_oid) new_oid = s.new_oid() assert new_oid == int8_to_str(2), repr(new_oid)
def c(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oid = r['a9']._p_oid del r['a9'] c.commit() c.pack() c.abort() r.clear() c.commit() c.pack() c.abort() new_oid = s.new_oid() assert new_oid == int8_to_str(1), repr(new_oid) new_oid = s.new_oid() assert new_oid == int8_to_str(2), repr(new_oid)
def check_fine_conflict(self): c1 = Connection(self._get_storage()) c2 = Connection(self._get_storage()) c1.get_root()['A'] = Persistent() c1.get_root()['A'].a = 1 c1.get_root()['B'] = Persistent() c1.commit() c2.abort() # c1 has A loaded. assert not c1.get_root()['A']._p_is_ghost() c1.get_root()['B'].b = 1 c2.get_root()['A'].a = 2 c2.commit() # Even though A has been changed by c2, # c1 has not accessed an attribute of A since # the last c1.commit(), so we don't want a ConflictError. c1.commit() assert c1.get_root()['A']._p_is_ghost() c1.get_root()['A'].a # accessed! c1.get_root()['B'].b = 1 c2.get_root()['A'].a = 2 c2.commit() raises(WriteConflictError, c1.commit)
def check_fine_conflict(self): c1 = Connection(self._get_storage()) c2 = Connection(self._get_storage()) c1.get_root()['A'] = Persistent() c1.get_root()['A'].a = 1 c1.get_root()['B'] = Persistent() c1.commit() c2.abort() # c1 has A loaded. assert not c1.get_root()['A']._p_is_ghost() c1.get_root()['B'].b = 1 c2.get_root()['A'].a = 2 c2.commit() # Even though A has been changed by c2, # c1 has not accessed an attribute of A since # the last c1.commit(), so we don't want a ConflictError. c1.commit() assert c1.get_root()['A']._p_is_ghost() c1.get_root()['A'].a # accessed! c1.get_root()['B'].b = 1 c2.get_root()['A'].a = 2 c2.commit() raises(WriteConflictError, c1.commit)
def a(self): f = File(prefix='shelftest') name = f.get_name() f.close() s = FileStorage(name) c = Connection(s) r = c.get_root() for x in range(10): r["a%s" % x] = Persistent() c.commit() deleted_oids = [ r['a0']._p_oid, r['a2']._p_oid, r['a7']._p_oid, r['a8']._p_oid] del r['a0'] del r['a2'] del r['a7'] del r['a8'] c.commit() c.pack() c.abort() assert c.get(deleted_oids[0])._p_is_ghost() assert c.get(deleted_oids[1])._p_is_ghost() raises(ReadConflictError, getattr, c.get(deleted_oids[0]), 'a') assert len([repr(oid) for oid, record in s.gen_oid_record()]) == 7 c.commit() c.pack() new_oid = s.new_oid() assert new_oid == deleted_oids[-1], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-2], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-3], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == deleted_oids[-4], (new_oid, deleted_oids) new_oid = s.new_oid() assert new_oid == int8_to_str(11), repr(new_oid) new_oid = s.new_oid() assert new_oid == int8_to_str(12), repr(new_oid)
def main(): parser = OptionParser() parser.set_description('Stress test a Durus Server') parser.add_option('--port', dest='port', default=DEFAULT_PORT, type='int', help='Port to listen on. (default=%s)' % DEFAULT_PORT) parser.add_option('--host', dest='host', default=DEFAULT_HOST, help='Host to listen on. (default=%s)' % DEFAULT_HOST) parser.add_option('--cache_size', dest="cache_size", default=4000, type="int", help="Size of client cache (default=4000)") parser.add_option('--max-loops', dest='loops', default=None, type='int', help='Maximum number of loops before exiting.') (options, args) = parser.parse_args() from durus.logger import logger logger.setLevel(5) storage = ClientStorage(host=options.host, port=options.port) connection = Connection(storage, cache_size=options.cache_size) try: if 'obj' not in connection.get_root(): init_db(connection) verify_db(connection, all=True) connection.commit() except ConflictError: connection.abort() n = options.loops while n is None or n > 0: if n is not None: n -= 1 try: if hasattr(sys, 'gettotalrefcount'): sys.stdout.write('refs = %s\n' % sys.gettotalrefcount()) if randbool(): connection.abort() verify_db(connection) mutate_db(connection) connection.commit() maybe_sleep() except ConflictError: sys.stdout.write('conflict\n') connection.abort() maybe_sleep()
def main(): parser = OptionParser() parser.set_description("Stress test a Durus Server") parser.add_option( "--port", dest="port", default=DEFAULT_PORT, type="int", help="Port to listen on. (default=%s)" % DEFAULT_PORT ) parser.add_option( "--host", dest="host", default=DEFAULT_HOST, help="Host to listen on. (default=%s)" % DEFAULT_HOST ) parser.add_option( "--cache_size", dest="cache_size", default=4000, type="int", help="Size of client cache (default=4000)" ) parser.add_option( "--max-loops", dest="loops", default=None, type="int", help="Maximum number of loops before exiting." ) (options, args) = parser.parse_args() from durus.logger import logger logger.setLevel(5) storage = ClientStorage(host=options.host, port=options.port) connection = Connection(storage, cache_size=options.cache_size) try: if "obj" not in connection.get_root(): init_db(connection) verify_db(connection, all=True) connection.commit() except ConflictError: connection.abort() n = options.loops while n is None or n > 0: if n is not None: n -= 1 try: if hasattr(sys, "gettotalrefcount"): sys.stdout.write("refs = %s\n" % sys.gettotalrefcount()) if randbool(): connection.abort() verify_db(connection) mutate_db(connection) connection.commit() maybe_sleep() except ConflictError: sys.stdout.write("conflict\n") connection.abort() maybe_sleep()
class XdserverBackend(object): """Schevo backend that directly uses Xdserver 3.9.""" DEFAULT_CACHE_SIZE = 100000 description = __doc__.splitlines()[0].strip() backend_args_help = """ cache_size=%(DEFAULT_CACHE_SIZE)i (int) Maximum number of objects to keep in the cache. client=None (xdserver.client.Client instance) An existing client connection to use; overrides host and port in URL. """ % locals() __test__ = False BTree = BTree PDict = PersistentDict PList = PersistentList conflict_exceptions = (ConflictError,) # TestMethods_CreatesDatabase = Xdserver_TestMethods_CreatesDatabase # TestMethods_CreatesSchema = Xdserver_TestMethods_CreatesSchema # TestMethods_EvolvesSchemata = Xdserver_TestMethods_EvolvesSchemata def __init__(self, database, cache_size=DEFAULT_CACHE_SIZE, host=xdserver.client.DEFAULT_HOST, port=xdserver.client.DEFAULT_PORT, client=None, ): self.database = database self.cache_size = cache_size self.host = host self.port = port self.client = client self.is_open = False self.open() @classmethod def usable_by_backend(cls, filename): """Return (`True`, *additional backend args*) if the named file is usable by this backend, or `False` if not.""" return False @property def has_db(self): """Return `True` if the backend contains a Schevo database.""" return self.get_root().has_key('SCHEVO') def close(self): """Close the underlying storage (and the connection if needed).""" self.storage.close() self.is_open = False def commit(self): """Commit the current transaction.""" self.conn.commit() def get_root(self): """Return the backend's `root` object.""" return self.conn.get_root() def open(self): """Open the underlying storage based on initial arguments.""" if not self.is_open: # Find or create storage. if self.client is not None: self.storage = self.client.storage(self.database) elif None not in (self.host, self.port): self.client = xdserver.client.Client(self.host, self.port) self.storage = self.client.storage(self.database) # Connect to storage. self.conn = Connection( self.storage, cache_size=self.cache_size) self.is_open = True def pack(self): """Pack the underlying storage.""" self.conn.pack() def rollback(self): """Abort the current transaction.""" self.conn.abort()
eliza = NamedObject('a bespectacled old lady', 'Eliza', set(['old', 'lady', 'woman']), startroom) eliza.addDelegate(ChattyDelegate(eliza)) startroom.add(eliza) if os.access("mudlib.durus", os.F_OK): os.remove("mudlib.durus") try: connection = Connection(FileStorage("mudlib.durus")) root = connection.get_root() # pylint: disable-msg= E1101,W0212 #pylint doesn't know about our metaclass hackery, and complains about the #use of the leading underscore variables. root['startroom'] = startroom root['all_rooms'] = Room._instances root['all_objects'] = MUDObject._instances root['targettable_objects_by_name'] = NamedObject._name_registry root['ticker'] = Ticker(0.1) # pylint: enable-msg= E1101,W0212 connection.commit() except: connection.abort() #if os.access("mudlib.durus", os.F_OK): # os.remove("mudlib.durus") raise
class Session(object): """ Representation of the game state. """ _persistent_attributes = ( 'scheduler', 'started', 'lastroom', 'universe', 'characters', 'player', 'debugging') # default values scheduler = None # Scheduler instance started = False # Is game started yet? (I.e. have player turns/actions begun) lastroom = None # Used to determine auto-placement of items universe = None # Top level container object (provides storage for entire game state) characters = () # List of character agents (references into universe) player = () # List of player character agents (normally only 1 in PUB) debugging = False # Debugging mode is for use during game development def __init__(self, storagefile="default.sav"): self.storage = Connection(FileStorage(storagefile)) self.root = self.storage.get_root() self.running = False def __setattr__(self, name, value): if name in self._persistent_attributes: self.root[name] = value else: object.__setattr__(self, name, value) def __getattribute__(self, name): persistent_attributes = object.__getattribute__(self, '_persistent_attributes') if name in persistent_attributes: try: return self.root[name] except KeyError: return getattr(self.__class__, name) else: return object.__getattribute__(self, name) def new_game(self): """ Start up a new game (clear the storage instance). """ self.scheduler = None self.started = True self.lastroom = None self.universe = None self.characters = None self.player = None self.debugging = False self.commit() self.pack() def commit(self): self.storage.commit() def abort(self): self.storage.abort() def pack(self): self.storage.pack()