Class: MogileFS::Backend
- Inherits:
-
Object
- Object
- MogileFS::Backend
- Defined in:
- lib/mogilefs/backend.rb
Overview
MogileFS::Backend communicates with the MogileFS trackers.
Instance Attribute Summary collapse
-
#lasterr ⇒ Object
readonly
The last error – TODO Use Exceptions.
-
#lasterrstr ⇒ Object
readonly
The string attached to the last error – TODO Use Exceptions.
Class Method Summary collapse
-
.add_command(*names) ⇒ Object
Adds MogileFS commands
names
.
Instance Method Summary collapse
-
#connect_to(host, port) ⇒ Object
Returns a new TCPSocket connected to
port
onhost
. -
#do_request(cmd, args) ⇒ Object
Performs the
cmd
request withargs
. -
#initialize(args) ⇒ Backend
constructor
Creates a new MogileFS::Backend.
-
#make_request(cmd, args) ⇒ Object
Makes a new request string for
cmd
andargs
. -
#parse_response(line) ⇒ Object
Turns the
line
response from the server into a Hash of options, an error, or raises, as appropriate. -
#readable? ⇒ Boolean
Raises if the socket does not become readable in @timeout seconds.
-
#shutdown ⇒ Object
Closes this backend’s socket.
-
#socket ⇒ Object
Returns a socket connected to a MogileFS tracker.
-
#url_decode(str) ⇒ Object
Turns a url params string into a Hash.
-
#url_encode(params) ⇒ Object
Turns a Hash (or Array of pairs) into a url params string.
-
#url_escape(str) ⇒ Object
Escapes naughty URL characters.
-
#url_unescape(str) ⇒ Object
Unescapes naughty URL characters.
Constructor Details
#initialize(args) ⇒ Backend
Creates a new MogileFS::Backend.
:hosts is a required argument and must be an Array containing one or more ‘hostname:port’ pairs as Strings.
:timeout adjusts the request timeout before an error is returned.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/mogilefs/backend.rb', line 43 def initialize(args) @hosts = args[:hosts] raise ArgumentError, "must specify at least one host" unless @hosts raise ArgumentError, "must specify at least one host" if @hosts.empty? unless @hosts == @hosts.select { |h| h =~ /:\d+$/ } then raise ArgumentError, ":hosts must be in 'host:port' form" end @mutex = Mutex.new @timeout = args[:timeout] || 3 @socket = nil @lasterr = nil @lasterrstr = nil @dead = {} end |
Instance Attribute Details
#lasterr ⇒ Object (readonly)
The last error – TODO Use Exceptions
26 27 28 |
# File 'lib/mogilefs/backend.rb', line 26 def lasterr @lasterr end |
#lasterrstr ⇒ Object (readonly)
The string attached to the last error – TODO Use Exceptions
33 34 35 |
# File 'lib/mogilefs/backend.rb', line 33 def lasterrstr @lasterrstr end |
Class Method Details
.add_command(*names) ⇒ Object
Adds MogileFS commands names
.
13 14 15 16 17 18 19 |
# File 'lib/mogilefs/backend.rb', line 13 def self.add_command(*names) names.each do |name| define_method name do |*args| do_request name, args.first || {} end end end |
Instance Method Details
#connect_to(host, port) ⇒ Object
Returns a new TCPSocket connected to port
on host
.
100 101 102 |
# File 'lib/mogilefs/backend.rb', line 100 def connect_to(host, port) return TCPSocket.new(host, port) end |
#do_request(cmd, args) ⇒ Object
Performs the cmd
request with args
.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/mogilefs/backend.rb', line 107 def do_request(cmd, args) @mutex.synchronize do request = make_request cmd, args begin bytes_sent = socket.send request, 0 rescue SystemCallError @socket = nil raise "couldn't connect to mogilefsd backend" end unless bytes_sent == request.length then raise "request truncated (sent #{bytes_sent} expected #{request.length})" end readable? return parse_response(socket.gets) end end |
#make_request(cmd, args) ⇒ Object
Makes a new request string for cmd
and args
.
131 132 133 |
# File 'lib/mogilefs/backend.rb', line 131 def make_request(cmd, args) return "#{cmd} #{url_encode args}\r\n" end |
#parse_response(line) ⇒ Object
Turns the line
response from the server into a Hash of options, an error, or raises, as appropriate.
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/mogilefs/backend.rb', line 139 def parse_response(line) if line =~ /^ERR\s+(\w+)\s*(.*)/ then @lasterr = $1 @lasterrstr = $2 ? url_unescape($2) : nil return nil end return url_decode($1) if line =~ /^OK\s+\d*\s*(\S*)/ raise "Invalid response from server: #{line.inspect}" end |
#readable? ⇒ Boolean
Raises if the socket does not become readable in @timeout seconds.
154 155 156 157 158 159 160 161 |
# File 'lib/mogilefs/backend.rb', line 154 def readable? found = select [socket], nil, nil, @timeout if found.nil? or found.empty? then peer = (@socket ? "#{@socket.peeraddr[3]}:#{@socket.peeraddr[1]} " : nil) raise MogileFS::UnreadableSocketError, "#{peer}never became readable" end return true end |
#shutdown ⇒ Object
Closes this backend’s socket.
63 64 65 66 |
# File 'lib/mogilefs/backend.rb', line 63 def shutdown @socket.close unless @socket.nil? or @socket.closed? @socket = nil end |
#socket ⇒ Object
Returns a socket connected to a MogileFS tracker.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/mogilefs/backend.rb', line 166 def socket return @socket if @socket and not @socket.closed? now = Time.now @hosts.sort_by { rand(3) - 1 }.each do |host| next if @dead.include? host and @dead[host] > now - 5 begin @socket = connect_to(*host.split(':')) rescue SystemCallError @dead[host] = now next end return @socket end raise "couldn't connect to mogilefsd backend" end |
#url_decode(str) ⇒ Object
Turns a url params string into a Hash.
190 191 192 193 194 195 196 |
# File 'lib/mogilefs/backend.rb', line 190 def url_decode(str) pairs = str.split('&').map do |pair| pair.split('=', 2).map { |v| url_unescape v } end return Hash[*pairs.flatten] end |
#url_encode(params) ⇒ Object
Turns a Hash (or Array of pairs) into a url params string.
201 202 203 204 205 |
# File 'lib/mogilefs/backend.rb', line 201 def url_encode(params) return params.map do |k,v| "#{url_escape k.to_s}=#{url_escape v.to_s}" end.join("&") end |
#url_escape(str) ⇒ Object
Escapes naughty URL characters.
210 211 212 |
# File 'lib/mogilefs/backend.rb', line 210 def url_escape(str) return str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+') end |
#url_unescape(str) ⇒ Object
Unescapes naughty URL characters.
217 218 219 |
# File 'lib/mogilefs/backend.rb', line 217 def url_unescape(str) return str.gsub(/%([a-f0-9][a-f0-9])/i) { [$1.to_i(16)].pack 'C' }.tr('+', ' ') end |