Commit fd836247 authored by Hanno Schlichting's avatar Hanno Schlichting

Clean up some of the thread locks, context managers are awesome

parent da65d353
...@@ -19,11 +19,14 @@ from Acquisition import aq_base ...@@ -19,11 +19,14 @@ from Acquisition import aq_base
from Acquisition import aq_parent from Acquisition import aq_parent
from Products.PluginIndexes.interfaces import IUniqueValueIndex from Products.PluginIndexes.interfaces import IUniqueValueIndex
reports_lock = allocate_lock() REPORTS_LOCK = allocate_lock()
reports = {} REPORTS = {}
value_indexes_lock = allocate_lock() PRIORITYMAP_LOCK = allocate_lock()
value_indexes = frozenset() PRIORITYMAP = {}
VALUE_INDEXES_LOCK = allocate_lock()
VALUE_INDEXES = frozenset()
MAX_DISTINCT_VALUES = 10 MAX_DISTINCT_VALUES = 10
REFRESH_RATE = 100 REFRESH_RATE = 100
...@@ -38,13 +41,13 @@ def determine_value_indexes(indexes): ...@@ -38,13 +41,13 @@ def determine_value_indexes(indexes):
# of unique values, where the number of items for each value differs a # of unique values, where the number of items for each value differs a
# lot. If the number of items per value is similar, the duration of a # lot. If the number of items per value is similar, the duration of a
# query is likely similar as well. # query is likely similar as well.
global value_indexes global VALUE_INDEXES
if value_indexes: if VALUE_INDEXES:
# Calculating all the value indexes is quite slow, so we do this once # Calculating all the value indexes is quite slow, so we do this once
# for the first query. Since this is an optimization only, slightly # for the first query. Since this is an optimization only, slightly
# outdated results based on index changes in the running process # outdated results based on index changes in the running process
# can be ignored. # can be ignored.
return value_indexes return VALUE_INDEXES
new_value_indexes = set() new_value_indexes = set()
for name, index in indexes.items(): for name, index in indexes.items():
...@@ -54,22 +57,17 @@ def determine_value_indexes(indexes): ...@@ -54,22 +57,17 @@ def determine_value_indexes(indexes):
# Only consider indexes which actually return a number # Only consider indexes which actually return a number
# greater than zero # greater than zero
new_value_indexes.add(name) new_value_indexes.add(name)
try:
value_indexes_lock.acquire()
value_indexes = frozenset(new_value_indexes)
finally:
value_indexes_lock.release()
return value_indexes with VALUE_INDEXES_LOCK:
VALUE_INDEXES = frozenset(new_value_indexes)
return VALUE_INDEXES
def clear_value_indexes(): def clear_value_indexes():
global value_indexes global VALUE_INDEXES
try: with VALUE_INDEXES_LOCK:
value_indexes_lock.acquire() VALUE_INDEXES = frozenset()
value_indexes = frozenset()
finally:
value_indexes_lock.release()
from zope.testing.cleanup import addCleanUp from zope.testing.cleanup import addCleanUp
...@@ -143,18 +141,12 @@ class CatalogPlan(object): ...@@ -143,18 +141,12 @@ class CatalogPlan(object):
self.stop_time = None self.stop_time = None
self.duration = None self.duration = None
def prioritymap(self):
# holds the benchmark of each index
prioritymap = getattr(self.catalog, '_v_prioritymap', None)
if prioritymap is None:
prioritymap = self.catalog._v_prioritymap = {}
return prioritymap
def benchmark(self): def benchmark(self):
# holds the benchmark of each index # holds the benchmark of each index
bm = self.prioritymap().get(self.key, None) bm = PRIORITYMAP.get(self.key, None)
if bm is None: if bm is None:
self.prioritymap()[self.key] = {} with PRIORITYMAP_LOCK:
PRIORITYMAP[self.key] = {}
return bm return bm
def plan(self): def plan(self):
...@@ -207,8 +199,9 @@ class CatalogPlan(object): ...@@ -207,8 +199,9 @@ class CatalogPlan(object):
key = self.key key = self.key
benchmark = self.benchmark() benchmark = self.benchmark()
prioritymap = self.prioritymap()
prioritymap[key] = benchmark with PRIORITYMAP_LOCK:
PRIORITYMAP[key] = benchmark
# calculate mean time of search # calculate mean time of search
stats = getattr(self.catalog, '_v_stats', None) stats = getattr(self.catalog, '_v_stats', None)
...@@ -235,34 +228,28 @@ class CatalogPlan(object): ...@@ -235,34 +228,28 @@ class CatalogPlan(object):
key = self.key key = self.key
recent = RecentQuery(duration=total, details=self.res) recent = RecentQuery(duration=total, details=self.res)
reports_lock.acquire() with REPORTS_LOCK:
try: if self.cid not in REPORTS:
if self.cid not in reports: REPORTS[self.cid] = {}
reports[self.cid] = {}
previous = reports[self.cid].get(key) previous = REPORTS[self.cid].get(key)
if previous: if previous:
counter, mean, last = previous counter, mean, last = previous
mean = (mean * counter + total) / float(counter + 1) mean = (mean * counter + total) / float(counter + 1)
reports[self.cid][key] = Report(counter + 1, mean, recent) REPORTS[self.cid][key] = Report(counter + 1, mean, recent)
else: else:
reports[self.cid][key] = Report(1, total, recent) REPORTS[self.cid][key] = Report(1, total, recent)
finally:
reports_lock.release()
def reset(self): def reset(self):
reports_lock.acquire() with REPORTS_LOCK:
try: REPORTS[self.cid] = {}
reports[self.cid] = {}
finally:
reports_lock.release()
def report(self): def report(self):
"""Returns a statistic report of catalog queries as list of dicts. """Returns a statistic report of catalog queries as list of dicts.
The duration is provided in millisecond. The duration is provided in millisecond.
""" """
rval = [] rval = []
for key, report in reports.get(self.cid, {}).items(): for key, report in REPORTS.get(self.cid, {}).items():
last = report.last last = report.last
info = { info = {
'query': key, 'query': key,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment