예제 #1
0
class Fixed(Float):

    fixed_digits = 1
    fixed_scale = 0

    def mdl_typeCode(klass):
        return TypeCode(kind=TCKind.Fixed,
                        fixed_digits=klass.fixed_digits,
                        fixed_scale=klass.fixed_scale)

    mdl_typeCode = binding.classAttr(binding.Make(mdl_typeCode))
예제 #2
0
class String(PrimitiveType):

    length = 0

    def mdl_fromString(klass, value):
        return value

    mdl_typeKind = TCKind.tk_string

    def mdl_typeCode(klass):
        return TypeCode(kind=klass.mdl_typeKind, length=klass.length)

    mdl_typeCode = binding.classAttr(binding.Make(mdl_typeCode))
예제 #3
0
class FacadeDM(binding.Component):

    """DM that just returns objects from other DM(s) via a different key"""

    protocols.advise(
        instancesProvide=[IKeyableDM]
    )

    def __getitem__(self, oid, state=None):

        ob = self.cache.get(oid,self)

        if ob is not self:

            # double-check identity
            if oid==self.oidFor(ob):
                return ob

            # Oops, key no longer valid, drop it
            del self.cache[oid]

        ob = self._retrieve(oid, state)

        if ob is not None:
            self.cache[oid] = ob
            return ob

        raise KeyError, oid

    preloadState = __getitem__

    cache = binding.Make('peak.storage.caches:WeakCache')

    def _retrieve(self, oid, state=None):
        """Look up 'oid' in underlying storage and return it, or 'None'"""
        raise NotImplementedError

    def oidFor(self, ob):
        """Return this DM's OID for 'ob'; used to validate consistency"""
        raise NotImplementedError
예제 #4
0
class EntityDM(QueryDM):

    protocols.advise(
        instancesProvide=[IWritableDM]
    )

    def oidFor(self, ob):

        if ob._p_jar is self:

            oid = ob._p_oid

            if oid is None:
                # force it to have an ID by saving it
                ob._p_changed = 1
                self.flush(ob)
                return ob._p_oid

            else:
                return oid

        else:
            return self._thunk(ob)


    def newItem(self,klass=None):

        if klass is None:
            klass = self.defaultClass

        if klass is None:
            raise NotImplementedError

        ob=klass()
        ob.__setstate__(self._defaultState(ob))

        self.add(ob)
        return ob



    # Set/state management

    dirty = binding.Make(dict)
    saved = binding.Make(dict)
    to_delete = binding.Make(list)

    def flush(self, ob=None):

        markSaved = self.saved.setdefault
        dirty = self.dirty
        orig_ob = ob

        if ob is None:
            obs = dirty.values()
        else:
            obs = [ob]

        for ob in obs:

            if ob._p_oid is None:

                # No oid, it's a new object that needs saving
                oid = ob._p_oid = self._new(ob)
                self.cache[oid]=ob

            else:
                # just save it the ordinary way
                self._save(ob)

            # Update status flags and object sets
            key = id(ob)
            markSaved(key,ob)
            if key in dirty:
                del dirty[key]
            ob._p_changed = False

        if orig_ob is None and self.to_delete:
            self._delete_oids(self.to_delete)
            del self.to_delete


    # Private abstract methods/attrs

    defaultClass = None

    def _save(self, ob):
        raise NotImplementedError

    def _new(self, ob):
        raise NotImplementedError

    def _defaultState(self, ob):
        return ob.__getstate__()

    def _thunk(self, ob):
        raise NotImplementedError

    def _delete_oids(self,oidList):
        raise NotImplementedError

    def _check(self,ob):
        """Override this to raise an error if 'ob' is unsuitable for storing"""

    # Persistence.IPersistentDataManager methods

    def register(self, ob):
        # Ensure that we have a transaction service and we've joined
        # the transaction in progress...
        self.joinedTxn

        # precondition:
        #   object has been changed since last save
        # postcondition:
        #   ob is in 'dirty' set
        #   DM is registered w/transaction if not previously registered
        key = id(ob)

        # Ensure it's in the 'dirty' set
        self.dirty.setdefault(key,ob)

        return self.joinedTxn

    # ITransactionParticipant methods

    def readyToVote(self, txnService):
        if self.dirty or self.to_delete:
            self.flush()
            return False
        else:
            return True


    def voteForCommit(self, txnService):
        # Everything should have been written by now...  If not, it's VERY BAD
        # because the DB we're storing to might've already gotten a tpc_vote(),
        # and won't accept writes any more.  So raise holy hell if we're dirty!
        assert not self.dirty and not self.to_delete


    def commitTransaction(self, txnService):
        self.saved.clear()
        self._delBinding('to_delete')


    def abortTransaction(self, txnService):

        for ob in self.dirty.values():
            ob._p_changed = False
            ob._p_deactivate()

        self.dirty.clear()

        for ob in self.saved.values():
            if ob._p_jar is self:   # don't deactivate formerly-owned objects               
                ob._p_deactivate()

        self.saved.clear()
        self._delBinding('to_delete')





    def add(self,ob):
        if not isinstance(ob,Persistent):
            raise TypeError("Not a persistent object", ob)

        if ob._p_jar is self:
            return  # Nothing needed here
        elif ob._p_jar is not None:
            raise ValueError("Already in another DM", ob, ob._p_jar)

        self._check(ob)
        if ob._p_oid is not None:
            if self.get(ob._p_oid) is not None:
                raise InvalidKeyError("Duplicate key", ob._p_oid)
            self.cache[ob._p_oid] = ob

        ob._p_jar = self
        self.register(ob)


    def remove(self,ob):
        if ob._p_jar is not self:
            raise ValueError("Doesn't belong to this DM", ob, ob._p_jar)

        key = id(ob)
        if key in self.dirty:
            del self.dirty[key]

        # note: don't delete from 'saved', because we might still need to roll
        # back the object's state if it gets re-added, but the txn aborts, and
        # we don't have 'resetStatesAfterTxn' set.

        del self.cache[ob._p_oid]
        ob._p_jar = None

        self.to_delete.append(ob._p_oid)

        # Ensure that we have a transaction service and we've joined
        # the transaction in progress...
        self.joinedTxn
