backport stable branch
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 31 Jul 2009 14:25:30 +0200
changeset 2589 92f2bc945261
parent 2586 879912fe94e1 (current diff)
parent 2588 3a590ff82e99 (diff)
child 2590 45d5f2d73561
backport stable branch
server/__init__.py
server/migractions.py
server/session.py
server/sources/native.py
vregistry.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/migration/3.3.5_Any.py	Fri Jul 31 14:25:30 2009 +0200
@@ -0,0 +1,8 @@
+# some entities have been added before schema entities, fix the 'is' and
+# 'is_instance_of' relations
+for rtype in ('is', 'is_instance_of'):
+    sql('INSERT INTO %s_relation '
+        'SELECT X.eid, ET.cw_eid FROM entities as X, cw_CWEType as ET '
+        'WHERE X.type=ET.cw_name AND NOT EXISTS('
+        '      SELECT 1 from is_relation '
+        '      WHERE eid_from=X.eid AND eid_to=ET.cw_eid)' % rtype)
--- a/server/__init__.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/server/__init__.py	Fri Jul 31 14:25:30 2009 +0200
@@ -92,14 +92,11 @@
         else:
             login, pwd = unicode(source['db-user']), source['db-password']
     print '-> inserting default user and default groups.'
-    needisfix = []
     for group in BASE_GROUPS:
         rset = session.execute('INSERT CWGroup X: X name %(name)s',
                                {'name': unicode(group)})
-        needisfix.append( (rset.rows[0][0], rset.description[0][0]) )
     rset = session.execute('INSERT CWUser X: X login %(login)s, X upassword %(pwd)s',
                            {'login': login, 'pwd': pwd})
-    needisfix.append( (rset.rows[0][0], rset.description[0][0]) )
     session.execute('SET U in_group G WHERE G name "managers"')
     session.commit()
     # reloging using the admin user
@@ -109,13 +106,6 @@
     handler = config.migration_handler(schema, interactive=False,
                                        cnx=cnx, repo=repo)
     initialize_schema(config, schema, handler)
-    # admin user and groups have been added before schema entities, fix the 'is'
-    # relation
-    for eid, etype in needisfix:
-        handler.session.unsafe_execute('SET X is E WHERE X eid %(x)s, E name %(name)s',
-                                       {'x': eid, 'name': etype}, 'x')
-        handler.session.unsafe_execute('SET X is_instance_of E WHERE X eid %(x)s, E name %(name)s',
-                                       {'x': eid, 'name': etype}, 'x')
     # insert versions
     handler.cmd_add_entity('CWProperty', pkey=u'system.version.cubicweb',
                            value=unicode(config.cubicweb_version()))
@@ -123,6 +113,15 @@
         handler.cmd_add_entity('CWProperty',
                                pkey=u'system.version.%s' % cube.lower(),
                                value=unicode(config.cube_version(cube)))
+    # some entities have been added before schema entities, fix the 'is' and
+    # 'is_instance_of' relations
+    for rtype in ('is', 'is_instance_of'):
+        handler.sqlexec(
+            'INSERT INTO %s_relation '
+            'SELECT X.eid, ET.cw_eid FROM entities as X, cw_CWEType as ET '
+            'WHERE X.type=ET.cw_name AND NOT EXISTS('
+            '      SELECT 1 from is_relation '
+            '      WHERE eid_from=X.eid AND eid_to=ET.cw_eid)' % rtype)
     # yoo !
     cnx.commit()
     config.enabled_sources = None
--- a/server/migractions.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/server/migractions.py	Fri Jul 31 14:25:30 2009 +0200
@@ -159,6 +159,7 @@
                 except (KeyboardInterrupt, EOFError):
                     print 'aborting...'
                     sys.exit(0)
+            self.session.keep_pool_mode('transaction')
             return self._cnx
 
     @property
--- a/server/session.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/server/session.py	Fri Jul 31 14:25:30 2009 +0200
@@ -59,6 +59,7 @@
         self.timestamp = self.creation
         self.is_internal_session = False
         self.is_super_session = False
+        self.default_mode = 'read'
         # short cut to querier .execute method
         self._execute = repo.querier.execute
         # shared data, used to communicate extra information between the client
@@ -110,13 +111,33 @@
 
     # connection management ###################################################
 
