class QuartzTorrent::IoFacade
This class provides a facade for an IO object. The read method on this object acts as a blocking read. Internally it reads nonblockingly and passes processing to other ready sockets if this socket would block.
Attributes
logger[RW]
Public Class Methods
new(ioInfo, logger = nil)
click to toggle source
# File lib/quartz_torrent/reactor.rb, line 215 def initialize(ioInfo, logger = nil) @ioInfo = ioInfo @io = ioInfo.io @logger = logger end
Public Instance Methods
close()
click to toggle source
Close the io.
# File lib/quartz_torrent/reactor.rb, line 295 def close @io.close end
closed?()
click to toggle source
Check if the io is closed.
# File lib/quartz_torrent/reactor.rb, line 300 def closed? @io.closed? end
flush()
click to toggle source
Flush data.
# File lib/quartz_torrent/reactor.rb, line 290 def flush @io.flush end
read(length)
click to toggle source
Read ‘length` bytes.
# File lib/quartz_torrent/reactor.rb, line 230 def read(length) data = '' while data.length < length begin toRead = length-data.length rateLimited = false if @ioInfo.readRateLimit avail = @ioInfo.readRateLimit.avail.to_i if avail < toRead toRead = avail rateLimited = true end @ioInfo.readRateLimit.withdraw toRead end @logger.debug "IoFacade: must read: #{length} have read: #{data.length}. Reading #{toRead} bytes now" if @logger data << @io.read_nonblock(toRead) if toRead > 0 # If we tried to read more than we are allowed to by rate limiting, yield. Fiber.yield if rateLimited rescue Errno::EWOULDBLOCK # Wait for more data. @logger.debug "IoFacade: read would block" if @logger Fiber.yield rescue Errno::EAGAIN, Errno::EINTR # Wait for more data. @logger.debug "IoFacade: read was interrupted" if @logger Fiber.yield rescue @logger.debug "IoFacade: read error: #{$!}" if @logger # Read failure occurred @ioInfo.lastReadError = $! if @ioInfo.useErrorhandler @ioInfo.state = :error Fiber.yield else raise $! end end end data end
readRateLimit=(rate)
click to toggle source
# File lib/quartz_torrent/reactor.rb, line 304 def readRateLimit=(rate) raise "The argument must be a RateLimit" if ! rate.nil? && ! rate.is_a?(RateLimit) @ioInfo.readRateLimit = rate end
removeFromIOHash(hash)
click to toggle source
Method needed for disposeIo to work without breaking encapsulation of WriteOnlyIoFacade
.
# File lib/quartz_torrent/reactor.rb, line 225 def removeFromIOHash(hash) hash.delete @io end
seek(amount, whence)
click to toggle source
Seek on the io. @param amount amount to seek. @param whence one of the whence constants from IO::seek.
# File lib/quartz_torrent/reactor.rb, line 285 def seek(amount, whence) @io.seek amount, whence if @ioInfo.seekable? end
write(data)
click to toggle source
Write data to the IO.
# File lib/quartz_torrent/reactor.rb, line 272 def write(data) # Issue: what about write, read, read on files opened for read/write? Write should happen at offset X, but reads moved to offset N. Since writes # are buffered, write may happen after read which means write will happen at the wrong offset N. Can fix by always seeking (if needed) before writes to the # position where the write was queued, but this should only be done for files since other fds don't support seek. This is satisfactory for files opened # for write only since the file position will be where we expect so we won't need to seek. Same for read only. @ioInfo.outputBuffer.append data @logger.debug "wrote #{data.length} bytes to the output buffer of IO metainfo=#{@ioInfo.metainfo}" if @logger data.length end
writeRateLimit=(rate)
click to toggle source
# File lib/quartz_torrent/reactor.rb, line 309 def writeRateLimit=(rate) raise "The argument must be a RateLimit" if ! rate.nil? && !rate.is_a?(RateLimit) @ioInfo.writeRateLimit = rate end