Esempio n. 1
0
class TransactionManager(object):

    def __init__(self):
        from ZODB.utils import WeakSet

        self._txn = None
        self._synchs = WeakSet()

    def begin(self):
        if self._txn is not None:
            self._txn.abort()
        txn = self._txn = Transaction(self._synchs, self)
        _new_transaction(txn, self._synchs)
        return txn

    def get(self):
        if self._txn is None:
            self._txn = Transaction(self._synchs, self)
        return self._txn

    def free(self, txn):
        assert txn is self._txn
        self._txn = None

    def registerSynch(self, synch):
        self._synchs.add(synch)

    def unregisterSynch(self, synch):
        self._synchs.remove(synch)

    def commit(self, sub=_marker):
        if sub is _marker:
            sub = None
        else:
            from ZODB.utils import deprecated37
            deprecated37("subtransactions are deprecated; use "
                         "transaction.savepoint() instead of "
                         "transaction.commit(1)")
        return self.get().commit(sub, deprecation_wng=False)

    def abort(self, sub=_marker):
        if sub is _marker:
            sub = None
        else:
            from ZODB.utils import deprecated37
            deprecated37("subtransactions are deprecated; use "
                         "sp.rollback() instead of "
                         "transaction.abort(1), where `sp` is the "
                         "corresponding savepoint captured earlier")
        return self.get().abort(sub, deprecation_wng=False)

    def savepoint(self, optimistic=False):
        return self.get().savepoint(optimistic)
Esempio n. 2
0
    def __init__(self, pool_size):
        # The largest # of connections we expect to see alive simultaneously.
        self.pool_size = pool_size

        # A weak set of all connections we've seen.  A connection vanishes
        # from this set if pop() hands it out, it's not reregistered via
        # repush(), and it becomes unreachable.
        self.all = WeakSet()

        # A stack of connections available to hand out.  This is a subset
        # of self.all.  push() and repush() add to this, and may remove
        # the oldest available connections if the pool is too large.
        # pop() pops this stack.  There are never more than pool_size entries
        # in this stack.
        # In Python 2.4, a collections.deque would make more sense than
        # a list (we push only "on the right", but may pop from both ends).
        self.available = []
Esempio n. 3
0
 def get(self):
     tid = thread.get_ident()
     txn = self._txns.get(tid)
     if txn is None:
         synchs = self._synchs.get(tid)
         if synchs is None:
             synchs = self._synchs[tid] = WeakSet()
         txn = self._txns[tid] = Transaction(synchs, self)
     return txn
Esempio n. 4
0
class TransactionManager(object):
    def __init__(self):
        self._txn = None
        self._synchs = WeakSet()

    def begin(self):
        if self._txn is not None:
            self._txn.abort()
        txn = self._txn = Transaction(self._synchs, self)
        _new_transaction(txn, self._synchs)
        return txn

    def get(self):
        if self._txn is None:
            self._txn = Transaction(self._synchs, self)
        return self._txn

    def free(self, txn):
        assert txn is self._txn
        self._txn = None

    def registerSynch(self, synch):
        self._synchs.add(synch)

    def unregisterSynch(self, synch):
        self._synchs.remove(synch)

    def isDoomed(self):
        return self.get().isDoomed()

    def doom(self):
        return self.get().doom()

    def commit(self):
        return self.get().commit()

    def abort(self):
        return self.get().abort()

    def savepoint(self, optimistic=False):
        return self.get().savepoint(optimistic)
Esempio n. 5
0
    def get(self):
        tid = thread.get_ident()

        txn = self._txns.get(tid)
        if txn is None:
            synchs = self._synchs.get(tid)
            if synchs is None:
                from ZODB.utils import WeakSet
                synchs = self._synchs[tid] = WeakSet()
            if self._global_syncs:
                [synchs.add(gs) for gs in self._global_syncs]
            txn = self._txns[tid] = Transaction(synchs, self)
        return txn