+    def keep_pool_mode(self, mode):
+        """set pool_mode, e.g. how the session will keep its pool:
+
+        * if mode == 'write', the pool is freed after each ready query, but kept
+          until the transaction's end (eg commit or rollback) when a write query
+          is detected (eg INSERT/SET/DELETE queries)
+
+        * if mode == 'transaction', the pool is only freed after the
+          transaction's end
+
+        notice that a repository has a limited set of pools, and a session has to
+        wait for a free pool to run any rql query (unless it already has a pool
+        set).
+        """
+        assert mode in ('transaction', 'write')
+        if mode == 'transaction':
+            self.default_mode = 'transaction'
+        else: # mode == 'write'
+            self.default_mode = 'read'
+
     def get_mode(self):
-        return getattr(self._threaddata, 'mode', 'read')
+        return getattr(self._threaddata, 'mode', self.default_mode)
     def set_mode(self, value):
         self._threaddata.mode = value
     mode = property(get_mode, set_mode,
-                    doc='transaction mode (read/write), resetted to read on '
-                    'commit / rollback')
+                    doc='transaction mode (read/write/transaction), resetted to'
+                    ' default_mode on commit / rollback')
 
     def get_commit_state(self):
         return getattr(self._threaddata, 'commit_state', None)
@@ -145,11 +166,11 @@
             self._threads_in_transaction.add(threading.currentThread())
         return self._threaddata.pool
 
-    def reset_pool(self):
+    def reset_pool(self, ignoremode=False):
         """the session is no longer using its pool, at least for some time"""
         # pool may be none if no operation has been done since last commit
         # or rollback
-        if self.pool is not None and self.mode == 'read':
+        if self.pool is not None and (ignoremode or self.mode == 'read'):
             # even in read mode, we must release the current transaction
             pool = self.pool
             try:
@@ -165,7 +186,7 @@
         """update latest session usage timestamp and reset mode to read"""
         self.timestamp = time()
         self.local_perm_cache.clear()
-        self._threaddata.mode = 'read'
+        self._threaddata.mode = self.default_mode
 
     # shared data handling ###################################################
 
@@ -308,7 +329,7 @@
             self.pending_operations[:] = []
             self.transaction_data.clear()
             if reset_pool:
-                self.reset_pool()
+                self.reset_pool(ignoremode=True)
 
     def rollback(self, reset_pool=True):
         """rollback the current session's transaction"""
@@ -333,7 +354,7 @@
             self.pending_operations[:] = []
             self.transaction_data.clear()
             if reset_pool:
-                self.reset_pool()
+                self.reset_pool(ignoremode=True)
 
     def close(self):
         """do not close pool on session close, since they are shared now"""
--- a/server/sources/native.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/server/sources/native.py	Fri Jul 31 14:25:30 2009 +0200
@@ -113,6 +113,12 @@
           'help': 'database host',
           'group': 'native-source', 'inputlevel': 1,
           }),
+        ('db-port',
+         {'type' : 'string',
+          'default': '',
+          'help': 'database port',
+          'group': 'native-source', 'inputlevel': 1,
+          }),
         ('db-name',
          {'type' : 'string',
           'default': REQUIRED,
--- a/server/test/unittest_repository.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/server/test/unittest_repository.py	Fri Jul 31 14:25:30 2009 +0200
@@ -324,6 +324,10 @@
         self.assertRaises(BadConnectionId, repo.set_shared_data, cnxid, 'data', 0)
         self.assertRaises(BadConnectionId, repo.get_shared_data, cnxid, 'data')
 
+    def test_schema_is_relation(self):
+        no_is_rset = self.execute('Any X WHERE NOT X is ET')
+        self.failIf(no_is_rset, no_is_rset.description)
+
 
 class DataHelpersTC(RepositoryBasedTC):
 
--- a/vregistry.py	Fri Jul 31 10:47:15 2009 +0200
+++ b/vregistry.py	Fri Jul 31 14:25:30 2009 +0200
@@ -266,7 +266,7 @@
                 oid = obj.id
             except AttributeError:
                 continue
-            if oid:
+            if oid and not '__abstract__' in obj.__dict__:
                 self.register(obj)
 
     def register(self, obj, registryname=None, oid=None, clear=False):