<commit_before>module MCollective
    module RPC 
        # Class to wrap all the stats and to keep track of some timings
        class Stats
            attr_reader :noresponsefrom, :starttime, :discoverytime, :blocktime, :responses, :totaltime
            attr_reader :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom, :responsesfrom

            def initialize
                reset
            end

            # Resets stats, if discovery time is set we keep it as it was
            def reset
                @noresponsefrom = []
                @responsesfrom = []
                @responses = 0
                @starttime = Time.now.to_f
                @discoverytime = 0 unless @discoverytime
                @blocktime = 0
                @totaltime = 0
                @discovered = 0
                @discovered_nodes = []
                @okcount = 0
                @failcount = 0
                @noresponsefrom = []
            end
        end

        # returns a hash of our stats
        def to_hash
            {:noresponsefrom   => @noresponsefrom,
             :starttime        => @starttime,
             :discoverytime    => @discoverytime,
             :blocktime        => @blocktime,
             :responses        => @responses,
             :totaltime        => @totaltime,
             :discovered       => @discovered,
             :discovered_nodes => @discovered_nodes,
             :noresponsefrom   => @noresponsefrom,
             :okcount          => @okcount,
             :failcount        => @failcount}
        end

        # Fake hash access to keep things backward compatible
        def [](key)
            to_hash[key]
        end

        # increment the count of ok hosts
        def ok 
            @okcount += 1
        end

        # increment the count of failed hosts
        def fail
            @failcount += 1
        end
        # Re-initializes the object with stats from the basic client
        def client_stats=(stats)
            @noresponsefrom = stats[:noresponsefrom]
            @responses = stats[:responses]
            @starttime = stats[:starttime]
            @blocktime = stats[:blocktime]
            @totaltime = stats[:totaltime]
            @discoverytime = stats[:discoverytime] if @discoverytime == 0
        end

        # Utility to time discovery from :start to :end
        def time_discovery(action)
            if action == :start
                @discovery_start = Time.now.to_f
            elsif action == :end
                @discoverytime = Time.now.to_f - @discovery_start
            else
                raise("Uknown discovery action #{action}")
            end
        end

        # helper to time block execution time
        def time_block_execution(action)
            if action == :start
                @block_start = Time.now.to_f
            elsif action == :end
                @blocktime += @block_start - Time.now.to_f
            else
                raise("Uknown block action #{action}")
            end
        end

        # Update discovered and discovered_nodes based on 
        # discovery results
        def discovered_agents(agents)
            @discovered_nodes = agents
            @discovered = agents.size
        end

        # Helper to calculate total time etc
        def finish_request
            @totaltime = @blocktime + @discoverytime

            # figures out who we had no responses from
            dhosts = @discovered_nodes.clone
            @responsesfrom.each {|r| dhosts.delete(r)}
            @noresponsefrom = dhosts
        end

        # Helper to keep track of who we received responses from
        def node_responded(node)
            @responsesfrom << node
        end

        # Returns a blob of text representing the request status based on the 
        # stats contained in this class<commit_msg>Add exception handling to the Stats class wherever it gets external calls to keep it sane if clients do weird things<commit_after>module MCollective
    module RPC 
        # Class to wrap all the stats and to keep track of some timings
        class Stats
            attr_reader :noresponsefrom, :starttime, :discoverytime, :blocktime, :responses, :totaltime
            attr_reader :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom, :responsesfrom

            def initialize
                reset
            end

            # Resets stats, if discovery time is set we keep it as it was
            def reset
                @noresponsefrom = []
                @responsesfrom = []
                @responses = 0
                @starttime = Time.now.to_f
                @discoverytime = 0 unless @discoverytime
                @blocktime = 0
                @totaltime = 0
                @discovered = 0
                @discovered_nodes = []
                @okcount = 0
                @failcount = 0
                @noresponsefrom = []
            end
        end

        # returns a hash of our stats
        def to_hash
            {:noresponsefrom   => @noresponsefrom,
             :starttime        => @starttime,
             :discoverytime    => @discoverytime,
             :blocktime        => @blocktime,
             :responses        => @responses,
             :totaltime        => @totaltime,
             :discovered       => @discovered,
             :discovered_nodes => @discovered_nodes,
             :noresponsefrom   => @noresponsefrom,
             :okcount          => @okcount,
             :failcount        => @failcount}
        end

        # Fake hash access to keep things backward compatible
        def [](key)
            to_hash[key]
        rescue
             nil
        end

        # increment the count of ok hosts
        def ok 
            @okcount += 1
        rescue
            @okcount = 1
        end

        # increment the count of failed hosts
        def fail
            @failcount += 1
        rescue
            @failcount = 1
        end

        # Re-initializes the object with stats from the basic client
        def client_stats=(stats)
            @noresponsefrom = stats[:noresponsefrom]
            @responses = stats[:responses]
            @starttime = stats[:starttime]
            @blocktime = stats[:blocktime]
            @totaltime = stats[:totaltime]
            @discoverytime = stats[:discoverytime] if @discoverytime == 0
        end

        # Utility to time discovery from :start to :end
        def time_discovery(action)
            if action == :start
                @discovery_start = Time.now.to_f
            elsif action == :end
                @discoverytime = Time.now.to_f - @discovery_start
            else
                raise("Uknown discovery action #{action}")
            end
        rescue
            @discoverytime = 0
        end

        # helper to time block execution time
        def time_block_execution(action)
            if action == :start
                @block_start = Time.now.to_f
            elsif action == :end
                @blocktime += @block_start - Time.now.to_f
            else
                raise("Uknown block action #{action}")
            end
        rescue
            @blocktime = 0
        end

        # Update discovered and discovered_nodes based on 
        # discovery results
        def discovered_agents(agents)
            @discovered_nodes = agents
            @discovered = agents.size
        end

        # Helper to calculate total time etc
        def finish_request
            @totaltime = @blocktime + @discoverytime

            # figures out who we had no responses from
            dhosts = @discovered_nodes.clone
            @responsesfrom.each {|r| dhosts.delete(r)}
            @noresponsefrom = dhosts
        rescue
            @totaltime = 0
            @noresponsefrom = []
        end

        # Helper to keep track of who we received responses from
        def node_responded(node)
            @responsesfrom << node
        rescue
            @responsesfrom = [node]
        end

        # Returns a blob of text representing the request status based on the 
        # stats contained in this class
{'fraction_non_alphanumeric': 0.06733594515181195, 'fraction_numerical': 0.0030607247796278158, 'mean_word_length': 1.4326980345443716, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '897865', 'n_tokens_mistral': 2087, 'n_tokens_neox': 1954, 'n_words': 632}