class Aspera::Fasp::HttpGW
executes a local “ascp”, connects mgt port, equivalent of “Fasp Manager”
Constants
- OK_MESSAGE
message returned by HTTP GW in case of success
- UPLOAD_REFRESH_SEC
refresh rate for progress
Public Class Methods
new(params)
click to toggle source
Calls superclass method
# File lib/aspera/fasp/http_gw.rb, line 180 def initialize(params) raise "params must be Hash" unless params.is_a?(Hash) params=params.symbolize_keys raise "must have only one param: url" unless params.keys.eql?([:url]) super() @gw_api=Rest.new({:base_url => params[:url]}) api_info = @gw_api.read('info')[:data] Log.log.info("#{api_info}") @upload_chunksize=128000 # TODO: configurable ? end
Public Instance Methods
download(transfer_spec)
click to toggle source
# File lib/aspera/fasp/http_gw.rb, line 118 def download(transfer_spec) transfer_spec['zip_required']||=false transfer_spec['source_root']||='/' # is normally provided by application, like package name if !transfer_spec.has_key?('download_name') # by default it is the name of first file dname=File.basename(transfer_spec['paths'].first['source']) # we remove extension dname=dname.gsub(/\.@gw_api.*$/,'') # ands add indication of number of files if there is more than one if transfer_spec['paths'].length > 1 dname=dname+" #{transfer_spec['paths'].length} Files" end transfer_spec['download_name']=dname end creation=@gw_api.create('download',{'transfer_spec'=>transfer_spec})[:data] transfer_uuid=creation['url'].split('/').last if transfer_spec['zip_required'] or transfer_spec['paths'].length > 1 # it is a zip file if zip is required or there is more than 1 file file_dest=transfer_spec['download_name']+'.zip' else # it is a plain file if we don't require zip and there is only one file file_dest=File.basename(transfer_spec['paths'].first['source']) end file_dest=File.join(transfer_spec['destination_root'],file_dest) @gw_api.call({:operation=>'GET',:subpath=>"download/#{transfer_uuid}",:save_to_file=>file_dest}) end
shutdown()
click to toggle source
terminates monitor thread
# File lib/aspera/fasp/http_gw.rb, line 172 def shutdown end
start_transfer(transfer_spec,options={})
click to toggle source
start FASP transfer based on transfer spec (hash table) note that it is asynchronous HTTP download only supports file list
# File lib/aspera/fasp/http_gw.rb, line 149 def start_transfer(transfer_spec,options={}) raise "GW URL must be set" unless !@gw_api.nil? raise "option: must be hash (or nil)" unless options.is_a?(Hash) raise "paths: must be Array" unless transfer_spec['paths'].is_a?(Array) raise "on token based transfer is supported in GW" unless transfer_spec['token'].is_a?(String) transfer_spec['authentication']||='token' case transfer_spec['direction'] when 'send' upload(transfer_spec) when 'receive' download(transfer_spec) else raise "error" end end
upload(transfer_spec)
click to toggle source
# File lib/aspera/fasp/http_gw.rb, line 27 def upload(transfer_spec) # precalculate size total_size=0 # currently, files are sent flat source_path=[] transfer_spec['paths'].each do |item| filepath=item['source'] item['source']=item['destination']=File.basename(filepath) total_size+=item['file_size']=File.size(filepath) source_path.push(filepath) end session_id=SecureRandom.uuid ws=::WebSocket::Client::Simple::Client.new error=nil received=0 ws.on :message do |msg| Log.log.info("ws: message: #{msg.data}") message=msg.data if message.eql?(OK_MESSAGE) received+=1 else message.chomp! if message[0].eql?('"') and message[-1].eql?('"') error=JSON.parse(Base64.strict_decode64(message.chomp[1..-2]))['message'] else error="expecting quotes in [#{message}]" end end end ws.on :error do |e| error=e end ws.on :open do Log.log.info("ws: open") end ws.on :close do Log.log.info("ws: close") end # open web socket to end point ws.connect("#{@gw_api.params[:base_url]}/upload") while !ws.open? and error.nil? do Log.log.info("ws: wait") sleep(0.2) end notify_begin(session_id,total_size) ws_send(ws,:transfer_spec,transfer_spec) # current file index filenum=0 # aggregate size sent sent_bytes=0 # last progress event lastevent=Time.now-1 transfer_spec['paths'].each do |item| # TODO: on destination write same path? destination_path=item['source'] # TODO: get mime type? file_mime_type='' total=item['file_size'] # compute total number of slices numslices=1+(total-1)/@upload_chunksize # current slice index slicenum=0 File.open(source_path[filenum]) do |file| while !file.eof? do data=file.read(@upload_chunksize) slice_data={ name: destination_path, type: file_mime_type, size: total, data: Base64.strict_encode64(data), slice: slicenum, total_slices: numslices, fileIndex: filenum } ws_send(ws,:slice_upload, slice_data) sent_bytes+=data.length currenttime=Time.now if (currenttime-lastevent)>UPLOAD_REFRESH_SEC notify_progress(session_id,sent_bytes) lastevent=currenttime end slicenum+=1 raise error unless error.nil? end end filenum+=1 end ws.close notify_end(session_id) end
url=(api_url)
click to toggle source
# File lib/aspera/fasp/http_gw.rb, line 175 def url=(api_url) end
wait_for_transfers_completion()
click to toggle source
wait for completion of all jobs started @return list of :success or error message
# File lib/aspera/fasp/http_gw.rb, line 167 def wait_for_transfers_completion return [:success] end
ws_send(ws,type,data)
click to toggle source
send message on http gw web socket
# File lib/aspera/fasp/http_gw.rb, line 23 def ws_send(ws,type,data) ws.send(JSON.generate({type => data})) end