From 7649f03c7004b25c5144d13b3dfe62f13fbd4b6a Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 25 May 2016 12:39:48 -0400 Subject: [PATCH] CacheProxyDb: adds LRU cache for handle lookups --- gramps/gen/proxy/__init__.py | 1 + gramps/gen/proxy/cache.py | 182 +++++++++++++++++++++++ gramps/plugins/webreport/narrativeweb.py | 4 +- 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 gramps/gen/proxy/cache.py diff --git a/gramps/gen/proxy/__init__.py b/gramps/gen/proxy/__init__.py index b52164b42..e471cbe4b 100644 --- a/gramps/gen/proxy/__init__.py +++ b/gramps/gen/proxy/__init__.py @@ -26,3 +26,4 @@ from .filter import FilterProxyDb from .living import LivingProxyDb from .private import PrivateProxyDb from .referencedbyselection import ReferencedBySelectionProxyDb +from .cache import CacheProxyDb diff --git a/gramps/gen/proxy/cache.py b/gramps/gen/proxy/cache.py new file mode 100644 index 000000000..3bc2db8b5 --- /dev/null +++ b/gramps/gen/proxy/cache.py @@ -0,0 +1,182 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (c) 2016 Gramps Development Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Proxy class for the Gramps databases. Caches lookups from handles. +""" + +class CacheProxyDb: + """ + A Proxy for a database with cached lookups on handles. + + Does not invalid caches. Should be used only in read-only + places, and not where caches are altered. + """ + def __init__(self, database): + """ + CacheProxy will cache items based on their handle. + + Assumes all handles (regardless of type) are unique. + Database is called self.db for consistancy with other + proxies. + """ + self.db = database + self.clear_cache() + + def __getattr__(self, attr): + """ + If an attribute isn't found here, use the self.db + version. + """ + return self.db.__getattr__(attr) + + def clear_cache(self, handle=None): + """ + Clears all caches if handle is None, or + specific entry. + """ + from gramps.gui.views.treemodels.lru import LRU + if handle: + del self.cache_handle[handle] + else: + self.cache_handle = LRU(100000) + + def get_person_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_person_from_handle(handle) + return self.cache_handle[handle] + + def get_event_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_event_from_handle(handle) + return self.cache_handle[handle] + + def get_family_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_family_from_handle(handle) + return self.cache_handle[handle] + + def get_repository_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_repository_from_handle(handle) + return self.cache_handle[handle] + + def get_place_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_place_from_handle(handle) + return self.cache_handle[handle] + + def get_place_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_place_from_handle(handle) + return self.cache_handle[handle] + + def get_citation_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_citation_from_handle(handle) + return self.cache_handle[handle] + + def get_source_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_source_from_handle(handle) + return self.cache_handle[handle] + + def get_note_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_note_from_handle(handle) + return self.cache_handle[handle] + + def get_media_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_media_from_handle(handle) + return self.cache_handle[handle] + + def get_tag_from_handle(self, handle): + """ + Gets item from cache if it exists. Converts + handles to string, for uniformity. + """ + if isinstance(handle, bytes): + handle = str(handle, "utf-8") + if handle not in self.cache_handle: + self.cache_handle[handle] = self.db.get_tag_from_handle(handle) + return self.cache_handle[handle] + + diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index 040302938..0388961d8 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -125,7 +125,7 @@ from gramps.gen.utils.image import image_size # , resize_to_jpeg_buffer from gramps.gen.display.name import displayer as _nd from gramps.gen.display.place import displayer as _pd from gramps.gen.datehandler import displayer as _dd -from gramps.gen.proxy import LivingProxyDb +from gramps.gen.proxy import LivingProxyDb, CacheProxyDb from gramps.plugins.lib.libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS from gramps.gen.datehandler import get_date @@ -7990,6 +7990,8 @@ class NavWebReport(Report): None, yearsafterdeath) + self.database = CacheProxyDb(self.database) + filters_option = menu.get_option_by_name('filter') self.filter = filters_option.get_filter()