#!/usr/bin/ruby

require 'optparse'
require 'ostruct'

$cfield = "kernel"
$cfield_hash = Hash.new
$cfield_array = Array.new
$cases = Hash.new

opts = OptionParser.new do |opts|
        opts.banner = "Usage: compare.rb [options] cases..."

        opts.separator ""
        opts.separator "options:"

        opts.on("-c FIELD", "--compare FIELD", "compare FIELD: fs/kernel/nr/thresh") do |field|
                $cfield = field
		# puts "#{$cfield}\n"
        end
       
        opts.on_tail("-h", "--help", "Show this message") do
                puts opts
                exit
        end

end

opts.parse!(ARGV)

# http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html
def roundUpToNextPowerOfTwo(x)
	x -= 1
	x |= x >> 1;  # handle  2 bit numbers
	x |= x >> 2;  # handle  4 bit numbers
	x |= x >> 4;  # handle  8 bit numbers
	x |= x >> 8;  # handle 16 bit numbers
	x |= x >> 16; # handle 32 bit numbers
	x += 1
	return x;
end

def add_dd(path)
	# nfs-10dd-1M-1p-32069M-20:10-3.1.0-rc4+
	# written = system("grep nr_written #{path}/vmstat-end")
	# written = written[11..-1]
	return if ! File.exist?("#{path}/vmstat-end")
	vmstat = File.new("#{path}/vmstat-end").readlines
	written = 0
	vmstat.grep(/nr_written (\d+)/) { written = $1.to_i }
	# File.open("#{path}/vmstat-end").each_line do |line|
	# 	if line =~ /nr_written (\d+)/
	# 		written = $1.to_i
	# 		break
	# 	end
	# end
	prefix = ""
	if path =~ /(.*\/)(.*)/
		prefix = $1
		path = $2
	end
	path =~ /([a-z0-9]+)-([0-9]+dd)-(\d+[kM])-(\d+p)-(\d+M)-([0-9M]+):([0-9M]+)-(.*)/;
	all, fs, dd, bs, cpu, mem, thresh, bg_thresh, kernel = *$~
	m = roundUpToNextPowerOfTwo(mem.to_i)
	mem = "#{m}M"
	ckey = ""
	eval "ckey = #{$cfield}; #{$cfield} = 'X'"
	$cfield_array.push(ckey) if !$cfield_hash.has_key?(ckey)
	$cfield_hash[ckey] = 1
	key = "#{prefix}#{fs}-#{dd}-#{bs}-#{cpu}-#{mem}-#{thresh}:#{bg_thresh}-#{kernel}"
	if !$cases.has_key?(key)
		$cases[key] = { ckey => written }
	else
		$cases[key][ckey] = written
	end
	# puts path
	# print "#{fs}-#{dd}-#{mem}-#{written}\n"
end

ARGV.each { |path|
	add_dd path
}

$cfield_array.each { |ckey|
	printf "%24s  ", ckey
}
puts
$cfield_array.each {
	printf "------------------------  "
}
puts
$cases.sort.each { |key, value|
	n = 0
	$cfield_hash.each_key { |ckey|
		n += 1 if $cases[key][ckey]
	}
	next if n < 2
	$cfield_array.each_index { |i|
		ckey = $cfield_array[i]
		written = $cases[key][ckey] || 0
		written0 = $cases[key][$cfield_array[0]] || 0
		if i == 0 || written == 0 || written0 == 0
			printf "%24d  ", written
		else
			printf "%+10.1f%% %12d  ", 100.0 * (written - written0) / written0, written
		end
	}
	printf "%s\n", key
}
