Exemplo n.º 1
0
class EventEmitter2(object):

    def __init__(self):
        """
        """
        self.events = OrderedMultiDict()
        self.on = self.add_listener
        self.off = self.remove_listener
        # TODO: Add listener to remove

    def add_listener(self, event, listener, count=0):
        if not (isinstance(listener, FunctionType)) or (isinstance(listener, BuiltinFunctionType)):
            raise Exception("Invalid Listener: %s" % (str(listener)))
        _event = re.compile(event)
        _listener = {"handler": listener, "calls": 0, "calls_left": count}
        self.events.add(_event, _listener)
        return True

    def emit(self, event, kwargs):
        for pattern, listener in self.events.iteritems(multi=True):
            if pattern.match(event):
                if not listener["calls_left"]:
                    log.debug("Removing Listener: %s on Pattern: %s") % (
                        listener, pattern)
                    self.remove_listener(pattern, listener)
                listener["calls"] += 1
                listener["calls_left"] -= 1
                yield listener["handler"](**kwargs)

    def remove_listener(self, pattern, listener):
        pattern = re.compile(pattern)
        listeners = self.events.getlist(pattern)
        for pattern, _listener in self.events.iteritems(multi=True):
            if _listener['handler'] == listener:
                listener = _listener
                break
        listeners = self.events.getlist(pattern)
        listeners.remove(listener)
        if len(listeners):
            self.events.update({pattern: listeners})
        else:
            self.events._remove(pattern)
        return True

    def on_any(self, listener):
        raise NotImplementedError

    def off_any(self, listener):
        raise NotImplementedError

    def once(self, event, listener):
        self.add_listener(event, listener, left=1)

    def many(self, event, listener, left):
        self.add_listener(event, listener, left)
Exemplo n.º 2
0
class EventEmitter2(object):
    def __init__(self):
        """
        """
        self.events = OrderedMultiDict()
        self.on = self.add_listener
        self.off = self.remove_listener
        # TODO: Add listener to remove

    def add_listener(self, event, listener, count=0):
        if (isinstance(listener, BuiltinFunctionType)):
            raise Exception("Invalid Listener: %s" % (str(listener)))
        _event = re.compile(event)
        _listener = {"handler": listener, "calls": 0, "calls_left": count}
        self.events.add(_event, _listener)
        return True

    def emit(self, event, kwargs):
        for pattern, listener in self.events.iteritems(multi=True):
            if pattern.match(event):
                if not listener["calls_left"]:
                    log.debug("Removing Listener: %s on Pattern: %s") % (
                        listener, pattern)
                    self.remove_listener(pattern, listener)
                listener["calls"] += 1
                listener["calls_left"] -= 1
                yield listener["handler"](**kwargs)

    def remove_listener(self, pattern, listener):
        pattern = re.compile(pattern)
        listeners = self.events.getlist(pattern)
        for pattern, _listener in self.events.iteritems(multi=True):
            if _listener['handler'] == listener:
                listener = _listener
                break
        listeners = self.events.getlist(pattern)
        listeners.remove(listener)
        if len(listeners):
            self.events.update({pattern: listeners})
        else:
            self.events._remove(pattern)
        return True

    def on_any(self, listener):
        raise NotImplementedError

    def off_any(self, listener):
        raise NotImplementedError

    def once(self, event, listener):
        self.add_listener(event, listener, left=1)

    def many(self, event, listener, left):
        self.add_listener(event, listener, left)
Exemplo n.º 3
0
def epi_suite_values(epi_blob):
    '''Extracts some information as key-value pairs from EPI Suite output.
    Pretty rough (work in progress).'''
    data = OMD()
    try:
        lines = epi_blob.split('\n')
        for i in lines:
            j = i.strip()
            if j.startswith('Log Kow (') or j.startswith('Log BCF'):
                data.update(dict_from_line(i, '='))
            if j.startswith('Henrys LC') or\
               j.startswith('Log Koa (KOAWIN') or\
               j.startswith('Log Koa (experimental') or\
               j.startswith('Ready Biodegradability Prediction'):
                data.update(dict_from_line(i))
        if 'Fugacity' in epi_blob:
            model_table = epi_blob.split('Level III Fugacity Model:', 1)[1]
            data.add('Level III Fugacity Model', model_table)
    except:
        pass
    return data
