#!/usr/bin/perl
use IO::File;
use DB_File;
use Fcntl;
use Time::localtime;
use DateTime;
use Time::HiRes qw(gettimeofday);

#####Determine number of cores in system
my $coresdetected = 0;
open(CPUINFO, "/proc/stat") or return undef;
while(<CPUINFO>){
	chomp;
        if(/^cpu\d+/)
        {
		$coresdetected++;
	}
}
close(CPUINFO);

print "CORES detected: $coresdetected\n";

my $coresdetected = --$coresdetected;
#print "decremented: $coresdetected\n";



#creating and/or opening database
tie (%lscpu_db, DB_File, "/tmp/lscpu.db", O_CREAT|O_RDWR, 0644) ||
die ("Cannot create or open /tmp/lscpu.db");

my $num = 0;  
if (exists $lscpu_db{"cpu$num"}) {
        my $var = $lscpu_db{"cpu$num"};
        $num = $var;
        #my $test = $lscpu_db{"cpu$num"};
        print "DB detected started where left off at entry $num\n";
        
        #my $var2 = $lscpu_db{"cpu$var"};
        
        #$var2 =~ /(.{3}\s+.{3}\s+\d{1,2}\s+.{8}\s+\d{4})/;
        #print "Last entry was $var on $1\n";
}else{
        print "place holder key cpu0 does not exist. created!\n";
        $lscpu_db{"cpu0"} = "$num";
}
                        
close database
untie(%lscpu_db);

$num++;
my $i = 1;
my $stupidvar = 0;
my $stupidvar2 = 0;
my %value = ();
my $stop = 1;
        
####### MAIN LOOP  WRITES 10 1MIN ENTRIES TO DB ONCE EVERY 10MIN
do{
	my(%coins) = minutes($coresdetected);
        #my(%coins) = minutes();
        $i = 1;
        
        $stop = 1;

        while ( $stop == 1)
        {
                if (-e "/tmp/lscpulock")
                {
                        $stop = 1;

                        #if lock file exists copy %coins to %value

                        #$value{0} = $value{0} + 10;
                       for ($mycore = 0; $mycore <= $coresdetected; $mycore++)
                       {
				#print "$coins[$core]->[$i]\n";
				for ($i = 10; $i >= 1; $i--)
				{
                                       $stupidvar = $stupidvar2 + 10;
        
                                       $value[$mycore]->[$stupidvar] = $coins[$mycore]->[$i];
                                }
                       }
         
                
                        #let db writing logic know 10 more are going to be added ($backup needs to be made 0 once these are written
                        $stupidvar2 += 10;

                        # 10 were added
                        #$value{"a"} = $value{"a"} + 10;
                        
                        #grab a fresh set
                        my(%coins) = minutes($coresdetected);

                }else{
                        #if lock file does not exist cause while loop to exit and write data to db
                        $stop = 0;
                }
        }
                                
                        
        #create lock file
        open lscpulock, ">/tmp/lscpulock";
        #opening database
        tie (%lscpu_db, DB_File, "/tmp/lscpu.db") ||
        die ("Cannot open /tmp/lscpu.db");
                           
        if ($stupidvar2 > 0)       
        {               
                        
                $i = 1; 
		#$stupidvar2;
                
                while($i <= $stupidvar2) 
                {
                        #$value{$core}{$i} =~ /^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
                        #Wed Feb  4 10:03:37 2009 2026.77 437.45 459.96 459.29 1589.32 10722.93 10722.92 0.01
                        #print "$1";
                        $num = $lscpu_db{"cpu0"};
                        $num++;

                       	for ($mycore = 0; $mycore <= $coresdetected; $mycore++)
                       	{
				
                        	#$lscpu_db{$numcore$mycore} = $value[$mycore]->[$i];
				$lscpu_db[core$mycore]->[$num] = $value[$mycore]->[$i];
			}
			$lscpu_db{"cpu0"} = "$num";
                        $i++;
                }               

                $stupidvar2 = 0;
        }
        
        $i = 1;
        while($i <= 10)
        {
                #$coins[$mycore]->[$i] =~
                #Feb 13 14:03:34 2009 1.20 98.47 0.25 0.00 0.00 0.00 0.03 130.00
                #print "$1";
                $num = $lscpu_db{"cpu0"};
                $num++;
		for ($mycore = 0; $mycore <= $coresdetected; $mycore++)
		{
			$lscpu_db[core$mycore]->[$num] = $coins[$mycore]->[$i];
		}

                #$lscpu_db{"cpu$num"} = "$1";
                $lscpu_db{"cpu0"} = "$num";
                $i++;
        }
                        
        #close database
        untie(%lscpu_db);
        #remove lock file
        close lscpulock;
        unlink "/tmp/lscpulock";
                        
}while(1 == 1);  
######### END MAIN LOOP          


