/* 
** ZABBIX
** Copyright (C) 2000-2005 SIA Zabbix
**
** 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 2 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, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**/

#include "common.h"

#include "sysinfo.h"
#include "threads.h"

#include "stats.h"

#include "log.h"

int	USER_PERFCOUNTER(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
	PERF_COUNTERS *perfs = NULL;

	int	ret = SYSINFO_RET_FAIL;

	if ( !PERF_COLLECTOR_STARTED(collector) )
	{
		SET_MSG_RESULT(result, strdup("Collector is not started!"));
		return SYSINFO_RET_OK;
	}

	for(perfs = collector->perfs.pPerfCounterList; perfs; perfs=perfs->next)
	{
		if ( 0 == strcmp(perfs->name, param) )
		{
			SET_DBL_RESULT(result, perfs->lastValue);
			ret = SYSINFO_RET_OK;
			break;
		}
	}

	return ret;
}

int	PERF_MONITOR(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
	HQUERY				query;
	HCOUNTER			counter;
	PDH_STATUS			status;
	PDH_RAW_COUNTER			rawData, rawData2;
	PDH_FMT_COUNTERVALUE		counterValue;
	char				counter_path[PDH_MAX_COUNTER_PATH],
					tmp[MAX_STRING_LEN];
	int				ret = SYSINFO_RET_FAIL, interval;
	PERF_COUNTERS *perfs;

	if (num_param(param) > 2)
		return SYSINFO_RET_FAIL;

	if (0 != get_param(param, 1, counter_path, sizeof(counter_path)))
		*counter_path = '\0';

	if (*counter_path == '\0')
		return SYSINFO_RET_FAIL;

	if (0 != get_param(param, 2, tmp, sizeof(tmp)))
		*tmp = '\0';

	if (*tmp != '\0' && FAIL == is_uint(tmp))
		return SYSINFO_RET_FAIL;

	interval = *tmp == '\0' ? 1 : atoi(tmp);

	if (FAIL == check_counter_path(counter_path))
		return SYSINFO_RET_FAIL;

	if (interval > 1) {
		if ( !PERF_COLLECTOR_STARTED(collector) ) {
			SET_MSG_RESULT(result, strdup("Collector is not started!"));
			return SYSINFO_RET_OK;
		}

		for (perfs = collector->perfs.pPerfCounterList; perfs != NULL; perfs = perfs->next) {
			if (0 == strcmp(perfs->counterPath, counter_path) && perfs->interval == interval) {
				SET_DBL_RESULT(result, perfs->lastValue);
				return SYSINFO_RET_OK;
			}
		}

		if (FAIL == add_perf_counter("", counter_path, interval))
			return SYSINFO_RET_FAIL;
	}

	if (ERROR_SUCCESS == (status = PdhOpenQuery(NULL, 0, &query)))
	{
		if (ERROR_SUCCESS == (status = PdhAddCounter(query,counter_path,0,&counter)))
		{
			if (ERROR_SUCCESS == (status = PdhCollectQueryData(query)))
			{
				if(ERROR_SUCCESS == (status = PdhGetRawCounterValue(counter, NULL, &rawData)) &&
					(rawData.CStatus == PDH_CSTATUS_VALID_DATA || rawData.CStatus == PDH_CSTATUS_NEW_DATA))
				{
					if( PDH_CSTATUS_INVALID_DATA == (status = PdhCalculateCounterFromRawValue(
						counter, 
						PDH_FMT_DOUBLE, 
						&rawData, 
						NULL, 
						&counterValue
						)) )
					{
						zbx_sleep(1);
						PdhCollectQueryData(query);
						PdhGetRawCounterValue(counter, NULL, &rawData2);
						status = PdhCalculateCounterFromRawValue(
							counter, 
							PDH_FMT_DOUBLE, 
							&rawData2, 
							&rawData, 
							&counterValue);

					}

					if(ERROR_SUCCESS == status) {
						SET_DBL_RESULT(result, counterValue.doubleValue);
						ret = SYSINFO_RET_OK;
					} else
						zabbix_log(LOG_LEVEL_DEBUG, "Can't format counter value \"%s\": %s",
								counter_path, strerror_from_module(status, "PDH.DLL"));
				} else {
					if (ERROR_SUCCESS == status)
						status = rawData.CStatus;

					zabbix_log(LOG_LEVEL_DEBUG, "Can't get counter value \"%s\": %s",
							counter_path, strerror_from_module(status, "PDH.DLL"));
				}
			} else
				zabbix_log(LOG_LEVEL_DEBUG, "Can't collect data \"%s\": %s",
						counter_path, strerror_from_module(status, "PDH.DLL"));

			PdhRemoveCounter(&counter);
		} else
			zabbix_log(LOG_LEVEL_DEBUG, "Can't add counter \"%s\": %s",
					counter_path, strerror_from_module(status, "PDH.DLL"));

		PdhCloseQuery(query);
	} else
		zabbix_log(LOG_LEVEL_DEBUG, "Can't initialize performance counters \"%s\": %s",
				counter_path, strerror_from_module(status, "PDH.DLL"));

	return ret;
}
