pvl/syslog/syslog.py
author Tero Marttila <terom@fixme.fi>
Fri, 04 Jan 2013 21:27:17 +0200
changeset 60 9326ed989645
parent 50 0bbe2e7561a1
child 63 510a9a944f5a
permissions -rw-r--r--
pvl.syslog.source: fix iteration over filter/parser/source
"""
    Syslog handling.
"""

import select

import logging; log = logging.getLogger('pvl.syslog.source')

class SyslogSource (object) :
    """
        Process syslog input from a given source.
        
        Implements an iterable mainloop doing continuous polling on the source, using either a timeout or
        select():able source.
    """
    
    def __init__ (self, source, parser, filter, poll=None) :
        """
            Using given underlying line source.
                
                source      - source to select() if poll=True
                poll        - polling behaviour
        """
        
        self.source = source
        self.parser = parser
        self.filter = filter

        self._poll = poll

    def syslog (self) :
        """
            Yield available input.
        """

        return self.filter(self.parser(self.source))

    def poll (self, poll=None) :
        """
            Poll our source for input, with given polling behaviour:
                True    - select() on source
                False   - peek on source
                float   - timeout in seconds

            Returns True if we have input waiting, False on timeout with no input. None on indeterminate.
        """

        reading = writing = ()
        
        if poll is True :
            timeout = None # block
            reading += (self.source, ) # file-like object with fileno()

        elif not poll :
            timeout = 0.0 # do not block

        else :
            timeout = float(poll)

        log.debug("%s", timeout)
    
        # select
        readable, writeable, ex = select.select(reading, writing, [], timeout)

        if readable :
            return True

        elif reading :
            # timeout
            return False

        else :
            # unknown
            return None

    def main (self, poll=None) :
        """
            yield items from syslog source, polling as given.

            Returns once no more lines are available.

            XXX: reconnect? or source takes care of that..
            TODO: SIGINT -> finish iteration and return?
        """

        if poll is None :
            poll = self._poll
        
        # mainloop
        while True :
            # pull in messages
            for item in self.syslog() :
                log.debug("%s", item)
                yield item
            
            # poll
            if poll :
                # wait
                self.poll(poll)
            else :
                # done
                break

        log.debug("exit")