5 require 'mogilefs/backend'
6 require 'mogilefs/util'
9 # HTTPFile wraps up the new file operations for storing files onto an HTTP
12 # You really don't want to create an HTTPFile by hand. Instead you want to
13 # create a new file using MogileFS::MogileFS.new_file.
16 # TODO dup'd content in MogileFS::NFSFile
18 class MogileFS::HTTPFile < StringIO
19 include MogileFS::Util
21 class EmptyResponseError < MogileFS::Error; end
22 class BadResponseError < MogileFS::Error; end
23 class UnparseableResponseError < MogileFS::Error; end
26 # The path this file will be stored to.
31 # The key for this file. This key won't represent a real file until you've
37 # The class of this file.
42 # The bigfile name in case we have file > 256M
44 attr_accessor :bigfile
47 # Works like File.open. Use MogileFS::MogileFS#new_file instead of this
53 return fp unless block_given?
63 # Creates a new HTTPFile with MogileFS-specific data. Use
64 # MogileFS::MogileFS#new_file instead of this method.
66 def initialize(mg, fid, path, devid, klass, key, dests, content_length)
76 @dests = dests.map { |(_,u)| URI.parse u }
83 # Closes the file handle and marks it as closed in MogileFS.
90 # Don't try to run out of memory
91 fp = File.open(@bigfile)
92 file_size = File.size(@bigfile)
93 @socket.write "PUT #{@path.request_uri} HTTP/1.0\r\nContent-Length: #{file_size}\r\n\r\n"
94 sysrwloop(fp, @socket)
97 @socket.write "PUT #{@path.request_uri} HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n#{string}"
103 raise EmptyResponseError, 'Unable to read response line from server'
106 if line =~ %r%^HTTP/\d+\.\d+\s+(\d+)% then
109 when 200..299 then # success!
111 raise BadResponseError, "HTTP response status from upload: #{status}"
114 raise InvalidResponseError, "Response line not understood: #{line}"
120 @mg.backend.create_close(:fid => @fid, :devid => @devid,
121 :domain => @mg.domain, :key => @key,
122 :path => @path, :size => length)
123 return file_size if @bigfile
130 return !(@socket.nil? or @socket.closed?)
134 return @socket if connected?
141 raise 'Unable to open socket to storage node' if @path.nil?
144 @socket = TCPSocket.new @path.host, @path.port
149 @dests.each do |dest|
150 unless @tried.include? dest then