Exemple #1
0
    def _do_write_events(self):
        event_queue = self._event_queue
        write = sys.stdout.write
        got_shutdown_signal = False

        while 1:
            try:
                events = event_queue.get(timeout=3)
            except Queue.Empty:
                # We need drain the queue before shutdown
                # timeout means empty for now
                if got_shutdown_signal:
                    logger.info("ModinputEventWriter is going to exit...")
                    break
                else:
                    continue

            if events is not None:
                if isinstance(events, (str, unicode)):
                    # for legacy interface
                    write(events)
                else:
                    for event in events:
                        write(event.to_string())
                    sys.stdout.flush()
            else:
                logger.info("ModinputEventWriter got tear down signal")
                got_shutdown_signal = True
Exemple #2
0
    def run(self, jobs):
        if self._started:
            return
        self._started = True

        self._event_writer.start()
        self._executor.start()
        self._timer_queue.start()
        self._scheduler.start()
        logger.info("TADataLoader started.")

        def _enqueue_io_job(job):
            job_props = job.get_props()
            real_job = job_props["real_job"]
            self.run_io_jobs((real_job, ))

        for job in jobs:
            j = sjob.Job(_enqueue_io_job, {"real_job": job},
                         job.get_interval())
            self._scheduler.add_jobs((j, ))

        self._wait_for_tear_down()

        for job in jobs:
            job.stop()

        self._scheduler.tear_down()
        self._timer_queue.tear_down()
        self._executor.tear_down()
        self._event_writer.tear_down()
        logger.info("DataLoader stopped.")
Exemple #3
0
    def start(self):
        if self._started:
            return
        self._started = True

        self._event_writer.start()
        logger.info("ModinputEventWriter started.")
    def resize(self, new_size):
        """
        Resize the pool size, spawn or destroy threads if necessary
        """

        if new_size <= 0:
            return

        if self._lock.locked() or not self._started:
            logger.info("Try to resize thread pool during the tear "
                        "down process, do nothing")
            return

        with self._lock:
            self._remove_exited_threads_with_lock()
            size = self._last_size
            self._last_size = new_size
            if new_size > size:
                for _ in range(new_size - size):
                    thr = threading.Thread(target=self._run)
                    thr.daemon = self._daemon
                    thr.start()
                    self._thrs.append(thr)
            elif new_size < size:
                for _ in range(size - new_size):
                    self._work_queue.put(None)
        logger.info("Finished ThreadPool resizing. New size=%d", new_size)
Exemple #5
0
    def _check_and_execute(self):
        wakeup_queue = self._wakeup_queue
        while 1:
            (next_expired_time, expired_timers) = self._get_expired_timers()
            for timer in expired_timers:
                try:
                    timer()
                except Exception:
                    logger.error(traceback.format_exc())

            self._reset_timers(expired_timers)

            # Calc sleep time
            if next_expired_time:
                now = time()
                if now < next_expired_time:
                    sleep_time = next_expired_time - now
                else:
                    sleep_time = 0.1
            else:
                sleep_time = 1

            try:
                wakeup = wakeup_queue.get(timeout=sleep_time)
                if wakeup is None:
                    break
            except Queue.Empty:
                pass
        logger.info("TimerQueue stopped.")
    def _run(self):
        """
        Threads callback func, run forever to handle jobs from the job queue
        """

        work_queue = self._work_queue
        count_lock = self._count_lock
        while 1:
            logger.debug("Going to get job")
            func = work_queue.get()
            if func is None:
                break

            if not self._started:
                break

            logger.debug("Going to exec job")
            with count_lock:
                self._occupied_threads += 1

            try:
                func()
            except Exception:
                logger.error(traceback.format_exc())

            with count_lock:
                self._occupied_threads -= 1

            logger.debug("Done with exec job")
            logger.info("Thread work_queue_size=%d", work_queue.qsize())

        logger.debug("Worker thread %s stopped.",
                     threading.current_thread().getName())
Exemple #7
0
    def tear_down(self):
        if not self._started:
            return
        self._started = False

        self._event_queue.put(None)
        self._event_writer.join()
        logger.info("ModinputEventWriter stopped.")
Exemple #8
0
    def start(self):
        """
        Start the timer queue to make it start function
        """

        if self._started:
            return
        self._started = True

        self._thr.start()
        logger.info("TimerQueue started.")
Exemple #9
0
    def tear_down(self):
        """
        Stop the schduler which will stop the internal thread for scheduling
        jobs.
        """

        if not self._started:
            logger.info("Scheduler already tear down.")
            return

        self._wakeup_q.put(True)
