<s> import collections <EOL> from oslo_concurrency import lockutils <EOL> from oslo_utils import timeutils <EOL> from neutron . openstack . common . cache import backends <EOL> class MemoryBackend ( backends . BaseCache ) : <EOL> def __init__ ( self , parsed_url , options = None ) : <EOL> super ( MemoryBackend , self ) . __init__ ( parsed_url , options ) <EOL> self . _clear ( ) <EOL> def _set_unlocked ( self , key , value , ttl = <NUM_LIT:0> ) : <EOL> expires_at = <NUM_LIT:0> <EOL> if ttl != <NUM_LIT:0> : <EOL> expires_at = timeutils . utcnow_ts ( ) + ttl <EOL> self . _cache [ key ] = ( expires_at , value ) <EOL> if expires_at : <EOL> self . _keys_expires [ expires_at ] . add ( key ) <EOL> def _set ( self , key , value , ttl = <NUM_LIT:0> , not_exists = False ) : <EOL> with lockutils . lock ( key ) : <EOL> if not_exists and self . _exists_unlocked ( key ) : <EOL> return False <EOL> self . _set_unlocked ( key , value , ttl ) <EOL> return True <EOL> def _get_unlocked ( self , key , default = None ) : <EOL> now = timeutils . utcnow_ts ( ) <EOL> try : <EOL> timeout , value = self . _cache [ key ] <EOL> except KeyError : <EOL> return ( <NUM_LIT:0> , default ) <EOL> if timeout and now >= timeout : <EOL> try : <EOL> del self . _cache [ key ] <EOL> except KeyError : <EOL> pass <EOL> try : <EOL> self . _keys_expires [ timeout ] . remove ( key ) <EOL> except ( KeyError , ValueError ) : <EOL> pass <EOL> return ( <NUM_LIT:0> , default ) <EOL> return ( timeout , value ) <EOL> def _get ( self , key , default = None ) : <EOL> with lockutils . lock ( key ) : <EOL> return self . _get_unlocked ( key , default ) [ <NUM_LIT:1> ] <EOL> def _exists_unlocked ( self , key ) : <EOL> now = timeutils . utcnow_ts ( ) <EOL> try : <EOL> timeout = self . _cache [ key ] [ <NUM_LIT:0> ] <EOL> return not timeout or now <= timeout <EOL> except KeyError : <EOL> return False <EOL> def __contains__ ( self , key ) : <EOL> with lockutils . lock ( key ) : <EOL> return self . _exists_unlocked ( key ) <EOL> def _incr_append ( self , key , other ) : <EOL> with lockutils . lock ( key ) : <EOL> timeout , value = self . _get_unlocked ( key ) <EOL> if value is None : <EOL> return None <EOL> ttl = timeutils . utcnow_ts ( ) - timeout <EOL> new_value = value + other <EOL> self . _set_unlocked ( key , new_value , ttl ) <EOL> return new_value <EOL> def _incr ( self , key , delta ) : <EOL> if not isinstance ( delta , int ) : <EOL> raise TypeError ( '<STR_LIT>' ) <EOL> return self . _incr_append ( key , delta ) <EOL> def _append_tail ( self , key , tail ) : <EOL> return self . _incr_append ( key , tail ) <EOL> def _purge_expired ( self ) : <EOL> """<STR_LIT>""" <EOL> now = timeutils . utcnow_ts ( ) <EOL> for timeout in sorted ( self . _keys_expires . keys ( ) ) : <EOL> if now < timeout : <EOL> break <EOL> for subkey in self . _keys_expires . pop ( timeout ) : <EOL> try : <EOL> if self . _cache [ subkey ] [ <NUM_LIT:0> ] == timeout : <EOL> del self . _cache [ subkey ] <EOL> except KeyError : <EOL> continue <EOL> def __delitem__ ( self , key ) : <EOL> self . _purge_expired ( ) <EOL> value = self . _cache . pop ( key , None ) <EOL> if value : <EOL> try : <EOL> self . _keys_expires [ value [ <NUM_LIT:0> ] ] . remove ( key ) <EOL> except ( KeyError , ValueError ) : <EOL> pass <EOL> def _clear ( self ) : <EOL> self . _cache = { } <EOL> self . _keys_expires = collections . defaultdict ( set ) <EOL> def _get_many ( self , keys , default ) : <EOL> return super ( MemoryBackend , self ) . _get_many ( keys , default ) <EOL> def _set_many ( self , data , ttl = <NUM_LIT:0> ) : <EOL> return super ( MemoryBackend , self ) . _set_many ( data , ttl ) <EOL> def _unset_many ( self , keys ) : <EOL> return super ( MemoryBackend , self ) . _unset_many ( keys ) </s>
