Cached configuration manager class added and caching added for get_category_name endpoint
@@ -10,6 +10,7 @@ import copy
import json
import inspect
import ipaddress
+import datetime
from foglamp.common.storage_client.payload_builder import PayloadBuilder
from foglamp.common.storage_client.storage_client import StorageClientAsync
@@ -30,6 +31,56 @@ _valid_type_strings = sorted(['boolean', 'integer', 'string', 'IPv4', 'IPv6', 'X
'URL', 'enumeration'])
+class CachedConfiguration(object):
+ """Cached Configuration Manager"""
+
+ MAX_CACHE_SIZE = 10
+
+ def __init__(self):
+ """
+ cache: value dictionary as per category_name
+ max_cache_size: Hold the 10 recently requested categories in the cache
+ hit: number of times an item is read from the cache
+ miss: number of times an item was not found in the cache and a read of the storage layer was required
+ """
+ self.cache = {}
+ self.max_cache_size = self.MAX_CACHE_SIZE
+ self.hit = 0
+ self.miss = 0
+
+ def __contains__(self, category_name):
+ """Returns True or False depending on whether or not the key is in the cache
+ and update the hit and data_accessed value only If True"""
+ if category_name in self.cache:
+ current_hit = self.cache[category_name]['hit']
+ self.cache[category_name].update({'date_accessed': datetime.datetime.now(), 'hit': current_hit + 1})
+ return True
+ return False
+
+ def update(self, category_name, category):
+ """Update the cache dictionary and remove the oldest item"""
+ if category_name not in self.cache and len(self.cache) >= self.max_cache_size:
+ self.remove_oldest()
+
+ self.cache[category_name] = {'date_accessed': datetime.datetime.now(), 'value': category, 'hit': self.hit, 'miss': self.miss}
+ _logger.info("Updated Cache %s", self.cache)
+
+ def remove_oldest(self):
+ """Remove the entry that has the oldest accessed date"""
+ oldest_entry = None
+ for category_name in self.cache:
+ if oldest_entry is None:
+ oldest_entry = category_name
+ elif self.cache[category_name]['date_accessed'] < self.cache[oldest_entry]['date_accessed']:
+ oldest_entry = category_name
+ self.cache.pop(oldest_entry)
+
+ @property
+ def size(self):
+ """Return the size of the cache"""
+ return len(self.cache)
+
+
class ConfigurationManagerSingleton(object):
""" ConfigurationManagerSingleton
@@ -69,6 +120,7 @@ class ConfigurationManager(ConfigurationManagerSingleton):
_storage = None
_registered_interests = None
+ _cacheManager = None
def __init__(self, storage=None):
ConfigurationManagerSingleton.__init__(self)
@@ -78,6 +130,8 @@ class ConfigurationManager(ConfigurationManagerSingleton):
self._storage = storage
if self._registered_interests is None:
self._registered_interests = {}
+ if self._cacheManager is None:
+ self._cacheManager = CachedConfiguration()
async def _run_callbacks(self, category_name):
callbacks = self._registered_interests.get(category_name)
@@ -373,7 +427,13 @@ class ConfigurationManager(ConfigurationManagerSingleton):
None
"""
try:
- return await self._read_category_val(category_name)
+ if category_name in self._cacheManager:
+ return self._cacheManager.cache[category_name]['value']
+
+ cat = await self._read_category_val(category_name)
+ if cat is not None:
+ self._cacheManager.update(category_name, cat)
+ return cat
except:
_logger.exception(
'Unable to get all category names based on category_name %s', category_name)
