From: Alina Quereilhac <alina.quereilhac@inria.fr> Date: Tue, 5 Jul 2011 10:50:03 +0000 (+0200) Subject: merged ConnectorTyper for design and execution X-Git-Tag: nepi-3.0.0~381^2~6 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=b0921e10db3b3fc0e9b6330ca9146498bc9d5a15;p=nepi.git merged ConnectorTyper for design and execution --- diff --git a/src/nepi/core/connector.py b/src/nepi/core/connector.py index e85d2bfd..e8ff719f 100644 --- a/src/nepi/core/connector.py +++ b/src/nepi/core/connector.py @@ -2,31 +2,49 @@ # -*- coding: utf-8 -*- """ -Common connector base classes +Common connector class """ import sys -class ConnectorTypeBase(object): - def __init__(self, testbed_id, factory_id, name, max = -1, min = 0): - super(ConnectorTypeBase, self).__init__() +class ConnectorType(object): + def __init__(self, testbed_id, factory_id, name, help, max = -1, min = 0): + super(ConnectorType, self).__init__() + if max == -1: max = sys.maxint elif max <= 0: raise RuntimeError, "The maximum number of connections allowed need to be more than 0" if min < 0: raise RuntimeError, "The minimum number of connections allowed needs to be at least 0" + # max -- maximum amount of connections that this type support, + # -1 for no limit + self._max = max + # min -- minimum amount of connections required by this type of connector + self._min = min + # connector_type_id -- univoquely identifies a connector type # across testbeds self._connector_type_id = self.make_connector_type_id( testbed_id, factory_id, name) + # name -- display name for the connector type self._name = name - # max -- maximum amount of connections that this type support, - # -1 for no limit - self._max = max - # min -- minimum amount of connections required by this type of connector - self._min = min + + # help -- help text + self._help = help + + # from_connections -- connections where the other connector is the "From" + # to_connections -- connections where the other connector is the "To" + # keys in the dictionary correspond to the + # connector_type_id for possible connections. The value is a tuple: + # (can_cross, connect) + # can_cross: indicates if the connection is allowed accros different + # testbed instances + # code: is the connection function to be invoked when the elements + # are connected + self._from_connections = dict() + self._to_connections = dict() def __str__(self): return "ConnectorType%r" % (self._connector_type_id,) @@ -39,6 +57,10 @@ class ConnectorTypeBase(object): def name(self): return self._name + @property + def help(self): + return self._help + @property def max(self): return self._max @@ -69,4 +91,44 @@ class ConnectorTypeBase(object): if (None, None, name) != connector_type_id: yield (None, None, name) + def add_from_connection(self, testbed_id, factory_id, name, can_cross, + init_code, compl_code): + type_id = self.make_connector_type_id(testbed_id, factory_id, name) + self._from_connections[type_id] = (can_cross, init_code, compl_code) + + def add_to_connection(self, testbed_id, factory_id, name, can_cross, + init_code, compl_code): + type_id = self.make_connector_type_id(testbed_id, factory_id, name) + self._to_connections[type_id] = (can_cross, init_code, compl_code) + + def connect_to_init_code(self, testbed_id, factory_id, name, must_cross): + return self._connect_to_code(testbed_id, factory_id, name, must_cross)[0] + + def connect_to_compl_code(self, testbed_id, factory_id, name, must_cross): + return self._connect_to_code(testbed_id, factory_id, name, must_cross)[1] + + def _connect_to_code(self, testbed_id, factory_id, name, + must_cross): + connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name) + for lookup_type_id in self._type_resolution_order(connector_type_id): + if lookup_type_id in self._to_connections: + (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id] + if not must_cross or can_cross: + return (init_code, compl_code) + else: + return (False, False) + + def can_connect(self, testbed_id, factory_id, name, must_cross): + connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name) + for lookup_type_id in self._type_resolution_order(connector_type_id): + if lookup_type_id in self._from_connections: + (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id] + elif lookup_type_id in self._to_connections: + (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id] + else: + # keep trying + continue + return not must_cross or can_cross + else: + return False diff --git a/src/nepi/core/design.py b/src/nepi/core/design.py index 03d63193..100fff92 100644 --- a/src/nepi/core/design.py +++ b/src/nepi/core/design.py @@ -6,7 +6,7 @@ Experiment design API """ from nepi.core.attributes import AttributesMap, Attribute -from nepi.core.connector import ConnectorTypeBase +from nepi.core.connector import ConnectorType from nepi.core.metadata import Metadata from nepi.util import validation from nepi.util.guid import GuidGenerator @@ -14,35 +14,6 @@ from nepi.util.graphical_info import GraphicalInfo from nepi.util.parser._xml import XmlExperimentParser import sys -class ConnectorType(ConnectorTypeBase): - def __init__(self, testbed_id, factory_id, name, help, max = -1, min = 0): - super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min) - - # help -- help text - self._help = help - - # allowed_connections -- keys in the dictionary correspond to the - # connector_type_id for possible connections. The value indicates if - # the connection is allowed accros different testbed instances - self._allowed_connections = dict() - - @property - def help(self): - return self._help - - def add_allowed_connection(self, testbed_id, factory_id, name, can_cross): - type_id = self.make_connector_type_id(testbed_id, factory_id, name) - self._allowed_connections[type_id] = can_cross - - def can_connect(self, connector_type_id, testbed_guid1, testbed_guid2): - for lookup_type_id in self._type_resolution_order(connector_type_id): - if lookup_type_id in self._allowed_connections: - can_cross = self._allowed_connections[lookup_type_id] - if can_cross or (testbed_guid1 == testbed_guid2): - return True - else: - return False - class Connector(object): """A Connector sepcifies the connection points in an Object""" def __init__(self, box, connector_type): @@ -100,11 +71,12 @@ class Connector(object): return False if self.is_connected(connector): return False - connector_type_id = connector.connector_type.connector_type_id + (testbed_id, factory_id, name) = connector.connector_type.connector_type_id testbed_guid1 = self.box.testbed_guid testbed_guid2 = connector.box.testbed_guid - return self.connector_type.can_connect(connector_type_id, - testbed_guid1, testbed_guid2) + must_cross = (testbed_guid1 != testbed_guid2) + return self.connector_type.can_connect(testbed_id, factory_id, name, + must_cross) def destroy(self): for connector in self.connections: diff --git a/src/nepi/core/execute.py b/src/nepi/core/execute.py index 5a191aef..8c97638c 100644 --- a/src/nepi/core/execute.py +++ b/src/nepi/core/execute.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- from nepi.core.attributes import Attribute, AttributesMap -from nepi.core.connector import ConnectorTypeBase from nepi.util import validation from nepi.util.constants import ApplicationStatus as AS, TIME_NOW from nepi.util.parser._xml import XmlExperimentParser @@ -18,63 +17,6 @@ ATTRIBUTE_PATTERN_BASE = re.compile(r"\{#\[(?P<label>[-a-zA-Z0-9._]*)\](?P<expr> ATTRIBUTE_PATTERN_GUID_SUB = r"{#[%(guid)s]%(expr)s#}" COMPONENT_PATTERN = re.compile(r"(?P<kind>[a-z]*)\[(?P<index>.*)\]") -class ConnectorType(ConnectorTypeBase): - def __init__(self, testbed_id, factory_id, name, max = -1, min = 0): - super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min) - # from_connections -- connections where the other connector is the "From" - # to_connections -- connections where the other connector is the "To" - # keys in the dictionary correspond to the - # connector_type_id for possible connections. The value is a tuple: - # (can_cross, connect) - # can_cross: indicates if the connection is allowed accros different - # testbed instances - # code: is the connection function to be invoked when the elements - # are connected - self._from_connections = dict() - self._to_connections = dict() - - def add_from_connection(self, testbed_id, factory_id, name, can_cross, - init_code, compl_code): - type_id = self.make_connector_type_id(testbed_id, factory_id, name) - self._from_connections[type_id] = (can_cross, init_code, compl_code) - - def add_to_connection(self, testbed_id, factory_id, name, can_cross, - init_code, compl_code): - type_id = self.make_connector_type_id(testbed_id, factory_id, name) - self._to_connections[type_id] = (can_cross, init_code, compl_code) - - def can_connect(self, testbed_id, factory_id, name, count, - must_cross): - connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name) - for lookup_type_id in self._type_resolution_order(connector_type_id): - if lookup_type_id in self._from_connections: - (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id] - elif lookup_type_id in self._to_connections: - (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id] - else: - # keep trying - continue - return not must_cross or can_cross - else: - return False - - def _connect_to_code(self, testbed_id, factory_id, name, - must_cross): - connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name) - for lookup_type_id in self._type_resolution_order(connector_type_id): - if lookup_type_id in self._to_connections: - (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id] - if not must_cross or can_cross: - return (init_code, compl_code) - else: - return (False, False) - - def connect_to_init_code(self, testbed_id, factory_id, name, must_cross): - return self._connect_to_code(testbed_id, factory_id, name, must_cross)[0] - - def connect_to_compl_code(self, testbed_id, factory_id, name, must_cross): - return self._connect_to_code(testbed_id, factory_id, name, must_cross)[1] - class Factory(AttributesMap): def __init__(self, factory_id, create_function, start_function, stop_function, status_function, diff --git a/src/nepi/core/metadata.py b/src/nepi/core/metadata.py index ca1be8d5..894874d2 100644 --- a/src/nepi/core/metadata.py +++ b/src/nepi/core/metadata.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from nepi.core.attributes import Attribute, AttributesMap +from nepi.core.connector import ConnectorType import sys import getpass from nepi.util import validation @@ -407,7 +408,7 @@ class Metadata(object): self._add_design_traces(factory, info) self._add_tags(factory, info) - self._add_design_connector_types(factory, info) + self._add_connector_types(factory, info) factories.append(factory) return factories @@ -443,7 +444,7 @@ class Metadata(object): self._add_execute_traces(factory, info) self._add_tags(factory, info) - self._add_execute_connector_types(factory, info) + self._add_connector_types(factory, info) factories.append(factory) return factories @@ -511,40 +512,7 @@ class Metadata(object): for tag_id in info["tags"]: factory.add_tag(tag_id) - def _add_design_connector_types(self, factory, info): - from nepi.core.design import ConnectorType - if "connector_types" in info: - connections = dict() - for connection in self._metadata.connections: - from_ = connection["from"] - to = connection["to"] - can_cross = connection["can_cross"] - if from_ not in connections: - connections[from_] = list() - if to not in connections: - connections[to] = list() - connections[from_].append((to, can_cross)) - connections[to].append((from_, can_cross)) - for connector_id in info["connector_types"]: - connector_type_info = self._metadata.connector_types[ - connector_id] - name = connector_type_info["name"] - help = connector_type_info["help"] - max = connector_type_info["max"] - min = connector_type_info["min"] - testbed_id = self._testbed_id - factory_id = factory.factory_id - connector_type = ConnectorType(testbed_id, factory_id, name, - help, max, min) - for (to, can_cross) in connections[(testbed_id, factory_id, - name)]: - (testbed_id_to, factory_id_to, name_to) = to - connector_type.add_allowed_connection(testbed_id_to, - factory_id_to, name_to, can_cross) - factory.add_connector_type(connector_type) - - def _add_execute_connector_types(self, factory, info): - from nepi.core.execute import ConnectorType + def _add_connector_types(self, factory, info): if "connector_types" in info: from_connections = dict() to_connections = dict() @@ -568,12 +536,13 @@ class Metadata(object): connector_type_info = self._metadata.connector_types[ connector_id] name = connector_type_info["name"] + help = connector_type_info["help"] max = connector_type_info["max"] min = connector_type_info["min"] testbed_id = self._testbed_id factory_id = factory.factory_id connector_type = ConnectorType(testbed_id, factory_id, name, - max, min) + help, max, min) connector_key = (testbed_id, factory_id, name) if connector_key in to_connections: for (from_, can_cross, init_code, compl_code) in \ diff --git a/src/nepi/core/testbed_impl.py b/src/nepi/core/testbed_impl.py index 291a24b1..4a19e473 100644 --- a/src/nepi/core/testbed_impl.py +++ b/src/nepi/core/testbed_impl.py @@ -110,10 +110,17 @@ class TestbedController(execute.TestbedController): connector_type_name2): factory1 = self._get_factory(guid1) factory_id2 = self._create[guid2] - count = self._get_connection_count(guid1, connector_type_name1) + # TODO VALIDATE!!! + #if self.box.guid == connector.box.guid: + # return False + #if self.is_full() or connector.is_full(): + # return False + #if self.is_connected(connector): + # return False + #count = self._get_connection_count(guid1, connector_type_name1) connector_type = factory1.connector_type(connector_type_name1) connector_type.can_connect(self._testbed_id, factory_id2, - connector_type_name2, count, False) + connector_type_name2, False) if not guid1 in self._connect: self._connect[guid1] = dict() if not connector_type_name1 in self._connect[guid1]: @@ -131,10 +138,17 @@ class TestbedController(execute.TestbedController): cross_testbed_guid, cross_testbed_id, cross_factory_id, cross_connector_type_name): factory = self._get_factory(guid) - count = self._get_connection_count(guid, connector_type_name) + # TODO VALIDATE!!! + #if self.box.guid == connector.box.guid: + # return False + #if self.is_full() or connector.is_full(): + # return False + #if self.is_connected(connector): + # return False + #count = self._get_connection_count(guid, connector_type_name) connector_type = factory.connector_type(connector_type_name) connector_type.can_connect(cross_testbed_id, cross_factory_id, - cross_connector_type_name, count, True) + cross_connector_type_name, True) if not guid in self._cross_connect: self._cross_connect[guid] = dict() if not connector_type_name in self._cross_connect[guid]: