import logging import time from d4s_cache_controller import D4S_Cache_Controller from icproxycontroller import D4S_IS_DiscoveryCatalogueNamespaces from threading import Event, Thread CATEGORY = 'category' NOCATEOGORY = 'nocategory' log = logging.getLogger(__name__) cancel_future_calls = None # Refreshing time for namespaces cache in secs. NAMESPACES_CACHE_REFRESHING_TIME = 60 * 60 # Funtion to call repeatedly another function def call_repeatedly(interval, func, *args): log.info("call_repeatedly called on func '{}' with interval {} sec".format(func.func_name, interval)) stopped = Event() def loop(): while not stopped.wait(interval): # the first call is in `interval` secs func(*args) th = Thread(name='daemon_caching_namespaces', target=loop) th.setDaemon(True) th.start() return stopped.set def reload_namespaces_from_IS(urlICProxy, resourceID, gcubeToken): log.info("_reload_namespaces_from_IS called") try: discovery_ctg_namespaces = D4S_IS_DiscoveryCatalogueNamespaces(urlICProxy, resourceID, gcubeToken) namespaces_list_of_dict = discovery_ctg_namespaces.getNamespacesDictFromResource() if namespaces_list_of_dict is not None and len(namespaces_list_of_dict) > 0: log.debug("namespaces read from IS are: %s" % namespaces_list_of_dict) D4S_Cache_Controller().write_namespaces(namespaces_list_of_dict) else: log.info("namespaces list read from IS is empty. Skipping caching update") except Exception as e: print("Error occurred on reading namespaces from IS and refilling the cache!") print(e) # Created by Francesco Mangiacrapa # francesco.mangiacrapa@isti.cnr.it # ISTI-CNR Pisa (ITALY) # D4S_IS_DiscoveryCatalogueNamespacesController is used to discovery namespaces for Catalogue Categories (implemented as a Singleton) # @param: urlICProxy is the URI of IC proxy rest-full service provided by IS # @param: resourceID is the resource ID of the Generic Resource: "Namespaces Catalogue Categories" # @param: gcubeToken the gcube token used to contact the IC proxy class D4S_Namespaces_Controller(): __instance = None @staticmethod def getInstance(): """ Static access method. """ if D4S_Namespaces_Controller.__instance is None: D4S_Namespaces_Controller() return D4S_Namespaces_Controller.__instance def __init__(self): """ Virtually private constructor. """ log.debug("__init__ D4S_Namespaces_Controller") if D4S_Namespaces_Controller.__instance is not None: raise Exception("This class is a singleton!") else: D4S_Namespaces_Controller.__instance = self self._d4s_cache_controller = D4S_Cache_Controller() self._urlICProxy = None self._resourceID = None self._gcubeToken = None def load_namespaces(self, urlICProxy, resourceID, gcubeToken): log.debug("readNamespaces called") self._urlICProxy = urlICProxy self._resourceID = resourceID self._gcubeToken = gcubeToken return self._check_namespaces() def _read_namespaces(self): return self._d4s_cache_controller.read_namespaces() def _check_namespaces(self): log.debug("_check_namespaces called") if self._d4s_cache_controller is None: self._d4s_cache_controller = D4S_Cache_Controller() namespace_list = self._read_namespaces() # when the Cache is empty if namespace_list is None or not namespace_list: # reading namespaces from IS and filling the DB log.info("The Cache is empty. Reading the namespace from IS and filling the Cache") reload_namespaces_from_IS(self._urlICProxy, self._resourceID, self._gcubeToken) # reloading the namespaces from the cache namespace_list = self._read_namespaces() # starting Thread daemon for refreshing the namespaces Cache global cancel_future_calls if cancel_future_calls is None: cancel_future_calls = call_repeatedly(NAMESPACES_CACHE_REFRESHING_TIME, reload_namespaces_from_IS, self._urlICProxy, self._resourceID, self._gcubeToken) return namespace_list def get_dict_ctg_namespaces(self): log.debug("get_dict_ctg_namespaces called") namespace_list_of_dict = self._check_namespaces() return self.convert_namespaces_to_d4s_namespacedict(namespace_list_of_dict) # Private method @staticmethod def convert_namespaces_to_d4s_namespacedict(namespace_list_of_dict): log.debug("convert_namespaces_to_d4s_namespacedict called on %s" % namespace_list_of_dict) return D4S_IS_DiscoveryCatalogueNamespaces.to_namespaces_dict_index_for_id(namespace_list_of_dict)