class Flare::Tools::Cluster

Description

Cluster is a class that discribes a cluster information.

Constants

Role
RoleMaster
RoleProxy
RoleSlave
Roles
StatPartition
State
StateActive
StateDown
StatePrepare
StateReady
States

Public Class Methods

build(flare_xml) click to toggle source
# File lib/flare/tools/cluster.rb, line 301
def self.build flare_xml
  doc = REXML::Document.new flare_xml
  nodemap = doc.elements['/boost_serialization/node_map']
  thread_type = doc.elements['/boost_serialization/thread_type']
  count = nodemap.elements['count'].get_text.to_s.to_i
  item_version = nodemap.elements['item_version'].get_text.to_s.to_i
  nodestat = []
  nodemap.elements.each('item') do |item|
    nodekey = item.elements['first'].get_text.to_s
    elem = item.elements['second'].elements
    node = {
      'server_name' => elem['node_server_name'].get_text.to_s,
      'server_port' => elem['node_server_port'].get_text.to_s,
      'role'        => elem['node_role'].get_text.to_s,
      'state'       => elem['node_state'].get_text.to_s,
      'partition'   => elem['node_partition'].get_text.to_s,
      'balance'     => elem['node_balance'].get_text.to_s,
      'thread_type' => elem['node_thread_type'].get_text.to_s
    }
    nodestat << [nodekey, node]
  end
  Cluster.new(DefaultIndexServerName, DefaultIndexServerPort, nodestat)
end
new(index_server_hostname, index_server_port, nodes_stat) click to toggle source
# File lib/flare/tools/cluster.rb, line 94
def initialize(index_server_hostname, index_server_port, nodes_stat)
  @index_server_hostname = index_server_hostname
  @index_server_port = index_server_port
  @nodes_stat = nodes_stat
  max_partition = -1
  nodes_stat.each do |nodekey,node_stat|
    p = node_stat[StatPartition].to_i
    max_partition = p if p > max_partition
  end
  @partition = if max_partition >= 0
                 (0..max_partition).map {Hash.new}
               else
                 []
               end
  @partition_size = max_partition+1
  nodes_stat.each do |nodekey,node_stat|
    p = node_stat[StatPartition].to_i
    @partition[p][nodekey] = node_stat if p >= 0
  end
  @nodes = {}
  nodes_stat.each do |k,v|
    @nodes[k] = NodeStat.new(v)
  end
end

Public Instance Methods

has_nodekey?(nodekey) click to toggle source
# File lib/flare/tools/cluster.rb, line 234
def has_nodekey?(nodekey)
  @nodes.has_key? nodekey
end
master_and_slave_nodekeys() click to toggle source
# File lib/flare/tools/cluster.rb, line 209
def master_and_slave_nodekeys
  nodekeys_ {|v| v[Role] == RoleMaster || v[Role] == RoleSlave }
end
master_in_partition(p) click to toggle source
# File lib/flare/tools/cluster.rb, line 171
def master_in_partition(p)
  return nil if partition(p).nil?
  partition(p).inject(nil) {|r,i|
    nodekey, node = i
    if node[Role] == RoleMaster then nodekey else r end
  }
end
master_nodekeys() click to toggle source
# File lib/flare/tools/cluster.rb, line 205
def master_nodekeys
  nodekeys_ {|v| v[Role] == RoleMaster }
end
node_stat(nodekey) click to toggle source
# File lib/flare/tools/cluster.rb, line 213
def node_stat(nodekey)
  @nodes[nodekey]
end
nodekeys() click to toggle source
# File lib/flare/tools/cluster.rb, line 201
def nodekeys
  nodekeys_
end
nodekeys_(&block) click to toggle source
# File lib/flare/tools/cluster.rb, line 184
def nodekeys_(&block)
  unordered = if block.nil?
                @nodes.keys
              else
                ret = []
                @nodes.each do |k,v|
                  ret << k if block.call(v)
                end
                ret
              end
  unordered.sort_by do |i|
    p = @nodes[i].partition
    p = @partition_size if p < 0
    [p, @nodes[i].role, i]
  end
end
partition(p) click to toggle source
# File lib/flare/tools/cluster.rb, line 167
def partition(p)
  @partition[p.to_i]
end
partition_of_nodename(node) click to toggle source

proxy -> -1 not found -> nil

