def _start_nodes_parallel(self, nodes, max_thread_pool_size):
        """
        Start the nodes using a pool of multiprocessing threads for speed-up.

        Return set of nodes that were actually started.
        """
        # Create one thread for each node to start
        thread_pool_size = min(len(nodes), max_thread_pool_size)
        thread_pool = Pool(processes=thread_pool_size)
        log.debug("Note: starting %d nodes concurrently.", thread_pool_size)

        # pressing Ctrl+C flips this flag, which in turn stops the main loop
        # down below
        keep_running = True

        def sigint_handler(signal, frame):
            """
            Makes sure the cluster is saved, before the sigint results in
            exiting during node startup.
            """
            log.error("Interrupted: will save cluster state and exit"
                      " after all nodes have started.")
            keep_running = False

        # intercept Ctrl+C
        with sighandler(signal.SIGINT, sigint_handler):
            result = thread_pool.map_async(self._start_node, nodes)
            while not result.ready():
                result.wait(1)
                # check if Ctrl+C was pressed
                if not keep_running:
                    log.error("Aborting upon user interruption ...")
                    # FIXME: `.close()` will keep the pool running until all
                    # nodes have been started; should we use `.terminate()`
                    # instead to interrupt node creation as soon as possible?
                    thread_pool.close()
                    thread_pool.join()
                    self.repository.save_or_update(self)
                    # FIXME: should raise an exception instead!
                    sys.exit(1)

            # keep only nodes that were successfully started
            return set(node
                       for node, ok in itertools.izip(nodes, result.get())
                       if ok)
Esempio n. 2
0
    def _start_nodes_parallel(self, nodes, max_thread_pool_size):
        """
        Start the nodes using a pool of multiprocessing threads for speed-up.

        Return set of nodes that were actually started.
        """
        # Create one thread for each node to start
        thread_pool_size = min(len(nodes), max_thread_pool_size)
        thread_pool = Pool(processes=thread_pool_size)
        log.debug("Created pool of %d threads", thread_pool_size)

        # pressing Ctrl+C flips this flag, which in turn stops the main loop
        # down below
        keep_running = True

        def sigint_handler(signal, frame):
            """
            Makes sure the cluster is saved, before the sigint results in
            exiting during node startup.
            """
            log.error(
                "Interrupted: will save cluster state and exit"
                " after all nodes have started.")
            keep_running = False

        # intercept Ctrl+C
        with sighandler(signal.SIGINT, sigint_handler):
            result = thread_pool.map_async(self._start_node, nodes)
            while not result.ready():
                result.wait(1)
                # check if Ctrl+C was pressed
                if not keep_running:
                    log.error("Aborting upon user interruption ...")
                    # FIXME: `.close()` will keep the pool running until all
                    # nodes have been started; should we use `.terminate()`
                    # instead to interrupt node creation as soon as possible?
                    thread_pool.close()
                    thread_pool.join()
                    self.repository.save_or_update(self)
                    # FIXME: should raise an exception instead!
                    sys.exit(1)

            # keep only nodes that were successfully started
            return set(node for node, ok
                       in itertools.izip(nodes, result.get()) if ok)