/*
 * 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);
}

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");
}
