Parent

MogileFS::Backend

MogileFS::Backend communicates with the MogileFS trackers.

Constants

BACKEND_ERRORS
(Not documented)

Attributes

lasterr[R]

The last error

lasterrstr[R]

The string attached to the last error

Public Class Methods

add_command(*names) click to toggle source

Adds MogileFS commands names.

# 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
add_error(err_snake) click to toggle source

this converts an error code from a mogilefsd tracker to an exception:

Examples of some exceptions that get created:

  class AfterMismatchError < MogileFS::Error; end
  class DomainNotFoundError < MogileFS::Error; end
  class InvalidCharsError < MogileFS::Error; end
# File lib/mogilefs/backend.rb, line 29
  def self.add_error(err_snake)
    err_camel = err_snake.gsub(/(?:^|_)([a-z])/) { $1.upcase }
    err_camel << 'Error' unless /Error\z/ =~ err_camel
    unless self.const_defined?(err_camel)
      self.class_eval("class #{err_camel} < MogileFS::Error; end")
    end
    BACKEND_ERRORS[err_snake] = self.const_get(err_camel)
  end
new(args) click to toggle source

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.

# File lib/mogilefs/backend.rb, line 56
  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

Public Instance Methods

shutdown() click to toggle source

Closes this backend’s socket.

# File lib/mogilefs/backend.rb, line 76
  def shutdown
    if @socket
      @socket.close rescue nil # ignore errors
      @socket = nil
    end
  end

Private Instance Methods

do_request(cmd, args) click to toggle source

Performs the cmd request with args.

# File lib/mogilefs/backend.rb, line 153
  def do_request(cmd, args)
    @mutex.synchronize do
      request = make_request cmd, args

      begin
        bytes_sent = socket.send request, 0
      rescue SystemCallError
        shutdown
        raise MogileFS::UnreachableBackendError
      end

      unless bytes_sent == request.length then
        raise MogileFS::RequestTruncatedError,
          "request truncated (sent #{bytes_sent} expected #{request.length})"
      end

      readable?

      parse_response(socket.gets)
    end
  end
error(err_snake) click to toggle source

this converts an error code from a mogilefsd tracker to an exception Most of these exceptions should already be defined, but since the MogileFS server code is liable to change and we may not always be able to keep up with the changes

# File lib/mogilefs/backend.rb, line 186
  def error(err_snake)
    BACKEND_ERRORS[err_snake] || self.class.add_error(err_snake)
  end
make_request(cmd, args) click to toggle source

Makes a new request string for cmd and args.

# File lib/mogilefs/backend.rb, line 178
  def make_request(cmd, args)
    "#{cmd} #{url_encode args}\r\n"
  end
parse_response(line) click to toggle source

Turns the line response from the server into a Hash of options, an error, or raises, as appropriate.

# File lib/mogilefs/backend.rb, line 194
  def parse_response(line)
    if line =~ /^ERR\s+(\w+)\s*(.*)/ then
      @lasterr = $1
      @lasterrstr = $2 ? url_unescape($2) : nil
      raise error(@lasterr), @lasterrstr
      return nil
    end

    return url_decode($1) if line =~ /^OK\s+\d*\s*(\S*)/

    raise MogileFS::InvalidResponseError,
          "Invalid response from server: #{line.inspect}"
  end
readable?() click to toggle source

Raises if the socket does not become readable in +@timeout+ seconds.

# File lib/mogilefs/backend.rb, line 211
  def readable?
    timeleft = @timeout
    peer = nil
    loop do
      t0 = Time.now
      found = IO.select([socket], nil, nil, timeleft)
      return true if found && found[0]
      timeleft -= (Time.now - t0)

      if timeleft < 0
        peer = @socket ? "#{@socket.mogilefs_peername} " : nil

        # we DO NOT want the response we timed out waiting for, to crop up later
        # on, on the same socket, intersperesed with a subsequent request! so,
        # we close the socket if it times out like this
        shutdown
        raise MogileFS::UnreadableSocketError, "#{peer}never became readable"
        break
      end
      shutdown
    end
    false
  end
socket() click to toggle source

Returns a socket connected to a MogileFS tracker.

# File lib/mogilefs/backend.rb, line 238
  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 = Socket.mogilefs_new(*(host.split(/:/) << @timeout))
      rescue SystemCallError, MogileFS::Timeout
        @dead[host] = now
        next
      end

      return @socket
    end

    raise MogileFS::UnreachableBackendError
  end
url_decode(str) click to toggle source

Turns a url params string into a Hash.

# File lib/mogilefs/backend.rb, line 262
  def url_decode(str)
    Hash[*(str.split(/&/).map { |pair|
      pair.split(/=/, 2).map { |x| url_unescape(x) }
    } ).flatten]
  end
url_encode(params) click to toggle source

Turns a Hash (or Array of pairs) into a url params string.

# File lib/mogilefs/backend.rb, line 271
  def url_encode(params)
    params.map do |k,v|
      "#{url_escape k.to_s}=#{url_escape v.to_s}"
    end.join("&")
  end
url_escape(str) click to toggle source

(Not documented)

# File lib/mogilefs/backend.rb, line 280
    def url_escape(str)
      str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1.ord }.tr(' ', '+')
    end
url_escape(str) click to toggle source

(Not documented)

# File lib/mogilefs/backend.rb, line 284
    def url_escape(str)
      str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+')
    end
url_unescape(str) click to toggle source

Unescapes naughty URL characters.

# File lib/mogilefs/backend.rb, line 292
  def url_unescape(str)
    str.gsub(/%([a-f0-9][a-f0-9])/i) { [$1.to_i(16)].pack 'C' }.tr('+', ' ')
  end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.