diff -r 521fec9bb663 -r 24dc72473ff9 fifo.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fifo.py Wed Mar 26 02:30:34 2008 +0200 @@ -0,0 +1,100 @@ +# read a stream from a fifo + +from twisted.internet import reactor, interfaces +from twisted.python import log +from zope.interface import implements + +import os, fcntl, errno + +class EOF (Exception) : pass + +BUF_SIZE = 2048 + +class Fifo (object) : + implements(interfaces.IReadDescriptor) + + def __init__ (self, path) : + self.path = path + self._open() + + def _open (self) : + self.fd = os.open(self.path, os.O_RDONLY | os.O_NONBLOCK) + + reactor.addReader(self) + + log.msg("opened fifo %s as %d" % (self.path, self.fd)) + + def _close (self) : + if self.fd : + reactor.removeReader(self) + os.close(self.fd) + + log.msg("closed fifo %d at %s" % (self.fd, self.path)) + + self.fd = None + close = _close + + def reopen (self) : + """ + Close and re-open the fifo. This is useful for handling EOF + """ + self._close() + self._open() + + def _read (self, length) : + + log.msg("(read %d bytes from %d:%s)" % (length, self.fd, self.path)) + try : + data = os.read(self.fd, length) + + except OSError, e : + if e.errno == errno.EAGAIN : + log.msg("\tEAGAIN") + return None + else : + log.msg("\tERROR: %s" % e) + raise + + if not data : + log.msg("\tEOF") + raise EOF() + + log.msg("\tDATA: %d: %r" % (len(data), data)) + return data + + def fileno (self) : + return self.fd + + def doRead (self) : + while True : + log.msg("fifo doRead loop") + + try : + data = self._read(BUF_SIZE) + except EOF : + self.handleEOF() + return + + if data : + self.dataReceived(data) + else : + break + + def dataReceived (self, data) : + pass + + def handleEOF (self) : + pass + + def connectionLost (self, reason) : + self.close() + + def logPrefix (self) : + return "FIFO:%d:%s" % (self.fd, self.path) + + def __del__ (self) : + """ + !!! this is important + """ + self.close() +