Esempio n. 6
0
    def begin(self):
        tid = thread.get_ident()
        txn = self._txns.get(tid)
        if txn is not None:
            txn.abort()

        synchs = self._synchs.get(tid)
        if synchs is None:
            synchs = self._synchs[tid] = WeakSet()

        txn = self._txns[tid] = Transaction(synchs, self)
        _new_transaction(txn, synchs)
        return txn
Esempio n. 7
0
    def begin(self):
        tid = thread.get_ident()
        txn = self._txns.get(tid)
        if txn is not None:
            txn.abort()

        synchs = self._synchs.get(tid)
        if synchs is None:
            from ZODB.utils import WeakSet
            synchs = self._synchs[tid] = WeakSet()
        if self._global_syncs:
            [synchs.add(gs) for gs in self._global_syncs]
        txn = self._txns[tid] = Transaction(synchs, self)
        _new_transaction(txn, synchs)
        return txn
Esempio n. 8
0
    def __init__(self, pool_size):
        # The largest # of connections we expect to see alive simultaneously.
        self.pool_size = pool_size

        # A weak set of all connections we've seen.  A connection vanishes
        # from this set if pop() hands it out, it's not reregistered via
        # repush(), and it becomes unreachable.
        self.all = WeakSet()

        # A stack of connections available to hand out.  This is a subset
        # of self.all.  push() and repush() add to this, and may remove
        # the oldest available connections if the pool is too large.
        # pop() pops this stack.  There are never more than pool_size entries
        # in this stack.
        # In Python 2.4, a collections.deque would make more sense than
        # a list (we push only "on the right", but may pop from both ends).
        self.available = []
Esempio n. 9
0
    def __init__(self, synchronizers=None, manager=None):
        self.status = Status.ACTIVE
        # List of resource managers, e.g. MultiObjectResourceAdapters.
        self._resources = []

        # Weak set of synchronizer objects to call.
        if synchronizers is None:
            from ZODB.utils import WeakSet
            synchronizers = WeakSet()
        self._synchronizers = synchronizers

        self._manager = manager

        # _adapters: Connection/_p_jar -> MultiObjectResourceAdapter[Sub]
        self._adapters = {}
        self._voted = {}  # id(Connection) -> boolean, True if voted
        # _voted and other dictionaries use the id() of the resource
        # manager as a key, because we can't guess whether the actual
        # resource managers will be safe to use as dict keys.

        # The user, description, and _extension attributes are accessed
        # directly by storages, leading underscore notwithstanding.
        self._extension = {}

        self.log = logging.getLogger("txn.%d" % thread.get_ident())
        self.log.debug("new transaction")

        # If a commit fails, the traceback is saved in _failure_traceback.
        # If another attempt is made to commit, TransactionFailedError is
        # raised, incorporating this traceback.
        self._failure_traceback = None

        # List of (hook, args, kws) tuples added by addBeforeCommitHook().
        self._before_commit = []

        # List of (hook, args, kws) tuples added by addAfterCommitHook().
        self._after_commit = []
