From 77668397094dedf69d3bc3422cd26d5b8dbe86b7 Mon Sep 17 00:00:00 2001
From: Yoshinori Okuji <yo@nexedi.com>
Date: Wed, 8 Aug 2007 21:27:30 +0000
Subject: [PATCH] Enable the read-only transaction cache temporarily when
 checking category membership, because this is guaranteed not to change
 categories. This change improves the performance significantly when there are
 many membership criterion categories.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@15573 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/Document/Predicate.py | 40 +++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/product/ERP5/Document/Predicate.py b/product/ERP5/Document/Predicate.py
index e2687dac4f..1010b4baab 100644
--- a/product/ERP5/Document/Predicate.py
+++ b/product/ERP5/Document/Predicate.py
@@ -37,6 +37,7 @@ from Products.ERP5Type.Core.Folder import Folder
 from Products.ERP5Type.Document import newTempBase
 from Products.ERP5Type.XMLObject import XMLObject
 from Products.ERP5Type.Utils import convertToUpperCase
+from Products.ERP5Type.Cache import getReadOnlyTransactionCache, enableReadOnlyTransactionCache, disableReadOnlyTransactionCache
 
 from zLOG import LOG
 
@@ -132,23 +133,34 @@ class Predicate(XMLObject, Folder):
           membership_criterion_category_list if x.split('/', 1)[0] in \
           tested_base_category_list]
 
-    for c in membership_criterion_category_list:
-      bc = c.split('/', 1)[0]
-      if (bc not in tested_base_category) and \
-         (bc in multimembership_criterion_base_category_list):
-        tested_base_category[bc] = 1
-      elif (bc not in tested_base_category) and \
-           (bc in membership_criterion_base_category_list):
-        tested_base_category[bc] = 0
-      if (bc in multimembership_criterion_base_category_list):
-        tested_base_category[bc] = tested_base_category[bc] and \
-                                   context.isMemberOf(c)
+    # Test category memberships. Enable the read-only transaction cache
+    # temporarily, if not enabled, because this part is strictly read-only,
+    # and context.isMemberOf is very expensive, when the category list has
+    # many items.
+    enabled = (getReadOnlyTransactionCache(self) is not None)
+    try:
+      if not enabled:
+        enableReadOnlyTransactionCache(self)
+      for c in membership_criterion_category_list:
+        bc = c.split('/', 1)[0]
+        if (bc not in tested_base_category) and \
+           (bc in multimembership_criterion_base_category_list):
+          tested_base_category[bc] = 1
+        elif (bc not in tested_base_category) and \
+             (bc in membership_criterion_base_category_list):
+          tested_base_category[bc] = 0
+        if (bc in multimembership_criterion_base_category_list):
+          tested_base_category[bc] = tested_base_category[bc] and \
+                                     context.isMemberOf(c)
 #        LOG('predicate test', 0,
 #            '%s after multi membership to %s' % \
 #            (tested_base_category[bc], c))
-      elif (bc in membership_criterion_base_category_list):
-        tested_base_category[bc] = tested_base_category[bc] or \
-                                   context.isMemberOf(c)
+        elif (bc in membership_criterion_base_category_list):
+          tested_base_category[bc] = tested_base_category[bc] or \
+                                     context.isMemberOf(c)
+    finally:
+      if not enabled:
+        disableReadOnlyTransactionCache(self)
 
 #        LOG('predicate test', 0,
 #            '%s after single membership to %s' % \
-- 
2.30.9