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)
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 = []
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
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)
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
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
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
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 = []
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)
def __init__(self): from ZODB.utils import WeakSet self._txn = None self._synchs = WeakSet()
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)
def __init__(self): self._txn = None self._synchs = WeakSet()
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)