server/sources/native.py
changeset 5655 ef903fff826d
parent 5627 a7e40cccdc9b
parent 5649 a07dee204187
child 5691 ba2347050144
equal deleted inserted replaced
5654:8bb34548be86 5655:ef903fff826d
   254         self._cache = Cache(repo.config['rql-cache-size'])
   254         self._cache = Cache(repo.config['rql-cache-size'])
   255         self._temp_table_data = {}
   255         self._temp_table_data = {}
   256         # we need a lock to protect eid attribution function (XXX, really?
   256         # we need a lock to protect eid attribution function (XXX, really?
   257         # explain)
   257         # explain)
   258         self._eid_creation_lock = Lock()
   258         self._eid_creation_lock = Lock()
       
   259         self._eid_creation_cnx = self.get_connection()
   259         # (etype, attr) / storage mapping
   260         # (etype, attr) / storage mapping
   260         self._storages = {}
   261         self._storages = {}
   261         # entity types that may be used by other multi-sources instances
   262         # entity types that may be used by other multi-sources instances
   262         self.multisources_etypes = set(repo.config['multi-sources-etypes'])
   263         self.multisources_etypes = set(repo.config['multi-sources-etypes'])
   263         # XXX no_sqlite_wrap trick since we've a sqlite locking pb when
   264         # XXX no_sqlite_wrap trick since we've a sqlite locking pb when
   269             self.get_connection = lambda: ConnectionWrapper(self)
   270             self.get_connection = lambda: ConnectionWrapper(self)
   270             self.check_connection = lambda cnx: cnx
   271             self.check_connection = lambda cnx: cnx
   271             def pool_reset(cnx):
   272             def pool_reset(cnx):
   272                 cnx.close()
   273                 cnx.close()
   273             self.pool_reset = pool_reset
   274             self.pool_reset = pool_reset
       
   275         if self.dbdriver == 'sqlite':
       
   276             self._create_eid = None
       
   277             self.create_eid = self._create_eid_sqlite
   274 
   278 
   275     @property
   279     @property
   276     def _sqlcnx(self):
   280     def _sqlcnx(self):
   277         # XXX: sqlite connections can only be used in the same thread, so
   281         # XXX: sqlite connections can only be used in the same thread, so
   278         #      create a new one each time necessary. If it appears to be time
   282         #      create a new one each time necessary. If it appears to be time
   709         except:
   713         except:
   710             pass
   714             pass
   711         return None
   715         return None
   712 
   716 
   713     def make_temp_table_name(self, table):
   717     def make_temp_table_name(self, table):
   714         try: # XXX remove this once 
   718         try: # XXX remove this once
   715             return self.dbhelper.temporary_table_name(table)
   719             return self.dbhelper.temporary_table_name(table)
   716         except AttributeError:
   720         except AttributeError:
   717             import warnings
   721             import warnings
   718             warnings.warn('Please hg up logilab.database')
   722             warnings.warn('Please hg up logilab.database')
   719             return table
   723             return table
   727         # running with an ldap source, and table will be deleted manually any way
   731         # running with an ldap source, and table will be deleted manually any way
   728         # on commit
   732         # on commit
   729         sql = self.dbhelper.sql_temporary_table(table, schema, False)
   733         sql = self.dbhelper.sql_temporary_table(table, schema, False)
   730         self.doexec(session, sql)
   734         self.doexec(session, sql)
   731 
   735 
   732     def create_eid(self, session):
   736     def _create_eid_sqlite(self, session):
   733         self._eid_creation_lock.acquire()
   737         self._eid_creation_lock.acquire()
   734         try:
   738         try:
   735             for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
   739             for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
   736                 cursor = self.doexec(session, sql)
   740                 cursor = self.doexec(session, sql)
   737             return cursor.fetchone()[0]
   741             return cursor.fetchone()[0]
   738         finally:
   742         finally:
   739             self._eid_creation_lock.release()
   743             self._eid_creation_lock.release()
       
   744 
       
   745 
       
   746     def create_eid(self, session):
       
   747         self.debug('create eid')
       
   748         # lock needed to prevent 'Connection is busy with results for another command (0)' errors with SQLServer
       
   749         self._eid_creation_lock.acquire()
       
   750         try:
       
   751             return self._create_eid()
       
   752         finally:
       
   753             self._eid_creation_lock.release()
       
   754 
       
   755     def _create_eid(self):
       
   756         # internal function doing the eid creation without locking.
       
   757         # needed for the recursive handling of disconnections (otherwise we
       
   758         # deadlock on self._eid_creation_lock
       
   759         if self._eid_creation_cnx is None:
       
   760             self._eid_creation_cnx = self.get_connection()
       
   761         cnx = self._eid_creation_cnx
       
   762         cursor = cnx.cursor()
       
   763         try:
       
   764             for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
       
   765                 cursor.execute(sql)
       
   766             eid = cursor.fetchone()[0]
       
   767         except (self.OperationalError, self.InterfaceError):
       
   768             # FIXME: better detection of deconnection pb
       
   769             self.warning("trying to reconnect create eid connection")
       
   770             self._eid_creation_cnx = None
       
   771             return self._create_eid()
       
   772         except (self.DbapiError,), exc:
       
   773             # We get this one with pyodbc and SQL Server when connection was reset
       
   774             if exc.args[0] == '08S01':
       
   775                 self.warning("trying to reconnect create eid connection")
       
   776                 self._eid_creation_cnx = None
       
   777                 return self._create_eid()
       
   778             else:
       
   779                 raise
       
   780         except: # WTF?
       
   781             cnx.rollback()
       
   782             self._eid_creation_cnx = None
       
   783             self.exception('create eid failed in an unforeseen way on SQL statement %s', sql)
       
   784             raise
       
   785         else:
       
   786             cnx.commit()
       
   787             return eid
       
   788 
   740 
   789 
   741     def add_info(self, session, entity, source, extid, complete):
   790     def add_info(self, session, entity, source, extid, complete):
   742         """add type and source info for an eid into the system table"""
   791         """add type and source info for an eid into the system table"""
   743         # begin by inserting eid/type/source/extid into the entities table
   792         # begin by inserting eid/type/source/extid into the entities table
   744         if extid is not None:
   793         if extid is not None: