terom@2: """ terom@2: Syslog handling. terom@2: terom@2: XXX: this belongs in pvl.syslog.source (apart from __iter__?) terom@2: """ terom@2: terom@2: import select terom@2: terom@2: import logging; log = logging.getLogger('pvl.syslog.source') terom@2: terom@2: class SyslogSource (object) : terom@2: """ terom@2: Process syslog input from a given source. terom@2: terom@2: Implements an iterable mainloop doing continuous polling on the source, using either a timeout or terom@2: select():able source. terom@2: """ terom@2: terom@2: def __init__ (self, source, parser, filter, poll=None) : terom@2: """ terom@2: Using given underlying line source. terom@2: terom@2: source - source to select() if poll=True terom@2: poll - polling behaviour for source terom@2: """ terom@2: terom@2: self.source = source terom@2: self.parser = parser terom@2: self.filter = filter terom@2: terom@2: self.poll = poll terom@2: terom@2: def __iter__ (self) : terom@2: """ terom@2: Yield available input. terom@2: terom@2: Raises EOFError if source has been closed. terom@2: """ terom@2: terom@2: return self.filter(self.parser(self.source)) terom@2: terom@2: def fileno (self) : terom@2: return self.source.fileno() terom@2: terom@2: def select (self, poll=None, reading=(), writing=()) : terom@2: """ terom@2: Poll our source for input, with given polling behaviour: terom@2: True - select() on source terom@2: False - peek on source terom@2: float - timeout in seconds terom@2: terom@2: Returns None on unknown, empty sequence on timeout, list of readables on select. terom@2: """ terom@2: terom@2: if poll is True : terom@2: timeout = None # block terom@2: reading += (self, ) # source.fileno() terom@2: terom@2: elif not poll : terom@2: timeout = 0.0 # do not block terom@2: terom@2: else : terom@2: timeout = float(poll) terom@2: terom@2: log.debug("%s (%s)", reading, timeout) terom@2: terom@2: # select terom@2: readable, writeable, ex = select.select(reading, writing, [], timeout) terom@2: terom@2: log.debug("select: %s", readable) terom@2: terom@2: if readable : terom@2: return readable terom@2: terom@2: elif reading : terom@2: # timeout terom@2: # XXX: this is the same as readable terom@2: return () terom@2: terom@2: else : terom@2: # unknown terom@2: return None terom@2: terom@2: def main (self, poll=None) : terom@2: """ terom@2: Yield active syslog sources, polling as given. terom@2: terom@2: Returns once no more lines are available. terom@2: terom@2: XXX: reconnect? or source takes care of that.. terom@2: TODO: SIGINT -> finish iteration and return? terom@2: """ terom@2: terom@2: # from __init__ terom@2: # note that we must interpret poll here, since False -> never poll terom@2: if poll is None : terom@2: poll = self.poll terom@2: terom@2: # mainloop terom@2: while True : terom@2: # caller is responsible for reading them! terom@2: yield self terom@2: terom@2: # poll terom@2: if poll : terom@2: # wait terom@2: self.select(poll) terom@2: terom@2: else : terom@2: # done terom@2: break terom@2: terom@2: log.debug("exit") terom@2: terom@2: def close (self) : terom@2: """ terom@2: Close the syslog source, if possible. terom@2: terom@2: """ terom@2: terom@2: # XXX: do all sources support close? terom@2: self.source.close() terom@2: terom@2: def __str__ (self) : terom@2: return ' | '.join((str(self.source), str(self.parser), str(self.filter))) terom@2: