def __init__(self): self._cpex_lock=RLock() # cpex switch list lock, used for setting/getting the "primary" cpex switch. self._cache_lock=Lock() # domain value cache lock. self._cpex_switch_map_lock = Lock() # lock for cpex switches cache data structure self._cache_value=None self._cache_time=0 self._cpex_switch_map_cache=SwitchMap({}) self._cpex_switch_map_time=0 self.ttl=30 self._reinit() return
class EnergywiseDomain(Node): def __init__(self): self._cpex_lock=RLock() # cpex switch list lock, used for setting/getting the "primary" cpex switch. self._cache_lock=Lock() # domain value cache lock. self._cpex_switch_map_lock = Lock() # lock for cpex switches cache data structure self._cache_value=None self._cache_time=0 self._cpex_switch_map_cache=SwitchMap({}) self._cpex_switch_map_time=0 self.ttl=30 self._reinit() return def _not_running(self, *args, **kw): raise ENotRunning("%r is not running." % self.as_node_url()) def _empty_domain_usage(self, importance=100, skipCache=False): return 0.0 def _reinit(self): self._cpex_switches = [] self._snmp_switches = [] self._all_switches = [] self._all_domains = [] self.domain = '' self.trend_node = None self.energywise_domain_usage = self._not_running return def configure(self, config): Node.configure(self, config) set_attribute(self, 'ttl', 30, config, int) return def configuration(self): config = Node.configuration(self) get_attribute(self, 'ttl', config, str) return config def start(self): self._cpex_lock.acquire() try: for child in self.children_nodes(): if isinstance(child,EnergywiseSwitch): if child.PROTOCOL_SNMP == child.protocol: self._snmp_switches.append(child) else: self._cpex_switches.append(child) self._all_switches.append(child) elif isinstance(child,EnergywiseDomain): self._all_domains.append(child) # elif @fixme magic hook for reverse compatibility. if self._snmp_switches and self._cpex_switches: raise EConfiguration( "All switches in a domain must be configurtion to use the" " same protocol." ) self._cpex_switches.sort(_cpex_switch_cmp) finally: self._cpex_lock.release() if not self.domain: self.domain = _find_domain(self) if self._snmp_switches: self.energywise_domain_usage = self.snmp_domain_usage elif self._cpex_switches: self.energywise_domain_usage = self.cpex_domain_usage else: self.energywise_domain_usage = self._empty_domain_usage Node.start(self) return def stop(self): self._reinit() Node.stop(self) return def cpex_domain_usage(self, importance=100, skipCache=False, max_attempts=3): self._cpex_lock.acquire() aggr_result = 0 try: if not self._cpex_switches: raise ENoDomainSwitches( "No switches are configured for the %r domain." % self.domain ) for switch in self._cpex_switches: for i in range(0, max_attempts): try: result = switch.cpex_domain_usage(importance) if result: aggr_result += result break except: pass except ENoDomainSwitches: raise finally: self._cpex_lock.release() return aggr_result # caching for cpex switches under a domain # @return A dictionary of Energywise usage values keyed by switch address, possibly from cache. def cpex_switch_usage_map(self, importance=100, skipCache=False): self._cpex_switch_map_lock.acquire() try: if skipCache or self._is_cpex_switch_map_stale(time.time()): #fetch actual value usage_map = self._cpex_switch_usage_map(importance) self._update_cpex_switch_map(usage_map, time.time()) return self._cpex_switch_map_cache finally: self._cpex_switch_map_lock.release() raise EUnreachableCode("Executed unreachable code!") ## # Call cpex_switch_usage_map on the primary cpex switch. # @return A dictionary of Energywise usage values keyed by switch address. def _cpex_switch_usage_map(self, importance=100, max_attempts=3): self._cpex_lock.acquire() aggr_result = {} try: if not self._cpex_switches: raise ENoDomainSwitches( "No switches are configured for the %r domain." % self.domain ) for switch in self._cpex_switches: for i in range(0, max_attempts): try: result = switch.cpex_switch_usage_map(importance) if result: aggr_result.update(result) break except: pass except ENoDomainSwitches: raise finally: self._cpex_lock.release() return aggr_result def snmp_domain_usage(self, importance=100, skipCache=False): result = 0 for switch in self._snmp_switches: try: result += switch.snmp_switch_usage(importance, skipCache) except: msglog.exception() msglog.log("Energywise",msglog.types.ERR, "Failed to get data from %r switch" %switch.name ) return result def _is_cpex_switch_map_stale(self, timestamp): return (self._cpex_switch_map_time + self.ttl) < timestamp def _update_cpex_switch_map(self, switch_map, timestamp): self._cpex_switch_map_cache = SwitchMap(switch_map) self._cpex_switch_map_time = timestamp def _is_domain_cache_stale(self,timestamp): assert self._cache_lock.locked() return (self._cache_time + self.ttl) < timestamp def _update_domain_cache(self,value, timestamp): self._cache_value = value self._cache_time = timestamp #caching the domain-usage def aggregate_domain_usage(self, importance=100, skipCache=False): self._cache_lock.acquire() try: if skipCache or self._is_domain_cache_stale(time.time()): #fetch the actual value and update the cache try: result = self.energywise_domain_usage(importance, skipCache) except: msglog.exception() result = 0 for sub in self._all_domains: result += sub.aggregate_domain_usage(importance, skipCache) self._update_domain_cache(result, time.time()) return self._cache_value else: # use the cached value return self._cache_value finally: self._cache_lock.release() raise EUnreachableCode("Executed unreachable code!") def new_trend(self,period): return new_trend(self,period) def delete_trend(self): return delete_trend(self) def get(self, skipCache=False): return self.aggregate_domain_usage() def get_result(self, skipCache=False): return Result(self.get(skipCache), time.time(), cached=False)