/*
 * Copyright 2010, Intel Corporation
 *
 * This file is part of PowerTOP
 *
 * This program file 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; version 2 of the License.
 *
 * 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 in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 * or just google for it.
 *
 * Authors:
 *	Arjan van de Ven <arjan@linux.intel.com>
 */

/*
 * Code to track centrally which process has what /dev files open
 */
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <vector>
#include <algorithm>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>

using namespace std;

#include "devlist.h"
#include "lib.h"
#include "report.h"

#include "process/process.h"
#include "devices/device.h"
/*

* collect list of processes that have devices open
  (alternate between before and after lists)

* charge a "surcharge" to a device (sub)string
  - count how many openers
  - add proprotion to each process that has it open

* list of devices + power they use for processing

*/

static vector<struct devuser *> one;
static vector<struct devuser *> two;

static int phase;
/*
 * 0 - one = before,  two = after
 * 1 - one = after,   two = before
 */



void collect_open_devices(void)
{
	struct dirent *entry;
	DIR *dir;
	char filename[4096];
	char link[4096];
	unsigned int i;
	vector<struct devuser *> *target;

	if (phase == 1)
		target = &one;
	else
		target = &two;

	for (i = 0; i < target->size(); i++) {
		free((*target)[i]);
	}
	target->resize(0);


	dir = opendir("/proc/");
	if (!dir)
		return;
	while (1) {
		struct dirent *entry2;
		DIR *dir2;
		entry = readdir(dir);

		if (!entry)
			break;
		if (entry->d_name[0] == '.')
			continue;
		if (strcmp(entry->d_name, "self") == 0)
			continue;

		sprintf(filename, "/proc/%s/fd/", entry->d_name);

		dir2 = opendir(filename);
		if (!dir2)
			continue;
		while (1) {
			int ret;
			struct devuser * dev;
			entry2 = readdir(dir2);
			if (!entry2)
				break;
			if (entry2->d_name[0] == '.')
				continue;
			sprintf(filename, "/proc/%s/fd/%s", entry->d_name, entry2->d_name);
			memset(link, 0, 4096);
			ret = readlink(filename, link, 4095);
			if (ret < 0)
				continue;

			if (strcmp(link, "/dev/null") == 0)
				continue;
			if (strcmp(link, "/dev/.udev/queue.bin") == 0)
				continue;
			if (strcmp(link, "/dev/initctl") == 0)
				continue;
			if (strcmp(link, "/dev/ptmx") == 0)
				continue;
			if (strstr(link, "/dev/pts/"))
				continue;
			if (strstr(link, "/dev/shm/"))
				continue;
			if (strstr(link, "/dev/urandom"))
				continue;
			if (strstr(link, "/dev/tty"))
				continue;

			if (strncmp(link, "/dev", 4)==0) {
				dev = (struct devuser *)malloc(sizeof(struct devuser));
				if (!dev)
					continue;
				dev->pid = strtoull(entry->d_name, NULL, 10);
				strncpy(dev->device, link, 251);
				sprintf(filename, "/proc/%s/comm", entry->d_name);
				strncpy(dev->comm, read_sysfs_string("/proc/%s/comm", entry->d_name).c_str(), 31);
				target->push_back(dev);

			}
		}
		closedir(dir2);
	}
	closedir(dir);

	if (phase)
		phase = 0;
	else
		phase = 1;
}


