server/session.py
changeset 2647 b0a2e779845c
parent 2630 b3f997bc8c26
child 2650 18aec79ec3a3
--- a/server/session.py	Sun Aug 02 11:58:55 2009 +0200
+++ b/server/session.py	Sun Aug 02 12:00:17 2009 +0200
@@ -88,6 +88,54 @@
         finally:
             self.is_super_session = False
 
+    def update_rel_cache_add(self, subject, rtype, object, symetric=False):
+        self._update_entity_rel_cache_add(subject, rtype, 'subject', object)
+        if symetric:
+            self._update_entity_rel_cache_add(object, rtype, 'subject', subject)
+        else:
+            self._update_entity_rel_cache_add(object, rtype, 'object', subject)
+
+    def update_rel_cache_del(self, subject, rtype, object, symetric=False):
+        self._update_entity_rel_cache_del(subject, rtype, 'subject', object)
+        if symetric:
+            self._update_entity_rel_cache_del(object, rtype, 'object', object)
+        else:
+            self._update_entity_rel_cache_del(object, rtype, 'object', subject)
+
+    def _rel_cache(self, eid, rtype, role):
+        try:
+            entity = self.entity_cache(eid)
+        except KeyError:
+            return
+        return entity.relation_cached(rtype, role)
+
+    def _update_entity_rel_cache_add(self, eid, rtype, role, targeteid):
+        rcache = self._rel_cache(eid, rtype, role)
+        if rcache is not None:
+            rset, entities = rcache
+            rset.rows.append([targeteid])
+            if isinstance(rset.description, list): # else description not set
+                rset.description.append([self.describe(targeteid)[0]])
+            rset.rowcount += 1
+            targetentity = self.entity_from_eid(targeteid)
+            entities.append(targetentity)
+
+    def _update_entity_rel_cache_del(self, eid, rtype, role, targeteid):
+        rcache = self._rel_cache(eid, rtype, role)
+        if rcache is not None:
+            rset, entities = rcache
+            for idx, row in enumerate(rset.rows):
+                if row[0] == targeteid:
+                    break
+            else:
+                raise Exception('cache inconsistency for %s %s %s %s' %
+                                (eid, rtype, role, targeteid))
+            del rset.rows[idx]
+            if isinstance(rset.description, list): # else description not set
+                del rset.description[idx]
+            del entities[idx]
+            rset.rowcount -= 1
+
     # resource accessors ######################################################
 
     def actual_session(self):
@@ -221,12 +269,30 @@
     # request interface #######################################################
 
     def set_entity_cache(self, entity):
-        # no entity cache in the server, too high risk of inconsistency
-        # between pre/post hooks
-        pass
+        # XXX session level caching may be a pb with multiple repository
+        #     instances, but 1. this is probably not the only one :$ and 2. it
+        #     may be an acceptable risk. Anyway we could activate it or not
+        #     according to a configuration option
+        try:
+            self.transaction_data['ecache'].setdefault(entity.eid, entity)
+        except KeyError:
+            self.transaction_data['ecache'] = ecache = {}
+            ecache[entity.eid] = entity
 
     def entity_cache(self, eid):
-        raise KeyError(eid)
+        try:
+            return self.transaction_data['ecache'][eid]
+        except:
+            raise
+
+    def cached_entities(self):
+        return self.transaction_data.get('ecache', {}).values()
+
+    def drop_entity_cache(self, eid=None):
+        if eid is None:
+            self.transaction_data.pop('ecache', None)
+        else:
+            del self.transaction_data['ecache'][eid]
 
     def base_url(self):
         url = self.repo.config['base-url']
@@ -276,7 +342,7 @@
         self.set_pool()
         return csession
 
-    def unsafe_execute(self, rql, kwargs=None, eid_key=None, build_descr=False,
+    def unsafe_execute(self, rql, kwargs=None, eid_key=None, build_descr=True,
                        propagate=False):
         """like .execute but with security checking disabled (this method is
         internal to the server, it's not part of the db-api)