DebugClients/Ruby/AsyncFile.rb

changeset 0
de9c2efb9d02
child 13
1af94a91f439
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2005 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 =begin edoc
7 File implementing an asynchronous file like socket interface for the debugger.
8 =end
9
10 if RUBY_VERSION < "1.9"
11 $KCODE = 'UTF8'
12 require 'jcode'
13 end
14
15 require 'socket'
16
17 require 'DebugProtocol'
18
19 def AsyncPendingWrite(file)
20 =begin edoc
21 Module function to check for data to be written.
22
23 @param file The file object to be checked (file)
24 @return Flag indicating if there is data wating (int)
25 =end
26 begin
27 pending = file.pendingWrite
28 rescue
29 pending = 0
30 end
31 return pending
32 end
33
34 class AsyncFile
35 =begin edoc
36 # Class wrapping a socket object with a file interface.
37 =end
38 @@maxtries = 10
39 @@maxbuffersize = 1024 * 1024 * 4
40
41 def initialize(sock, mode, name)
42 =begin edoc
43 Constructor
44
45 @param sock the socket object being wrapped
46 @param mode mode of this file (string)
47 @param name name of this file (string)
48 =end
49
50 # Initialise the attributes.
51 @closed = false
52 @sock = sock
53 @mode = mode
54 @name = name
55 @nWriteErrors = 0
56
57 @wpending = ''
58 end
59
60 def checkMode(mode)
61 =begin edoc
62 Private method to check the mode.
63
64 This method checks, if an operation is permitted according to
65 the mode of the file. If it is not, an IOError is raised.
66
67 @param mode the mode to be checked (string)
68 =end
69 if mode != @mode
70 raise IOError, '[Errno 9] Bad file descriptor'
71 end
72 end
73
74 def nWrite(n)
75 =begin edoc
76 Private method to write a specific number of pending bytes.
77
78 @param n the number of bytes to be written (int)
79 =end
80 if n > 0
81 begin
82 buf = "%s%s" % [@wpending[0...n], EOT]
83 sent = @sock.send(buf, 0)
84 if sent > n
85 sent -= EOT.length
86 end
87 @wpending = @wpending[sent..-1]
88 @nWriteErrors = 0
89 rescue IOError
90 @nWriteErrors += 1
91 if @nWriteErrors > self.maxtries
92 raise # assume that an error that occurs 10 times wont go away
93 end
94 end
95 end
96 end
97
98 def pendingWrite
99 =begin edoc
100 Public method that returns the number of bytes waiting to be written.
101
102 @return the number of bytes to be written (int)
103 =end
104 ind = @wpending.rindex("\n")
105 if ind
106 return ind + 1
107 else
108 return 0
109 end
110 end
111
112 def close
113 =begin edoc
114 Public method to close the file.
115 =end
116 if not @closed
117 flush()
118 begin
119 @sock.close()
120 rescue IOError
121 end
122 @closed = true
123 end
124 end
125
126 def flush
127 =begin edoc
128 Public method to write all pending bytes.
129 =end
130 nWrite(@wpending.length)
131 end
132
133 def isatty
134 =begin edoc
135 Public method to indicate whether a tty interface is supported.
136
137 @return always false
138 =end
139 return false
140 end
141
142 def fileno
143 =begin edoc
144 Public method returning the file number.
145
146 @return file number (int)
147 =end
148 return @sock.fileno()
149 end
150
151 def getSock
152 =begin edoc
153 Public method to get the socket object.
154
155 @return the socket object
156 =end
157 return @sock
158 end
159
160 def read(size = -1)
161 =begin edoc
162 Public method to read bytes from this file.
163
164 @param size maximum number of bytes to be read (int)
165 @return the bytes read (any)
166 =end
167 checkMode('r')
168
169 if size < 0
170 size = 20000
171 end
172
173 return @sock.recv(size)
174 end
175
176 def readline(size = -1)
177 =begin edoc
178 Public method to read a line from this file.
179
180 <b>Note</b>: This method will not block and may return
181 only a part of a line if that is all that is available.
182
183 @param size maximum number of bytes to be read (int)
184 @return one line of text up to size bytes (string)
185 =end
186 checkMode('r')
187
188 if size < 0
189 size = 20000
190 end
191
192 # The integration of the debugger client event loop and the connection
193 # to the debugger relies on the two lines of the debugger command being
194 # delivered as two separate events. Therefore we make sure we only
195 # read a line at a time.
196 line = @sock.recv(size, Socket::MSG_PEEK)
197
198 eol = line.index("\n")
199
200 if eol and eol >= 0
201 size = eol + 1
202 else
203 size = line.length
204 end
205
206 # Now we know how big the line is, read it for real.
207 return @sock.recv(size)
208 end
209
210 def readlines(sizehint = -1)
211 =begin edoc
212 Public method to read all lines from this file.
213
214 @param sizehint hint of the numbers of bytes to be read (int)
215 @return list of lines read (list of strings)
216 =end
217 lines = []
218 room = sizehint
219
220 line = readline(room)
221 linelen = line.length
222
223 while linelen > 0
224 lines << line
225
226 if sizehint >= 0
227 room = room - linelen
228
229 if room <= 0
230 break
231 end
232 end
233
234 line = readline(room)
235 linelen = line.length
236 end
237
238 return lines
239 end
240
241 def seek(offset, whence=IO::SEEK_SET)
242 =begin edoc
243 Public method to move the filepointer.
244
245 @exception IOError This method is not supported and always raises an
246 IOError.
247 =end
248 raise IOError, '[Errno 29] Illegal seek'
249 end
250
251 def tell
252 =begin edoc
253 Public method to get the filepointer position.
254
255 @exception IOError This method is not supported and always raises an
256 IOError.
257 =end
258 raise IOError, '[Errno 29] Illegal seek'
259 end
260
261 def <<(s)
262 =begin edoc
263 Synonym for write(s).
264
265 @param s bytes to be written (string)
266 =end
267 write(s)
268 end
269
270 def write(s)
271 =begin edoc
272 Public method to write a string to the file.
273
274 @param s bytes to be written (string)
275 =end
276 checkMode("w")
277 tries = 0
278 s = s.to_s
279 if @wpending.length == 0
280 @wpending = s.dup
281 elsif @wpending.length + s.length > @@maxbuffersize
282 # flush wpending if too big
283 while @wpending.length > 0
284 # if we have a persistent error in sending the data, an exception
285 # will be raised in nWrite
286 flush
287 tries += 1
288 if tries > @@maxtries
289 raise IOError, "Too many attempts to send data"
290 end
291 end
292 @wpending = s.dup
293 else
294 @wpending << s
295 end
296 nWrite(pendingWrite())
297 end
298
299 def writelines(list)
300 =begin edoc
301 Public method to write a list of strings to the file.
302
303 @param list the list to be written (list of string)
304 =end
305 list.each do |s|
306 write(s)
307 end
308 end
309 end

eric ide

mercurial