Esempio n. 10
0
class _ConnectionPool(object):
    """Manage a pool of connections.

    CAUTION:  Methods should be called under the protection of a lock.
    This class does no locking of its own.

    There's no limit on the number of connections this can keep track of,
    but a warning is logged if there are more than pool_size active
    connections, and a critical problem if more than twice pool_size.

    New connections are registered via push().  This will log a message if
    "too many" connections are active.

    When a connection is explicitly closed, tell the pool via repush().
    That adds the connection to a stack of connections available for
    reuse, and throws away the oldest stack entries if the stack is too large.
    pop() pops this stack.

    When a connection is obtained via pop(), the pool holds only a weak
    reference to it thereafter.  It's not necessary to inform the pool
    if the connection goes away.  A connection handed out by pop() counts
    against pool_size only so long as it exists, and provided it isn't
    repush()'ed.  A weak reference is retained so that DB methods like
    connectionDebugInfo() can still gather statistics.
    """

    def __init__(self, pool_size):
        # The largest # of connections we expect to see alive simultaneously.
        self.pool_size = pool_size

        # A weak set of all connections we've seen.  A connection vanishes
        # from this set if pop() hands it out, it's not reregistered via
        # repush(), and it becomes unreachable.
        self.all = WeakSet()

        # A stack of connections available to hand out.  This is a subset
        # of self.all.  push() and repush() add to this, and may remove
        # the oldest available connections if the pool is too large.
        # pop() pops this stack.  There are never more than pool_size entries
        # in this stack.
        # In Python 2.4, a collections.deque would make more sense than
        # a list (we push only "on the right", but may pop from both ends).
        self.available = []

    # Change our belief about the expected maximum # of live connections.
    # If the pool_size is smaller than the current value, this may discard
    # the oldest available connections.
    def set_pool_size(self, pool_size):
        self.pool_size = pool_size
        self._reduce_size()

    # Register a new available connection.  We must not know about c already.
    # c will be pushed onto the available stack even if we're over the
    # pool size limit.
    def push(self, c):
        assert c not in self.all
        assert c not in self.available
        self._reduce_size(strictly_less=True)
        self.all.add(c)
        self.available.append(c)
        n, limit = len(self.all), self.pool_size
        if n > limit:
            reporter = logger.warn
            if n > 2 * limit:
                reporter = logger.critical
            reporter("DB.open() has %s open connections with a pool_size "
                     "of %s", n, limit)

    # Reregister an available connection formerly obtained via pop().  This
    # pushes it on the stack of available connections, and may discard
    # older available connections.
    def repush(self, c):
        assert c in self.all
        assert c not in self.available
        self._reduce_size(strictly_less=True)
        self.available.append(c)

    # Throw away the oldest available connections until we're under our
    # target size (strictly_less=False) or no more than that (strictly_less=
    # True, the default).
    def _reduce_size(self, strictly_less=False):
        target = self.pool_size - bool(strictly_less)
        while len(self.available) > target:
            c = self.available.pop(0)
            self.all.remove(c)
            # While application code may still hold a reference to `c`,
            # there's little useful that can be done with this Connection
            # anymore.  Its cache may be holding on to limited resources,
            # and we replace the cache with an empty one now so that we
            # don't have to wait for gc to reclaim it.  Note that it's not
            # possible for DB.open() to return `c` again:  `c` can never
            # be in an open state again.
            # TODO:  Perhaps it would be better to break the reference
            # cycles between `c` and `c._cache`, so that refcounting reclaims
            # both right now.  But if user code _does_ have a strong
            # reference to `c` now, breaking the cycle would not reclaim `c`
            # now, and `c` would be left in a user-visible crazy state.
            c._resetCache()

    # Pop an available connection and return it, or return None if none are
    # available.  In the latter case, the caller should create a new
    # connection, register it via push(), and call pop() again.  The
    # caller is responsible for serializing this sequence.
    def pop(self):
        result = None
        if self.available:
            result = self.available.pop()
            # Leave it in self.all, so we can still get at it for statistics
            # while it's alive.
            assert result in self.all
        return result

    # For every live connection c, invoke f(c).
    def map(self, f):
        self.all.map(f)
Esempio n. 11
0
    def __init__(self):
        from ZODB.utils import WeakSet

        self._txn = None
        self._synchs = WeakSet()