Exemple #10
0
 def _wait_for_tear_down(self):
     wakeup_q = self._wakeup_queue
     while 1:
         try:
             go_exit = wakeup_q.get(timeout=1)
         except queue.Empty:
             pass
         else:
             if go_exit:
                 logger.info("DataLoader got stop signal")
                 self._stopped = True
                 break
Exemple #11
0
    def _wait_for_tear_down(self):
        wakeup_q = self._wakeup_queue
        while 1:
            try:
                go_exit = wakeup_q.get(timeout=1)
            except Queue.Empty:
                go_exit = self._orphan_checker.is_orphan()

            if go_exit:
                logger.info("DataLoaderManager got stop signal")
                self._started = False
                break
Exemple #12
0
    def start(self):
        """
        Start the schduler which will start the internal thread for scheduling
        jobs. Please do tear_down when doing cleanup
        """

        if self._started:
            logger.info("Scheduler already started.")
            return
        self._started = True

        self._thr.start()
Exemple #13
0
 def _do_jobs(self):
     while 1:
         (sleep_time, jobs) = self.get_ready_jobs()
         self._do_execution(jobs)
         try:
             done = self._wakeup_q.get(timeout=sleep_time)
         except queue.Empty:
             pass
         else:
             if done:
                 break
     self._started = False
     logger.info("Scheduler exited.")
Exemple #14
0
    def tear_down(self):
        """
        Tear down the pool
        """

        if self._stopped:
            logger.info("ProcessPool has already stopped.")
            return
        self._stopped = True

        self._pool.close()
        self._pool.join()
        logger.info("ProcessPool stopped.")
Exemple #15
0
    def apply(self, func, args=(), kwargs={}):
        """
        :param func: callable
        :param args: free params
        :param kwargs: named params
        :return whatever the func returns
        """

        if self._stopped:
            logger.info("ProcessPool has already stopped.")
            return None

        return self._pool.apply(func, args, kwargs)
    def enqueue_funcs(self, funcs, block=True):
        """
        run jobs in a fire and forget way, no result will be handled
        over to clients
        :param funcs: tuple/list-like or generator like object, func shall be
                      callable
        """

        if not self._started:
            logger.info("ThreadPool has already stopped.")
            return

        for func in funcs:
            self._work_queue.put(func, block)
Exemple #17
0
    def apply_async(self, func, args=(), kwargs={}, callback=None):
        """
        :param func: callable
        :param args: free params
        :param kwargs: named params
        :callback: when func is done without exception, call this callack
        :return whatever the func returns
        """

        if self._stopped:
            logger.info("ProcessPool has already stopped.")
            return None

        return self._pool.apply_async(func, args, kwargs, callback)
Exemple #18
0
    def remove_timer(self, timer):
        """
        Remove timer from the queue.
        """

        with self._lock:
            try:
                self._timers.remove(timer)
            except ValueError:
                logger.info(
                    "Timer=%s is not in queue, move it to cancelling "
                    "list", timer.ident())
            else:
                self._cancelling_timers[timer.ident()] = timer
    def apply(self, func, args=(), kwargs=None):
        """
        :param func: callable
        :param args: free params
        :param kwargs: named params
        :return whatever the func returns
        """

        if not self._started:
            logger.info("ThreadPool has already stopped.")
            return None

        res = self.apply_async(func, args, kwargs)
        return res.get()
    def apply_async(self, func, args=(), kwargs=None, callback=None):
        """
        :param func: callable
        :param args: free params
        :param kwargs: named params
        :callback: when func is done and without exception, call the callback
        :return AsyncResult, clients can poll or wait the result through it
        """

        if not self._started:
            logger.info("ThreadPool has already stopped.")
            return None

        res = AsyncResult(func, args, kwargs, callback)
        self._work_queue.put(res)
        return res
    def start(self):
        """
        Start threads in the pool
        """

        with self._lock:
            if self._started:
                return
            self._started = True

            for thr in self._thrs:
                thr.daemon = self._daemon
                thr.start()

            self._admin_thr.start()
        logger.info("ThreadPool started.")
    def _do_admin(self):
        admin_q = self._admin_queue
        resize_win = self._resize_window
        while 1:
            try:
                wakup = admin_q.get(timeout=resize_win + 1)
            except queue.Empty:
                self._do_resize_according_to_loads()
                continue

            if wakup is None:
                break
            else:
                self._do_resize_according_to_loads()
        logger.info("ThreadPool admin thread=%s stopped.",
                    threading.current_thread().getName())
