/*  
    lsnet is a light weight computer resource/stats monitor.
    Copyright (C) 2009  sterling pickens

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include  <sys/types.h>
#include <dirent.h>
#include "cores.h"
#include "processes.h"
#include "cpuinfo.h"
#include "frequency.h"
#include "meminfo.h"
#include "netinfo.h"
#include "errors.h"

//int maxtextbuffer = sizeof(char)*250;
//#define SIZE sizeof(char)*250
#define SIZE 255

int count, count2, count3;
char *cpu = "cpu";
char *mem = "mem";
char *net = "net";

double cpuarray1[3][64][10];
double minutearray[61][64][9];
double minutearray2[64][9];
double walltime[61];
//double tenminutearray[64][9][10];

int memarray1[9];
int memarray2[61][9];
int memtenarray2[11][9];

double netarray1[2][9];
double netarray2[4];

int pid;

void title() {
        printf("\tlsnet is a product of the linuxsociety team and licensed under GPLv3\n");
        printf("\tThis is version 0.3.6 dated 12/03/2009\n");
        printf("\n");
return;  
}

void usage() {
        printf("Usage: lsnet -[option]\n");
        printf("Options:\n");
        printf("        -h: display this help menu\n");  
        printf("        -a: run all monitors\n");
	printf("        -s: stop all monitors\n");
        printf("        -1: run cpu monitor only\n");
        printf("        -2: run mem monitor only\n");
        printf("        -3: run net monitor only\n");
        printf("\n");           
}

 //runall(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime,  memfrequency, memarray1, memarray2, memtenarray2, netfrequency, netarray1, netarray2);
 


int runall(int cores, int cpufrequency, double cpuarray1[3][64][10], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61], 
	int memfrequency, int memarray1[9], int memarray2[61][9], int memtenarray2[11][9], int netfrequency, double netarray1[2][9], double netarray2[4]) 
{
        title();

	pid = fork();
	if (pid == 0) 
        	cputenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
     	else 
        	pid = fork();
		if (pid == 0)
			memtenminute(memfrequency, memarray1, memarray2, memtenarray2);
		else
			pid = fork();
			if (pid == 0)
				netenminute(netfrequency, netarray1, netarray2);
			else

	//tenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
        //int processes2 = processes();
        printf( "\n\tMonitor daemons started.\t\n");

        return 0;  
}



int main(int argc, char **argv) {
        int cpufrequency = frequency(cpu);
        //cpufrequency = atoi(cpufrequency);
	int memfrequency = frequency(mem);
	//memfrequency = atoi(memfrequency);
        int netfrequency = frequency(net);
        //netfrequency = atoi(netfrequency);

        int cores = coresdetected();
        int count4;
        int o;
        while((o=getopt(argc, argv, "ha123s")) != EOF) {
                switch(o) {
                        case 'h':
				title();
                                usage();
                                exit(1);
                                break;
                        case 'a':
				clockskew();
				cpulock();
				memlock();
				netlock();
				runall(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime, memfrequency, memarray1, memarray2, memtenarray2, netfrequency, netarray1, netarray2);
				//printf("\n\n\tRuntime error!\n");
                                
                                exit(1);
                                break;
                        case '1':
                                title();
				clockskew();
				cpulock();
			        pid = fork();
				if (pid == 0)
                			cputenminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
        			else
                                printf("\n\n\tCpu Daemon Started.\n");
                                exit(1);
                                break;
                        case '2':
                                title();
				clockskew();
				memlock();
				pid = fork();
				if (pid == 0)
					memtenminute(memfrequency, memarray1, memarray2, memtenarray2);
				else
                                printf("\n\n\tMem Daemon Started.\n");
                                exit(1);
                                break;
                        case '3':
                                title();
				clockskew();
				netlock();
				pid = fork();
				if (pid == 0)
					netenminute(netfrequency, netarray1, netarray2);
				else 
                                printf("\n\n\tNet Daemon Started.\n");
                                exit(1);
                                break;
			case 's':
				system("rm /var/lib/lsnet/*lock");
				system("killall -9 lsnetd");
				printf("\n\n\tDaemons Stopped.\n");
				exit(1);
				break;
                       default:
                                break;   
                        }
        }
        while(optind) {
                title();
                usage();
                printf("\nError: No run options specified!\n\n");
                exit(1);
        }
return 0;
}
                                

int memtenminute(int memfrequency, int memarray1[9], int memarray2[61][9], int memtenarray2[11][9]){
	struct tm *local;
	time_t t;

	char *token;
	char *line;
	char *search = "X";

	int i,whatever,count1,count2;
	local = localtime(&t);

        char singlentrystr[20];
	char datestr[30];
	char bigstr[ (  ( sizeof(datestr)*10 ) + (sizeof(singlentrystr)*8) * 10) + 100];
        int emptyvarstr;

	int var1 = 0; 
	int var2 = 0;
        FILE* fp;
	int poll = 60 / memfrequency;
	while (1 == 1)
	{	
		//memset( (void *) minutearray2, '\0', sizeof(double) * 64 * 9);
		//memset ((void*) memarray2, '\0', sizeof (memarray2) * 9);
		memset ((void*) bigstr, '\0', sizeof (bigstr));
		memset ((void*) memtenarray2, '\0', sizeof (int) * 11 * 9);

		//memset ((void*) datestr, '\0', sizeof (datestr));		
		//memset ((void*) bigstr, '\0', sizeof (bigstr));
		for(i = 1; i <= 10; i++)
		{
			memset ((void*) singlentrystr, '\0', sizeof (singlentrystr));
			memset ((void*) datestr, '\0', sizeof (datestr));
			//memset ((void*) memarray2, '\0', sizeof(int) * 60 * 9);		
			//printf("calling meminfo\n");
			memoneminute(memfrequency, memarray1, memarray2);
			//printf("finished min %d\n", i);
			t = time(NULL);
			local = localtime(&t);
                        strcat(datestr, asctime(local));
			datestr[strlen(datestr)-1]='\0';

			strcat (bigstr, datestr);
			strcat (bigstr, " ");
			//printf("datestr: %s\n", datestr);
			var1 = 0;
			var2 = 0;
			for (count1 = 1; count1 <= poll; count1++)
			{
				//printf("memarray2 %d %d: %d\n",count1, count2, memarray2[count1][5] );

				//var1 = 0;
				//var2 = 0;
				var1 = memarray2[count1][5];
				var2 = memtenarray2[i][5];
				//printf("var1: %d\n", var1 );
				//printf("var2: %d\n", var2);
				for (count2 = 1; count2 <= 8; count2++)
				{
					//printf("memarray2 %d %d: %d\n",count1, count2, memarray2[count1][count2] );
					if (var1 > var2){
						memtenarray2[i][count2] = memarray2[count1][count2];
					}
						//printf("wrote: %d\n", memtenarray2[i][count2]); 
						//only save the polling interval variables with the highest memused instance
				
				}
			

			}

			//printf("out of 3 loops!\n");
			for (count2 = 1; count2 <= 8; count2++)
			{	// add variables onto date
				if (count2 != 1)
				{
					emptyvarstr = sprintf( singlentrystr, " %d", memtenarray2[i][count2]);
				}else{
					emptyvarstr = sprintf( singlentrystr, "%d", memtenarray2[i][count2]);
					//printf("memtenarray: %d\n",memtenarray2[i][count2]);
					//printf("singlentrystr: %s\n",singlentrystr);
				}
				strcat (bigstr, singlentrystr);
				//memset ((void*) singlentrystr, '\0', sizeof (singlentrystr));
			}
			//add an X to the end of bullshit for splitting later
			if (i != 10)
			{
				strcat (bigstr, "X");
			}
			//printf("bigstr: %s\n", bigstr);
			//memset ((void*) memarray2, '\0', sizeof (memarray2));
		}
			//printf("finished 10min\n");

		//int memtotal, memfree, buffers, cached, memused, swaptotal, swapfree, swapused;
		//Sun Feb 22 22:20:13 2009 2026.77 379.44 713.68 238.45 1647.33 10722.93 10563.75 159.18
	
		if (fp = fopen("/var/lib/lsnet/lsmem.log", "a"))
		{

			//printf("10min up bigstr: %s\n", bigstr);
			//fclose( fp );
			//exit(1);
			//line = bullshit;
			token = strtok(bigstr, search);
			for (count1 = 1; count1 <= 10; count1++)
			{
				//line = bullshit;
				//token = strtok(line, search);
				fprintf(fp, "%s\n", token );
				//printf("%s\n", token);
				token = strtok(NULL, search);
				//fprintf(fp, "%s\n", token );
				//token = strtok(NULL, search);
				//fprintf(fp, "%s\n", token );
			}



		}

		fclose( fp );
	}

	return 0;
}




int cputenminute(int cores, int cpufrequency, double cpuarray1[2][4][8], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61]) 
{
	struct tm *local;
	time_t t;
	int i,whatever,count2,count3;
	local = localtime(&t);

        char processtr[(sizeof(double) + 1)];
	int processnum;
	char singlentrystr[sizeof(double) + 1];
	char onemincpustr[((10*cores*8)+cores)];
	char datestr[( (sizeof(char) * 30) + sizeof(processtr) + sizeof(onemincpustr) + 2)];
	char bigstr[((10 * sizeof(datestr)) + 10)];

        int emptyreturnvar;
        char *token;
        char *line;
        char *search = "X";



	//printf("bullshit: %d\n", cpufrequency);
	FILE* fp;
	while (1 == 1)
	{
			memset ((void*) bigstr, '\0', sizeof (bigstr));
			//memset ((void*) datestr, '\0', sizeof (datestr));
        		for(i = 1; i <= 10; i++)
        		{
				memset ((void*) processtr, '\0', sizeof (processtr));
				memset ((void*) onemincpustr, '\0', sizeof (onemincpustr));
				memset ((void*) datestr, '\0', sizeof (datestr));
				//memset ((void*) whatever2, '\0', sizeof (whatever2));
				cpuoneminute(cores, cpufrequency, cpuarray1, minutearray, minutearray2, walltime);
				t = time(NULL);
				//local = localtime(&t);
				//local = gmtime(&t);
				local = localtime(&t);
				strcat(datestr, asctime(local));
				datestr[strlen(datestr)-1]='\0';
				processnum = processes();
				//printf ("processes: %d\n", processnum);
				//exit (1);
				emptyreturnvar = sprintf( processtr, "%d", processnum);
				//strcat(datestr, processstr);
				//printf("\nProcesstr: %s\n", processtr);
				strcat(datestr, " ");
				strcat(datestr, processtr);
				strcat(datestr, " ");
                		for (count2 = 1; count2 <= cores; count2++)
                		{
					if(count2 != 1){
						strcat(onemincpustr, "+");
        				}
                        		for (count3 = 1; count3 < 8; count3++)
                        		{   
						if(count3 == 1){
							emptyreturnvar = sprintf( singlentrystr, "%lf", minutearray2[count2][count3]);
						}else{
                                		emptyreturnvar = sprintf( singlentrystr, " %lf", minutearray2[count2][count3]);
						}
        					strcat(onemincpustr, singlentrystr);
                        		}
					//strcat(onemincpustr, "+");
				}
				//printf("completed first minute: %s\n", );
				//strcat(datestr, processtr);
				//strcat(datestr, " ");
				strcat(datestr, onemincpustr);
				strcat(bigstr, datestr);
				if (i != 10){
					strcat(bigstr, "X");
				}
					
				//printf("completed minute %d: %s\n", i, bigstr);
				//printf("sizeof whatever2: %d\n", sizeof(whatever2));
			}
			//printf("completed 10 minutes: %s\n", bigstr);

        	if (fp = fopen("/var/lib/lsnet/lscpu.log", "a"))
        	{

			token = strtok(bigstr, search);
			for (i = 1; i <= 10; i++)
			{
				fprintf(fp, "%s\n",token ); 
				if (i != 10)
				{
					token = strtok(NULL, search);
				}
			}
		}
		fclose( fp );
		//memset ((void*) bigstring, '\0', sizeof (bigstring));
		//memset ((void*) bullshit4, '\0', sizeof (bullshit4));
	}
	return 0;
}

//double minutearray[61][64][9];
//double minutearray2[64][9];

int netenminute(int netfrequency, double netarray1[2][9], double netarray2[4])
{
        //printf("inside netenminute\n");
        struct tm *local;
        time_t t;
        int i,count1,count2,emptyreturnvar;
        local = localtime(&t);
        char singlentrystr[(sizeof(double) + 2)];
	char oneminnetstr[(sizeof(double)*4) + 2];
	char datestr[(30 + sizeof(oneminnetstr))];
	char bigstr[((10 * sizeof(datestr)) + 10)];
	//printf("inside netenminute 2\n");
        char *token;
        char *line;
        char *search = "X";

        FILE* fp;
        while (1 == 1)
        {
			memset ((void*) bigstr, '\0', sizeof (bigstr));
                        for(i = 1; i <= 10; i++)
                        {
				//memset( (void *) oneminnetstr, '\0', sizeof(double) * 64 * 9);

                                memset ((void*) oneminnetstr, '\0', sizeof (oneminnetstr));
				memset ((void*) singlentrystr, '\0', sizeof (singlentrystr));
                                memset ((void*) datestr, '\0', sizeof (datestr));
				//printf("inside netenminute 3\n");
				netoneminute(netfrequency, netarray1, netarray2, walltime);                                
                                t = time(NULL);
                                local = localtime(&t);
                                strcat(datestr, asctime(local));
                                datestr[strlen(datestr)-1]='\0';
				strcat(datestr, " ");
                                for (count1 = 1; count1 < 5; count1++)
                                {
         	                       if(count1 == 1){
                 	                      emptyreturnvar = sprintf( singlentrystr, "%lf", netarray2[count1]);
                                       }else{
                        	              emptyreturnvar = sprintf( singlentrystr, " %lf", netarray2[count1]);
                                       }
                                       strcat(oneminnetstr, singlentrystr);
                                }
				strcat(datestr, oneminnetstr);
				strcat(bigstr, datestr);
                                if(i != 10){
                                        strcat(bigstr, "X");
                                } 
				//strcat(bigstr, );
				//printf("bigstr: %s\n", bigstr);			

			}

                if (fp = fopen("/var/lib/lsnet/lsnet.log", "a"))
                {
 
                        token = strtok(bigstr, search);
                        for (i = 1; i <= 10; i++)
                        {
                                fprintf(fp, "%s\n",token );
                                if (i != 10)
                                {
                                        token = strtok(NULL, search);
                                }
                        }
                }
                fclose( fp );
	}
	return 0;

}


int cpuoneminute(int cores, int cpufrequency, double cpuarray1[2][4][8], double minutearray[61][64][9], double minutearray2[64][9], double walltime[61]) {
	//printf("cores: %d cpufrequency: %d inside onminute\n", cores, cpufrequency);
        int user, nice, system, idle, iowait, irq, softirq, totalcycles;
	int count1, count2, count3;
	int poll = 60 / cpufrequency;
	//int minutearray[poll][cores][8];
	//int minutearray2[cores][8];
	//double walltime[poll]; 
	double walltimetotal = 0;
	double te0;
	//minutearray[0][0][0] = 0;
	//memset ((void*) minutearray, '\0', sizeof (minutearray));
	for (count1 = 1; count1 <= poll; count1++)
	{
		te0 = cpuinfo(cores, cpufrequency, cpuarray1);
		//double cpuarray1[2][cores][8] = cpuinfo(cores, cpufrequency);
		for (count2 = 1; count2 <= cores; count2++)
		{
			
                        //for (count3 = 1; count3 < 8; count3++)
                        //{
                                //total cpu cycles used per core/run
                          //      minutearray[count1][count2][8] = minutearray[count1][count2][8] + cpuarray1[2][count2][count3];
				//runtime between reads
				

                        //}

				//poll cpu variable	 //run two minus run one, cycles for those variables
                	minutearray[count1][count2][1] = (cpuarray1[2][count2][1] - cpuarray1[1][count2][1]);
        		minutearray[count1][count2][2] = (cpuarray1[2][count2][2] - cpuarray1[1][count2][2]);
        		minutearray[count1][count2][3] = (cpuarray1[2][count2][3] - cpuarray1[1][count2][3]);  
        		minutearray[count1][count2][4] = (cpuarray1[2][count2][4] - cpuarray1[1][count2][4]);
        		minutearray[count1][count2][5] = (cpuarray1[2][count2][5] - cpuarray1[1][count2][5]);
        		minutearray[count1][count2][6] = (cpuarray1[2][count2][6] - cpuarray1[1][count2][6]);
        		minutearray[count1][count2][7] = (cpuarray1[2][count2][7] - cpuarray1[1][count2][7]);
			minutearray[count1][count2][8] = 0;
			for (count3 = 1; count3 < 8; count3++)
			{
				//total cpu cycles used per core/run
				minutearray[count1][count2][8] = (minutearray[count1][count2][8] + minutearray[count1][count2][count3]); 
			}
			//translate cycles into percentage use
                        minutearray[count1][count2][1] = ((minutearray[count1][count2][1] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][2] = ((minutearray[count1][count2][2] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][3] = ((minutearray[count1][count2][3] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][4] = ((minutearray[count1][count2][4] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][5] = ((minutearray[count1][count2][5] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][6] = ((minutearray[count1][count2][6] / minutearray[count1][count2][8]) * 100);
                        minutearray[count1][count2][7] = ((minutearray[count1][count2][7] / minutearray[count1][count2][8]) * 100);
                        //walltime[poll] = 

			
		}
		//the runtime between reads for that polling
		walltime[poll] = te0;
		//that total 
		walltimetotal = walltimetotal + te0;
	}
	// determine average percentage use for given minute, weighted average taking into account walltime of each polling
	//memset(minutearray2, 0, 9);
	//memset ((void*) minutearray2, '\0', sizeof (minutearray2));
	memset( (void *) minutearray2, '\0', sizeof(double) * 64 * 9);
        for (count1 = 1; count1 <= poll; count1++)
        {

		for (count2 = 1; count2 <= cores; count2++)
                {

			for (count3 = 1; count3 < 8; count3++)
                        {
				//minutearray2[count2][count3] = minutearray2[count2][count3] + (minutearray[count1][count2][count3] * (walltime[poll]/ walltimetotal));
				minutearray2[count2][count3] = (minutearray2[count2][count3] + (minutearray[count1][count2][count3] * (walltime[poll]/ walltimetotal)));

				//Replace NaN values with 0 if they are detected (rare, but they happen)
				if(minutearray2[count2][count3] != minutearray2[count2][count3])
				{
					minutearray2[count2][count3] = 0;
				}
			}

		}

	}
	return 0;
}


int memoneminute(int memfrequency, int memarray1[9], int memarray2[61][9])
{
	int poll = 60 / memfrequency;
	//printf("In memoneminute poll: %d\n", poll);
	int count1; 
	int count2;
	//memset ((void*) memarray2, '\0', sizeof (memarray2));
	//memset ((void*) memarray2, '\0', sizeof(int) * 60 * 9);
	memset ((void*) memarray2, '\0', sizeof(int) * 61 * 9);
	for (count1 = 1; count1 <= poll; count1++)
	{
		//memset ((void*) memarray2, '\0', sizeof (memarray2));
		//memset ((void*) memarray1, '\0', sizeof (memarray1));
		meminfo(memfrequency, memarray1);

		//printf("In memoneminute poll: %d\n", poll);
		//printf("Finished run %d of meminfo\n", firstcounter);

		for (count2 = 1; count2 <= 8; count2++)
		{
			memarray2[count1][count2] = memarray1[count2];
			//printf("In memoneminute memarray1 %d: %d\n", count2, memarray1[count2] );
			//printf("writen to memarray2 %d %d: %d\n",count1, count2, memarray2[count1][count2] );
		}

	}
	//printf("returning to memtenmin\n");
	return 0;
}

//netoneminute(netfrequency, netarray1, netarray2, walltime);

int netoneminute(int netfrequency, double netarray1[2][9], double netarray2[4])
{
	//printf("NETFREQUENCY: %d\n", netfrequency);
        int poll = 60 / netfrequency;
	double walltime1; 
	//double walltimesum = 0; 
        int count1 = 1; 
	int count2 = 1;
	//printf("inside netoneminute\n");



	walltime1 = 0;
	memset ((void*) netarray2, '\0', sizeof (netarray2));
        for (count1 = 1; count1 <= poll; count1++)
        {
		//sum of the walltimes
		walltime1 = walltime1 + netinfo(netfrequency, netarray1);
		for (count2 = 1; count2 <= 4; count2++)
		{	
			//sum of the results
			netarray2[count2] = netarray2[count2] + netarray1[1][count2];				
		}
		
	}
	
	for (count2 = 1; count2 <= 4; count2++)
	{	
		//results per total time  in kb/s pack/s
		netarray2[count2] = netarray2[count2] / walltime1;
	}

	//printf("oneminarray Total Netin: %lf\n", netarray2[1]);
	//printf("oneminarray total packin: %lf\n", netarray2[2]);  
	//printf("oneminarray Total Netout: %lf\n", netarray2[3]);
	//printf("oneminarray total packout: %lf\n", netarray2[4]);

	return 0;
}
