Class: QuartzTorrent::PieceIO

Inherits:
Object
  • Object
show all
Defined in:
lib/quartz_torrent/filemanager.rb

Overview

Can read and write pieces and blocks of a torrent.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(baseDirectory, torrinfo, ioManager = IOManager.new) ⇒ PieceIO

Create a new PieceIO that will map to files inside ‘baseDirectory’. Parameter ‘torrinfo’ should be a Metainfo::Info object (the info part of the metainfo).



148
149
150
151
152
153
154
155
# File 'lib/quartz_torrent/filemanager.rb', line 148

def initialize(baseDirectory, torrinfo, ioManager = IOManager.new)
  @baseDirectory = baseDirectory
  @torrinfo = torrinfo
  @pieceMapper = PieceMapper.new(baseDirectory, torrinfo)
  @ioManager = ioManager
  @logger = LogManager.getLogger("pieceio")
  @torrentDataLength = torrinfo.dataLength
end

Instance Attribute Details

#torrentDataLengthObject (readonly)

Get the overall length of the torrent data



158
159
160
# File 'lib/quartz_torrent/filemanager.rb', line 158

def torrentDataLength
  @torrentDataLength
end

Instance Method Details

#flushObject



214
215
216
# File 'lib/quartz_torrent/filemanager.rb', line 214

def flush
  @ioManager.flush
end

#readBlock(pieceIndex, offset, length) ⇒ Object

Read a block from a completed piece. Returns nil if the block doesn’t exist yet. Throws exceptions on error (for example, opening a file failed)



203
204
205
# File 'lib/quartz_torrent/filemanager.rb', line 203

def readBlock(pieceIndex, offset, length)
  readRegions @pieceMapper.findBlock(pieceIndex, offset, length)
end

#readPiece(pieceIndex) ⇒ Object

Read a piece. Returns nil if the piece is not yet present. NOTE: this method expects that if the ioManager is a reactor iomanager, that the io was set with errorHandler=false so that we get the EOF errors.



210
211
212
# File 'lib/quartz_torrent/filemanager.rb', line 210

def readPiece(pieceIndex)
  readRegions @pieceMapper.findPiece(pieceIndex)
end

#writeBlock(pieceIndex, offset, block) ⇒ Object

Write a block to an in-progress piece. The block is written to piece ‘peiceIndex’, at offset ‘offset’. The block data is in block. Throws exceptions on failure.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/quartz_torrent/filemanager.rb', line 163

def writeBlock(pieceIndex, offset, block)
  regions = @pieceMapper.findBlock(pieceIndex, offset, block.length)
  indexInBlock = 0
  regions.each do |region|
    # Get the IO for the file with path 'path'. If we are being used in a reactor, this is the IO facade. If we
    # are not then this is a real IO.
    io = @ioManager.get(region.path)
    if ! io
      # No IO for this file. 
      raise "This process doesn't have write permission for the file #{region.path}" if File.exists?(region.path) && ! File.writable?(region.path)

      # Ensure parent directories exist.
      dir = File.dirname region.path
      FileUtils.mkdir_p dir if ! File.directory?(dir)

      begin
        io = @ioManager.open(region.path)
      rescue
        @logger.error "Opening file #{region.path} failed: #{$!}"
        raise "Opening file #{region.path} failed"
      end
    end

    io.seek region.offset, IO::SEEK_SET
    begin
      io.write(block[indexInBlock, region.length])
      indexInBlock += region.length
    rescue
      # Error when writing...
      @logger.error "Writing block to file #{region.path} failed: #{$!}"
      piece = nil
      break
    end

    break if indexInBlock >= block.length
  end
end