Example #1
0
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()
Example #2
0
 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
Example #3
0
 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
Example #4
0
 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()
Example #5
0
 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']
Example #6
0
 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']
Example #7
0
 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()
Example #8
0
 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()
Example #9
0
 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)
Example #10
0
 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)
Example #11
0
 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)
Example #12
0
 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)
Example #13
0
 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)
Example #14
0
 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)
Example #15
0
 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)
Example #16
0
 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)
Example #17
0
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()
Example #18
0
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()
Example #19
0
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()
Example #20
0
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
Example #21
0
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()