repos.py :  » Network » Twisted » Twisted-1.0.3 » Twisted-1.0.3 » twisted » popsicle » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Twisted 
Twisted » Twisted 1.0.3 » Twisted 1.0.3 » twisted » popsicle » repos.py
# Twisted, the Framework of Your Internet
# Copyright (C) 2001-2002 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# -*- test-case-name: twisted.test.test_popsicle -*-


"""Abstract Repository classes for Popsicle.
"""

# System Imports
import os
import weakref

# Twisted Imports
from twisted.internet import defer
from twisted.persisted.styles import instance

# Sibling Imports
from twisted.popsicle.freezer import theFreezer,ISaver,PersistentReference,ref

class OIDNotFound(Exception):
    pass

class Repository:
    """A data storage that can be loaded from.  A repository of objects.

    I am an abstract class.  Subclass me and implement 'loadOID' and 'saveOID'

    Note that 'Repository' implementations are really open-ended.  This
    implementation strategy is suggested, though, and it is strongly suggested
    that authors of new repositories implement at least the caching shown here.

    However, facilities such as ad-hoc querying are omitted from this
    interface, and should be provided by e.g. an SQL Repository implementation.

    A repository is both a saver and a collection of PersistentReferences.
    """

    __implements__ = ISaver

    _lastOID = 0

    def saveOID(self, oid, obj):
        """
        Return a Deferred which will fire True when the object is saved.
        """
        raise NotImplementedError()


    def __init__(self):
        """Initialize me (set up cache).
        """
        self._cache = weakref.WeakValueDictionary()
        self._revCache = weakref.WeakKeyDictionary()
        self._pRefs = weakref.WeakValueDictionary()

    def load(self, oid):
        """Load an object from cache or by OID. Return a Deferred.

        This method should be called by external objects looking for a
        'starting point' into the repository.
        """
        oid = str(oid)
        if self._pRefs.has_key(oid):
            pRef = self._pRefs[oid]
        else:
            pRef = PersistentReference(str(oid), self, None)
        return pRef()

    def loadNow(self, oid):
        """External API for synchronously loading stuff.

        This should ONLY BE USED by code that is doing the actual
        loading/saving of structured objects.  Application code should always
        make calls through PersistentReference.__call__, otherwise it will not
        work on some back-ends.
        """
        oid = str(oid)
        if self._cache.get(oid):
            return self._cache[oid]
        # this code is copied and subtly changed from _cbLoadedOID.  I wish I
        # could have found a better way to do it, but -- expect bugs here!
        pRef = PersistentReference(oid, self, None)
        pRef.deferred = defer.Deferred()
        try:
            try:
                obj = self.loadOIDNow(oid)
            except:
                pRef.deferred.errback()
                raise
            else:
                theFreezer.setPersistentReference(obj, pRef)
                theFreezer.addSaver(obj, self)
                pRef.deferred.callback(obj)
                self.cache(oid, obj)
                return obj
        finally:
            del pRef.deferred

    def loadOIDNow(self, oid):
        """
        Implement me if you want to implement synchronous loading.
        """
        raise NotImplementedError()

    def loadOID(self, oid):
        """Implement me to return a Deferred if you want to implement asynchronous loading.
        """
        return defer.execute(self.loadOIDNow, oid)

    def createOID(self, oid, klass):
        """Create an instance with an oid and cache it.  This is useful during loading.
        """
        i = instance(klass)
        self.cache(oid, i, 0)
        return i

    def cleaned(self):
        """The freezer finished cleaning, and some of my objects were cleaned.
        """

    def loadRef(self, pRef):
        """
        Synonymous with ref.__call__().
        """
        oid = pRef.oid
        obj = self._cache.get(oid)
        if obj is not None:
            return defer.succeed(obj)
        elif self._pRefs.has_key(oid):
            # have a persistent ref, but no object
            return pRef.deferred
        else:
            # have no persistent ref
            d = defer.Deferred()
            self._pRefs[oid] = pRef
            pRef.deferred = d
            d2 = self.loadOID(oid)
            d2.addCallback(self._cbLoadedOID, oid, pRef)
            return d


    def _cbLoadedOID(self, result, oid, pref):
        theFreezer.setPersistentReference(result, pref)
        theFreezer.addSaver(result, self)
        self.cache(oid, result)
        pref.deferred.callback(result)
        del pref.deferred
        return result


    def generateOID(self, obj):
        """Generate an OID synchronously.

        Necessary for some types of persistence, but 
        """
        self._lastOID += 1
        return self._lastOID

    def cache(self, oid, obj, finished=1):
        """Weakly cache an object for the given OID.

        This means I own it, so also register it with the Freezer as such.
        """
        self._cache[oid] = obj
        self._revCache[obj] = oid

    def getOID(self, obj):
        if self._revCache.has_key(obj):
            return self._revCache[obj]
        else:
            # TODO: if OID generation really needs to be async...
            return ref(obj).acquireOID(self)

    def save(self, obj):
        """
        Save an object...

        If this is the first time I am saving this particular object, I need to
        locate a new unique ID for it.
        """
        theFreezer._savingRepo = self
        try:
            oid = self.getOID(obj)
            val = self.saveOID(oid, obj)
            self.cache(oid, obj)
            return val
        finally:
            theFreezer._savingRepo = None


class DirectoryRepository(Repository):
    def __init__(self, dirname):
        if not os.path.isdir(dirname):
            os.mkdir(dirname)
            fn = os.path.join(dirname,".popsiqnum")
        Repository.__init__(self)
        self.dirname = dirname

    def generateOID(self, obj):
        fn = os.path.join(self.dirname,".popsiqnum")
        try:
            seq = str(int(open(fn).read()) + 1)
        except IOError:
            seq = '0'
        open(fn,'w').write(seq)
        return seq

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.