Exemplo n.º 4
0
    def gen_connected_components(self):
        """
        Detect all the cut edges / cut endpoints (Tarjan Algorithm).
        Split the graph into different connected components.
        """

        # ----- temporary variables
        # temp: endpoints haven't been traversed
        self._tmp_untraversed = self.switches.copy()
        # temp: order of a node in the DFS
        self._tmp_order = defaultdict(lambda: INFTY)
        # temp: the lowest depth a node is connected to
        self._tmp_low = defaultdict(lambda: INFTY)
        # temp: parent of a node in the DFS
        self._tmp_parent = defaultdict(lambda: -1)

        # Initialize every ETH node with a distinct number
        node_connected_components = OrderedMultiDict(
            (nodeID, i) for i, (nodeID, n) in enumerate(node.items())
            if n['protocol'] == 'ETH')

        link_connected_components = OrderedMultiDict()

        # Initialize every ETH non-switch as type 2
        entity_type = OrderedMultiDict(
            (nodeID, 't2') for nodeID, n in node.items()
            if n['type'] != 'SWITCH' and n['protocol'] == 'ETH')

        while self._tmp_untraversed:
            # temp: all links of a connected components
            self._tmp_links = set()
            # temp: all endpoints of a connected components
            self._tmp_nodes = set()

            # ----- special links/endpoints
            ############################# Explanation ##########################
            """
            We categorize all the links and endpoints by 2 dimensions , so there
            are 2 * 2 = 4 categories in total. Suppose a link/endpoint is down,
            then there would be 4 possible results:

                                          New Routes are needed

                                            No      |       Yes  
                                                    |
                                    No      ---     |     Type I
            Some traffic will not                   |
            be reachable            ----------------+----------------
                                                    |
                                    Yes   Type II   |    Type III
                                                    |

            I'll use an example to explain these categories, and why we care
            about these scenarios:
            """
            
            ###################################################################
            #                                                                 #
            #                             A                                   #
            #                             |                                   #
            #                             |                                   #
            #                             |                                   #
            #                             1 ----- 2                           #
            #                              \     /                            #
            #                               \   /                             #
            #                                \ /                              #
            #                                 3                               #
            #                                 |                               #
            #                                 |                               #
            #                                 4                               #
            #                                / \                              #
            #                               /   \                             #
            #                              /     \                            #
            #                     C ----- 5       6 ------┐                   #
            #                             |       |       |                   #
            #                             |       |       B                   #
            #   A,B,C - DEVICES           |       |       |                   #
            #   1 ~ 8 - SWITCHES          7 ----- 8 ------┘                   #
            #                                                                 #
            ###################################################################

            """
            Type I: When the link/endpoint is down, new routes are needed, all
            traffic are still reachable
            - Endpoints: 2, 6, 7, 8
            - Links: 1-2, 1-3, 2-3, 4-5, 5-7, 7-8, 8-6, 6-4, 8-B, 6-B

            When one of these links/endpoints is down, the network will function
            as good, but traffic should take failover routes. Net Configurator
            will generate alternative routes for all of these scenarios.

            In the algorithm, such links/endpoints are not cut edges / cut 
            vertices.

            ------

            Type II: When the link/endpoint is down, every traffic will still
            take the primary route, while some of them will not be reachable.
            - Endpoints: A, B, C
            - Links: 3-4, 1-A, 5-C
            
            When one of these links/endpoints is down, some of the traffic will
            be dropped somewhere, but if a traffic is still reachable, then they
            will still take the primary route, so we will not generate new routes
            for these scenarios to reduce the ARL table size.

            In the algorithm, such links are cut edges; such endpoints are cut
            vertices, but not all cut vertices are type II endpoints. To be more
            precise, if an endpoint E connects to exactly one another endpoint, 
            or all the other endpoints that E connects to are not connected 
            w.r.t. any other endpoints except for E itself, then E is a type II
            endpoint.

            Note that in this example, if endpoint 5 is down, traffic between A 
            and B will not need a failover route, but 5 is not categorized as a
            type II endpoint, since 4 and 7 are connected w.r.t. some other
            links. Actually, we are not able to categorize 5 as type II to save
            memory, since connected components detection and link/node 
            categorization step is done before routes are calculated. Due to 
            that reason, 1 and 5 are not type II endpoints.

            I'm not sure if type II should exist. Although we can save memory
            in such scenarios, unreachable traffic will still take up the 
            bandwidth and resources of links/switches until they are dropped at
            the broken link/switch unless applications on top of IP Layer stops
            to send these traffic. Maybe we will decide to use more memory, but
            save runtime resources. There is a tradeoff.
            
            ------

            Type III: When the endpoint is down, some traffic will take failover
            routes while some may not and some traffic will be unreachable.
            - Endpoints: 1, 3, 4, 5

            When one of these endpoints is down, some traffic will be dropped
            and even some traffic are still reachable, they may need a failover
            route. In this scenario, we need to generate failover routes.

            In the algorithm, if an endpoint E connects to some endpoints that
            connect to each other w.r.t. links other than E, then E is a 
            type III endpoint.

            Note that no links are categorized as type III, since if a link is
            down, either all the devices are still connected in the same 
            connected component, or some are disconnected but we could use the 
            primary route and drop unreachable traffics somewhere.

            -----

            It will never happen that when a link/endpoint is down, no traffics
            are dropped and no failover route is needed. In this toy example,
            switch 2 is such an endpoint, but we still categorize it as type I
            because connected components detection and link/node categorization 
            step is done before routes are calculated.

            When we are calculating the shortest route tree, all the switches and
            links that not appears in the tree will be recorded. They will be a
            special part of type I that no failover routes will be generated for
            these links/switches. Endpoint 2, 7, 8 and links 1-2, 2-3, 5-7, 6-8,
            7-8, 8-B are such links/switches in this example.

            """

            # temp: non-cut links
            self._tmp_type1_links = set()
            # temp: cut links
            self._tmp_type2_links = set()

            # temp: non-cut endpoints
            self._tmp_type1_nodes = set()
            # temp: type 2 cut endpoints
            self._tmp_type2_nodes = set()
            # temp: type 3 cut endpoints
            self._tmp_type3_nodes = set()

            # order counter
            self.__order = 0 

            # randomly choose an endpoint as DFS root
            DFS_ROOT = self._tmp_untraversed.pop()

            self.bridge_update(DFS_ROOT)

            self._tmp_type1_links = self._tmp_links - self._tmp_type2_links

            ccID = node_connected_components[DFS_ROOT]

            node_connected_components.update({
                nodeID: ccID for nodeID in self._tmp_nodes
            })

            link_connected_components.update({
                linkID: ccID for linkID in self._tmp_links
            })

            entity_type.update({
                nodeID: 't1' for nodeID in self._tmp_type1_nodes
            })

            entity_type.update({
                nodeID: 't2' for nodeID in self._tmp_type2_nodes
            })

            entity_type.update({
                nodeID: 't3' for nodeID in self._tmp_type3_nodes
            })

            entity_type.update({
                linkID: 't1' for linkID in self._tmp_type1_links
            })

            entity_type.update({
                linkID: 't2' for linkID in self._tmp_type2_links
            })            

            self._tmp_untraversed -= self._tmp_nodes

        self.node_connected_components = node_connected_components
        self.link_connected_components = link_connected_components
        self.entity_type = entity_type