#!/usr/bin/perl -w

use strict;
use warnings;
use Time::ParseDate;
use File::Basename;
use Cwd qw(abs_path);

# set current path of this command
my $curpath = dirname(Cwd::abs_path(__FILE__));

my $CONFFILE = "/etc/osw2csv.conf";
if (-f "$curpath/".basename($CONFFILE)) {
	require "$curpath/".basename($CONFFILE);
} elsif (-f $CONFFILE) {
	require $CONFFILE;
}

require "$curpath/osw2csv_functions";


unless (-p STDIN) {
	print STDERR <<"END_OF_USAGE";
usage:	# cat iostatfile | $0 > csvfile.csv
description:
	This script generate csv file, which is from "iostat" output provided
	by OSWatcher or ExaWatcher.
	the iostat output is read from STDIN, and cvs is provided onto STDOUT.
END_OF_USAGE
	exit 1;
}


# belows are defined in $COMMONFUNCTIONS
our $sys_bootsecond ;  # set by $zzz_second and the 1st "top -" line.
our $zzz_second;  # set by "zzz ... " line. 0 means "there are no zzz line"

my @devices = ();  # devices which is shown in the *top of* the iostat file


# setLinuxLine() ... set $zzz_second by analyzing "Linux uname (host) date"
sub setDateInLinuxLine {
	my $line = $_[0];
	return if ($line !~ /^Linux\s+\S+/);

	my ($sec, $min, $hour,,,,,) = localtime($zzz_second);
	$_ = $line;
	my ($nowmon,$nowday,$nowyear) = /^Linux\s+\S+\s+\(\S+\)\s+(\d+)\/(\d+)\/(\d+)/;
	# check if the year is 2 digits, 99 -> 1999, 02 -> 2002
	$nowyear += 1900 if (70 <= $nowyear && $nowyear <= 99); 
	$nowyear += 2000 if (00 <= $nowyear && $nowyear < 70); 
	
	my $newdatestr = sprintf("%04d/%02d/%02d %02d:%02d:%02d",
			 $nowyear, $nowmon, $nowday, $hour, $min, $sec);
	my ($newsec, $err) = getSecondsFromDateString($newdatestr);
	if (!$newsec) {
		warning("Warning: date in 'Linux' line cannott be parsed:",
			"  Line : $line",
			"  Error: $err");
	} else {
		$zzz_second = $newsec;
	}
}


sub printIostatCSVBody {
	my $header_printed = 0; # T/F: whether header colmun has been printed
	my @header_entries = (); # entires by spliting "Device:" line

	# read/check the first line
	return if (!defined($_ = readNextLineFromSTDIN()));
	while (defined($_)) {
		# set current time if there is "zzz" or time line
		if (setZZZLine($_) || setZZZByTimeLine($_)) {
			$_ = readNextLineFromSTDIN();
			next;
		}
		# set current date if there is "Linux uname (name) date" line
		if (/^Linux\s+\d+\.\d+/) {
			setDateInLinuxLine($_);
			$_ = readNextLineFromSTDIN();
			next;
		}

		# ignore if the line is not /^Device:/
		if ($_ !~ /^Device:/) {
			$_ = readNextLineFromSTDIN();
			next;
		}
		# analyze "Device:" line for printing headers
		if (!$header_printed) {
			@header_entries = split(/\s+/);
			shift(@header_entries); # remove "Device:"
		}
		$_ = readNextLineFromSTDIN();

		my (@datalist, @devices);
		# process each device line, fill @datalist and @devices
		# CONSIDER: Is it better to loop here until "zzz" comes?
		while (defined($_) && $_ =~ /^(sd|md|hd|dm-|loop|xvd|cciss|nvme|vd|drbd)/) {
			my @data = split(/\s+/, $_);
			push(@devices, shift(@data));
			if ($#data < 0) {
				# for case "cciss/c0d0p1 \n  dat dat dat..."
				$_ = readNextLineFromSTDIN();
				s/^\s*(.*)\s*$/$1/;
				@data = split(/\s+/, $_);
			}
			push(@datalist, join(',', @data));
			$_ = readNextLineFromSTDIN();
		}

		# print header if necessary
		if (!$header_printed) {
			my @ary = ("Time","Timezone");
			foreach my $device (@devices) {
				foreach my $entry (@header_entries) {
					push(@ary, "$device $entry");
				}
			}
			print join(',', @ary)."\n";
			$header_printed = 1;
		}

		# print the data lines
		print getDateStringFromSeconds($zzz_second).",$ENV{TZ},";
		my @ary = ();
		foreach my $data (@datalist) {
			push(@ary, $data);
		}
		print join(',',@ary)."\n";
	}
}

printIostatCSVBody;
exit 0;


