Source code for CoreLayer.Cache
from AccessLayer import UtilityLayer
import logging as log
import collections
import sys
[docs]class Cache(object):
""" Cache tiles and preloaded keywords
Arguments
-----------
_runtime: :class:`RUNTIME`
Needed to make attributes for each instance
Attributes
-----------
_max_memory: int
``MAX`` from :data:`RUNTIME.CACHE`, and \
the max bytes of memory to be used.
_cach_meta: str
``MAX`` from :data:`RUNTIME.CACHE`, and \
the key for the size of cached keywords
_cache: Collections.OrderedDict
A Least recently used ordered dictionary
_now_memory: int
The current bytes of memory used
"""
def __init__(self, _runtime):
self._max_memory = _runtime.CACHE.MAX.VALUE
self._cache_meta = _runtime.CACHE.META.NAME
self._cache = collections.OrderedDict()
self._now_memory = 0
[docs] def get(self, key):
""" Get a value from the cache by key
Arguments
----------
key: str
The key from a :class:`Query` to access the cache
Returns
---------
anything
The value stored in the cache, or an empty list
"""
try:
# Get the value from the cache. Add to top.
value = self._cache.pop(key)
self._cache[key] = value
return value
except KeyError:
return []
[docs] def set(self, key, value):
""" Set a key in the cache to a value
Arguments
----------
key: str
The key from a :class:`Query` to access the cache
value: anything
The keywords or tile value to store in the cache
Returns
---------
int
0 if successful and -1 if value is too large
"""
value_memory = self.value_size(value)
# Do not cache if value more than total memory
if value_memory > self._max_memory:
# Log Value over Max Cache
msg = "Cannot cache {0}. {1} bytes is over max."
log.warning(msg.format(key, value_memory))
return -1
# Add new item to cache memory count
self._now_memory += value_memory
try:
self._cache.pop(key)
except KeyError:
while self._now_memory >= self._max_memory:
# Remove old item from cache and memory count
old_value = self._cache.popitem(last=False)[1]
self._now_memory -= self.value_size(old_value)
# Add new item to the cache
self._cache[key] = value
# Log successful add
msg = "Add {0} to cache. Cache now {1} bytes."
log.info(msg.format(key, self._now_memory))
return 0
[docs] def value_size(self, value):
""" Get actual memory size of a value
Arguments
----------
value: anything
expected to be a dict or a numpy.ndarray
Returns
--------
int:
the number of bytes used by the value
"""
if isinstance(value,dict):
return int(value[self._cache_meta])
return sys.getsizeof(value)