pvl/syslog/syslog.py
changeset 50 0bbe2e7561a1
parent 48 40ccb8d3c96e
child 60 9326ed989645
equal deleted inserted replaced
49:30c615bf7751 50:0bbe2e7561a1
     6 
     6 
     7 import logging; log = logging.getLogger('pvl.syslog.source')
     7 import logging; log = logging.getLogger('pvl.syslog.source')
     8 
     8 
     9 class SyslogSource (object) :
     9 class SyslogSource (object) :
    10     """
    10     """
    11         A source of syslog items.
    11         Process syslog input from a given source.
       
    12         
       
    13         Implements an iterable mainloop doing continuous polling on the source, using either a timeout or
       
    14         select():able source.
    12     """
    15     """
    13     
    16     
    14     def __init__ (self, source, parser, filter=None, poll=None) :
    17     def __init__ (self, syslog, source, poll=None) :
    15         """
    18         """
    16             Using given underlying line source.
    19             Using given underlying line source.
    17 
    20                 
    18                 source          - file-like object with poll() and iter()
    21                 syslog      - iterable
    19                 parser          - process() bytes -> items
    22                 source      - source to select() if poll=True
    20                 filter          - filter items
    23                 poll        - polling behaviour
    21                 poll            - using given polling style:
       
    22                     True            - select() source
       
    23                     float           - given interval
       
    24                     None/False      - single-shot
       
    25         """
    24         """
    26 
    25         
       
    26         self.syslog = syslog
    27         self.source = source
    27         self.source = source
    28         self.parser = parser
       
    29         self.filter = filter
       
    30 
       
    31         log.debug("source: %s", source)
       
    32 
       
    33         self._poll = poll
    28         self._poll = poll
    34 
    29 
    35     def __iter__ (self) :
    30     def poll (self, poll=None) :
    36         """
    31         """
    37             Read syslog messages from source.
    32             Poll our source for input, with given polling behaviour:
    38         """
    33                 True    - select() on source
    39         
    34                 False   - peek on source
    40         # directly iter across source
    35                 float   - timeout in seconds
    41         iter = self.source
       
    42         
       
    43         # parse
       
    44         iter = self.parser(iter)
       
    45         
       
    46         # filter ?
       
    47         if self.filter :
       
    48             iter = self.filter(iter)
       
    49         
       
    50         return iter
       
    51 
       
    52     def poll (self, timeout=None) :
       
    53         """
       
    54             Poll source for input, with given timeout in seconds (float).
       
    55 
       
    56             A timeout of None indicates to block forever, False indicates to never block.
       
    57 
    36 
    58             Returns True if we have input waiting, False on timeout with no input. None on indeterminate.
    37             Returns True if we have input waiting, False on timeout with no input. None on indeterminate.
    59         """
    38         """
    60 
    39 
    61         read = write = ()
    40         reading = writing = ()
    62         
    41         
    63         if timeout is True :
    42         if poll is True :
    64             timeout = None
    43             timeout = None # block
    65             read += (self.source, )
    44             reading += (self.source, ) # file-like object with fileno()
    66 
    45 
    67         elif timeout is False :
    46         elif not poll :
    68             timeout = 0.0
    47             timeout = 0.0 # do not block
       
    48 
       
    49         else :
       
    50             timeout = float(poll)
    69 
    51 
    70         log.debug("%s", timeout)
    52         log.debug("%s", timeout)
    71     
    53     
    72         # select
    54         # select
    73         read, write, ex = select.select(read, write, [], timeout)
    55         readable, writeable, ex = select.select(reading, writing, [], timeout)
    74 
    56 
    75         if read :
    57         if readable :
    76             return True
    58             return True
    77 
    59 
    78         else :
    60         elif reading :
    79             # timeout
    61             # timeout
    80             return False
    62             return False
    81 
    63 
    82     def loop (self) :
    64         else :
       
    65             # unknown
       
    66             return None
       
    67 
       
    68     def main (self, poll=None) :
    83         """
    69         """
    84             Continuously read items from syslog source, blocking as suitable.
    70             yield items from syslog source, polling as given.
    85 
    71 
    86             Returns once no more lines are available.
    72             Returns once no more lines are available.
    87 
    73 
    88             XXX: reconnect?
    74             XXX: reconnect? or source takes care of that..
       
    75             TODO: SIGINT -> finish iteration and return?
    89         """
    76         """
       
    77 
       
    78         if poll is None :
       
    79             poll = self._poll
    90         
    80         
    91         # mainloop
    81         # mainloop
    92         while True :
    82         while True :
    93             log.debug("tick")
       
    94 
       
    95             # pull in messages
    83             # pull in messages
    96             for item in self :
    84             for item in self.syslog :
    97                 log.debug("%s", item)
    85                 log.debug("%s", item)
    98                 yield item
    86                 yield item
    99             
    87             
   100             # poll
    88             # poll
   101             if self._poll :
    89             if poll :
   102                 # wait
    90                 # wait
   103                 self.poll(self._poll)
    91                 self.poll(poll)
   104             else :
    92             else :
   105                 # done
    93                 # done
   106                 break
    94                 break
   107 
    95 
   108         log.debug("exit")
    96         log.debug("exit")
   109     
       
   110     def stop (self) :
       
   111         """
       
   112             Stop loop after current iteration.
       
   113         """
       
   114 
    97 
   115         self._poll = False
    98     __iter__ = main
   116 
       
   117     def main (self) :
       
   118         """
       
   119             Mainloop.
       
   120         """
       
   121 
       
   122         # TODO: SIGINT -> stop()
       
   123         return loop()