/*
 * Test-program for some SysInfo.library features
 *
 * This file is public domain.
 *
 * Author: Petri Nordlund <petrin@megabaud.fi>
 *
 * $Id: test.c 1.3 1995/10/12 16:31:32 petrin Exp petrin $
 *
 */

#include "defs.h"
#include <proto/SysInfo.h>
#include <libraries/SysInfo.h>

/* VARIABLES */
struct SysInfo *si = NULL;
struct Library *SysInfoBase = NULL;


int
main(int argc, char **argv)
{
	if(!(SysInfoBase = OpenLibrary(SYSINFONAME, SYSINFOVERSION)))
	{
		puts("Can't open SysInfo.library");
		exit(RETURN_FAIL);
	}


	/* Initialize the SysInfo.library, this will make connection to the
     * server-process and allocate the SysInfo-structure. */
	if(!(si = InitSysInfo()))
	{
		puts("Couldn't initialize SysInfo");
		CloseLibrary(SysInfoBase);
		exit(RETURN_FAIL);
	}


	/* print our pid, ppid and pgrp */
	printf("pid:  %d\n",GetPid(si));
	if(si->GetPpid_implemented)
	{
		LONG p = GetPpid(si);
		if(p != -1)
			printf("ppid: %d\n",p);
		else
			printf("ppid: unknown\n");
	}
	if(si->GetPgrp_implemented)
	{
		LONG p = GetPgrp(si);
		if(p != -1)
			printf("pgrp: %d\n",p);
		else
			printf("pgrp: unknown\n");
	}


	/* If si->which_implemented is 0, then GetNice() and SetNice() are not available */
	/* We'll also make sure that the search methods we need have been implemented    */
	if(si->which_implemented && (si->which_implemented & (WHICHF_PRIO_TASK | WHICH_PRIO_PROCESS)))
	{
		LONG nice;

		/* display the nice-value for this task */
		nice=GetNice(si,WHICH_PRIO_TASK,0);
		if(nice == -1)
		{
			if(si->errno)
				printf("GetNice() failed, errno: %d\n",si->errno);
			else
				printf("nice: %d\n",nice);
		}
		else
			printf("nice: %d\n",nice);

		/* set our nice-value to +5 */
		if(SetNice(si,WHICH_PRIO_PROCESS,GetPid(si),5))
			printf("SetNice() failed, errno: %d\n",si->errno);
	}


	/* Ask for notify and output load averages every second for 10 seconds. */

	if(si->loadavg_type != LOADAVG_NONE)
	{
		struct SI_Notify *not;
		struct Message *msg;
		short i;

		if(si->notify_msg_implemented && (not=AddNotify(si,AN_USE_MESSAGES,10)))
		{
			printf("load averages (%d.%02d, %d.%02d, %d.%02d minutes):\n",
				si->loadavg_time1/60, si->loadavg_time1%60,
				si->loadavg_time2/60, si->loadavg_time2%60,
				si->loadavg_time3/60, si->loadavg_time3%60);

			for(i=0;i<10;i++)
			{
				/* We'll get a message every second. There may be more than
                 * one message in the port at once. */

				Wait(1L<<not->notify_port->mp_SigBit);
				while(msg = GetMsg(not->notify_port))
				{
					struct SI_LoadAverage load;	/* This will be filled by GetLoadAverage() */

					ReplyMsg(msg);

					GetLoadAverage(si, &load);	/* Ask SysInfo.library for current load averages */

					printf("load average:");

					switch(si->loadavg_type)
					{
						case LOADAVG_FIXEDPNT:

							/* Convert fixed point values to floating point values */

							if(si->loadavg_time1)
								printf(" %.2f",(float) load.lavg_fixed.load1 / (float) si->fscale);
							else
								printf(" N/A");

							if(si->loadavg_time2)
								printf(" %.2f",(float) load.lavg_fixed.load2 / (float) si->fscale);
							else
								printf(" N/A");

							if(si->loadavg_time3)
								printf(" %.2f\n",(float) load.lavg_fixed.load3 / (float) si->fscale);
							else
								printf(" N/A\n");

							break;
					}
				}
			}
			RemoveNotify(si,not);
		}
		else
			printf("Can't use notification.\n");
	}
	else
		printf("Load averages are not supported.\n");


	/* output cpu usage values */
	{
		struct SI_CpuUsage cu;

		GetCpuUsage(si,&cu);

		printf("cpu time:                 ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTAL_IMPLEMENTED)
			printf("%d seconds used, %d seconds idle\n",cu.total_used_cputime, cu.total_elapsed_time - cu.total_used_cputime);
		else
			printf("N/A\n");

		printf("cpu usage:                ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTAL_IMPLEMENTED)
			printf("%.2f%%\n",((float) cu.total_used_cputime * 100.0) / (float) cu.total_elapsed_time);
		else
			printf("N/A\n");

		printf("current cpu usage:        ");
		if(si->cpu_usage_implemented & CPU_USAGEF_LASTSEC_IMPLEMENTED)
			printf("%.2f%%\n",((float) cu.used_cputime_lastsec * 100.0) / (float) cu.used_cputime_lastsec_hz);
		else
			printf("N/A\n");

		printf("recent cpu usage:         ");
		if(si->cpu_usage_implemented & CPU_USAGEF_RECENT_IMPLEMENTED)
			printf("%.2f%% (%d seconds)\n",((float) cu.recent_used_cputime * 100.0) / (float) cu.recent_used_cputime_hz, cu.recent_seconds);
		else
			printf("N/A\n");

		printf("context switches:         ");
		if(si->cpu_usage_implemented & CPU_USAGEF_IVVOCSW_IMPLEMENTED)
			printf("%d involuntary, %d voluntary\n", cu.involuntary_csw, cu.voluntary_csw);
		else
			printf("N/A\n");

		printf("total context switches:   ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTALCSW_IMPLEMENTED)
			printf("%d\n", cu.total_csw);
		else
			printf("N/A\n");

		printf("current context switches: ");
		if(si->cpu_usage_implemented & CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED)
			printf("%d involuntary, %d voluntary\n", cu.involuntary_csw_lastsec, cu.voluntary_csw_lastsec);
		else
			printf("N/A\n");

		printf("current total csws:       ");
		if(si->cpu_usage_implemented & CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED)
			printf("%d\n", cu.total_csw_lastsec);
		else
			printf("N/A\n");
	}


	/* output cpu usage values for this task */
	{
		struct SI_TaskCpuUsage cu;

		if(!GetTaskCpuUsage(si,&cu,0))
		{
			printf("This task:\n");

			printf("cpu time:                   ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTAL_IMPLEMENTED)
				printf("%d.%d seconds\n",cu.total_used_cputime / cu.total_used_time_hz, cu.total_used_cputime % cu.total_used_time_hz);
			else
				printf("N/A\n");

			printf("cpu usage:                  ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTAL_IMPLEMENTED)
				printf("%.2f%%\n",(((float) cu.total_used_cputime) / ((float) cu.total_used_time_hz) * 100.0) / (float) cu.total_elapsed_time);
			else
				printf("N/A\n");

			printf("current cpu usage:          ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_LASTSEC_IMPLEMENTED)
				printf("%.2f%%\n",((float) cu.used_cputime_lastsec * 100.0) / (float) cu.used_cputime_lastsec_hz);
			else
				printf("N/A\n");

			printf("recent cpu usage:           ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_RECENT_IMPLEMENTED)
				printf("%.2f%% (%d seconds)\n",((float) cu.recent_used_cputime * 100.0) / (float) cu.recent_used_cputime_hz, cu.recent_seconds);
			else
				printf("N/A\n");

			printf("context switches:           ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_IVVOCSW_IMPLEMENTED)
				printf("%d involuntary, %d voluntary\n", cu.involuntary_csw, cu.voluntary_csw);
			else
				printf("N/A\n");

			printf("total context switches:     ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTALCSW_IMPLEMENTED)
				printf("%d\n", cu.total_csw);
			else
				printf("N/A\n");

			printf("context switches (ps):      ");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_IVVOCSW_LASTSEC_IMPLEMENTED)
				printf("%d involuntary, %d voluntary\n", cu.involuntary_csw_lastsec, cu.voluntary_csw_lastsec);
			else
				printf("N/A\n");

			printf("total context switches (ps):");
			if(si->task_cpu_usage_implemented & TASK_CPU_USAGEF_TOTALCSW_LASTSEC_IMPLEMENTED)
				printf("%d\n", cu.total_csw_lastsec);
			else
				printf("N/A\n");
		}
		else
			printf("Can't get CPU usage for this task.\n");
	}

	if(si)
		FreeSysInfo(si);

	if(SysInfoBase)
		CloseLibrary(SysInfoBase);

	return(RETURN_OK);
}