Esempio n. 12
0
class _ConnectionPool(object):
    """Manage a pool of connections.

    CAUTION:  Methods should be called under the protection of a lock.
    This class does no locking of its own.

    There's no limit on the number of connections this can keep track of,
    but a warning is logged if there are more than pool_size active
    connections, and a critical problem if more than twice pool_size.

    New connections are registered via push().  This will log a message if
    "too many" connections are active.

    When a connection is explicitly closed, tell the pool via repush().
    That adds the connection to a stack of connections available for
    reuse, and throws away the oldest stack entries if the stack is too large.
    pop() pops this stack.

    When a connection is obtained via pop(), the pool holds only a weak
    reference to it thereafter.  It's not necessary to inform the pool
    if the connection goes away.  A connection handed out by pop() counts
    against pool_size only so long as it exists, and provided it isn't
    repush()'ed.  A weak reference is retained so that DB methods like
    connectionDebugInfo() can still gather statistics.
    """

    def __init__(self, pool_size):
        # The largest # of connections we expect to see alive simultaneously.
        self.pool_size = pool_size

        # A weak set of all connections we've seen.  A connection vanishes
        # from this set if pop() hands it out, it's not reregistered via
        # repush(), and it becomes unreachable.
        self.all = WeakSet()

        # A stack of connections available to hand out.  This is a subset
        # of self.all.  push() and repush() add to this, and may remove
        # the oldest available connections if the pool is too large.
        # pop() pops this stack.  There are never more than pool_size entries
        # in this stack.
        # In Python 2.4, a collections.deque would make more sense than
        # a list (we push only "on the right", but may pop from both ends).
        self.available = []

    # Change our belief about the expected maximum # of live connections.
    # If the pool_size is smaller than the current value, this may discard
    # the oldest available connections.
    def set_pool_size(self, pool_size):
        self.pool_size = pool_size
        self._reduce_size()

    # Register a new available connection.  We must not know about c already.
    # c will be pushed onto the available stack even if we're over the
    # pool size limit.
    def push(self, c):
        assert c not in self.all
        assert c not in self.available
        self._reduce_size(strictly_less=True)
        self.all.add(c)
        self.available.append(c)
        n, limit = len(self.all), self.pool_size
        if n > limit:
            reporter = logger.warn
            if n > 2 * limit:
                reporter = logger.critical
            reporter("DB.open() has %s open connections with a pool_size "
                     "of %s", n, limit)

    # Reregister an available connection formerly obtained via pop().  This
    # pushes it on the stack of available connections, and may discard
    # older available connections.
    def repush(self, c):
        assert c in self.all
        assert c not in self.available
        self._reduce_size(strictly_less=True)
        self.available.append(c)

    # Throw away the oldest available connections until we're under our
    # target size (strictly_less=False) or no more than that (strictly_less=
    # True, the default).
    def _reduce_size(self, strictly_less=False):
        target = self.pool_size - bool(strictly_less)
        while len(self.available) > target:
            c = self.available.pop(0)
            self.all.remove(c)
            # While application code may still hold a reference to `c`,
            # there's little useful that can be done with this Connection
            # anymore.  Its cache may be holding on to limited resources,
            # and we replace the cache with an empty one now so that we
            # don't have to wait for gc to reclaim it.  Note that it's not
            # possible for DB.open() to return `c` again:  `c` can never
            # be in an open state again.
            # TODO:  Perhaps it would be better to break the reference
            # cycles between `c` and `c._cache`, so that refcounting reclaims
            # both right now.  But if user code _does_ have a strong
            # reference to `c` now, breaking the cycle would not reclaim `c`
            # now, and `c` would be left in a user-visible crazy state.
            c._resetCache()

    # Pop an available connection and return it, or return None if none are
    # available.  In the latter case, the caller should create a new
    # connection, register it via push(), and call pop() again.  The
    # caller is responsible for serializing this sequence.
    def pop(self):
        result = None
        if self.available:
            result = self.available.pop()
            # Leave it in self.all, so we can still get at it for statistics
            # while it's alive.
            assert result in self.all
        return result

    def map(self, f, open_connections=True):
        """For every live connection c, invoke f(c).

        If `open_connections` is false then only call f(c) on closed
        connections.

        """
        if open_connections:
            self.all.map(f)
        else:
            map(f, self.available)
Esempio n. 13
0
 def __init__(self):
     self._txn = None
     self._synchs = WeakSet()
Esempio n. 14
0
 def registerSynch(self, synch):
     tid = thread.get_ident()
     ws = self._synchs.get(tid)
     if ws is None:
         ws = self._synchs[tid] = WeakSet()
     ws.add(synch)