예제 #5
0
class QueryDM(TransactionComponent):

    resetStatesAfterTxn = True

    protocols.advise(
        instancesProvide=[IDataManager]
    )

    to_delete = ()

    def __getitem__(self, oid, state=None):

        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        if oid in self.to_delete:
            raise InvalidKeyError("Reference to deleted key", oid)

        ob = self.cache.get(oid,self)

        if ob is not self:
            return ob

        ob = self._ghost(oid,state)

        if isinstance(ob,Persistent):

            ob._p_jar = self
            ob._p_oid = oid

            if state is None:
                ob._p_deactivate()
            else:
                ob.__setstate__(state)

        self.cache[oid] = ob
        return ob

    preloadState = __getitem__

    # Private abstract methods/attrs

    cache = binding.Make('peak.storage.caches:WeakCache')

    defaultClass = PersistentQuery

    def _ghost(self, oid, state=None):

        klass = self.defaultClass

        if klass is None:
            raise NotImplementedError

        return klass()


    def _load(self, oid, ob):
        raise NotImplementedError


    # Persistence.IPersistentDataManager methods

    def setstate(self, ob):

        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        oid = ob._p_oid
        assert oid is not None
        ob.__setstate__(self._load(oid,ob))


    def mtime(self, ob):
        pass    # return None

    def register(self, ob):
        raise TypeError("Attempt to modify query result", ob)



    # ITransactionParticipant methods

    def finishTransaction(self, txnService, committed):

        if self.resetStatesAfterTxn:

            for oid, ob in self.cache.items():
                if isinstance(ob,Persistent):
                    ob._p_deactivate()

        super(QueryDM,self).finishTransaction(txnService,committed)

    # Misc.

    def __iter__(self):
        raise NotImplementedError


    def __contains__(self, ob):
        if isinstance(ob,Persistent):
            return ob._p_jar is self
        return self.get(ob) is not None


    def get(self,oid,default=None):
        if self.resetStatesAfterTxn:
            # must always be used in a txn
            self.joinedTxn

        if oid in self.cache:
            return self.cache[oid]
        elif oid in self.to_delete:
            return default
        try:
            state = self._load(oid,None)
        except InvalidKeyError:
            return default
        else:
            return self.preloadState(oid,state)