[Erp5-report] r36761 nicolas.dumazet - /erp5/trunk/products/ERP5/Document/

nobody at svn.erp5.org nobody at svn.erp5.org
Thu Jul 1 05:10:10 CEST 2010


Author: nicolas.dumazet
Date: Thu Jul  1 05:10:10 2010
New Revision: 36761

URL: http://svn.erp5.org?rev=36761&view=rev
Log:
do not load in step #3 the objects we've already loaded in step #2

The idea is that if catalog is up-to-date, the call in #2 will already return
and load from ZODB all descendants of self. We do not want in this case to
blindly/dumbly recurse over the descendants of self in step #3, loading them
again from ZODB.

We thus remember which objects we loaded in the Simulation Tree during #2 and
do not load them again in #3. Code complexity is higher, but this should make
step #3 virtually "free" when catalog is up-to-date.

Modified:
    erp5/trunk/products/ERP5/Document/SimulationMovement.py

Modified: erp5/trunk/products/ERP5/Document/SimulationMovement.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/SimulationMovement.py?rev=36761&r1=36760&r2=36761&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/SimulationMovement.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/SimulationMovement.py [utf8] Thu Jul  1 05:10:10 2010
@@ -616,33 +616,74 @@ class SimulationMovement(Movement, Prope
     ## Try catalog to find descendant movements, knowing
     # that it can be incomplete
 
+    class treeNode(dict):
+      """
+      Used to cache accesses to ZODB objects.
+      The idea is to put in visited_dict the objects we've already
+      loaded from ZODB in Step #2 to avoid loading them again in Step #3.
+
+      - self represents a single ZODB container c
+      - self.visited_dict contains an id->(ZODB obj) cache for subobjects of c
+      - self[id] contains the treeNode representing c[id]
+      """
+      def __init__(self):
+        dict.__init__(self)
+        self.visited_dict = dict()
+
+    path_tree = treeNode()
+    def updateTree(simulation_movement):
+      tree_node = path_tree
+      movement_path = simulation_movement.getPhysicalPath()
+      simulation_movement_id = movement_path[-1]
+      # find container
+      for path_id in movement_path[:-1]:
+        tree_node = tree_node.setdefault(path_id, treeNode())
+      # and mark the object as visited
+      tree_node.visited_dict[simulation_movement_id] = simulation_movement
+
     portal_catalog = self.getPortalObject().portal_catalog
     catalog_simulation_movement_list = portal_catalog(
       portal_type='Simulation Movement',
       causality_uid=[p.getUid() for p in remaining_path_set],
       path='%s/%%' % self.getPath())
 
-    for simulation in catalog_simulation_movement_list:
-      if not isBuiltAndCompleted(simulation, simulation.getCausalityValue()):
+    for movement in catalog_simulation_movement_list:
+      if not isBuiltAndCompleted(movement, movement.getCausalityValue()):
         return False
+      updateTree(movement)
 
     ### Step 3:
     ## We had no luck, we have to explore descendant movements in ZODB
     #
-    def _recurseGetValueList(document):
+    def _recurseGetValueList(document, tree_node):
       """
       generator yielding Simulation Movement descendants of document.
       It does _not_ explore the whole subtree if iteration is stopped.
+
+      It uses the tree we built previously to avoid loading again ZODB
+      objects that we already loaded during catalog querying
       """
-      subdocument_list = document.contentValues()
-      for subdocument in subdocument_list:
-        if subdocument.getPortalType() == "Simulation Movement":
-          yield subdocument
-      for subdocument in subdocument_list:
-        for d in _recurseGetValueList(subdocument):
+      object_id_list = document.objectIds()
+      for id in object_id_list:
+        if id not in tree_node.visited_dict:
+          # we had not visited it in step #2
+          subdocument = document[id]
+          if subdocument.getPortalType() == "Simulation Movement":
+            tree_node.visited_dict[id] = subdocument
+            yield subdocument
+
+      for id, subdocument in tree_node.visited_dict.iteritems():
+        subtree = tree_node.get(id, treeNode())
+        for d in _recurseGetValueList(subdocument, subtree):
           yield d
 
-    for descendant in _recurseGetValueList(self):
+    # descend in the tree to find self:
+    tree_node = path_tree
+    for path_id in self.getPhysicalPath():
+      tree_node = tree_node.setdefault(path_id, treeNode())
+
+    # explore subobjects of self
+    for descendant in _recurseGetValueList(self, tree_node):
       path = descendant.getCausalityValue()
       if path not in remaining_path_set:
         continue




More information about the Erp5-report mailing list