Django

Code

Ticket #463: mysql_rev2307.diff

File mysql_rev2307.diff, 4.1 kB (added by edgars.jekabsons@gmail.com, 3 years ago)

patch against trunk (rev. 2307)

  • mysql.py

    old new  
    1010from MySQLdb.converters import conversions 
    1111from MySQLdb.constants import FIELD_TYPE 
    1212import types 
     13import threading 
     14from sets import Set 
     15from django.utils.synch import RWLock 
    1316 
     17 
    1418DatabaseError = Database.DatabaseError 
    1519 
    1620django_conversions = conversions.copy() 
     
    4953 
    5054class DatabaseWrapper: 
    5155    def __init__(self): 
    52         self.connection = None 
     56        self.__connections = {} 
     57        self.__threads = Set() 
     58        self.__lock = RWLock() 
    5359        self.queries = [] 
    54  
    55     def cursor(self): 
    56         from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG 
    57         if self.connection is None: 
     60    def _valid_connection(self, con): 
     61        try: 
     62            con.ping() 
     63            return True 
     64        except DatabaseError: 
     65            con.close() # close connection 
     66            return False 
     67     
     68    def __connect(self): 
     69        id = threading.currentThread() 
     70        self.__lock.reader_enters() 
     71        try: 
     72            if (id in self.__connections) and (self._valid_connection(self.__connections[id])): 
     73                return self.__connections[id] 
     74        finally: 
     75            self.__lock.reader_leaves() 
     76             
     77        self.__lock.writer_enters() 
     78        try: 
     79            # remove deadwood 
     80            dead = self.__threads - Set(threading.enumerate()) 
     81            for name in dead: 
     82                self.__connections[name].close() 
     83                del self.__connections[name] 
     84            self.__threads -= dead 
     85         
     86            # create new connection 
     87            from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD 
    5888            kwargs = { 
    5989                'user': DATABASE_USER, 
    6090                'db': DATABASE_NAME, 
     
    6494            } 
    6595            if DATABASE_PORT: 
    6696                kwargs['port'] = DATABASE_PORT 
    67             self.connection = Database.connect(**kwargs) 
    68         cursor = self.connection.cursor() 
    69         if self.connection.get_server_info() >= '4.1': 
     97            connection = Database.connect(**kwargs) 
     98            self.__connections[id] = connection 
     99            self.__threads.add(id) 
     100            return connection 
     101        finally: 
     102            self.__lock.writer_leaves() 
     103 
     104    def cursor(self): 
     105        from django.conf.settings import DEBUG 
     106        connection = self.__connect() 
     107        cursor = connection.cursor() 
     108        if connection.get_server_info() >= '4.1': 
    70109            cursor.execute("SET NAMES utf8") 
    71110        if DEBUG: 
    72111            return base.CursorDebugWrapper(MysqlDebugWrapper(cursor), self) 
    73112        return cursor 
    74113 
    75114    def commit(self): 
    76         self.connection.commit() 
     115        id = threading.currentThread() 
     116        self.__lock.reader_enters() 
     117        try: 
     118            if id in self.__connections: 
     119                self.__connections[id].commit() 
     120        finally: 
     121            self.__lock.reader_leaves() 
    77122 
    78123    def rollback(self): 
    79         if self.connection: 
    80             try: 
    81                 self.connection.rollback() 
    82             except Database.NotSupportedError: 
    83                 pass 
     124        id = threading.currentThread() 
     125        self.__lock.reader_enters()  
     126        try:  
     127           if id in self.__connections:  
     128                try:  
     129                    self.__connections[id].rollback()  
     130                except Database.NotSupportedError:  
     131                    pass  
     132        finally:  
     133            self.__lock.reader_leaves()  
    84134 
    85135    def close(self): 
    86         if self.connection is not None: 
    87             self.connection.close() 
    88             self.connection = None 
     136        id = threading.currentThread()  
     137        self.__lock.writer_enters()  
     138        try:  
     139            if id in self.__connections:  
     140                self.__connections[id].close()  
     141                del self.__connections[id]  
     142        finally:  
     143            self.__lock.writer_leaves()  
    89144 
    90145    def quote_name(self, name): 
    91146        if name.startswith("`") and name.endswith("`"):