Exemplo n.º 1
0
    def shutdown(self):
        """Shut-down all simulators and close the server socket."""
        for sim in self.sims.values():
            util.sync_process(sim.stop(), self, ignore_errors=True)

        if self.srv_sock is not None:
            self.srv_sock.close()
            self.srv_sock = None
Exemplo n.º 2
0
    def get_data(self, entity_set, *attributes):
        """Get and return the values of all *attributes* for each entity of an
        *entity_set*.

        The return value is a dict mapping the entities of *entity_set* to
        dicts containing the values of each attribute in *attributes*::

            {
                Entity(...): {
                    'attr_1': 'val_1',
                    'attr_2': 'val_2',
                    ...
                },
                ...
            }

        """
        outputs_by_sim = defaultdict(dict)
        for entity in entity_set:
            outputs_by_sim[entity.sid][entity.eid] = attributes

        def request_data():
            requests = {
                self.sims[sid].proxy.get_data(outputs): sid
                for sid, outputs in outputs_by_sim.items()
            }
            try:
                results = yield self.env.all_of(requests)
            except ConnectionError as e:
                msg = ('Simulator "%s" closed its connection while executing '
                       '"World.get_data()".')
                # Try to find the simulator that closed its connection
                for req, sid in requests.items():
                    if req.triggered and not req.ok:
                        raise SimulationError(msg % sid, e) from None
                else:
                    raise RuntimeError('Could not determine which simulator '
                                       'closed its connection.')

            results_by_sim = {}
            for request, value in results.items():
                sid = requests[request]
                results_by_sim[sid] = value

            return results_by_sim

        results_by_sim = util.sync_process(request_data(), self)
        results = {}
        for entity in entity_set:
            results[entity] = results_by_sim[entity.sid][entity.eid]

        return results
Exemplo n.º 3
0
    def run(self, until, rt_factor=None, rt_strict=False):
        """Start the simulation until the simulation time *until* is reached.

        In order to perform real-time simulations, you can set *rt_factor* to
        a number > 0. An rt-factor of 1 means that 1 simulation time unit
        (usually a second) takes 1 second in real-time. An rt-factor 0f 0.5
        will let the simulation run twice as fast as real-time.

        If the simulators are too slow for the rt-factor you chose, mosaik
        prints by default only a warning. In order to raise
        a :exc:`RuntimeError`, you can set *rt_strict* to ``True``.

        Before this method returns, it stops all simulators and closes mosaik's
        server socket. So this method should only be called once.

        """
        if self.srv_sock is None:
            raise RuntimeError('Simulation has already been run and can only '
                               'be run once for a World instance.')

        # Check if a simulator is not connected to anything:
        for sid, deg in sorted(list(networkx.degree(self.df_graph))):
            if deg == 0:
                print('WARNING: %s has no connections.' % sid)

        print('Starting simulation.')
        import mosaik._debug as dbg  # always import, enable when requested
        if self._debug:
            dbg.enable()
        try:
            util.sync_process(scheduler.run(self, until, rt_factor, rt_strict),
                              self)
            print('Simulation finished successfully.')
        except KeyboardInterrupt:
            print('Simulation canceled. Terminating ...')
        finally:
            self.shutdown()
            if self._debug:
                dbg.disable()
