Example #1
0
    def __init__(self, ID, *url, **kw):
        """
        Instantiates me with an item store keyed to the supplied hashable
        I{ID}.  Ensures that I have access to a class-wide instance of a
        L{Search} object so that I can update the database's full-text index
        when writing values containing text content.

        In addition to any engine-specifying keywords supplied, the following
        are particular to this constructor:

        @param ID: A hashable object that is used as my unique identifier.
        
        @keyword search: Set C{True} if text indexing is to be updated when items
          are added, updated, or deleted.

        """
        try:
            self.ID = hash(ID)
        except:
            raise TypeError("Item IDs must be hashable")
        # In-memory Caches
        self.data, self.keyCache = {}, {}
        # For tracking lazy writes
        self.writeTracker = DeferredTracker()
        # My very own persistent items store
        if url:
            self.i = items.Items(self.ID, url[0], **kw)
        else:
            self.i = items.Items(self.ID)
        self.isPreloadMode = False
Example #2
0
class PersistentDictBase(DictMixin, object):
    """
    I am a base class for a database-persistent dictionary-like object uniquely
    identified by the hashable constructor argument I{ID}.

    Before you use any instance of me, you must specify the parameters for
    creating an SQLAlchemy database engine. A single argument is used, which
    specifies a connection to a database via an RFC-1738 url. In addition, the
    following keyword options can be employed, which are listed in the API docs
    for L{sasync} and L{sasync.database.AccessBroker}.

    You can set an engine globally, for all instances of me, via the
    L{sasync.engine} package-level function, or via the L{AccessBroker.engine}
    class method. Alternatively, you can specify an engine for one particular
    instance by supplying the parameters to my constructor.
    
    In my default mode of operation, both read and write item accesses occur
    asynchronously and return deferreds. However, you can put me into B{load}
    mode by calling my L{preload} method. At that point, all my items will be
    accessed synchronously as with any other dictionary. No other deferreds
    will be returned from any item access. Lazy writing will still be done, but
    behind the scenes and with no API access to write completions.

    B{IMPORTANT}: As with all sasync data store objects, make sure you call my
    L{shutdown} method for an instance of me that you're done with before
    allowing that instance to be deleted.

    @ivar isPreloadMode: Boolean flag that indicates if I am operating in
        preload mode.

    """
    def __init__(self, ID, *url, **kw):
        """
        Instantiates me with an item store keyed to the supplied hashable
        I{ID}.  Ensures that I have access to a class-wide instance of a
        L{Search} object so that I can update the database's full-text index
        when writing values containing text content.

        In addition to any engine-specifying keywords supplied, the following
        are particular to this constructor:

        @param ID: A hashable object that is used as my unique identifier.
        
        @keyword search: Set C{True} if text indexing is to be updated when items
          are added, updated, or deleted.

        """
        try:
            self.ID = hash(ID)
        except:
            raise TypeError("Item IDs must be hashable")
        # In-memory Caches
        self.data, self.keyCache = {}, {}
        # For tracking lazy writes
        self.writeTracker = DeferredTracker()
        # My very own persistent items store
        if url:
            self.i = items.Items(self.ID, url[0], **kw)
        else:
            self.i = items.Items(self.ID)
        self.isPreloadMode = False

    def preload(self):
        """
        This method preloads all my items from the database (which may take a
        while), returning a C{Deferred} that fires when everything's ready and
        I've completed the transition into B{preload} mode.
        """
        d = self.loadAll()
        d.addCallback(lambda _: setattr(self, 'isPreloadMode', True))
        return d
    
    def shutdown(self, *null):
        """
        Shuts down my database L{Transactor} and its synchronous task queue.
        """
        d = self.writeTracker.deferToAll()
        d.addCallback(self.i.shutdown)
        return d
    
    def loadAll(self, *null):
        """
        Loads all items from the database, setting my in-memory dict and key
        cache accordingly.
        """
        def loaded(items):
            self.data.clear()
            self.data.update(items)
            self.keyCache = dict.fromkeys(items.keys(), True)
            return self.data

        return self.i.loadAll().addCallback(loaded)

    def deferToWrites(self, lastOnly=False):
        """
        @see: L{DeferredTracker.deferToAll}
        
        """
        if lastOnly:
            d = self.writeTracker.deferToLast()
        else:
            d = self.writeTracker.deferToAll()
        return d