class Flare::Tools::Cli::Verify

Public Class Methods

new() click to toggle source
Calls superclass method Flare::Tools::Cli::SubCommand::new
# File lib/flare/tools/cli/verify.rb, line 47
def initialize
  super
  @numeric_hosts = false
  @key_hash_algorithm = :simple
  @use_test_data = false
  @debug = false
  @word_size = 32
  @bwlimit = 0
  @verbose = false
  @meta = false
  @quiet = false
end

Public Instance Methods

execute(config, args) click to toggle source
# File lib/flare/tools/cli/verify.rb, line 60
def execute(config, args)
  parse_index_server(config, args)
  keys = {}
  cout = STDERR
  status = S_OK
  info "connecting to index ..."
  Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], @timeout) do |s|
    nodes = s.stats_nodes.sort_by{|key, val| [val['partition'].to_i, val['role'], key]}

    # meta
    info "setting up key resolver ..."
    resolver = nil
    if @meta
      meta = s.meta
      stats = s.stats
      kha = meta['key-hash-algorithm']
      if kha
        @key_hash_algorithm = :crc32 if kha == 'crc32'
        @key_hash_algorithm = :simple if kha == 'simple'
      else
        @key_hash_algorithm = :simple
      end
      pointer_size = stats['pointer_size']
      option = {
        :partition_size => meta['partition-size'].to_i,
        :virtual => meta['partition-modular-virtual'].to_i,
        :hint => meta['partition-modular-hint'].to_i
      }
      resolver = Util::KeyResolver.new(:modular, option)
    else
      resolver = Util::KeyResolver.new
    end
    info "key_hash_algorithm = #{@key_hash_algorithm.to_s}"

    # check node list size
    if nodes.size == 0
      cout.puts "no nodes"
      return S_NG
    end
    hostname0, port0 = nodes[0][0].split(":", 2)

    # partition size
    partition_size = 1+nodes.inject(-1) do |r,entry|
      node, val = entry
      i = val['partition'].to_i
      if i >= r then i else r end
    end
    if partition_size <= 0
      info "no need to verify."
      return S_NG
    end
    info "partition_size: #{partition_size}"

    if @use_test_data
      info "storing test data ..."
      Flare::Tools::Node.open(hostname0, port0.to_i, @timeout) do |n|
        (1..10000).each do |i|
          key = ".test."+Digest::MD5.new.update(i.to_s).to_s
          n.set(key, i.to_s)
          keys[key] = :not_found
        end
      end
    end

    nodes.each do |nodekey,val|
      hostname, port = nodekey.split(":", 2)
      partition = val['partition'].to_i
      Flare::Tools::Node.open(hostname, port.to_i, @timeout) do |n|
        cout.write "checking #{nodekey} ... "
        msg = "OK"
        interruptible do
          count = 0
          cout.write "keydump ... "
          n.dumpkey(partition, partition_size) do |key|
            next if key.nil?
            type = @key_hash_algorithm
            hash = get_key_hash_value(key, type, @word_size)
            p = resolver.resolve(hash, partition_size)
            count += 1
            if p != partition then
              cout.puts "keydump failed: the partition for #{key}(#{hash}) is #{p} but it was dumpped from #{partition}." if @debug
              status = S_NG
              msg = "NG"
            else
              keys[key] = :found
            end
            false
          end
          cout.write "#{count} entries. "
          count = 0
          cout.write "dump ... "
          n.dump(0, partition, partition_size, @bwlimit) do |data, key, flag, len, version, expire|
            next if key.nil?
            type = @key_hash_algorithm
            hash = get_key_hash_value(key, type, @word_size)
            p = resolver.resolve(hash, partition_size)
            count += 1
            if p != partition then
              cout.puts "dump failed: the partition for #{key}(#{hash}) is #{p} but it was dumpped from #{partition}." if @debug
              status = S_NG
              msg = "NG"
            end
            false
          end
          cout.write "#{count} entries. "
        end # interruptible
        cout.write "#{msg}\n"
      end # Node.open
    end # nodes.each

    if @use_test_data && keys.size > 0
      # check total result
      remain = 0
      keys.each do |k,state|
        if state != :found
          error "failed: not found '#{k}'" if @verbose
          remain += 1
        end
      end
      error "failed: not found #{remain} keys" if remain > 0

      # delete
      Flare::Tools::Node.open(hostname0, port0.to_i, @timeout) do |n|
        keys.each do |k,v|
          n.delete(k)
        end
      end
    end

    # end of connection
  end
  if status == S_OK
    cout.puts "OK"
  else
    cout.puts "NG"
  end
  status
end
setup() click to toggle source
Calls superclass method Flare::Tools::Cli::SubCommand#setup
# File lib/flare/tools/cli/verify.rb, line 28
def setup
  super
  set_option_index_server
  @optp.on('--key-hash-algorithm=TYPE',              "key hash algorithm") do |v|
    case @key_hash_algorithm = v.to_sym
    when :simple, :crc32
    else
      puts "unknown type: #{v}"
      exit
    end
  end
  @optp.on('--use-test-data',                        "store test data")           {|v| @use_test_data = true}
  @optp.on('--debug',                                "use debug mode")            {|v| @debug = true}
  @optp.on('--64bit',                                "(experimental) 64bit mode") {|v| @word_size = 64}
  @optp.on('--verbose',                              "use verbose mode")          {|v| @verbose = true}
  @optp.on('--meta',                                 "use meta command")          {|v| @meta = true}
  @optp.on('--quiet',                                "use quiet mode")            {|v| @quiet = true}
end