Exemple #23
0
def update_or_create_hec(config):
    """
    :param config:
    {
    "server_uri": xxx,
    "session_key": xxx,
    "hec_name": xxx,
    "hec_port": xxx,
    "use_hec": 0/1,
    "use_raw_hec": 0/1,
    }
    """

    use_hec = utils.is_true(config.get("use_hec"))
    use_raw_hec = utils.is_true(config.get("use_raw_hec"))
    if not use_hec and not use_raw_hec:
        return

    hec = HECConfig(config["server_uri"], config["session_key"])

    hec_input = hec.get_http_input(config["hec_name"])
    port = config.get("hec_port", 8088)
    if not hec_input:
        logger.info("Create HEC data input")
        hec_settings = {
            "enableSSL": 1,
            "port": port,
            "output_mode": "json",
            "disabled": 0,
        }
        hec.update_settings(hec_settings)
        input_settings = {
            "name": config["hec_name"],
        }
        hec.create_http_input(input_settings)
        hec_input = hec.get_http_input(config["hec_name"])

    hostname, _ = utils.extract_hostname_port(config["server_uri"])
    hec_uri = "https://{hostname}:{port}".format(hostname=hostname, port=port)
    if hec_input:
        hec_input[0]["hec_server_uri"] = hec_uri
        return hec_input[0]
    else:
        raise Exception("Failed to get HTTP input configuration")
Exemple #24
0
    def check_changes(self):
        logger.debug("Checking files=%s", self._files)
        file_mtimes = self.file_mtimes
        changed_files = []
        for f, last_mtime in file_mtimes.items():
            try:
                current_mtime = op.getmtime(f)
                if current_mtime != last_mtime:
                    file_mtimes[f] = current_mtime
                    changed_files.append(f)
                    logger.info("Detect %s has changed, last=%s, current=%s",
                                f, last_mtime, current_mtime)
            except OSError:
                pass

        if changed_files:
            if self._callback:
                self._callback(changed_files)
            return True
        return False
Exemple #25
0
    def get_ready_jobs(self):
        """
        @return: a 2 element tuple. The first element is the next ready
                 duration. The second element is ready jobs list
        """

        now = time()
        ready_jobs = []
        sleep_time = 1

        with self._lock:
            job_set = self._jobs
            total_jobs = len(job_set)
            for job in job_set:
                if job.get_expiration() <= now:
                    ready_jobs.append(job)

            if ready_jobs:
                del job_set[:len(ready_jobs)]

            for job in ready_jobs:
                if job.get_interval() != 0 and not job.stopped():
                    # repeated job, calculate next due time and enqueue
                    job.update_expiration()
                    job_set.add(job)

            if job_set:
                sleep_time = job_set[0].get_expiration() - now
                if sleep_time < 0:
                    logger.warn("Scheduler satuation, sleep_time=%s",
                                sleep_time)
                    sleep_time = 0.1

        if ready_jobs:
            logger.info(
                "Get %d ready jobs, next duration is %f, "
                "and there are %s jobs scheduling", len(ready_jobs),
                sleep_time, total_jobs)

        ready_jobs.sort(key=lambda job: job.get("priority", 0), reverse=True)
        return (sleep_time, ready_jobs)
    def _do_resize_according_to_loads(self):
        if (self._last_resize_time
                and time() - self._last_resize_time < self._resize_window):
            return

        thr_size = self._last_size
        free_thrs = thr_size - self._occupied_threads
        work_size = self._work_queue.qsize()

        logger.info("current_thr_size=%s, free_thrs=%s, work_size=%s",
                    thr_size, free_thrs, work_size)
        if work_size and work_size > free_thrs:
            if thr_size < self._max_size:
                thr_size = min(thr_size * 2, self._max_size)
                self.resize(thr_size)
        elif free_thrs > 0:
            if work_size // free_thrs < self._low_watermark and free_thrs >= 2:
                thr_size = thr_size - free_thrs // 2
                if thr_size > self._min_size:
                    self.resize(thr_size)
        self._last_resize_time = time()
    def tear_down(self):
        """
        Tear down thread pool
        """

        with self._lock:
            if not self._started:
                return
            self._started = False

            for thr in self._thrs:
                self._work_queue.put(None, block=False)

            self._admin_queue.put(None)

            if not self._daemon:
                logger.info("Wait for threads to stop.")
                for thr in self._thrs:
                    thr.join()
            self._admin_thr.join()

        logger.info("ThreadPool stopped.")
Exemple #28
0
 def tear_down(self):
     self._wakeup_queue.put(True)
     logger.info("DataLoader is going to stop.")