Edgewall Software

Ticket #3504: even_more_threadsafe_pool-r3762.diff

File even_more_threadsafe_pool-r3762.diff, 2.7 KB (added by cboos, 6 years ago)

Ok, this last patch seems to be more correct. Please review. (take 2)

  • trac/db/pool.py

     
    3434    to the pool. 
    3535    """ 
    3636 
    37     def __init__(self, pool, cnx): 
     37    def __init__(self, pool, cnx, tid): 
    3838        ConnectionWrapper.__init__(self, cnx) 
    3939        self._pool = pool 
     40        self._tid = tid 
    4041 
    4142    def close(self): 
    4243        if self.cnx: 
    43             self._pool._return_cnx(self.cnx) 
     44            self._pool._return_cnx(self.cnx, self._tid) 
    4445            self.cnx = None 
    4546 
    4647    def __del__(self): 
     
    6263    def get_cnx(self, timeout=None): 
    6364        start = time.time() 
    6465        self._available.acquire() 
     66        print `self._active` 
    6567        try: 
    6668            tid = threading._get_ident() 
    6769            if tid in self._active: 
    68                 self._active[tid][0] += 1 
    69                 return PooledConnection(self, self._active[tid][1]) 
     70                num, cnx = self._active.get(tid) 
     71                if num == 0: 
     72                    cnx.rollback() 
     73                self._active[tid][0] = num + 1 
     74                return PooledConnection(self, cnx, tid) 
    7075            while True: 
    7176                if self._dormant: 
    7277                    cnx = self._dormant.pop() 
     
    8994                    else: 
    9095                        self._available.wait() 
    9196            self._active[tid] = [1, cnx] 
    92             return PooledConnection(self, cnx) 
     97            return PooledConnection(self, cnx, tid) 
    9398        finally: 
    9499            self._available.release() 
    95100 
    96     def _return_cnx(self, cnx): 
     101    def _return_cnx(self, cnx, tid): 
    97102        self._available.acquire() 
    98103        try: 
    99             tid = threading._get_ident() 
    100104            if tid in self._active: 
    101105                num, cnx_ = self._active.get(tid) 
    102106                assert cnx is cnx_ 
     
    111115        # Note: self._available *must* be acquired 
    112116        if tid in self._active: 
    113117            cnx = self._active.pop(tid)[1] 
    114             if cnx not in self._dormant: 
    115                 cnx.rollback() 
    116                 if cnx.poolable: 
     118            if cnx not in self._dormant: # hm, how could that happen? 
     119                if cnx.poolable: # i.e. we can manipulate it from other threads 
     120                    cnx.rollback() 
    117121                    self._dormant.append(cnx) 
    118                 else: 
     122                elif tid == threading._get_ident(): 
     123                    cnx.rollback() # non-poolable but same thread: close 
    119124                    cnx.close() 
    120125                    self._cursize -= 1 
     126                else: # non-poolable, different thread: do nothing 
     127                    self._active[tid][0] = 0 
    121128                self._available.notify() 
    122129 
    123130    def shutdown(self, tid=None):