######## GRAB 10min WORTH OF DATA FROM SECONDSARRAY AND PUT IT INTO AN ARRAY
sub minutes{
        my (%coins);
        my $coresdetected = sprintf("%d",$_[0]);
	#my $coresdetected = $_;
        $i = 1; #+ $backup;
        #$stopi = 10 + $backup;
        #print "in minutes sub! (every 10min) \n";
        #my @coins = ("test","test","test");
        do {
                my(%cpuhash2) = secondsarray($coresdetected);
                #print "string returned to minutes: $string\n";
	        for (my $mycore = 0; $mycore <= $coresdetected; $mycore++)
	        {

                	$coins[$mycore]->[$i] = "$cpuhash2{$mycore}";
		}
		#$coins[processes]->[$i] = "$cpuhash2{processes}";
                #print "@coins";
                #print "printed from array: $coins{$i}\n";
                $i++;
        } while ($i<=10);
        return (%coins);
}
####### RETURN ARRAY TO MAIN LOOP


###### POLL CPUINFO EVERY 1 SEC FOR 1 MIN
sub secondsarray{
        my (%cpuhash2);
	my $coresdetected = sprintf("%d",$_[0]);
        #my $coresdetected = $_;
        my $secs = 1;
        my $lastload = 0;
	my $lastproc = 0;
	my $lastidle = 0;
	my $variable1 = 0;
	my %totalhash1 = ();
	my %totalhash2 = ();
	#total = user + nice + system + idle + iowait + irq + softirq
	my $user = 0;
	my $nice = 0;
	my $system = 0;
	my $idle = 0;
	my $iowait = 0;
	my $irq = 0;
	my $softirq = 0;
	#my %cpuhash2 = ();

	#my %hgt_hash;

	#$hgt_hash{'key'} = 6;

	#my $ret_vals = {};

	#$ret_vals->{'hgt'} = {%hgt_hash};

	#give me something from the underlying hash

	#my $val = $ret_vals->{'hgt'}->{'key'};


        #print "in secondsarray sub! (every 1 min) \n";
#my $datetime2 = time();
#print "$datetime2\n";
#sleep(1);
#my $datetime2 = time(); 
#print "$datetime2\n";

#  my $dt = DateTime->new( year   => ,
#                          month  => ,
#                          day    => ,
#                          hour   => ,
#                          minute => ,
#                          second => ,
#                          nanosecond => ,
#                          time_zone  => '',
#                        );


#  use DateTime;
#  use Time::HiRes qw(time);
#  my $dt = DateTime->from_epoch( epoch => time() );
#  print $dt->strftime('%Y-%m-%d %H-%M-%S-%3N'), "\n";

#use Time::HiRes qw(gettimeofday);
#$one = gettimeofday;
#print STDOUT "start = $one\n";
#sleep(1);
#$two = gettimeofday;
#print STDOUT "two = $two\n";

#my $dt = DateTime->millisecond(epoch => time());
#$datetime->millisecond();
#print "DT: $dt\n";
        do {
		#my $datetime = ctime();
		#print "$datetime\n";

                #my $lastmemused = $memused;
		my(%cpuhash1) = cpuinfo($coresdetected);
		my $walltime = $cpuhash1{"wall"};
		my $processes = $cpuhash1{"processes"};
		#print "$walltime\n";
                #my($memsize,$memfree,$buffers,$cached,$memused,$swaptotal,$swapfree,$swapused) = meminfo();
                #my $datetime = ctime();
        
		for (my $mycore = 0; $mycore <= $coresdetected; $mycore++)
		{
			$variable1 = $cpuhash1{$mycore};
			 #print "$core $variable1\n";
			 #$variable1 =~ /^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
			$variable1 =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
			 #cpu0 2138341 99106279 2579616 3297846 14535 9478 15344 0 0
			 #cpu0 2213091 110313189 2611819 3429367 15012 10463 18450 0 0
			 #total = user + nice + system + idle + iowait + irq + softirq
			$total = ($1 + $2 + $3 + $4 + $5 + $6 + $7);
   			#$total = "5000000";
			#print "Total: $total $1 $2 $3 $4 $5 $6 $7\n";
			$user = ($1 / $total) * 100;
			$nice = ($2 / $total) * 100;
			$system = ($3 / $total) * 100;
			$idle = ($4 / $total) * 100;
			$iowait = ($5 / $total) * 100;
			$irq = ($6 / $total) * 100;
			$softirq = ($7 / $total) * 100;
			#$walltime = $;
                	 #print "TEST Core$mycore User: $user\%\n";
                	 #print "TEST Core$mycore Nice: $nice\%\n";
                	 #print "Core$mycore System: $system\%\n";
                	 #print "Core$mycore Idle: $idle\%\n";
                	 #print "Core$mycore IOWait: $iowait\%\n";
                	 #print "Core$mycore Irq: $irq\%\n";
                	 #print "Core$mycore SoftIrq: $softirq\%\n";

			 #$total = $1 + $2 + $3 + $4 + $5 + $6 + $7;
			 #$load = 100 - $idle;
			 #$totalhash1{"$core"} = \%core_seconds;
			#print "TESTING PROCS: $processes\n";
			$totalhash1[$mycore]->[$secs] = "$user $nice $system $idle $iowait $irq $softirq $walltime $processes";
			#print "$totalhash1[$core]->[$secs]\n";
			 #$totalhash1{processes}{$secs} = $cpuhash1{processes};
			 #$totalhash2{$secs} = 
		}


		 #$totalhash2{$secs} 
		 #$hash_r = \%totalhash1{$core};
		
		#$totalhash2{"procs$secs"} = "$processes";

                 #$num++;
                #sleep(1);
                $secs++;
        } while ($secs<=60);
#my $datetime3 = time();
#print "$datetime3\n";

#$two = gettimeofday;
#print STDOUT "End = $two\n";
#my $walltime = $two - $one;
#print STDOUT "time elapsed = $walltime\n";


	$load = 0;
        #$processes = 0;
	#my $datetime = ctime();
	#for ($secs = 1; $secs <= 60; $secs++)
	#{
	#		#for my $key ( keys %totalhash1 ) 
	#		#{
	#			#if ($key eq "processes")				
	#		#{
	#	$processes += $totalhash2{"procs$secs"};
	#			#}
	#		
	 #       #for ($core = 0; $core <= $coresdetected; $core++)
	#	#{
	#	#	$load += $totalhash1{"$core $secs"};
	#	#}
	#	
	#}
	#$processes = $processes / 60;
	#print "1min processes avg: $processes\n";
	#$cpuhash2{"procs"} = "$processes";
	$user = 0;
	$nice = 0;
	$system = 0;
	$idle = 0; 
	$iowait = 0;
	$irq = 0;
	$softirq = 0;
	$walltime = 0;
	#print "TEST123: $core\n";
	#$mycore = 0;
	for (my $mycore = 0; $mycore <= $coresdetected; $mycore++)
        {
		$user = 0;
	        $nice = 0;
        	$system = 0;
       		$idle = 0;
        	$iowait = 0;
        	$irq = 0;
        	$softirq = 0;
        	$walltime = 0;
		$processes = 0;

		print "testing: $mycore\n";
	        for ($secs = 1; $secs <= 60; $secs++)
		{
			 #$totalhash1{"$core $secs"} = "$user $nice $system $idle $iowait $irq $softirq";
			#print "$totalhash1[$core]->[$secs]\n";
			$totalhash1[$mycore]->[$secs] =~ /(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+.*\d*)\s+(\d+)/;
               		$user += $1; #sprintf("%.2f",$1)           #$totalhash1{"$core $secs"};
			$nice += $2; #sprintf("%.2f",$2)			
			$system += $3;
			$idle += $4;
			$iowait += $5;
			$irq += $6;
			$softirq += $7;
			$walltime += $8;
			$processes += $9;

		}
		#$load = sprintf("%.2f", $load / 12);
		$user = sprintf("%.2f", $user / $walltime);
		$nice = sprintf("%.2f", $nice / $walltime);
		$system = sprintf("%.2f", $system / $walltime);
		$idle = sprintf("%.2f", $idle / $walltime);
		$iowait = sprintf("%.2f", $iowait / $walltime);
		$irq = sprintf("%.2f", $irq / $walltime);
		$softirq = sprintf("%.2f", $softirq / $walltime);
		$processes = sprintf("%.2f", $processes / 60);
		#print "Core$core User: $user\%\n";
                #print "Core$core Nice: $nice\%\n";
                #print "Core$core System: $system\%\n";
                #print "Core$core Idle: $idle\%\n";
                #print "Core$core IOWait: $iowait\%\n";		
                #print "Core$core Irq: $irq\%\n";
                #print "Core$core SoftIrq: $softirq\%\n";
		my $datetime = ctime();
		#print "$datetime\n";
		
		$cpuhash2{"$mycore"} = "$datetime $user $nice $system $idle $iowait $irq $softirq $processes";

		#$cpuhash2{"$core"} = "$datetime $load";
		#$cpuhash2{"$core"} =~/.{3}\s+(.{3})\s+(\d{1,2})\s+(\d{1,2}).(\d{1,2}).(\d{1,2})\s+(\d{4})\s+(\d+)\s*/;
		 #print "1min load avg for core$core: $7\%\n";
        }
 	#my $processes = $cpuhash1{"processes"};
	#print "Processes (avg): $processes\n";
	






        #print "in secondsarray sub! (every 1 min) $string\n";
        return (%cpuhash2);   
}
##### RETURN Average Load % per core and Average processes for past min




