Class: Rmega::Downloader

Inherits:
Object
  • Object
show all
Includes:
Loggable
Defined in:
lib/rmega/downloader.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Loggable

included, #logger

Constructor Details

#initialize(params) ⇒ Downloader

Returns a new instance of Downloader.



12
13
14
15
16
17
# File 'lib/rmega/downloader.rb', line 12

def initialize(params)
  @pool = Pool.new(params[:threads])
  @filesize = params[:filesize]
  @base_url = params[:base_url]
  @local_path = params[:local_path]
end

Instance Attribute Details

#base_urlObject (readonly)

Returns the value of attribute base_url.



10
11
12
# File 'lib/rmega/downloader.rb', line 10

def base_url
  @base_url
end

#filesizeObject (readonly)

Returns the value of attribute filesize.



10
11
12
# File 'lib/rmega/downloader.rb', line 10

def filesize
  @filesize
end

#local_pathObject (readonly)

Returns the value of attribute local_path.



10
11
12
# File 'lib/rmega/downloader.rb', line 10

def local_path
  @local_path
end

#poolObject (readonly)

Returns the value of attribute pool.



10
11
12
# File 'lib/rmega/downloader.rb', line 10

def pool
  @pool
end

Instance Method Details

#allocateObject

Creates the local file allocating filesize-n bytes (of /dev/zero) for it. Opens the local file to start writing from the beginning of it.



21
22
23
24
25
26
# File 'lib/rmega/downloader.rb', line 21

def allocate
  `dd if=/dev/zero of="#{local_path}" bs=1 count=0 seek=#{filesize} > /dev/null 2>&1`
  raise "Unable to create file #{local_path}" if File.size(local_path) != filesize

  ::File.open(local_path, 'r+b').tap { |f| f.rewind }
end

#chunksObject



42
43
44
# File 'lib/rmega/downloader.rb', line 42

def chunks
  Utils.chunks(filesize)
end

#download(&block) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rmega/downloader.rb', line 46

def download(&block)
  @local_file = allocate

  progress = Progress.new(total: filesize, caption: 'Download')

  chunks.each do |start, size|
    pool.defer do
      encrypted_buffer = download_chunk(start, size)
      clean_buffer = yield(start, encrypted_buffer)
      progress.increment(size)
      pool.synchronize { write_chunk(start, clean_buffer) }
    end
  end

  # waits for the last running threads to finish
  pool.wait_done

  @local_file.flush

  pool.shutdown
ensure
  @local_file.close rescue nil
end

#download_chunk(start, size) ⇒ Object

Downloads a part of the remote file, starting from the start-n byte and ending after size-n bytes.



30
31
32
33
34
# File 'lib/rmega/downloader.rb', line 30

def download_chunk(start, size)
  stop = start + size - 1
  url = "#{base_url}/#{start}-#{stop}"
  HTTPClient.new.get_content(url)
end

#write_chunk(start, buffer) ⇒ Object

Writes a buffer in the local file, starting from the start-n byte.



37
38
39
40
# File 'lib/rmega/downloader.rb', line 37

def write_chunk(start, buffer)
  @local_file.seek(start)
  @local_file.write(buffer)
end