Skip to content

Commit 743942d

Browse files
AymericDufvennetier
authored andcommitted
IAM: Replace LRU cache with one that works
Previously, when we saved the same key multiple times in the cache (after expiration) and we overflowed the cache, a KeyError exception was raised. Also, if we overflowed the cache with many different keys, the overall cache size would only increase.
1 parent a64be4e commit 743942d

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
swift>=2.13.0
2+
functools32
23
lxml
34
requests!=2.9.0,>=2.8.1 # Apache-2.0
45
six>=1.9.0

swift3/iam.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
import time
1617
from fnmatch import fnmatchcase
1718
from functools import wraps
19+
from functools32 import lru_cache
1820

19-
from swift.common.utils import config_auto_int_value, get_logger, LRUCache
21+
from swift.common.utils import config_auto_int_value, get_logger
2022

2123
from swift3.exception import IAMException
2224
from swift3.response import AccessDenied
@@ -355,6 +357,30 @@ def wrapper(*args, **kwargs):
355357
return real_check_iam_access
356358

357359

360+
def tlru_cache(maxtime=30, maxsize=1000):
361+
"""
362+
Least-recently-used cache decorator with time-based cache invalidation.
363+
364+
Due to the technique used, an entry can expire before the TTL,
365+
but never after.
366+
"""
367+
def tlru_cache_decorator(func):
368+
@lru_cache(maxsize=maxsize)
369+
def salted_func(__salt, *args, **kwargs):
370+
return func(*args, **kwargs)
371+
372+
@wraps(func)
373+
def tlru_cache_wrapper(*args, **kwargs):
374+
# Generate an extra argument, which will be the same for
375+
# maxtime seconds. After maxtime seconds, the argument changes,
376+
# and thus triggers a cache miss.
377+
return salted_func(int(time.time() / maxtime), *args, **kwargs)
378+
379+
return tlru_cache_wrapper
380+
381+
return tlru_cache_decorator
382+
383+
358384
class IamMiddleware(object):
359385
"""
360386
Base class for IAM implementations.
@@ -368,8 +394,13 @@ def __init__(self, app, conf):
368394
self.connection = conf.get('connection')
369395
maxsize = config_auto_int_value(conf.get('cache_size'), 1000)
370396
maxtime = config_auto_int_value(conf.get('cache_ttl'), 30)
371-
self._load_rules_matcher = LRUCache(maxsize=maxsize, maxtime=maxtime)(
372-
self._build_rules_matcher)
397+
if maxsize > 0:
398+
if maxtime <= 0:
399+
maxtime = float('inf')
400+
self._load_rules_matcher = tlru_cache(
401+
maxsize=maxsize, maxtime=maxtime)(self._build_rules_matcher)
402+
else:
403+
self._load_rules_matcher = self._build_rules_matcher
373404

374405
def __call__(self, env, start_response):
375406
# Put the rules callback in the request environment so middlewares

0 commit comments

Comments
 (0)