Ticket #2157: _pollingfile.2.patch
| File _pollingfile.2.patch, 6.6 KB (added by synapsis, 7 years ago) |
|---|
-
_pollingfile.py
3 3 4 4 Implements a simple polling interface for file descriptors that don't work with 5 5 select() - this is pretty much only useful on Windows. 6 7 6 """ 8 7 8 import sys 9 9 from zope.interface import implements 10 10 11 11 from twisted.internet.interfaces import IConsumer, IPushProducer … … 13 13 MIN_TIMEOUT = 0.000000001 14 14 MAX_TIMEOUT = 0.1 15 15 16 class _PollableResource: 16 17 class _PollableResource(object): 17 18 active = True 18 19 19 20 def activate(self): … … 22 23 def deactivate(self): 23 24 self.active = False 24 25 25 class _PollingTimer: 26 27 class _PollingTimer(object): 26 28 # Everything is private here because it is really an implementation detail. 27 29 28 30 def __init__(self, reactor): … … 91 93 # If we ever (let's hope not) need the above functionality on UNIX, this could 92 94 # be factored into a different module. 93 95 94 import win32pipe95 96 import win32file 96 97 import win32api 97 98 import pywintypes 98 99 99 class _PollableReadPipe(_PollableResource):100 100 101 class _PollableReader(_PollableResource): 102 101 103 implements(IPushProducer) 102 104 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 106 107 self.receivedCallback = receivedCallback 107 108 self.lostCallback = lostCallback 108 109 109 110 def checkWork(self): 110 finished = 0 111 fullDataRead = [] 111 raise NotImplementedError() 112 112 113 while 1:114 try:115 buffer, bytesToRead, result = win32pipe.PeekNamedPipe(self.pipe, 1)116 # finished = (result == -1)117 if not bytesToRead:118 break119 hr, data = win32file.ReadFile(self.pipe, bytesToRead, None)120 fullDataRead.append(data)121 except win32api.error:122 finished = 1123 break124 125 dataBuf = ''.join(fullDataRead)126 if dataBuf:127 self.receivedCallback(dataBuf)128 if finished:129 self.cleanup()130 return len(dataBuf)131 132 113 def cleanup(self): 133 114 self.deactivate() 134 115 self.lostCallback() 135 116 136 117 def close(self): 118 # XXX why not cleanup? 137 119 try: 138 win32api.CloseHandle(self. pipe)120 win32api.CloseHandle(self.handle) 139 121 except pywintypes.error: 140 122 # You can't close std handles...? 141 123 pass … … 150 132 self.activate() 151 133 152 134 153 FULL_BUFFER_SIZE = 64 * 1024154 135 155 class _PollableWritePipe(_PollableResource): 136 class _PollableWriter(_PollableResource): 137 FULL_BUFFER_SIZE = 64 * 1024 156 138 157 139 implements(IConsumer) 158 159 def __init__(self, writePipe, lostCallback):140 141 def __init__(self, handle, lostCallback): 160 142 self.disconnecting = False 161 143 self.producer = None 162 144 self.producerPaused = 0 163 145 self.streamingProducer = 0 164 146 self.outQueue = [] 165 self. writePipe = writePipe147 self.handle = handle 166 148 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 pass175 149 176 150 def close(self): 177 151 self.disconnecting = True … … 219 193 def writeConnectionLost(self): 220 194 self.deactivate() 221 195 try: 222 win32api.CloseHandle(self. writePipe)196 win32api.CloseHandle(self.handle) 223 197 except pywintypes.error: 224 198 # OMG what 225 199 pass … … 232 206 if self.disconnecting: 233 207 return 234 208 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: 236 210 self.bufferFull() 237 211 238 212 def checkWork(self): 213 raise NotImplementedError() 214 215 216 217 # 218 # Pipe support 219 # 220 import win32pipe 221 222 223 class _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 252 class _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): 239 266 numBytesWritten = 0 240 267 if not self.outQueue: 241 268 if self.disconnecting: 242 269 self.writeConnectionLost() 243 270 return 0 244 271 try: 245 win32file.WriteFile(self. writePipe, '', None)272 win32file.WriteFile(self.handle, '', None) 246 273 except pywintypes.error: 247 274 self.writeConnectionLost() 248 275 return numBytesWritten … … 250 277 data = self.outQueue.pop(0) 251 278 errCode = 0 252 279 try: 253 errCode, nBytesWritten = win32file.WriteFile(self. writePipe,280 errCode, nBytesWritten = win32file.WriteFile(self.handle, 254 281 data, None) 255 282 except win32api.error: 256 283 self.writeConnectionLost() … … 266 293 if not resumed and self.disconnecting: 267 294 self.writeConnectionLost() 268 295 return numBytesWritten 269 270
