1313# See the License for the specific language governing permissions and
1414# limitations under the License.
1515
16+ import time
1617from fnmatch import fnmatchcase
1718from 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
2123from swift3 .exception import IAMException
2224from 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+
358384class 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