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 |
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: |