/* returns 0 if no process is identified as having the device open and a value > 0 otherwise */
int charge_device_to_openers(const char *devstring, double power, class device *_dev)
{
	unsigned int i;
	int openers = 0;
	class process *proc;
	/* 1. count the number of openers */

	for (i = 0; i < one.size(); i++) {
		if (strstr(one[i]->device, devstring))
			openers++;
		}
	for (i = 0; i < two.size(); i++) {
		if (strstr(two[i]->device, devstring))
			openers++;
	}


	/* 2. divide power by this number */

	if (!openers)
		return 0;
	power = power / openers;


	/* 3. for each process that has it open, add the charge */

	for (i = 0; i < one.size(); i++)
		if (strstr(one[i]->device, devstring)) {
			proc = find_create_process(one[i]->comm, one[i]->pid);
			if (proc) {
				proc->power_charge += power;
				if (strlen(_dev->guilty) < 2000 && strstr(_dev->guilty, one[i]->comm) == NULL) {
					strcat(_dev->guilty, one[i]->comm);
					strcat(_dev->guilty, " ");
				}
			}
		}

	for (i = 0; i < two.size(); i++)
		if (strstr(two[i]->device, devstring)) {
			proc = find_create_process(two[i]->comm, two[i]->pid);
			if (proc) {
				proc->power_charge += power;
				if (strlen(_dev->guilty) < 2000 && strstr(_dev->guilty, two[i]->comm) == NULL) {
					strcat(_dev->guilty, two[i]->comm);
					strcat(_dev->guilty, " ");
				}
			}
		}



	return openers;
}

static vector<struct devpower *> devpower;

void clear_devpower(void)
{
	unsigned int i;

	for (i = 0; i < devpower.size(); i++) {
		devpower[i]->power = 0.0;
		devpower[i]->dev->guilty[0] = 0;
	}
}

void register_devpower(const char *devstring, double power, class device *_dev)
{
	unsigned int i;
	struct devpower *dev =  NULL;

	for (i = 0; i < devpower.size(); i++)
		if (strcmp(devstring, devpower[i]->device) == 0) {
			dev = devpower[i];
		}

	if (!dev) {
		dev = (struct devpower *)malloc(sizeof (struct devpower));
		strcpy(dev->device, devstring);
		dev->power = 0.0;
		devpower.push_back(dev);
	}
	dev->dev = _dev;
	dev->power = power;
}

void run_devpower_list(void)
{
	unsigned int i;

	for (i = 0; i < devpower.size(); i++) {
		int ret;
		ret = charge_device_to_openers(devpower[i]->device, devpower[i]->power, devpower[i]->dev);
		if (ret)
			devpower[i]->dev->hide = true;
		else
			devpower[i]->dev->hide = false;

	}

}

static bool devlist_sort(struct devuser * i, struct devuser * j)
{
	if (i->pid != j->pid)
		return i->pid < j->pid;

	return (strcmp(i->device, j->device)< 0);
}

static const char *dev_class(int line)
{
	if (line & 1) {
		return "device_odd";
	}
	return "device_even";
}

void report_show_open_devices(void)
{
	vector<struct devuser *> *target;
	unsigned int i;
	char prev[128], proc[128];

	if ((!reportout.csv_report)&&(!reportout.http_report))
		return;

	prev[0] = 0;

	if (phase == 1)
		target = &one;
	else
		target = &two;

	if (target->size() == 0)
		return;

	sort(target->begin(), target->end(), devlist_sort);

	if (reporttype) {
		fprintf(reportout.http_report,"<h2>Process device activity</h2>\n <table width=\"100%%\">\n");
		fprintf(reportout.http_report,"<tr><th class=\"device\" width=\"40%%\">Process</th><th class=\"device\">Device</th></tr>\n");
	}else {
		fprintf(reportout.csv_report,"**Process Device Activity**, \n\n");
		fprintf(reportout.csv_report,"Process, Device, \n");
	}

	for (i = 0; i < target->size(); i++) {
		proc[0] = 0;

		if (strcmp(prev, (*target)[i]->comm) != 0)
			sprintf(proc, "%s", (*target)[i]->comm);

		if (reporttype)
			fprintf(reportout.http_report,
				"<tr class=\"%s\"><td>%s</td><td>%s</td></tr>\n",
				dev_class(i), proc, (*target)[i]->device);
		 else
			fprintf(reportout.csv_report,
				"%s, %s, \n",
				proc, (*target)[i]->device);

		sprintf(prev, "%s", (*target)[i]->comm);
	}
	if (reporttype)
		fprintf(reportout.http_report,"</table></div>\n");
	else
		fprintf(reportout.csv_report,"\n");
}
