def do_main_loop(self):
        # pylint: disable=too-many-branches, too-many-statements, too-many-locals
        """Main loop for an Alignak daemon

        :return: None
        """
        # Increased on each loop turn
        if self.loop_count is None:
            self.loop_count = 0

        # Daemon start timestamp
        if self.start_time is None:
            self.start_time = time.time()

        # For the pause duration
        logger.info("pause duration: %.2f", self.pause_duration)

        # For the maximum expected loop duration
        self.maximum_loop_duration = 1.1 * self.maximum_loop_duration
        logger.info("maximum expected loop duration: %.2f", self.maximum_loop_duration)

        # Treatments before starting the main loop...
        self.do_before_loop()

        elapsed_time = 0

        logger.info("starting main loop: %.2f", self.start_time)
        while not self.interrupted:
            loop_start_ts = time.time()

            # Maybe someone said we will stop...
            if self.will_stop and not self.type == 'arbiter':
                logger.debug("death-wait mode... waiting for death")
                _, _ = self.make_a_pause(1.0)
                continue

            # Increment loop count
            self.loop_count += 1
            if self.log_loop:
                logger.debug("--- %d", self.loop_count)

            # Maybe the arbiter pushed a new configuration...
            if self.watch_for_new_conf(timeout=0.05):
                logger.info("I got a new configuration...")
                # Manage the new configuration
                self.setup_new_conf()

            # Trying to restore our related daemons lost connections
            for satellite in list(self.get_links_of_type(s_type='').values()):
                # Not for configuration disabled satellites
                if not satellite.active:
                    continue
                if not satellite.alive and not satellite.passive:
                    logger.info("Trying to restore connection for %s/%s...",
                                satellite.type, satellite.name)
                    if self.daemon_connection_init(satellite):
                        logger.info("Connection restored")

            # Each loop turn, execute the daemon specific treatment...
            # only if the daemon has a configuration to manage
            if self.have_conf:
                _ts = time.time()
                self.do_loop_turn()
                statsmgr.timer('loop-turn', time.time() - _ts)
            else:
                logger.info("+++ loop %d, I do not have a configuration", self.loop_count)

            if self.daemon_monitoring and (self.loop_count % self.daemon_monitoring_period == 1):
                perfdatas = []
                my_process = psutil.Process()
                with my_process.oneshot():
                    perfdatas.append("num_threads=%d" % my_process.num_threads())
                    statsmgr.counter("system.num_threads", my_process.num_threads())
                    # perfdatas.append("num_ctx_switches=%d" % my_process.num_ctx_switches())
                    perfdatas.append("num_fds=%d" % my_process.num_fds())
                    statsmgr.counter("system.num_fds", my_process.num_fds())
                    # perfdatas.append("num_handles=%d" % my_process.num_handles())
                    perfdatas.append("create_time=%d" % my_process.create_time())
                    perfdatas.append("cpu_num=%d" % my_process.cpu_num())
                    statsmgr.counter("system.cpu_num", my_process.cpu_num())
                    perfdatas.append("cpu_usable=%d" % len(my_process.cpu_affinity()))
                    statsmgr.counter("system.cpu_usable", len(my_process.cpu_affinity()))
                    perfdatas.append("cpu_percent=%.2f%%" % my_process.cpu_percent())
                    statsmgr.counter("system.cpu_percent", my_process.cpu_percent())

                    cpu_times_percent = my_process.cpu_times()
                    for key in cpu_times_percent._fields:
                        perfdatas.append("cpu_%s_time=%.2fs" % (key,
                                                                getattr(cpu_times_percent, key)))
                        statsmgr.counter("system.cpu_%s_time" % key,
                                         getattr(cpu_times_percent, key))

                    memory = my_process.memory_full_info()
                    for key in memory._fields:
                        perfdatas.append("mem_%s=%db" % (key, getattr(memory, key)))
                        statsmgr.counter("system.mem_%s" % key, getattr(memory, key))

                    logger.debug("Daemon %s (%s), pid=%s, ppid=%s, status=%s, cpu/memory|%s",
                                 self.name, my_process.name(), my_process.pid, my_process.ppid(),
                                 my_process.status(), " ".join(perfdatas))

            if self.activity_log_period and (self.loop_count % self.activity_log_period == 1):
                logger.info("Daemon %s is living: loop #%s ;)", self.name, self.loop_count)

            # Maybe the arbiter pushed a new configuration...
            if self.watch_for_new_conf(timeout=0.05):
                logger.warning("The arbiter pushed a new configuration... ")

            # Loop end
            loop_end_ts = time.time()
            loop_duration = loop_end_ts - loop_start_ts

            pause = self.maximum_loop_duration - loop_duration
            if loop_duration > self.maximum_loop_duration:
                logger.info("The %s %s loop exceeded the maximum expected loop duration (%.2f). "
                            "The last loop needed %.2f seconds to execute. "
                            "You should try to reduce the load on this %s.",
                            self.type, self.name, self.maximum_loop_duration,
                            loop_duration, self.type)
                # Make a very very short pause ...
                pause = 0.01

            # Pause the daemon execution to avoid too much load on the system
            logger.debug("Before pause: timeout: %s", pause)
            work, time_changed = self.make_a_pause(pause)
            logger.debug("After pause: %.2f / %.2f, sleep time: %.2f",
                         work, time_changed, self.sleep_time)
            if work > self.pause_duration:
                logger.warning("Too much work during the pause (%.2f out of %.2f)! "
                               "The daemon should rest for a while... but one need to change "
                               "its code for this. Please log an issue in the project repository!",
                               work, self.pause_duration)
                # self.pause_duration += 0.1
            statsmgr.timer('sleep-time', self.sleep_time)
            self.sleep_time = 0.0

            # And now, the whole average time spent
            elapsed_time = loop_end_ts - self.start_time
            if self.log_loop:
                logger.debug("Elapsed time, current loop: %.2f, from start: %.2f (%d loops)",
                             loop_duration, elapsed_time, self.loop_count)
            statsmgr.gauge('loop-count', self.loop_count)
            statsmgr.timer('run-duration', elapsed_time)

            # Maybe someone said we will stop...
            if self.will_stop:
                if self.type == 'arbiter':
                    self.will_stop = False
                else:
                    logger.info("The arbiter said we will stop soon - go to death-wait mode")

            # Maybe someone asked us to die, if so, do it :)
            if self.interrupted:
                logger.info("Someone asked us to stop now")
                continue

            # If someone asked us a configuration reloading
            if self.need_config_reload and self.type == 'arbiter':
                logger.warning("Someone requested a configuration reload")
                logger.info("Exiting daemon main loop")
                return

            # If someone asked us to dump memory, do it
            if self.need_dump_environment:
                logger.debug('Dumping memory')
                self.dump_environment()
                self.need_dump_environment = False
        logger.info("stopped main loop: %.2f", time.time())