Ticket #2157: _pollingfile.patch

File _pollingfile.patch, 6.6 KB (added by synapsis, 10 years ago)

patch _pollingfile.py, version 2

  • _pollingfile.py

     
    33
    44Implements a simple polling interface for file descriptors that don't work with
    55select() - this is pretty much only useful on Windows.
    6 
    76"""
    87
     8import sys
    99from zope.interface import implements
    1010
    1111from twisted.internet.interfaces import IConsumer, IPushProducer
     
    1313MIN_TIMEOUT = 0.000000001
    1414MAX_TIMEOUT = 0.1
    1515
    16 class _PollableResource:
     16
     17class _PollableResource(object):
    1718    active = True
    1819
    1920    def activate(self):
     
    2223    def deactivate(self):
    2324        self.active = False
    2425
    25 class _PollingTimer:
     26
     27class _PollingTimer(object):
    2628    # Everything is private here because it is really an implementation detail.
    2729
    2830    def __init__(self, reactor):
     
    9193# If we ever (let's hope not) need the above functionality on UNIX, this could
    9294# be factored into a different module.
    9395
    94 import win32pipe
    9596import win32file
    9697import win32api
    9798import pywintypes
    9899
    99 class _PollableReadPipe(_PollableResource):
    100100
     101class _PollableReader(_PollableResource):
     102
    101103    implements(IPushProducer)
    102104
    103     def __init__(self, pipe, receivedCallback, lostCallback):
    104         # security attributes for pipes
    105         self.pipe = pipe
     105    def __init__(self, handle, receivedCallback, lostCallback):
     106        self.handle = handle
    106107        self.receivedCallback = receivedCallback
    107108        self.lostCallback = lostCallback
    108109
    109110    def checkWork(self):
    110         finished = 0
    111         fullDataRead = []
     111        raise NotImplementedError()
    112112
    113         while 1:
    114             try:
    115                 buffer, bytesToRead, result = win32pipe.PeekNamedPipe(self.pipe, 1)
    116                 # finished = (result == -1)
    117                 if not bytesToRead:
    118                     break
    119                 hr, data = win32file.ReadFile(self.pipe, bytesToRead, None)
    120                 fullDataRead.append(data)
    121             except win32api.error:
    122                 finished = 1
    123                 break
    124 
    125         dataBuf = ''.join(fullDataRead)
    126         if dataBuf:
    127             self.receivedCallback(dataBuf)
    128         if finished:
    129             self.cleanup()
    130         return len(dataBuf)
    131 
    132113    def cleanup(self):
    133114        self.deactivate()
    134115        self.lostCallback()
    135116
    136117    def close(self):
     118        # XXX why not cleanup?
    137119        try:
    138             win32api.CloseHandle(self.pipe)
     120            win32api.CloseHandle(self.handle)
    139121        except pywintypes.error:
    140122            # You can't close std handles...?
    141123            pass
     
    150132        self.activate()
    151133
    152134
    153 FULL_BUFFER_SIZE = 64 * 1024
    154135
    155 class _PollableWritePipe(_PollableResource):
     136class _PollableWriter(_PollableResource):
     137    FULL_BUFFER_SIZE = 64 * 1024
    156138
    157139    implements(IConsumer)
    158 
    159     def __init__(self, writePipe, lostCallback):
     140   
     141    def __init__(self, handle, lostCallback):
    160142        self.disconnecting = False
    161143        self.producer = None
    162144        self.producerPaused = 0
    163145        self.streamingProducer = 0
    164146        self.outQueue = []
    165         self.writePipe = writePipe
     147        self.handle = handle
    166148        self.lostCallback = lostCallback
    167         try:
    168             win32pipe.SetNamedPipeHandleState(writePipe,
    169                                               win32pipe.PIPE_NOWAIT,
    170                                               None,
    171                                               None)
    172         except pywintypes.error:
    173             # Maybe it's an invalid handle.  Who knows.
    174             pass
    175149
    176150    def close(self):
    177151        self.disconnecting = True
     
    219193    def writeConnectionLost(self):
    220194        self.deactivate()
    221195        try:
    222             win32api.CloseHandle(self.writePipe)
     196            win32api.CloseHandle(self.handle)
    223197        except pywintypes.error:
    224198            # OMG what
    225199            pass
     
    232206        if self.disconnecting:
    233207            return
    234208        self.outQueue.append(data)
    235         if sum(map(len, self.outQueue)) > FULL_BUFFER_SIZE:
     209        if sum(map(len, self.outQueue)) > self.FULL_BUFFER_SIZE:
    236210            self.bufferFull()
    237211
    238212    def checkWork(self):
     213        raise NotImplementedError()
     214
     215
     216
     217#
     218# Pipe support
     219#
     220import win32pipe
     221
     222
     223class _PollableReadPipe(_PollableReader):
     224    def __init__(self, pipe, receivedCallback, lostCallback):
     225        _PollableReader.__init__(self, pipe, receivedCallback, lostCallback)
     226        # security attributes for pipes
     227
     228    def checkWork(self):
     229        finished = 0
     230        fullDataRead = []
     231
     232        while 1:
     233            try:
     234                buffer, bytesToRead, result = win32pipe.PeekNamedPipe(self.handle, 1)
     235                # finished = (result == -1)
     236                if not bytesToRead:
     237                    break
     238                hr, data = win32file.ReadFile(self.handle, bytesToRead, None)
     239                fullDataRead.append(data)
     240            except win32api.error:
     241                finished = 1
     242                break
     243
     244        dataBuf = ''.join(fullDataRead)
     245        if dataBuf:
     246            self.receivedCallback(dataBuf)
     247        if finished:
     248            self.cleanup()
     249        return len(dataBuf)
     250
     251
     252class _PollableWritePipe(_PollableWriter):
     253    def __init__(self, writePipe, lostCallback):
     254        _PollableWriter.__init__(self, writePipe, lostCallback)
     255
     256        try:
     257            win32pipe.SetNamedPipeHandleState(writePipe,
     258                                              win32pipe.PIPE_NOWAIT,
     259                                              None,
     260                                              None)
     261        except pywintypes.error:
     262            # Maybe it's an invalid handle.  Who knows.
     263            pass
     264
     265    def checkWork(self):
    239266        numBytesWritten = 0
    240267        if not self.outQueue:
    241268            if self.disconnecting:
    242269                self.writeConnectionLost()
    243270                return 0
    244271            try:
    245                 win32file.WriteFile(self.writePipe, '', None)
     272                win32file.WriteFile(self.handle, '', None)
    246273            except pywintypes.error:
    247274                self.writeConnectionLost()
    248275                return numBytesWritten
     
    250277            data = self.outQueue.pop(0)
    251278            errCode = 0
    252279            try:
    253                 errCode, nBytesWritten = win32file.WriteFile(self.writePipe,
     280                errCode, nBytesWritten = win32file.WriteFile(self.handle,
    254281                                                             data, None)
    255282            except win32api.error:
    256283                self.writeConnectionLost()
     
    266293            if not resumed and self.disconnecting:
    267294                self.writeConnectionLost()
    268295        return numBytesWritten
    269 
    270