lib/roma/command/rt_command_receiver.rb

Summary

Maintainability
B
6 hrs
Test Coverage

module Roma
  module Command

    module RoutingCommandReceiver

      # join <node id>
      def ev_join(s)
        @rttable.add_node(s[1])
        send_data("ADDED\r\n")
      end

      # leave <node id>
      def ev_leave(s)
        @log.warn("receive a leave #{s[1]} message.")
        @rttable.leave(s[1])
        send_data("DELETED\r\n")
      end

      def ev_nodelist(s)
        nl = nil
        @rttable.nodes.each{ |nid|
          if nl
            nl << " #{nid}"
          else
            nl = nid.clone
          end
        }
        send_data("#{nl}\r\n")
      end

      def ev_create_nodes_from_v_idx(s)
        @rttable.create_nodes_from_v_idx
        send_data("CREATED\r\n")
      end

      # routingdump [yaml|json|yamlbytes|bin]\r\n
      def ev_routingdump(s)
        rt = @rttable
        rd = @rttable.sub_nid_rd(@addr)
        rt = Roma::Routing::RoutingTable.new(rd) if rd

        if s.length == 1
          dmp = rt.dump
          send_data("#{dmp.length}\r\n#{dmp}\r\nEND\r\n")
        elsif s[1] == 'yaml'
          dmp = rt.dump_yaml
          send_data("#{dmp}\r\nEND\r\n")
        elsif s[1] == 'json'
          dmp = rt.dump_json
          send_data("#{dmp}\r\nEND\r\n")
        elsif s[1] == 'yamlbytes'
          dmp = rt.dump_yaml
          send_data("#{dmp.length + 7}\r\nEND\r\n")
        elsif s[1] == 'bin'
          dmp = rt.dump_binary
          send_data("#{dmp.length}\r\n#{dmp}\r\nEND\r\n")
        else
          send_data("CLIENT_ERROR\r\n")
        end
      end

      def ev_enabled_repetition_in_routing?(s)
        rt = @rttable
        rd = @rttable.sub_nid_rd(@addr)
        rt = Roma::Routing::RoutingTable.new(rd) if rd

        if s.length == 1
          repetition = rt.check_repetition_in_routing
          send_data("#{repetition}\r\n")
        else
          send_data("CLIENT_ERROR\r\n")
        end
      end

      # setroute <vnode-id> <clock> <node-id> ...
      def ev_setroute(s)
        if s.length < 4
          send_data("CLIENT_ERROR\r\n")
        else
          nids=[]
          s[3..-1].each{ |nid| nids << nid }
          # check irregular node name
          nids.each{ |nid|
            if !nid.ascii_only? || nid.empty?
              send_data("CLIENT_ERROR : irregular node name was input.[\"#{nid}\"]\r\n")
              return
            end
          }
          res=@rttable.set_route(s[1].to_i, s[2].to_i, nids)
          if res.is_a?(Integer)
            send_data("STORED\r\n")
          else
            send_data("SERVER_ERROR #{res}\r\n")
          end
        end
      end

      # getroute <vnode-id>
      def ev_getroute(s)
        if s.length < 2
          send_data("CLIENT_ERROR\r\n")
          return
        end
        clk,nids = @rttable.search_nodes_with_clk(s[1].to_i)
        if clk == nil
          send_data("END\r\n")
          return
        end
        res = "#{clk-1}"
        nids.each{ |nid| res << " #{nid}" }
        send_data("#{res}\r\n")
      end

      # mklhash <id>
      def ev_mklhash(s)
        send_data("#{@rttable.mtree.get(s[1])}\r\n")
      end

      # history_of_lost [yyyymmddhhmmss]
      def ev_history_of_lost(s)
        if s.length != 2
          t = Time.mktime(2000, 1, 1, 0, 0, 0)
        else
          t = Time.mktime(s[1][0..3], s[1][4..5], s[1][6..7], s[1][8..9], s[1][10..11], s[1][12..13])
        end
        nodes = @rttable.search_lost_vnodes(t)
        nodes.each{|vn| send_data("#{vn}\r\n") }
        send_data("END\r\n")
      rescue =>e
        send_data("CLIENT_ERROR\r\n")
      end

      # set_auto_recover [true|false] <sec>
      def ev_set_auto_recover(s)
        #check argument
        if /^true$|^false$/ !~ s[1]
          return send_data("CLIENT_ERROR arguments must be true or false\r\n")
        elsif s.length != 2 && s.length != 3
          return send_data("CLIENT_ERROR number of arguments(0 for 1)\r\n")
        elsif s.length == 3 && s[2].to_i < 1
          return send_data("CLIENT_ERROR length must be greater than zero\r\n")
        end
        res = broadcast_cmd("rset_auto_recover #{s[1]} #{s[2]}\r\n")
        if s[1] == "true"
          @rttable.auto_recover = true
        elsif s[1] == "false"
          @rttable.auto_recover = false
        end
        @rttable.auto_recover_status = "waiting"
        @rttable.auto_recover_time = s[2].to_i if s[2]
        res[@stats.ap_str] = "STORED"
        send_data("#{res}\r\n")
      end

      def ev_rset_auto_recover(s)
        if /^true$|^false$/ !~ s[1]
          return send_data("CLIENT_ERROR arguments must be true or false #{s[1]} #{s[1].class} \r\n")
        elsif s.length != 2 && s.length != 3
          return send_data("CLIENT_ERROR number of arguments(0 for 1)\r\n")
        elsif s.length == 3 && s[2].to_i < 1
          return send_data("CLIENT_ERROR length must be greater than zero\r\n")
        end
        if s[1] == "true"
          @rttable.auto_recover = true
        elsif s[1] == "false"
          @rttable.auto_recover = false
        end
        @rttable.auto_recover_status = "waiting"
        @rttable.auto_recover_time = s[2].to_i if s[2]
        send_data("STORED\r\n")
      end

      # set_lost_action [auto_assign|shutdown]
      def ev_set_lost_action(s)
        if s.length != 2 || /^auto_assign$|^shutdown$/ !~ s[1]
          return send_data("CLIENT_ERROR changing lost_action must be auto_assign or shutdown\r\n")
        elsif /^auto_assign$|^shutdown$/ !~ @rttable.lost_action
          return send_data("CLIENT_ERROR can use this command only current lost action is auto_assign or shutdwn mode\r\n")
        end
        res = broadcast_cmd("rset_lost_action #{s[1]}\r\n")
        @rttable.lost_action = s[1].to_sym
        res[@stats.ap_str] = "STORED"
        send_data("#{res}\r\n")
      end
      
      def ev_rset_lost_action(s)
        if s.length != 2 || /^auto_assign$|^shutdown$/ !~ s[1]
          return send_data("CLIENT_ERROR changing lost_action must be auto_assign or shutdown\r\n")
        elsif /^auto_assign$|^shutdown$/ !~ @rttable.lost_action
          return send_data("CLIENT_ERROR can use this command only current lost action is auto_assign or shutdwn mode\r\n")
        end
        @rttable.lost_action = s[1].to_sym
        send_data("STORED\r\n")
      end  

      # set_threshold_for_failover <n>
      def ev_set_threshold_for_failover(s)
        if s.length != 2 || s[1].to_i == 0
          return send_data("usage:set_threshold_for_failover <n>\r\n")
        end
        res = broadcast_cmd("rset_threshold_for_failover #{s[1]}\r\n")
        @rttable.fail_cnt_threshold = s[1].to_i
        res[@stats.ap_str] = "STORED"
        send_data("#{res}\r\n")
      end

      # rset_threshold_for_failover <n>
      def ev_rset_threshold_for_failover(s)
        if s.length != 2 || s[1].to_i == 0
          return send_data("usage:set_threshold_for_failover <n>\r\n")
        end
        @rttable.fail_cnt_threshold = s[1].to_i
        send_data("STORED\r\n")
      end

      # set_gap_for_failover
      def ev_set_gap_for_failover(s)
        if s.length != 2
          return send_data("usage:set_gap_for_failover <n>\r\n")
        end
        res = broadcast_cmd("rset_gap_for_failover #{s[1]}\r\n")
        @rttable.fail_cnt_gap = s[1].to_f
        res[@stats.ap_str] = "STORED"
        send_data("#{res}\r\n")        
      end

      # rset_gap_for_failover
      def ev_rset_gap_for_failover(s)
        if s.length != 2
          return send_data("usage:rset_gap_for_failover <n>\r\n")
        end
        @rttable.fail_cnt_gap = s[1].to_f
        send_data("STORED\r\n")        
      end

      # cleat RTTABLE_SUB_NID map
      def ev_clear_rttable_sub_nid(s)
        res = broadcast_cmd("rclear_rttable_sub_nid\r\n")
        @rttable.sub_nid.clear()
        res[@stats.ap_str] = "CLEARED"
        send_data("#{res}\r\n")
      end

      def ev_rclear_rttable_sub_nid(s)
        @rttable.sub_nid.clear()
        send_data("CLEARED\r\n")
      end
      
      # add_rttable_sub_nid <netmask> <regexp> <replace>
      def ev_add_rttable_sub_nid(s)
        if s.length != 4
          return send_data("usage:add_rttable_sub_nid <netmask> <regexp> <replace>\r\n")
        end
        res = broadcast_cmd("radd_rttable_sub_nid #{s[1]} #{s[2]} #{s[3]}\r\n")
        @rttable.sub_nid[s[1]] = {:regexp => "#{s[2]}", :replace => "#{s[3]}"}
        res[@stats.ap_str] = "ADDED"
        send_data("#{res}\r\n")
      end

      # radd_rttable_sub_nid <netmask> <regexp> <replace>
      def ev_radd_rttable_sub_nid(s)
        if s.length != 4
          return send_data("usage:add_rttable_sub_nid <netmask> <regexp> <replace>\r\n")
        end
        @rttable.sub_nid[s[1]] = {:regexp => "#{s[2]}", :replace => "#{s[3]}"}
        send_data("ADDED\r\n")
      end

      # delete_rttable_sub_nid <netmask>
      def ev_delete_rttable_sub_nid(s)
        if s.length != 2
          return send_data("usage:delete_rttable_sub_nid <netmask>\r\n")
        end

        res = broadcast_cmd("rdelete_rttable_sub_nid #{s[1]}\r\n")
        unless @rttable.sub_nid.delete s[1]
          res[@stats.ap_str] = "NOT_FOUND"
        else
          res[@stats.ap_str] = "DELETED"
        end
        send_data("#{res}\r\n")
      end

      # rdelete_rttable_sub_nid <netmask>
      def ev_rdelete_rttable_sub_nid(s)
        if s.length != 2
          return send_data("usage:delete_rttable_sub_nid <netmask>\r\n")
        end

        unless @rttable.sub_nid.delete s[1]
          send_data("NOT_FOUND\r\n")
        else
          send_data("DELETED\r\n")
        end
      end

      # get_key_info <key>
      def ev_get_key_info(s)
        if s.length != 2
          return send_data("CLIENT_ERROR number of arguments(0 for 1)\r\n")
        end

        d = Digest::SHA1.hexdigest(s[1]).hex % @rttable.hbits
        vn = @rttable.get_vnode_id(d)
        nodes = @rttable.search_nodes_for_write(vn)
        send_data(sprintf("d = %s 0x%x\r\n",d,d))
        send_data(sprintf("vn = %s 0x%x\r\n",vn,vn))
        send_data("nodes = #{nodes.inspect}\r\n")
        send_data("END\r\n")
      end

    end # module RoutingCommandReceiver
  end # module Command
end # module Roma