freezer.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 » freezer.py
# -*- test-case-name: twisted.test.test_popsicle -*-
# 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
#

from twisted.internet import defer

import os
import weakref

from twisted.python import log

from twisted.persisted.styles import instance,instancemethod

try:
    True, False
except NameError:
    True, False = 1, 0

class Freezer:
    DELETE = 0
    SAVE = 1
    def __init__(self):
        self.persistentObjects = weakref.WeakKeyDictionary()
        self.dirtySet = {}
        self.cleaning = False
        self.pendingCall = None

    def addSaver(self, obj, saver):
        """Add an interested saver to a particular object.
        """
        ent = self.persistentObjects.get(obj)
        if not ent:
            ent = [None, []]
            self.persistentObjects[obj] = ent
        ent[1].append(saver)

    def removeSaver(self, obj, saver):
        ent = self.persistentObjects.get(obj)
        if not ent:
            return
        ent[1].remove(saver)

    def setPersistentReference(self, obj, pref):
        ent = self.persistentObjects.get(obj)
        if not ent:
            ent = [pref, []]
            self.persistentObjects[obj] = ent
        else:
            ent[0] = pref

    def getPersistentReference(self, obj, repo=None):
        ent = self.persistentObjects.get(obj)
        if not ent:
            pr = PersistentReference(None, None, obj)
            self.setPersistentReference(obj, pr)
            ent = self.persistentObjects[obj]
            if repo is not None:
                pr.acquireOID(repo)
        return ent[0]

    def dirty(self, obj, dirt=SAVE):
        if self.cleaning:
            raise RuntimeError("Can't flag an object as dirty while cleaning.")
        self._dirty(obj)
        from twisted.internet import reactor
        if not self.pendingCall:
            self.pendingCall = reactor.callLater(1.0, self._cleanTime)

    def _dirty(self, obj, dirt=SAVE):
        self.dirtySet[obj] = dirt

    def register(self, obj, repo):
        pr = self.getPersistentReference(obj, repo)
        self.dirty(obj)
        return pr

    def delete(self, obj):
        return self.dirty(obj, Freezer.DELETE)

    def _cleanTime(self):
        self.pendingCall = None
        self.clean()

    def clean(self):
        """Persistence tick.  Clean out the fridge, persist everything that
        wants to be saved.
        """
        #log.msg("cleaning popsicle")
        if self.pendingCall:
            self.pendingCall.cancel()
            self.pendingCall = None
        self.cleaning = True
        savers = {}
        try:
            while self.dirtySet:
                l = self.dirtySet.items()
                self.dirtySet.clear()
                for obj, doSave in l:
                    ent = self.persistentObjects.get(obj)
                    if not ent:
                        continue
                    for saver in ent[1]:
                        savers[saver] = 1
                        try:
                            if doSave:
                                # print 'saving',obj
                                saver.save(obj)
                            else:
                                # print 'deleting',obj
                                saver.delete(obj)
                        except:
                            # TODO: more error handling: backout transactions?
                            # restore state of objects?  what else?
                            log.deferr()
        finally:
            self.cleaning = False
            for saver in savers.keys():
                try:
                    saver.cleaned()
                except:
                    log.deferr()
            

try:
    theFreezer
except NameError:
    # Create the public interface singleton.
    theFreezer = Freezer()
    ref = theFreezer.getPersistentReference
    clean = theFreezer.clean
    dirty = theFreezer.dirty
    register = theFreezer.register

class ISaver:
    def save(self, object):
        """Save (and optionally index) the given object.
        """

    def delete(self, object):
        """Remove the given object.
        """


class PersistentReference:
    """I am a reference to a persistent object.

    The most interesting external interface is __call__: instances of this
    class should generally be treated as zero-argument functions which return
    Deferreds.
    """

    # Maintenance notes: there are 2 states for instances of this class.
    # either self.oid and self.repo are set to non-None values, in which case
    # this represents a stored object, or self.obj is set, in which case this
    # represents a value that *wants* to be stored.  In state 2, the object is
    # mutable, so care is taken to cache such objects (see
    # Freezer.getPersistentReference).  However, in state 1, prefs are
    # effectively immutable, so multiple may be instantiated with the same
    # OID/repo pair.
    
    def __init__(self, oid, repo, obj):
        self.oid = oid
        self.repo = repo
        self.obj = obj

    def __call__(self):
        """Load my object into memory, and return a Deferred which will fire
        it."""
        if self.obj is not None:
            return defer.succeed(self.obj)
        return self.repo.loadRef(self)

    def acquireOID(self, repo=None):
        """Take a PersistentReference that isn't really persistent yet, and
        associate it with a repository, give it an OID, and set it dirty.
        This should happen *synchronously during persistence*.
        """
        # TODO: better name for this method!!!
        if self.obj is not None:
            assert self.oid is None, "inconsistent state of p-ref: %s" % self.oid
            if repo is None:
                assert theFreezer._savingRepo is not None, "Calling acquireOID without repo outside of save!"
                repo = theFreezer._savingRepo
            o = self.obj
            self.repo = repo
            self.oid = repo.generateOID(o)
            self.obj = None
            theFreezer.addSaver(o, repo)
            # use internal API to avoid warning: we *really really* want to dirty
            theFreezer._dirty(o)
            repo.cache(self.oid, o, finished=0)
            return self.oid
        elif ((self.repo is repo) or
              repo is None and self.repo is theFreezer._savingRepo):
            assert self.oid is not None, "inconsistent state of p-ref"
            return self.oid
        else:
            # I don't belong to this repo, but I _do_ belong to someone else.
            return None
        ### assert False, "wrong repository!"
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.