253 self._cache = Cache(repo.config['rql-cache-size']) |
253 self._cache = Cache(repo.config['rql-cache-size']) |
254 self._temp_table_data = {} |
254 self._temp_table_data = {} |
255 # we need a lock to protect eid attribution function (XXX, really? |
255 # we need a lock to protect eid attribution function (XXX, really? |
256 # explain) |
256 # explain) |
257 self._eid_creation_lock = Lock() |
257 self._eid_creation_lock = Lock() |
|
258 self._eid_creation_cnx = self.get_connection() |
258 # (etype, attr) / storage mapping |
259 # (etype, attr) / storage mapping |
259 self._storages = {} |
260 self._storages = {} |
260 # entity types that may be used by other multi-sources instances |
261 # entity types that may be used by other multi-sources instances |
261 self.multisources_etypes = set(repo.config['multi-sources-etypes']) |
262 self.multisources_etypes = set(repo.config['multi-sources-etypes']) |
262 # XXX no_sqlite_wrap trick since we've a sqlite locking pb when |
263 # XXX no_sqlite_wrap trick since we've a sqlite locking pb when |
727 # on commit |
728 # on commit |
728 sql = self.dbhelper.sql_temporary_table(table, schema, False) |
729 sql = self.dbhelper.sql_temporary_table(table, schema, False) |
729 self.doexec(session, sql) |
730 self.doexec(session, sql) |
730 |
731 |
731 def create_eid(self, session): |
732 def create_eid(self, session): |
732 self._eid_creation_lock.acquire() |
733 self.debug('create eid') |
733 try: |
734 # lock needed to prevent 'Connection is busy with results for another command (0)' errors with SQLServer |
734 for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'): |
735 self._eid_creation_lock.acquire() |
735 cursor = self.doexec(session, sql) |
736 try: |
736 return cursor.fetchone()[0] |
737 return self.__create_eid() |
737 finally: |
738 finally: |
738 self._eid_creation_lock.release() |
739 self._eid_creation_lock.release() |
|
740 |
|
741 def __create_eid(self): |
|
742 # internal function doing the eid creation without locking. |
|
743 # needed for the recursive handling of disconnections (otherwise we |
|
744 # deadlock on self._eid_creation_lock |
|
745 if self._eid_creation_cnx is None: |
|
746 self._eid_creation_cnx = self.get_connection() |
|
747 cnx = self._eid_creation_cnx |
|
748 cursor = cnx.cursor() |
|
749 try: |
|
750 for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'): |
|
751 cursor.execute(sql) |
|
752 eid = cursor.fetchone()[0] |
|
753 except (self.OperationalError, self.InterfaceError): |
|
754 # FIXME: better detection of deconnection pb |
|
755 self.warning("trying to reconnect create eid connection") |
|
756 self._eid_creation_cnx = None |
|
757 return self.__create_eid() |
|
758 except (self.DbapiError,), exc: |
|
759 # We get this one with pyodbc and SQL Server when connection was reset |
|
760 if exc.args[0] == '08S01': |
|
761 self.warning("trying to reconnect create eid connection") |
|
762 self._eid_creation_cnx = None |
|
763 return self.__create_eid() |
|
764 else: |
|
765 raise |
|
766 except: # WTF? |
|
767 cnx.rollback() |
|
768 self._eid_creation_cnx = None |
|
769 self.exception('create eid failed in an unforeseen way on SQL statement %s', sql) |
|
770 raise |
|
771 else: |
|
772 cnx.commit() |
|
773 return eid |
|
774 |
739 |
775 |
740 def add_info(self, session, entity, source, extid, complete): |
776 def add_info(self, session, entity, source, extid, complete): |
741 """add type and source info for an eid into the system table""" |
777 """add type and source info for an eid into the system table""" |
742 # begin by inserting eid/type/source/extid into the entities table |
778 # begin by inserting eid/type/source/extid into the entities table |
743 if extid is not None: |
779 if extid is not None: |