Mercurial > moin > 1.9
changeset 6031:1b2e1497f5ed
replace slow get_by_filter() calls by faster _getUserIdByKey calls
get_by_filter is O(N) with N being the amount of users.
it reads all user profiles from disk, so it is very slow if you have many.
_getUserIdByKey uses a cached dictionary with direct lookup search value -> userid
implement optional case-insensitive lookup for _getUserIdByKey
use lower-cased search value and lower-cased dict keys to support the case-insensitive
the lowercase support dicts are only built / kept in memory and not cached to disk
author | Thomas Waldmann <tw AT waldmann-edv DOT de> |
---|---|
date | Fri, 14 Feb 2014 17:01:16 +0100 |
parents | 5ab38cec99f7 |
children | 9248e31d7a95 |
files | MoinMoin/user.py |
diffstat | 1 files changed, 37 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/MoinMoin/user.py Fri Feb 14 15:29:47 2014 +0100 +++ b/MoinMoin/user.py Fri Feb 14 17:01:16 2014 +0100 @@ -21,6 +21,7 @@ """ import os, time, codecs, base64 +from copy import deepcopy import md5crypt try: @@ -57,7 +58,10 @@ return userlist def get_by_filter(request, filter_func): - """ Searches for an user with a given filter function """ + """ Searches for a user with a given filter function + + Be careful: SLOW for big wikis, rather use _getUserIdByKey & related. + """ for uid in getUserList(request): theuser = User(request, uid) if filter_func(theuser): @@ -65,16 +69,13 @@ def get_by_email_address(request, email_address): """ Searches for an user with a particular e-mail address and returns it. """ - filter_func = lambda user: user.valid and user.email.lower() == email_address.lower() - return get_by_filter(request, filter_func) + return _getUserIdByKey(request, 'email', email_address, case=False) def get_by_jabber_id(request, jabber_id): """ Searches for an user with a perticular jabber id and returns it. """ - filter_func = lambda user: user.valid and user.jid.lower() == jabber_id.lower() - return get_by_filter(request, filter_func) + return _getUserIdByKey(request, 'jid', jabber_id, case=False) - -def _getUserIdByKey(request, key, search): +def _getUserIdByKey(request, key, search, case=True): """ Get the user ID for a specified key/value pair. This method must only be called for keys that are @@ -82,14 +83,18 @@ @param key: the key to look in @param search: the value to look for + @param case: do a case-sensitive lookup? @return the corresponding user ID or None """ if key not in CACHED_USER_ATTRS: raise ValueError("unsupported key, must be in CACHED_USER_ATTRS") if not search: return None + cfg_cache_attr = key + "2id" + if not case: + cfg_cache_attr += "_lower" + search = search.lower() cfg = request.cfg - cfg_cache_attr = key + "2id" try: attr2id = getattr(cfg.cache, cfg_cache_attr) from_disk = False @@ -128,14 +133,18 @@ or None to delete the in-memory cache. """ for attrname in CACHED_USER_ATTRS: - cfg_cache_attr = attrname + "2id" if cache is None: try: - delattr(request.cfg.cache, cfg_cache_attr) + delattr(request.cfg.cache, attrname + "2id") + except: + pass + try: + delattr(request.cfg.cache, attrname + "2id_lower") except: pass else: - setattr(request.cfg.cache, cfg_cache_attr, cache[attrname]) + setattr(request.cfg.cache, attrname + "2id", cache[attrname]) + setattr(request.cfg.cache, attrname + "2id_lower", cache[attrname + "_lower"]) def loadLookupCaches(request): @@ -148,7 +157,8 @@ cache = {} for attrname in CACHED_USER_ATTRS: cache[attrname] = {} - setMemoryLookupCaches(request, cache) + cache_with_lowercase = addLowerCaseKeys(cache) + setMemoryLookupCaches(request, cache_with_lowercase) def rebuildLookupCaches(request): @@ -176,7 +186,8 @@ else: attr2id[value] = userid - setMemoryLookupCaches(request, cache) + cache_with_lowercase = addLowerCaseKeys(cache) + setMemoryLookupCaches(request, cache_with_lowercase) diskcache.update(cache) diskcache.unlock() return cache @@ -190,6 +201,17 @@ caching.CacheEntry(request, arena, key, scope=scope).remove() +def addLowerCaseKeys(cache): + """add lowercased lookup keys, so we can support case-insensitive lookup""" + c = deepcopy(cache) # we do not want to modify cache itself + for attrname in CACHED_USER_ATTRS: + attr2id = c[attrname] + attr2id_lower = c[attrname + "_lower"] = {} + for key, value in attr2id.iteritems(): + attr2id_lower[key.lower()] = value + return c + + def getUserId(request, searchName): """ Get the user ID for a specific user NAME. @@ -1030,7 +1052,8 @@ else: attr2id[value] = userid - setMemoryLookupCaches(self._request, cache) + cache_with_lowercase = addLowerCaseKeys(cache) + setMemoryLookupCaches(self._request, cache_with_lowercase) diskcache.update(cache) diskcache.unlock()