Exemplo n.º 4
0
def make_proxy(world,
               sim_name,
               sim_config,
               sim_id,
               sim_params,
               proc=None,
               addr=None):
    """Try to establish a connection with *sim_name* and perform the ``init()``
    API call.

    Return a new :class:`RemoteProcess` sim proxy.

    Raise a :exc:`~mosaik.exceptions.ScenarioError` if something goes wrong.

    This method is a SimPy process used by :func:`start_proc()` and
    :func:`start_connect()`.

    """
    start_timeout = world.env.timeout(world.config['start_timeout'])

    def greeter():
        if proc:
            # Wait for connection from "sim_name"
            accept_con = world.srv_sock.accept()
            results = yield accept_con | start_timeout
            if start_timeout in results:
                raise SimulationError('Simulator "%s" did not connect to '
                                      'mosaik in time.' % sim_name)
            else:
                sock = results[accept_con]
        else:
            # Connect to "sim_name"
            try:
                sock = backend.TCPSocket.connection(world.env, addr)
            except (ConnectionError, OSError):
                raise SimulationError('Simulator "%s" could not be started: '
                                      'Could not connect to "%s"' %
                                      (sim_name, sim_config['connect']))

        rpc_con = JsonRpc(Packet(sock, max_packet_size=10 * 1024 * 1024))

        # Make init() API call and wait for sim_name's meta data.
        init = rpc_con.remote.init(sim_id, **sim_params)
        try:
            results = yield init | start_timeout
        except ConnectionError as e:
            raise SimulationError(
                'Simulator "%s" closed its connection during'
                ' the init() call.' % sim_name, e)

        if start_timeout in results:
            raise SimulationError('Simulator "%s" did not reply to the init() '
                                  'call in time.' % sim_name)
        else:
            meta = results[init]

        return RemoteProcess(sim_name, sim_id, meta, proc, rpc_con, world)

    # Add a error callback that waits for "proc" to stop if "proc" is not None:
    def terminate():
        try:
            # See if it terminates on its own ...
            proc.wait(timeout=1)
        except subprocess.TimeoutExpired:
            # ... or kill it ...
            proc.terminate()
            proc.wait(timeout=1)

    cb = None if proc is None else terminate
    return sync_process(greeter(), world, errback=cb)
Exemplo n.º 5
0
    def run(self, until, rt_factor=None, rt_strict=False):

        if "control" in self.commands:  #cerca se ci sono altri simulatori in attesa
            control = dict(self.commands["control"])

            for sim, data in control.items():
                self.sim_config[sim] = {"connect": data["port"]}

                if "prefix" in data:
                    factor = self.start(sim, eid_prefix=data["prefix"])
                    eval(
                        "factor." + data["create"] + ".create(" +
                        str(len(data['dests'])) + ")"
                    )  #bisogna mettere molti controlli prima di questa funzione

            for sim, data in control.items():
                i = 0
                if "prefix" in data:
                    for model, conns in data["dests"].items():
                        string = sim + "-0." + model
                        for conn, couples in conns.items():
                            for a, b in couples.items():
                                tupla = (a, b)
                                self.connect(self.models[string],
                                             self.models[conn],
                                             tupla,
                                             async_requests=True)
        """Start the simulation until the simulation time *until* is reached.

        In order to perform real-time simulations, you can set *rt_factor* to
        a number > 0. An rt-factor of 1 means that 1 simulation time unit
        (usually a second) takes 1 second in real-time. An rt-factor 0f 0.5
        will let the simulation run twice as fast as real-time.

        If the simulators are too slow for the rt-factor you chose, mosaik
        prints by default only a warning. In order to raise
        a :exc:`RuntimeError`, you can set *rt_strict* to ``True``.

        Before this method returns, it stops all simulators and closes mosaik's
        server socket. So this method should only be called once.

        """
        if self.srv_sock is None:
            raise RuntimeError('Simulation has already been run and can only '
                               'be run once for a World instance.')

        # Check if a simulator is not connected to anything:
        for sid, deg in sorted(list(networkx.degree(self.df_graph))):
            if deg == 0:
                print('WARNING: %s has no connections.' % sid)

        print('Starting simulation.')
        import mosaik._debug as dbg  # always import, enable when requested
        if self._debug:
            dbg.enable()
        try:
            util.sync_process(scheduler.run(self, until, rt_factor, rt_strict),
                              self)
            print('Simulation finished successfully.')
        except KeyboardInterrupt:
            print('Simulation canceled. Terminating ...')
        finally:
            self.shutdown()
            if self._debug:
                dbg.disable()