Ejemplo n.º 1
0
    def get(self, oid):
        """Return the persistent object with oid 'oid'."""
        if self.opened is None:
            raise ConnectionStateError("The database connection is closed")

        obj = self._cache.get(oid, None)
        if obj is not None:
            return obj
        obj = self._added.get(oid, None)
        if obj is not None:
            return obj
        obj = self._pre_cache.get(oid, None)
        if obj is not None:
            return obj

        p, _ = self._storage.load(oid)
        obj = self._reader.getGhost(p)

        # Avoid infiniate loop if obj tries to load its state before
        # it is added to the cache and it's state refers to it.
        # (This will typically be the case for non-ghostifyable objects,
        # like persistent caches.)
        self._pre_cache[oid] = obj
        self._cache.new_ghost(oid, obj)
        self._pre_cache.pop(oid)
        return obj
Ejemplo n.º 2
0
    def get(self, oid):
        """Return the persistent object with oid 'oid'."""
        if self._opened is None:
            raise ConnectionStateError("The database connection is closed")

        obj = self._cache.get(oid, None)
        if obj is not None:
            return obj
        obj = self._added.get(oid, None)
        if obj is not None:
            return obj
        obj = self._pre_cache.get(oid, None)
        if obj is not None:
            return obj

        # This appears to be an MVCC violation because we are loading
        # the must recent data when perhaps we shouldnt. The key is
        # that we are only creating a ghost!
        p, serial = self._storage.load(oid, self._version)
        obj = self._reader.getGhost(p)

        # Avoid infiniate loop if obj tries to load its state before
        # it is added to the cache and it's state refers to it.
        self._pre_cache[oid] = obj
        obj._p_oid = oid
        obj._p_jar = self
        obj._p_changed = None
        obj._p_serial = serial
        self._pre_cache.pop(oid)
        self._cache[oid] = obj
        return obj
Ejemplo n.º 3
0
    def close(self, primary=True):
        """Close the Connection."""
        if not self._needs_to_join:
            # We're currently joined to a transaction.
            raise ConnectionStateError("Cannot close a connection joined to "
                                       "a transaction")

        if self._cache is not None:
            self._cache.incrgc()  # This is a good time to do some GC

        # Call the close callbacks.
        if self.__onCloseCallbacks is not None:
            callbacks = self.__onCloseCallbacks
            self.__onCloseCallbacks = None
            for f in callbacks:
                try:
                    f()
                except:  # except what?
                    f = getattr(f, 'im_self', f)
                    self._log.exception("Close callback failed for %s", f)

        self._debug_info = ()

        if self.opened and self.transaction_manager is not None:
            # transaction_manager could be None if one of the __onCloseCallbacks
            # closed the DB already, .e.g, ZODB.connection() does this.
            self.transaction_manager.unregisterSynch(self)

        am = self._db._activity_monitor
        if am is not None:
            am.closedConnection(self)

        # Drop transaction manager to release resources and help prevent errors
        self.transaction_manager = None

        if hasattr(self._storage, 'afterCompletion'):
            self._storage.afterCompletion()

        if primary:
            for connection in self.connections.values():
                if connection is not self:
                    connection.close(False)

            # Return the connection to the pool.
            if self.opened is not None:
                self._db._returnToPool(self)

                # _returnToPool() set self.opened to None.
                # However, we can't assert that here, because self may
                # have been reused (by another thread) by the time we
                # get back here.
        else:
            self.opened = None
Ejemplo n.º 4
0
    def add(self, obj):
        """Add a new object 'obj' to the database and assign it an oid."""
        if self.opened is None:
            raise ConnectionStateError("The database connection is closed")

        marker = object()
        oid = getattr(obj, "_p_oid", marker)
        if oid is marker:
            raise TypeError(
                "Only first-class persistent objects may be"
                " added to a Connection.", obj)
        elif obj._p_jar is None:
            self._add(obj, self.new_oid())
        elif obj._p_jar is not self:
            raise InvalidObjectReference(obj, obj._p_jar)