# File lib/flare/tools/cluster.rb, line 227
def partition_of_nodename node
  @nodes.each do |k,v|
    return v[StatPartition].to_i if k == node
  end
  return nil
end
partition_size() click to toggle source
# File lib/flare/tools/cluster.rb, line 221
def partition_size
  @partition_size
end
reconstructable?(nodekey) click to toggle source

check if the partition of a nodekey has at least one active slave

# File lib/flare/tools/cluster.rb, line 120
def reconstructable?(nodekey)
  node = node_stat(nodekey)
  ret = if node[State] == StateActive
          case node[Role]
          when RoleProxy
            false
          when RoleSlave
            true
          when RoleMaster
            # if the partition has at least one active slave, one of the slaves will take over the master.
            slaves_in_partition(node[StatPartition]).inject(false) do |r, slave_nodekey|
              r || node_stat(slave_nodekey)[State] == StateActive
            end
          else
            error "unknown role: #{node[Role]}"
            false
          end
        else
          false
        end
  ret
end
safely_reconstructable?(nodekey) click to toggle source
# File lib/flare/tools/cluster.rb, line 143
def safely_reconstructable?(nodekey)
  node = node_stat(nodekey)
  return false if node[State] != StateActive
  case node[Role]
  when RoleProxy
    false
  when RoleSlave
    slaves_in_partition(node[StatPartition]).inject(false) do |r, slave_nodekey|
      if slave_nodekey != nodekey
        node_stat(slave_nodekey)[State] == StateActive
      else
        r
      end
    end
  when RoleMaster
    count = slaves_in_partition(node[StatPartition]).inject(0) do |r, slave_nodekey|
      if node_stat(slave_nodekey)[State] == StateActive then r+1 else r end
    end
    (count >= 2)
  else
    raise "internal error."
  end
end
serattr_(x) click to toggle source
# File lib/flare/tools/cluster.rb, line 238
def serattr_ x
  return "" if x.nil?
  " class_id=\"#{x['class_id']}\" tracking_level=\"#{x['tracking_level']}\" version=\"#{x['version']}\""
end
serialize(node_map_version = nil) click to toggle source
# File lib/flare/tools/cluster.rb, line 243
      def serialize(node_map_version = nil)
        thread_type = 0

        node_map_id = {"class_id"=>"0", "tracking_level"=>"0", "version"=>"0"}
        item_id = {"class_id"=>"1", "tracking_level"=>"0", "version"=>"0"}
        second_id = {"class_id"=>"2", "tracking_level"=>"0", "version"=>"0"}

        output =<<"EOS"

<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="4">
EOS

        if node_map_version
          output +=<<"EOS"
<version>#{node_map_version}</version>
EOS
        end

        output +=<<"EOS"
<node_map#{serattr_(node_map_id)}>
\t<count>#{@nodes.size}</count>
\t<item_version>0</item_version>
EOS
        @nodes.each do |k,v|
          node_server_name, node_server_port = k.split(':')
          node_role = Roles[v['role']]
          node_state = States[v['state']]
          node_partition = v['partition']
          node_balance = v['balance']
          node_thread_type = v['thread_type'].to_i
          
          output +=<<"EOS"
\t<item#{serattr_(item_id)}>
\t\t<first>#{k}</first>
\t\t<second#{serattr_(second_id)}>
\t\t\t<node_server_name>#{node_server_name}</node_server_name>
\t\t\t<node_server_port>#{node_server_port}</node_server_port>
\t\t\t<node_role>#{node_role}</node_role>
\t\t\t<node_state>#{node_state}</node_state>
\t\t\t<node_partition>#{node_partition}</node_partition>
\t\t\t<node_balance>#{node_balance}</node_balance>
\t\t\t<node_thread_type>#{node_thread_type}</node_thread_type>
\t\t</second>
\t</item>
EOS
          item_id = nil
          second_id  = nil
          thread_type = node_thread_type+1 if node_thread_type >= thread_type
        end
        output +=<<"EOS"
</node_map>
<thread_type>#{thread_type}</thread_type>
</boost_serialization>
EOS
        output
      end
size() click to toggle source
# File lib/flare/tools/cluster.rb, line 217
def size
  @nodes.size
end
slaves_in_partition(p) click to toggle source
# File lib/flare/tools/cluster.rb, line 179
def slaves_in_partition(p)
  return nil if partition(p).nil?
  partition(p).inject([]) {|r,i| if i[1][Role] == RoleSlave then r << i[0] else r end}
end