def calculate_function_value(self, call_function_instruction): if call_function_instruction.function_name == 'size': var_name = call_function_instruction.args[0] if var_name not in self.variables: raise RuntimeException( "Variable {0} not defined in communication algorithm {1}.". format(var_name, self.algorithm_name)) value = self.variables[var_name] # If tuple element expression if len(call_function_instruction.args) > 1: if not isinstance(value, TupleExpression): raise RuntimeException( "Variable {0} in communication algorithm {1} is not tuple, it is: {2}." .format(var_name, self.algorithm_name, unicode(value))) index = call_function_instruction.args[1] if len(value.elements) <= index: raise RuntimeException( "Variable {0} in communication algorithm {1} has " "{2} elements while index {3} is asked.".format( var_name, self.algorithm_name, len(value.elements), index)) value = value.elements[index] return self.context.metrics_manager.get_expression_size( value, self.context, self.host) elif call_function_instruction.function_name == 'quality': if self.link_quality is None: raise RuntimeException( "Link quality is undefined in {0} algorithm. ".format( self.algorithm_name)) return self.link_quality raise RuntimeException( "Unresolved reference to function {0}() in algorithm {1}.".format( call_function_instruction.function_name, self.algorithm_name))
def _predefined_routing_next_function__populate(call_function_expression, host, populator, context=None): topology_name = call_function_expression.arguments[0].identifier receiver_function_id_expression = populator.populate( call_function_expression.arguments[1], host) receiver_function_id_expression = _predefined_id_function__populate( receiver_function_id_expression, host, populator) receiver_name = getattr(receiver_function_id_expression, '_host_name') receiver = None for h in context.hosts: if h.name == receiver_name: receiver = h break sender = host sender_name = sender.name if len(call_function_expression.arguments) > 2: sender_function_id_expression = populator.populate( call_function_expression.arguments[2], host) sender_function_id_expression = _predefined_id_function__populate( sender_function_id_expression, host, populator) sender_name = getattr(sender_function_id_expression, '_host_name') if sender_name != sender.name: sender = None for h in context.hosts: if h.name == sender_name: sender = h break if sender is None: raise RuntimeException("Host '%s' undefined." % sender_name) if receiver is None: raise RuntimeException("Host '%s' undefined." % receiver_name) if sender == receiver: next_host = receiver else: next_host = context.channels_manager.get_router().get_next_hop_host( topology_name, sender, receiver) if next_host is None: raise RuntimeException( "The route from host '%s' to host '%s' cannot be found." % (sender_name, receiver_name)) # DEBUG # print host.name, ': ', unicode(call_function_expression), ' -> ', next_host.name # DEBUG id_function = CallFunctionExpression( 'id', arguments=[IdentifierExpression(next_host.name)]) setattr(id_function, '_host_name', next_host.name) return id_function
def _make_rpn(self, expression): """ """ stack = [] rpn = [] for token in expression: # if operator if self._is_operation_token(token): while len(stack) > 0: top_operator = stack[len(stack) - 1] # if current operator is left-associative and its order is lower or equal than top operator # or current operator is right-associative and its order is lower than top operator if (token in self.left_associative_operators and self._operator_order(token) <= self._operator_order(top_operator))\ or (token in self.right_associative_operators and self._operator_order(token) < self._operator_order(top_operator)): rpn.append(stack.pop()) else: break stack.append(token) elif token == '(': stack.append(token) elif token == ')': found_paran = False while len(stack) > 0: top_operator = stack[len(stack) - 1] if top_operator == '(': found_paran = True stack.pop() break else: rpn.append(stack.pop()) if not found_paran: raise RuntimeException( "Incorrect number of brackets in algorithm {0}.". format(self.algorithm_name)) else: # else number if isinstance(token, AlgCallFunction): token = self.calculate_function_value(token) elif isinstance(token, basestring): if token not in self.variables: raise RuntimeException( "Variable {0} not defined in communication algorithm {1}." .format(token, self.algorithm_name)) token = self.variables[token] rpn.append(float(token)) while len(stack) > 0: rpn.append(stack.pop()) return rpn
def _get_current_for_communication(self, context, host, channel, metric, message, receiver=None): """ Returns current (in A) of sending/receiving'listening for a message """ if metric['type'] == 'metric': metric_value = metric['value'] elif metric['type'] == 'algorithm': algorithm_name = metric['name'] if not context.algorithms_resolver.has_algorithm(algorithm_name): raise RuntimeException( "Communication algorithm {0} undeclared.".format( algorithm_name)) link_quality = context.channels_manager.get_router( ).get_link_quality(channel.tag_name, message.sender, receiver) alg = context.algorithms_resolver.get_algorithm(algorithm_name) variables = { 'link_quality': link_quality, alg['parameter']: message.expression, } metric_value = context.algorithms_resolver.calculate( context, host, algorithm_name, variables) else: return 0 # unit = metric['unit'] # exact current (only mA) return metric_value / 1000.0
def are_equal_call_function_expressions(self, left, right): if not isinstance(left, CallFunctionExpression) or not isinstance( right, CallFunctionExpression): raise RuntimeException( "Trying to compare predefined functions expressions, but they are not." ) return self.functions_map[left.function_name]['are_equal'](left, right)
def wait_for_message(self, request): """ Add host to the queue of hosts waiting for messages. Host can wait for many expressions. """ if not self.is_connected_with_host(request.receiver): raise RuntimeException( "Channel '%s' is not connected with host '%s'." % (self.name, request.receiver.name)) # Check if this request already exists existing_request = self.get_existing_request_for_instruction( request.receiver, request.instruction) # If it does not exist add if not existing_request: # print 'IN', unicode(self.name), unicode(request.receiver), unicode(request.instruction) self._waiting_requests.append(request) else: # If request exists, check if it is waiting on IN instruction now if not existing_request.is_waiting: # If it is now (request stays in channel only to fill the buffer) start waiting on this request existing_request.start_waiting() # Check if request can be bound with expressions self._bind_messages_with_receivers()
def _calculate_operation(self, operator, left, right): """ """ if operator == '+': return left + right elif operator == '-': return left - right elif operator == '*': return left * right elif operator == '/': return left / right elif operator == '==': return left == right elif operator == '!=': return left != right elif operator == '>=': return left >= right elif operator == '>': return left > right elif operator == '<=': return left <= right elif operator == '<': return left < right else: raise RuntimeException( "Incorrect operator {0} of brackets in algorithm {1}.".format( operator, self.algorithm_name))
def calculate(self): while not self.finished(): self.execute_current_instruction() if self.return_value is None: raise RuntimeException( "Algorithm {0} has no return value. Did you forget to use return instruction?" .format(self.algorithm_name)) return self.return_value
def find_primitive(self, host, call_function_expression): """ Method finds metric for function call in host. Method searches the metric in three kinds: normal, plus and star. If more than one metrics is found, runtime exception is raised. """ found_host_metric = None for host_metric in self.host_metrics: if host_metric.is_connected_with_host(host): found_host_metric = host_metric break if not found_host_metric: return None normal_metrics = [] plus_metrics = [] star_metrics = [] if len(found_host_metric.normal_blocks) > 0: for mb in found_host_metric.normal_blocks: if len(mb.params) <= len( call_function_expression.qop_arguments): normal_metrics.extend( mb.find_primitives( call_function_expression.function_name, call_function_expression.qop_arguments)) if len(found_host_metric.plus_blocks) > 0: for mb in found_host_metric.plus_blocks: if len(mb.params) <= len( call_function_expression.qop_arguments): plus_metrics.extend( mb.find_primitives( call_function_expression.function_name, call_function_expression.qop_arguments)) if len(found_host_metric.star_blocks) > 0: for mb in found_host_metric.star_blocks: if len(mb.params) <= len( call_function_expression.qop_arguments): star_metrics.extend( mb.find_primitives( call_function_expression.function_name, call_function_expression.qop_arguments)) if len(normal_metrics) + len(plus_metrics) + len(star_metrics) > 1: raise RuntimeException("Found many metrics for function '%s' with qopanalysis arguments: %s." \ % (call_function_expression.function_name, ', '.join(call_function_expression.qop_arguments))) if len(normal_metrics) > 0: return normal_metrics[0] if len(plus_metrics) > 0: return plus_metrics[0] if len(star_metrics) > 0: return star_metrics[0] return None
def _get_time_for_communication_step(self, context, host, channel, metric, message, receiver=None): """ Returns time of sending/receiving message """ if metric['type'] == 'metric': metric_value = metric['value'] elif metric['type'] == 'algorithm': algorithm_name = metric['name'] if not context.algorithms_resolver.has_algorithm(algorithm_name): raise RuntimeException( "Communication algorithm {0} undeclared.".format( algorithm_name)) link_quality = context.channels_manager.get_router( ).get_link_quality(channel.tag_name, message.sender, receiver) alg = context.algorithms_resolver.get_algorithm(algorithm_name) variables = { 'link_quality': link_quality, alg['parameter']: message.expression, } metric_value = context.algorithms_resolver.calculate( context, host, algorithm_name, variables) else: return 0 unit = metric['unit'] if unit == 'ms': # exact time return metric_value / 1000.0 else: # time depending on the size populated_expression = context.expression_populator.populate( message.expression, message.sender) # size in bytes size = context.metrics_manager.get_expression_size( populated_expression, context, message.sender) mspB = 0 if unit == 'mspB': mspB = float(metric_value) elif unit == 'mspb': mspB = float(metric_value) * 8.0 elif unit == 'kbps': mspB = 1.0 / (float(metric_value) * 0.128) elif unit == 'mbps': mspB = 1.0 / (float(metric_value) * 0.000128) spB = mspB / 1000.0 return spB * size
def _operator_order(self, operator): """ Returns the order of operator as number. """ orders = [['==', '!=', '<=', '>=', '>', '<', '&&', '||'], ['--', '-', '+'], ['*', '/']] for i in range(0, len(orders)): if operator in orders[i]: return i raise RuntimeException( "Operator {0} undefined in algorithm {1}.".format( operator, self.algorithm_name))
def _compute_current_expression(self, expression, context): """ Computes the expression from current assignment instruction. """ if isinstance(expression, BooleanExpression): return expression.clone() if isinstance(expression, IdentifierExpression) or isinstance(expression, CallFunctionExpression) \ or isinstance(expression, TupleExpression) or isinstance(expression, TupleElementExpression): # Population of variables which were previously populated (ie. additional attrs) return context.expression_populator.populate(expression, context.get_current_host()) raise RuntimeException("Expression '%s' cannot be a value of variable.")
def fulfill(self): """ Assigns requested variables with received messages. """ if not self.ready_to_fulfill(): raise RuntimeException( "Request of host {0} in instruction {1} is not ready to fulfill." .format(self.receiver.name, unicode(self.instruction))) # Set variable sent in message self.receiver.set_variable(self.instruction.variable_name, self.assigned_message.expression.clone()) # Move instructions context to the next instruction # print unicode(self.receiver.get_instructions_context_of_instruction(self.instruction).get_current_instruction()) self.receiver.get_instructions_context_of_instruction(self.instruction)\ .goto_next_instruction() # print unicode(self.receiver.get_instructions_context_of_instruction(self.instruction)) self.receiver.mark_changed()
def execute_instruction(self, context, **kwargs): """ Overriden """ instruction = context.get_current_instruction() channel = context.channels_manager.find_channel_for_current_instruction(context) if context.channels_manager.find_channel(instruction.channel_name) is None: raise RuntimeException("Channel {0} undefined.".format(instruction.channel_name)) if not channel: context.get_current_host().get_current_instructions_context().goto_next_instruction() context.get_current_host().mark_changed() return ExecutionResult(consumes_cpu=True, custom_index_management=True) if instruction.communication_type == COMMUNICATION_TYPE_OUT: if kwargs is not None and 'sent_message' in kwargs: message = kwargs['sent_message'] else: message = context.channels_manager.build_message( context.get_current_host(), context.get_current_host().get_variable(instruction.variable_name).clone(), context.expression_checker) kwargs['sent_message'] = message channel.send_message(context.get_current_host(), message, context.channels_manager.get_router()) # Go to next instruction context.get_current_host().get_current_instructions_context().goto_next_instruction() context.get_current_host().mark_changed() else: if kwargs is not None and 'messages_request' in kwargs: request = kwargs['messages_request'] else: request = context.channels_manager.build_message_request(context.get_current_host(), instruction, context.expression_populator) kwargs['messages_request'] = request channel.wait_for_message(request) return ExecutionResult(consumes_cpu=True, custom_index_management=True, result_kwargs=kwargs)
def _execute_hook(self, hook_type): """ Execute all hooks of given type. Pre instruction and post instruction hooks cannot be executed manually. """ if hook_type not in self._hooks: return if hook_type in [ HOOK_TYPE_PRE_INSTRUCTION_EXECUTION, HOOK_TYPE_POST_INSTRUCTION_EXECUTION ]: raise RuntimeException( "Cannot execute pre instruction and post instruction hooks manually." ) for h in self._hooks[hook_type]: h.execute(self.context)
def send_message(self, sender_host, message, router): """ Accept message with expressions. """ if not self.is_connected_with_host(sender_host): raise RuntimeException( "Channel '%s' is not connected with host '%s'." % (self.name, sender_host.name)) # print 'OUT', unicode(self.name), unicode(sender_host), unicode(message.expression) # Put sent message in the buffers of receivers # Receivers are retrieved from the requests present in the channel # When the channel is synchronous the buffers are cleaned after the binding try # and requests are removed after they are fulfilled for request in self.get_filtered_requests(message, router): if request.receiver not in self._buffers: self._buffers[request.receiver] = [] self._buffers[request.receiver].append(message) # Check if request can be bound with expressions self._bind_messages_with_receivers()
def get_next_hop_host(self, medium_name, sender, receiver): """ Returns the next host which is in the path between sender and receiver. If path does not exist, None is returned. """ # Check if path already exists existing_next_hop = self._find_existing_next_hop_host( medium_name, sender, receiver) if existing_next_hop is not None: return existing_next_hop # Build path using Dijsktra algorithm topology = self.mediums[medium_name]['topology'] def find_closest_host(distances, out): closest_host = None d = -1 for h in distances: if d < 0 or d > distances[h]: if h not in out: closest_host = h d = distances[h] return closest_host, d # Dijsktra distances = {sender: 0} out = [] closest, closes_distance = find_closest_host(distances, out) while (closest is not None) and (closest != receiver): if closest in topology: qualities = self.get_sender_links_qualities( medium_name, closest, exclude_broadcast=True) for next_host in qualities: if (next_host not in distances) \ or ((closes_distance + qualities[next_host]) < distances[next_host]): distances[ next_host] = closes_distance + qualities[next_host] out.append(closest) closest, closes_distance = find_closest_host(distances, out) # for h in distances: # print h.name, distances[h] def update_paths(medium_name, receiver, distances): routing = self.routing[medium_name] # Start from receiver current_host = receiver distance = distances[receiver] # Add receiver to path hosts_path = [receiver] # Repeat until we finish handling sender while distance > 0: # Find all hosts that are connected with current host previous_hosts = self.get_hosts_sending_to_receiver( medium_name, current_host) for prev_host in previous_hosts: # If prev host has not calculated distance, omit him if prev_host not in distances: continue # Check if this host is on the shortest path prev_quality = previous_hosts[prev_host] if distances[prev_host] + prev_quality == distances[ current_host]: # Go one step earlier current_host = prev_host # Decrease current distance distance = distances[prev_host] if prev_host not in routing: routing[prev_host] = {} next_host = hosts_path[0] if next_host not in routing[prev_host]: routing[prev_host][next_host] = [] for i in range(0, len(hosts_path)): routing[prev_host][next_host].append(hosts_path[i]) # Add host to path hosts_path.insert(0, prev_host) break # Printer().print_routing(self.routing[medium_name]) if receiver not in distances: raise RuntimeException( "The path between {0} and {1} undefined.".format( sender.name, receiver.name)) update_paths(medium_name, receiver, distances) return self._find_existing_next_hop_host(medium_name, sender, receiver)
def get_expression_size(self, expression, context, host): """ Returns the size in bytes of expression according to metrics. Metrics van specify exact size (ie. in bytes, bits, kilobytes, kilobits, megabytes, megabits) or ratio size (ie. 0.5 equals 50%) used ie. in compression. Expression cannot have variables - it must be filled with variables' values. """ size = 0 if isinstance(expression, IdentifierExpression): # If expression is an variable, get its value size return self.get_expression_size( host.get_variable(expression.identifier), context, host) if isinstance(expression, TupleElementExpression): variable = host.get_variable(expression.variable_name) variable = context.expression_reducer.reduce(variable) if not isinstance(variable, TupleExpression): raise RuntimeException( 'Cannot get tuple element on expression: %s.' % unicode(variable)) return self.get_expression_size( variable.elements[expression.index], context, host) elif isinstance(expression, TupleExpression): # If expression is tuple, just sum its elements' sizes for expr in expression.elements: size += self.get_expression_size(expr, context, host) return size if isinstance(expression, CallFunctionExpression) or isinstance( expression, CallFunctionInstruction): expression = context.expression_reducer.reduce(expression) metric = self.find_primitive(host, expression) if not metric: raise RuntimeException( "Cannot get expression size: No metric found for expression '%s'." % unicode(expression)) block = metric.block for i in range(0, len(block.service_params)): sparam = block.service_params[i] if sparam.service_name.lower() != "size": continue metric_type = sparam.param_name.lower() metric_unit = sparam.unit metric_value = metric.service_arguments[i] if metric_type == "ratio": mparts = metric_value.split(':') element_index = int(mparts[0]) - 1 percent = float(mparts[1]) size = self.get_expression_size(expression.arguments[element_index], context, host) \ * percent elif metric_type == "sum_ratio": ratios = metric_value.split(',') size = 0.0 for ratio in ratios: rparts = ratio.strip().split(':') element_index = int(rparts[0]) - 1 percent = float(rparts[1]) size += self.get_expression_size(expression.arguments[element_index], context, host) \ * percent elif metric_type == "exact": if metric_unit == 'B': size = float(metric_value) elif metric_unit == 'b': size = float(metric_value) / 8.0 else: raise RuntimeException( 'Cannot get expression size: Unsupported size value for exact type.' ) elif metric_type == "block": mparts = metric_value.split(':') element_index = int(mparts[0]) - 1 unit_value = int(mparts[1]) factor = 1.0 if metric_unit == 'b': factor = 1.0 / 8.0 argument_size = self.get_expression_size( expression.arguments[element_index], context, host) argument_size_excess = argument_size % unit_value size = argument_size if argument_size_excess > 0: size += unit_value - argument_size_excess size *= factor elif metric_type == "nested": mparts = metric_value.split(':') element_index = int(mparts[0]) - 1 nested_element_index = int(mparts[1]) - 1 nested_expression = expression.arguments[element_index] if isinstance(nested_expression, IdentifierExpression): nested_expression = host.get_variable( nested_expression.identifier) if not isinstance(nested_expression, CallFunctionExpression) and \ not isinstance(nested_expression, CallFunctionInstruction): raise RuntimeException( 'Cannot get nested expression size: Not a function call.' ) size = self.get_expression_size( nested_expression.arguments[nested_element_index], context, host) else: raise RuntimeException( 'Cannot get expression size: Unsupported size type.') return size raise RuntimeException( 'Cannot get expression size: Unsupported expression type. Expression: {0}.' .format(unicode(expression)))
def _update_vars_simple(self, context, expression): """ Update reputation variables in host according to call function expression. """ # Firstly update vars according to nested call functions for e in expression.arguments: self._update_vars(context, e) # Now update vars according to current call function host = context.get_current_host() self._prepare_host_variables(host) metric_expression = CallFunctionExpression(expression.function_name, expression.arguments, []) metric = context.metrics_manager\ .find_primitive(host, metric_expression) if metric: block = metric.block algorithm_name = None for i in range(0, len(block.service_params)): sparam = block.service_params[i] if sparam.service_name.lower() != "reputation": continue metric_type = sparam.param_name.lower() metric_value = metric.service_arguments[i] if metric_type == "algorithm": algorithm_name = metric_value break if algorithm_name: algorithm = self.module.get_algorithm(algorithm_name) if len(expression.qop_arguments) != len( algorithm['parameters']): raise RuntimeException( 'Reputation algorithm "%s" required %d parameters, %d given.' % (algorithm_name, len(algorithm['parameters']), len(expression.qop_arguments))) vars = self.module.get_host_vars(host) i = 0 for qop_arg in expression.qop_arguments: try: val = float(qop_arg) vars[algorithm['parameters'][i]] = val i += 1 except ValueError: raise RuntimeException( 'Reputation argument "%s" in expression "%s" not a float number.' % (qop_arg, unicode(expression))) vars = update_vars(host, algorithm['instructions'], vars) for var_name in self.module.init_vars: self.module.set_reputation_var(host, var_name, vars[var_name])
def reduce(self, expression): """ Reduces expression with usage of equations. Returns reduced expression. Raises exception if ambiguity is found. """ continue_reducing = True """ # Wrap expression and user wrapper variable # Used to simulate real pass-by-reference # If expression was passed without wrapped variable and equation wanted to # replace whole exception, it would not work, because whole variable cannot be changed # For example: # eq enc(K, dec(K, X)) = X # expression: enc(k(), dec(k(), b()) should be reduced to b() # If we pass whole expression variable to reduce we cannot change it whole # def f(x,v) -> x = v # e = A(a=1) # f(e, A(a=2)) - will not work, because e is reference to instance, but passed by value # When we pass wrapper, we can change its element (ie. expression) """ # Reduce until no reduction can be performed. # One reduction can give way for another reduction. while continue_reducing: continue_reducing = False # For each equation we find points where expression can be reduced reduction_points = self._get_reduction_points(expression) if len(reduction_points) > 0: # For each point: # - temporary reduce at this point # - remove used point from reduction points list # - generate new reduction points list for reduced expression # - if any of points from old list is not present in new list raise ambiguity exception # ! New reduction points may come for reduction_point in reduction_points: # Generate list with reduction points before reduction old_reduction_points = copy.copy(reduction_points) old_reduction_points.remove(reduction_point) # Reduce temporary expression = reduction_point.reduce() # Generate new reduction points new_reduction_points = self._get_reduction_points( expression) for old_reduction_point in old_reduction_points: found = False for new_reduction_point in new_reduction_points: if old_reduction_point.equals_to( new_reduction_point): found = True break if not found: raise RuntimeException( "Equations '%s' and '%s are ambiguous for expression: %s." % (unicode(old_reduction_point.equation), unicode(reduction_point.equation), unicode(expression))) # Cancel reduction expression = reduction_point.rollback() # Ambiguity error checked # Make factual reduction reduction_point = reduction_points[0] # Reduce and commit reduction expression = reduction_point.reduce() continue_reducing = True return expression
def populate(self, expression, host, main_expression=None): """ Returns new expression with replaced variables names with copies of values of variables from variables list. Reducer is used for special types of variables, eg. tuple element expressions. """ if main_expression is None: main_expression = expression variables = host.get_variables() if isinstance(expression, IdentifierExpression): if expression.identifier not in variables: raise RuntimeException( "Variable {0} undefined in expression '{1}'.".format( expression.identifier, unicode(main_expression))) return variables[expression.identifier].clone() if isinstance(expression, CallFunctionExpression): if self.is_function_predefined(expression.function_name): populated = self.predefined_functions_manager.populate_call_function_expression_result( expression, host, self) return populated.clone() arguments = [] for arg in expression.arguments: arguments.append( self.populate(arg, host, main_expression=main_expression)) qop_arguments = [] for qop_arg in expression.qop_arguments: qop_arguments.append(qop_arg) return CallFunctionExpression(expression.function_name, arguments, qop_arguments) if isinstance(expression, TupleExpression): elements = [] for e in expression.elements: elements.append( self.populate(e, host, main_expression=main_expression)) return TupleExpression(elements) if isinstance(expression, TupleElementExpression): if expression.variable_name not in variables: raise RuntimeException( "Variable {0} does not exist in host {1}. Trying expression '{2}'." .format(expression.variable_name, host.name, unicode(main_expression))) expr = variables[expression.variable_name] if not isinstance(expr, TupleExpression): expr = self.reducer.reduce(expr) if not isinstance(expr, TupleExpression): raise RuntimeException( "Cannot compute expression '{0}' in host {1}. Variable {2} is not a tuple. It is: {3}." .format(unicode(main_expression), host.name, expression.variable_name, unicode(expr))) if len(expr.elements) <= expression.index: raise RuntimeException( "Cannot compute expression '{0}' in host {1}. " "Variable {2} does not have index {3}. It has {4} elements: {5}." .format(unicode(main_expression), host.name, expression.variable_name, expression.index, len(expr.elements), unicode(expr))) return self.populate(expr.elements[expression.index], host, main_expression=main_expression) return expression.clone()
def get_variable(self, name): """ Get host's variable """ if name not in self._variables: raise RuntimeException("Variable '%s' undefined in host '%s'." % (name, self.name)) return self._variables[name]
def _get_time_details_for_simple_expression(self, context, expression): """ Calculate time for expression. """ time = 0 time_details = [] metric = context.metrics_manager\ .find_primitive(context.get_current_host(), expression) if metric: block = metric.block for i in range(0, len(block.service_params)): sparam = block.service_params[i] if sparam.service_name.lower().strip() != "time": continue metric_type = sparam.param_name.lower().strip() metric_unit = sparam.unit metric_value = metric.service_arguments[i].strip() if metric_type in ["exact", "range"]: time = self._get_time_for_exact_range_metric( metric_type, metric_unit, metric_value, expression, context.get_current_host(), context) elif metric_type == "block": time = self._get_time_for_block_metric( metric_type, metric_unit, metric_value, expression, context.get_current_host(), context) elif metric_type == 'algorithm': algorithm_name = metric_value if not context.algorithms_resolver.has_algorithm( algorithm_name): raise RuntimeException( "Communication algorithm {0} undeclared.".format( algorithm_name)) alg = context.algorithms_resolver.get_algorithm( algorithm_name) variables = {alg['parameter']: expression} time = context.algorithms_resolver.calculate( context, context.get_current_host(), algorithm_name, variables) # Update time according to the time unit if metric_unit == "ms": time /= 1000.0 if time > 0: time_details.append((expression, time)) for expr in expression.arguments: argument_time, argument_time_details = self._get_time_details_for_expression( context, expr) time += argument_time time_details.extend(argument_time_details) return time, time_details