/*
 * 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>
 */



#include "process.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#include <iostream>
#include <fstream>


vector <class process *> all_processes;

void process::account_disk_dirty(void)
{
	disk_hits++;
}

void process::schedule_thread(uint64_t time, int thread_id)
{
	running_since = time;
	running = 1;
}


uint64_t process::deschedule_thread(uint64_t time, int thread_id)
{
	uint64_t delta;

	if (!running_since)
		return 0;

	delta = time - running_since;

	if (time < running_since)
		printf("%llu time    %llu since \n", (unsigned long long)time,
						     (unsigned long long)running_since);

	if (thread_id == 0) /* idle thread */
		delta = 0;
	accumulated_runtime += delta;
	running = 0;

	return delta;
}

static void cmdline_to_string(char *str)
{
	char *c = str;
	char prev = 0;

	while (prev != 0 || *c  != 0) {
		prev = *c;
		if (*c == 0)
			*c = ' ';
		c++;
	}
}


process::process(const char *_comm, int _pid, int _tid) : power_consumer()
{
	char line[4096];
	ifstream file;

	strcpy(comm, _comm);
	pid = _pid;
	is_idle = 0;
	running = 0;
	last_waker = NULL;
	waker = NULL;
	is_kernel = 0;
	tgid = _tid;

	if (_tid == 0) {
		sprintf(line, "/proc/%i/status", _pid);
		file.open(line);
		while (file) {
			file.getline(line, 4096);
			if (strstr(line, "Tgid")) {
				char *c;
				c = strchr(line, ':');
				if (!c)
					continue;
				c++;
				tgid = strtoull(c, NULL, 10);
				break;
			}
		}
		file.close();
	}

	if (strncmp(_comm, "kondemand/", 10) == 0)
		is_idle = 1;

	strcpy(desc, comm);

	sprintf(line, "/proc/%i/cmdline", _pid);
	file.open(line, ios::binary);
	if (file) {
		memset(line, 0, sizeof(line));
		file.read(line, 4096);
		file.close();
		if (strlen(line) < 1) {
			is_kernel = 1;
			sprintf(desc, "[%s]", comm);
		} else {
			int sz = sizeof(desc) - 1;
			cmdline_to_string(line);
			strncpy(desc, line, sz);
			desc[sz] = 0x00;
		}
	}
}

const char * process::description(void)
{

	if (child_runtime > accumulated_runtime)
		child_runtime = 0;

	return desc;
}

double process::usage_summary(void)
{
	double t;
	t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
	return t;
}

const char * process::usage_units_summary(void)
{
	return "%";
}

class process * find_create_process(const char *comm, int pid)
{
	unsigned int i;
	class process *new_proc;

	for (i = 0; i < all_processes.size(); i++) {
		if (all_processes[i]->pid == pid && strcmp(comm, all_processes[i]->comm) == 0)
			return all_processes[i];
	}

	new_proc = new class process(comm, pid);
	all_processes.push_back(new_proc);
	return new_proc;
}

class process * find_create_process(char *comm, int pid)
{
	return find_create_process((const char*)comm, pid);
}

static void merge_process(class process *one, class process *two)
{
	one->accumulated_runtime += two->accumulated_runtime;
	one->child_runtime += two->child_runtime;
	one->wake_ups += two->wake_ups;
	one->disk_hits += two->disk_hits;
	one->hard_disk_hits += two->hard_disk_hits;
	one->xwakes += two->xwakes;
	one->gpu_ops += two->gpu_ops;
	one->power_charge += two->power_charge;
}


void merge_processes(void)
{
	std::vector<class process*>::iterator it1, it2;
	class process *one, *two;

	it1 = all_processes.begin();
	while (it1 != all_processes.end()) {
		it2 = it1 + 1;
		one = *it1;
		while (it2 != all_processes.end()) {
			two = *it2;
			/* fold threads */
			if (one->pid == two->tgid && two->tgid != 0) {
				merge_process(one, two);
				delete *it2;
				it2 = all_processes.erase(it2);
				continue;
			}
			/* find dupes and add up */
			if (!strcmp(one->desc, two->desc)) {
				merge_process(one, two);
				delete *it2;
				it2 = all_processes.erase(it2);
				continue;
			}
			++it2;
		}
		++it1;
	}
}

void all_processes_to_all_power(void)
{
	unsigned int i;
	for (i = 0; i < all_processes.size() ; i++)
		if (all_processes[i]->accumulated_runtime)
			all_power.push_back(all_processes[i]);
}

void clear_processes(void)
{
	std::vector <class process *>::iterator it = all_processes.begin();
	while (it != all_processes.end()) {
		delete *it;
		it = all_processes.erase(it);
	}
}