#total = user + nice + system + idle + iowait + irq + softirq

##### RETRIEVE CPU INFO
sub cpuinfo{
	#my $one = gettimeofday;
	#print STDOUT "Start = $one\n";
	#my $walltime = $two - $one;
	#print STDOUT "time elapsed = $walltime\n";


        my(%cpuhash1);
        my $coresdetected = sprintf("%d",$_[0]);
	#print "CORES detected: $coresdetected\n";
        #my $coresdetected = $_;
	#my $coresdetected = 3;
	my $processes1 = 0;
        open(CPUINFO, "/proc/stat") or return undef;
	my $one = gettimeofday;
        #print "in cpuinfo sub! (every second) \n";
        while(<CPUINFO>){
                chomp;
		#$one = gettimeofday;			
		#need a hash for the transfer of info
		for(my $mycore = 0; $mycore <= $coresdetected; $mycore++)
		{
			#print "$core\n";
			#my $fuckingstupid = "/^cpu$core\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s+/";
                	if(/^cpu$mycore\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s*/)
			{
				#cpu0 2138341 99106279 2579616 3297846 14535 9478 15344 0 0
                        	my $user = sprintf("%d",$1);
                                my $nice = sprintf("%d",$2);
                                my $system = sprintf("%d",$3);
                                my $idle = sprintf("%d",$4);
                                my $iowait = sprintf("%d",$5);
                                my $irq = sprintf("%d",$6);
                                my $softirq = sprintf("%d",$7);
                                #$p = sprintf("%.2f",$1/1024);
			        #for($i = 0; $i <= ; $i++)                    
				#{
                		#	$coins{$i} = $string;  
        			#}
				$string = "$user $nice $system $idle $iowait $irq $softirq";
				#print "in cpuinfo this is string for core$mycore: $string\n";
				$cpuhash1{$mycore} = "$string";
				#print "#1 $string\n";
                	}
			
		}
		
		#if(/^processes\s+(\d+)/){
		#	$processes1 = sprintf("%d",$1);
		#	#print "Processes: $processes\n";
		#	#$cpuhash1{procs} = "$processes";
		#}
        }
        #my $memused = sprintf("%.2f" ,$memsize - $memfree);
        #my $swapused = sprintf("%.2f" ,$swaptotal - $swapfree);
        close(CPUINFO);

	sleep(1);


        open(CPUINFO, "/proc/stat") or return undef;
	my $two = gettimeofday;
        #print "in cpuinfo sub! (every second) \n";
        while(<CPUINFO>){
                chomp;
                                  
                #need a hash for the transfer of info
                for(my $mycore = 0; $mycore <= $coresdetected; $mycore++)
                {
                        #print "$core\n";
                        #my $fuckingstupid = "/^cpu$core\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s+/";
                        if(/^cpu$mycore\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+\d+\s*/)
                        {
                                #cpu0 2138341 99106279 2579616 3297846 14535 9478 15344 0 0
                                my $user = sprintf("%d",$1);
                                my $nice = sprintf("%d",$2);
                                my $system = sprintf("%d",$3);
                                my $idle = sprintf("%d",$4);
                                my $iowait = sprintf("%d",$5);
                                my $irq = sprintf("%d",$6);
                                my $softirq = sprintf("%d",$7);

                                #$string = "$user $nice $system $idle $iowait $irq $softirq";
                                #print "in cpuinfo this is string for core$core: $string\n";
				#print "TEST IDLE: $idle\n";
				
                                $cpuhash1{"$mycore"} =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
				$user = $user - $1;
				$nice = $nice - $2;
				$system = $system - $3;
				$idle = $idle - $4;
				$iowait = $iowait - $5;
				$irq = $irq - $6;
				$softirq = $softirq - $7;
				#print "TEST 1: $4\n";
				#print "TEST 2: $idle\n";
                                my $string2 = "$user $nice $system $idle $iowait $irq $softirq";
				$cpuhash1{$mycore} = $string2;
				#print "#2 $cpuhash1{$core}\n";
                        }
                                
                }
                                
                #if(/^processes\s+(\d+)/){
                #        my $processes = sprintf("%d",$1);   
                #        #print "Processes: $processes\n";
                #        #$cpuhash1{procs} = "$processes";  
                #}
        }
        #my $memused = sprintf("%.2f" ,$memsize - $memfree);
        #my $swapused = sprintf("%.2f" ,$swaptotal - $swapfree);
        close(CPUINFO);
	my $walltime = $two - $one;
	#print "$walltime\n";
	$cpuhash1{"wall"} = $walltime; #"0.000429868698120117"; 


	my $count = 0;
	my $directory = '/proc';
	for my $dir ($directory) 
	{
		opendir DIR, $dir or die "$dir: $!\n";
		#$file =~ m:^\.: or ++$count
		while ($file = readdir DIR)
		{
			if ($file =~ /^\d+/)
			{
				++$count;
			}
		} 
		#while ($file = readdir DIR);

		closedir DIR;
	}
	#print "$count\n";
	$cpuhash1{"processes"} = $count;

	#print "in cpuinfo walltime: $walltime\n";
        return(%cpuhash1);
}
##### RETURN HASH FOR CPU INFO

