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 |
728 # on commit |
729 # on commit |
729 sql = self.dbhelper.sql_temporary_table(table, schema, False) |
730 sql = self.dbhelper.sql_temporary_table(table, schema, False) |
730 self.doexec(session, sql) |
731 self.doexec(session, sql) |
731 |
732 |
732 def create_eid(self, session): |
733 def create_eid(self, session): |
733 self._eid_creation_lock.acquire() |
734 self.debug('create eid') |
734 try: |
735 # lock needed to prevent 'Connection is busy with results for another command (0)' errors with SQLServer |
735 for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'): |
736 self._eid_creation_lock.acquire() |
736 cursor = self.doexec(session, sql) |
737 try: |
737 return cursor.fetchone()[0] |
738 return self.__create_eid() |
738 finally: |
739 finally: |
739 self._eid_creation_lock.release() |
740 self._eid_creation_lock.release() |
|
741 |
|
742 def __create_eid(self): |
|
743 # internal function doing the eid creation without locking. |
|
744 # needed for the recursive handling of disconnections (otherwise we |
|
745 # deadlock on self._eid_creation_lock |
|
746 if self._eid_creation_cnx is None: |
|
747 self._eid_creation_cnx = self.get_connection() |
|
748 cnx = self._eid_creation_cnx |
|
749 cursor = cnx.cursor() |
|
750 try: |
|
751 for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'): |
|
752 cursor.execute(sql) |
|
753 eid = cursor.fetchone()[0] |
|
754 except (self.OperationalError, self.InterfaceError): |
|
755 # FIXME: better detection of deconnection pb |
|
756 self.warning("trying to reconnect create eid connection") |
|
757 self._eid_creation_cnx = None |
|
758 return self.__create_eid() |
|
759 except (self.DbapiError,), exc: |
|
760 # We get this one with pyodbc and SQL Server when connection was reset |
|
761 if exc.args[0] == '08S01': |
|
762 self.warning("trying to reconnect create eid connection") |
|
763 self._eid_creation_cnx = None |
|
764 return self.__create_eid() |
|
765 else: |
|
766 raise |
|
767 except: # WTF? |
|
768 cnx.rollback() |
|
769 self._eid_creation_cnx = None |
|
770 self.exception('create eid failed in an unforeseen way on SQL statement %s', sql) |
|
771 raise |
|
772 else: |
|
773 cnx.commit() |
|
774 return eid |
|
775 |
740 |
776 |
741 def add_info(self, session, entity, source, extid, complete): |
777 def add_info(self, session, entity, source, extid, complete): |
742 """add type and source info for an eid into the system table""" |
778 """add type and source info for an eid into the system table""" |
743 # begin by inserting eid/type/source/extid into the entities table |
779 # begin by inserting eid/type/source/extid into the entities table |
744 if extid is not None: |
780 if extid is not None: |