Ejemplo n.º 5
0
    def close(self, primary=True):
        """Close the Connection."""
        if not self._needs_to_join:
            # We're currently joined to a transaction.
            raise ConnectionStateError("Cannot close a connection joined to "
                                       "a transaction")

        if self._cache is not None:
            self._cache.incrgc()  # This is a good time to do some GC

        # Call the close callbacks.
        if self.__onCloseCallbacks is not None:
            callbacks = self.__onCloseCallbacks
            self.__onCloseCallbacks = None
            for f in callbacks:
                try:
                    f()
                except:  # except what?
                    f = getattr(f, 'im_self', f)
                    self._log.exception("Close callback failed for %s", f)

        self._debug_info = ()

        if self.opened:
            self.transaction_manager.unregisterSynch(self)

        if primary:
            for connection in self.connections.values():
                if connection is not self:
                    connection.close(False)

            # Return the connection to the pool.
            if self.opened is not None:
                self._db._returnToPool(self)

                # _returnToPool() set self.opened to None.
                # However, we can't assert that here, because self may
                # have been reused (by another thread) by the time we
                # get back here.
        else:
            self.opened = None

        am = self._db._activity_monitor
        if am is not None:
            am.closedConnection(self)
Ejemplo n.º 6
0
    def setstate(self, obj):
        """Turns the ghost 'obj' into a real object by loading its state from
        the database."""
        oid = obj._p_oid

        if self._opened is None:
            msg = ("Shouldn't load state for %s "
                   "when the connection is closed" % oid_repr(oid))
            self._log.error(msg)
            raise ConnectionStateError(msg)

        try:
            self._setstate(obj)
        except ConflictError:
            raise
        except:
            self._log.error("Couldn't load state for %s",
                            oid_repr(oid),
                            exc_info=sys.exc_info())
            raise
Ejemplo n.º 7
0
    def get(self, oid):
        """Return the persistent object with oid 'oid'."""
        if self._opened is None:
            raise ConnectionStateError("The database connection is closed")

        obj = self._cache.get(oid, None)
        if obj is not None:
            return obj
        obj = self._added.get(oid, None)
        if obj is not None:
            return obj

        p, serial = self._storage.load(oid, self._version)
        obj = self._reader.getGhost(p)

        obj._p_oid = oid
        obj._p_jar = self
        obj._p_changed = None
        obj._p_serial = serial

        self._cache[oid] = obj
        return obj
Ejemplo n.º 8
0
    def setstate(self, obj):
        """Load the state for an (ghost) object
        """

        oid = obj._p_oid

        if self.opened is None:
            msg = ("Shouldn't load state for %s %s "
                   "when the connection is closed" %
                   (className(obj), oid_repr(oid)))
            try:
                raise ConnectionStateError(msg)
            except:
                self._log.exception(msg)
                raise

        try:
            p, serial = self._storage.load(oid)

            self._load_count += 1

            self._reader.setGhostState(obj, p)
            obj._p_serial = serial
            self._cache.update_object_size_estimation(oid, len(p))
            obj._p_estimated_size = len(p)

            # Blob support
            if isinstance(obj, Blob):
                obj._p_blob_uncommitted = None
                obj._p_blob_committed = self._storage.loadBlob(oid, serial)

        except ConflictError:
            raise
        except:
            self._log.exception("Couldn't load state for %s %s",
                                className(obj), oid_repr(oid))
            raise
Ejemplo n.º 9
0
    def add(self, obj):
        """Add a new object 'obj' to the database and assign it an oid."""
        if self._opened is None:
            raise ConnectionStateError("The database connection is closed")

        marker = object()
        oid = getattr(obj, "_p_oid", marker)
        if oid is marker:
            raise TypeError(
                "Only first-class persistent objects may be"
                " added to a Connection.", obj)
        elif obj._p_jar is None:
            assert obj._p_oid is None
            oid = obj._p_oid = self._storage.new_oid()
            obj._p_jar = self
            if self._added_during_commit is not None:
                self._added_during_commit.append(obj)
            self._register(obj)
            # Add to _added after calling register(), so that _added
            # can be used as a test for whether the object has been
            # registered with the transaction.
            self._added[oid] = obj
        elif obj._p_jar is not self:
            raise InvalidObjectReference(obj, obj._p_jar)
Ejemplo n.º 10
0
 def isReadOnly(self):
     """Returns True if this connection is read only."""
     if self.opened is None:
         raise ConnectionStateError("The database connection is closed")
     return self._storage.isReadOnly()
Ejemplo n.º 11
0
 def getVersion(self):
     """Returns the version this connection is attached to."""
     if self._storage is None:
         raise ConnectionStateError("The database connection is closed")
     return self._version
Ejemplo n.º 12
0
 def raise_(unused_instance):
     from ZODB.POSException import ConnectionStateError
     raise ConnectionStateError()