server/sources/native.py
changeset 5655 ef903fff826d
parent 5627 a7e40cccdc9b
parent 5649 a07dee204187
child 5691 ba2347050144
--- a/server/sources/native.py	Tue Jun 01 17:06:41 2010 +0200
+++ b/server/sources/native.py	Thu Jun 03 10:17:44 2010 +0200
@@ -256,6 +256,7 @@
         # we need a lock to protect eid attribution function (XXX, really?
         # explain)
         self._eid_creation_lock = Lock()
+        self._eid_creation_cnx = self.get_connection()
         # (etype, attr) / storage mapping
         self._storages = {}
         # entity types that may be used by other multi-sources instances
@@ -271,6 +272,9 @@
             def pool_reset(cnx):
                 cnx.close()
             self.pool_reset = pool_reset
+        if self.dbdriver == 'sqlite':
+            self._create_eid = None
+            self.create_eid = self._create_eid_sqlite
 
     @property
     def _sqlcnx(self):
@@ -711,7 +715,7 @@
         return None
 
     def make_temp_table_name(self, table):
-        try: # XXX remove this once 
+        try: # XXX remove this once
             return self.dbhelper.temporary_table_name(table)
         except AttributeError:
             import warnings
@@ -729,7 +733,7 @@
         sql = self.dbhelper.sql_temporary_table(table, schema, False)
         self.doexec(session, sql)
 
-    def create_eid(self, session):
+    def _create_eid_sqlite(self, session):
         self._eid_creation_lock.acquire()
         try:
             for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
@@ -738,6 +742,51 @@
         finally:
             self._eid_creation_lock.release()
 
+
+    def create_eid(self, session):
+        self.debug('create eid')
+        # lock needed to prevent 'Connection is busy with results for another command (0)' errors with SQLServer
+        self._eid_creation_lock.acquire()
+        try:
+            return self._create_eid()
+        finally:
+            self._eid_creation_lock.release()
+
+    def _create_eid(self):
+        # internal function doing the eid creation without locking.
+        # needed for the recursive handling of disconnections (otherwise we
+        # deadlock on self._eid_creation_lock
+        if self._eid_creation_cnx is None:
+            self._eid_creation_cnx = self.get_connection()
+        cnx = self._eid_creation_cnx
+        cursor = cnx.cursor()
+        try:
+            for sql in self.dbhelper.sqls_increment_sequence('entities_id_seq'):
+                cursor.execute(sql)
+            eid = cursor.fetchone()[0]
+        except (self.OperationalError, self.InterfaceError):
+            # FIXME: better detection of deconnection pb
+            self.warning("trying to reconnect create eid connection")
+            self._eid_creation_cnx = None
+            return self._create_eid()
+        except (self.DbapiError,), exc:
+            # We get this one with pyodbc and SQL Server when connection was reset
+            if exc.args[0] == '08S01':
+                self.warning("trying to reconnect create eid connection")
+                self._eid_creation_cnx = None
+                return self._create_eid()
+            else:
+                raise
+        except: # WTF?
+            cnx.rollback()
+            self._eid_creation_cnx = None
+            self.exception('create eid failed in an unforeseen way on SQL statement %s', sql)
+            raise
+        else:
+            cnx.commit()
+            return eid
+
+
     def add_info(self, session, entity, source, extid, complete):
         """add type and source info for an eid into the system table"""
         # begin by inserting eid/type/source/extid into the entities table