Example #1
0
File: atop.c Project: ryandoyle/pcp
/*
** The engine() drives the main-loop of the program
*/
void
engine(void)
{
	int 			i, j;
	struct sigaction 	sigact;
	double 			timed, delta;
	void			getusr1(int), getusr2(int);

	/*
	** reserve space for system-level statistics
	*/
	static struct sstat	*cursstat; /* current   */
	static struct sstat	*presstat; /* previous  */
	static struct sstat	*devsstat; /* deviation */
	static struct sstat	*hlpsstat;

	/*
	** reserve space for task-level statistics
	*/
	static struct tstat	*curtpres;	/* current present list      */
	static int		 curtlen;	/* size of present list      */

	struct tstat		*curpexit;	/* exited process list	     */
	struct tstat		*devtstat;	/* deviation list	     */
	struct tstat		**devpstat;	/* pointers to processes     */
						/* in deviation list         */

	unsigned int		ntaskpres;	/* number of tasks present   */
	unsigned int		nprocexit;	/* number of exited procs    */
	unsigned int		nprocexitnet;	/* number of exited procs    */
						/* via netatopd daemon       */
	unsigned int		ntaskdev;       /* nr of tasks deviated      */
	unsigned int		nprocdev;       /* nr of procs deviated      */
	int			nprocpres;	/* nr of procs present       */
	int			totrun, totslpi, totslpu, totzombie;
	unsigned int		noverflow;

	/*
	** initialization: allocate required memory dynamically
	*/
	cursstat = sstat_alloc("current sysstats");
	presstat = sstat_alloc("prev    sysstats");
	devsstat = sstat_alloc("deviate sysstats");

	curtlen  = PROCMIN * 3 / 2;	/* add 50% for threads */
	curtpres = calloc(curtlen, sizeof(struct tstat));
	ptrverify(curtpres, "Malloc failed for %d procstats\n", curtlen);

	/*
	** install the signal-handler for ALARM, USR1 and USR2 (triggers
	** for the next sample)
	*/
	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr1;
	sigaction(SIGUSR1, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr2;
	sigaction(SIGUSR2, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getalarm;
	sigaction(SIGALRM, &sigact, (struct sigaction *)0);

	if (interval.tv_sec || interval.tv_usec)
		setalarm(&interval);

	/*
	** MAIN-LOOP:
	**    -	Wait for the requested number of seconds or for other trigger
	**
	**    -	System-level counters
	**		get current counters
	**		calculate the differences with the previous sample
	**
	**    -	Process-level counters
	**		get current counters from running & exited processes
	**		calculate the differences with the previous sample
	**
	**    -	Call the print-function to visualize the differences
	*/
	for (sampcnt=0; sampcnt < nsamples; sampcnt++)
	{
		char	lastcmd;

		/*
		** wait for alarm-signal to arrive (except first sample)
		** or wait for SIGUSR1/SIGUSR2
		*/
		if (sampcnt > 0 && awaittrigger && !rawreadflag)
			pause();

		awaittrigger = 1;

		/*
		** take a snapshot of the current system-level statistics 
		*/
		hlpsstat = cursstat;	/* swap current/prev. stats */
		cursstat = presstat;
		presstat = hlpsstat;

		photosyst(cursstat);	/* obtain new counters     */

		/*
		** take a snapshot of the current task-level statistics 
		**
		** first register active tasks
		**  --> atop malloc's a minimal amount of space which is
		**      only extended when needed
		*/
		memset(curtpres, 0, curtlen * sizeof(struct tstat));

		ntaskpres = photoproc(&curtpres, &curtlen);

		/*
		** register processes that exited during last sample;
		** first determine how many processes exited
		**
		** the number of exited processes is limited to avoid
		** that atop explodes in memory and introduces OOM killing
		*/
		nprocexit = acctprocnt();	/* number of exited processes */

		if (nprocexit > MAXACCTPROCS)
		{
			noverflow = nprocexit - MAXACCTPROCS;
			nprocexit = MAXACCTPROCS;
		}
		else
			noverflow = 0;

		/*
		** determine how many processes have been exited
		** for the netatop module (only processes that have
		** used the network)
		*/
		if (nprocexit > 0 && (supportflags & NETATOPD))
			nprocexitnet = netatop_exitstore();
		else
			nprocexitnet = 0;

		/*
		** reserve space for the exited processes and read them
		*/
		if (nprocexit > 0)
		{
			curpexit = malloc(nprocexit * sizeof(struct tstat));

			ptrverify(curpexit,
			          "Malloc failed for %d exited processes\n",
			          nprocexit);

			memset(curpexit, 0, nprocexit * sizeof(struct tstat));

			nprocexit = acctphotoproc(curpexit, nprocexit);

			/*
 			** reposition offset in accounting file when not
			** all exited processes have been read (i.e. skip
			** those processes)
			*/
			if (noverflow)
				acctrepos(noverflow);
		}
		else
		{
			curpexit    = NULL;
		}

		/*
		** calculate the deviations (i.e. calculate the activity
		** during the last sample).  Note for PMAPI calls we had
		** to delay changing curtime until after sampling due to
		** the way pmSetMode(3) works.
		*/
		pretime  = curtime;	/* timestamp for previous sample */
		curtime  = cursstat->stamp; /* timestamp for this sample */
		timed = __pmtimevalToReal(&curtime);
		delta = timed - __pmtimevalToReal(&pretime);

		deviatsyst(cursstat, presstat, devsstat, delta);

		devtstat = malloc((ntaskpres+nprocexit) * sizeof(struct tstat));

		ptrverify(devtstat, "Malloc failed for %d modified tasks\n",
			          			ntaskpres+nprocexit);

		ntaskdev = deviattask(curtpres,  ntaskpres,
		                      curpexit,  nprocexit, deviatonly,
		                      devtstat,  devsstat,
		                      &nprocdev, &nprocpres,
		                      &totrun, &totslpi, &totslpu, &totzombie);

  	      	/*
 		** create list of pointers specifically to the process entries
		** in the task list
		*/
       		devpstat = malloc(sizeof (struct tstat *) * nprocdev);

		ptrverify(devpstat, "Malloc failed for %d process ptrs\n",
			          				nprocdev);

		for (i=0, j=0; i < ntaskdev; i++)
		{
			if ( (devtstat+i)->gen.isproc)
				devpstat[j++] = devtstat+i;
		}

		/*
		** activate the installed print-function to visualize
		** the deviations
		*/
		lastcmd = (vis.show_samp)(timed,
				     delta > 1.0 ? delta : 1.0,
		           	     devsstat,  devtstat, devpstat,
		                     ntaskdev,  ntaskpres, nprocdev, nprocpres, 
		                     totrun, totslpi, totslpu, totzombie, 
		                     nprocexit, noverflow, sampcnt==0);

		if (rawreadflag)
			__pmtimevalInc(&curtime, &interval);

		/*
		** release dynamically allocated memory
		*/
		if (nprocexit > 0)
			free(curpexit);

		if (nprocexitnet > 0)
			netatop_exiterase();

		free(devtstat);
		free(devpstat);

		if (lastcmd == 'r')	/* reset requested ? */
		{
			sampcnt = -1;

			curtime = origin;

			/* set current (will be 'previous') counters to 0 */
			memset(curtpres, 0, curtlen * sizeof(struct tstat));
			sstat_reset(cursstat);

			/* remove all tasks in database */
			pdb_makeresidue();
			pdb_cleanresidue();
		}
	} /* end of main-loop */
}
Example #2
0
/*
** The engine() drives the main-loop of the program
*/
static void
engine(void)
{
	int 			i, j;
	struct sigaction 	sigact;
	static time_t		timelimit;
	void			getusr1(int), getusr2(int);

	/*
	** reserve space for system-level statistics
	*/
	static struct sstat	*cursstat; /* current   */
	static struct sstat	*presstat; /* previous  */
	static struct sstat	*devsstat; /* deviation */
	static struct sstat	*hlpsstat;

	/*
	** reserve space for task-level statistics
	*/
	static struct tstat	*curpact;	/* current active list  */
	static int		curplen;	/* current active size  */

	struct tstat		*curpexit;	/* exited process list	*/
	struct tstat		*devtstat;	/* deviation list	*/
	struct tstat		**devpstat;	/* pointers to processes*/
						/* in deviation list    */

	unsigned int		ntask, nexit, nexitnet;
	unsigned int		noverflow, ndeviat, nactproc;
	int			totproc, totrun, totslpi, totslpu, totzombie;

	/*
	** initialization: allocate required memory dynamically
	*/
	cursstat = calloc(1, sizeof(struct sstat));
	presstat = calloc(1, sizeof(struct sstat));
	devsstat = calloc(1, sizeof(struct sstat));

	curplen  = countprocs() * 3 / 2;	/* add 50% for threads */
	curpact  = calloc(curplen, sizeof(struct tstat));

	ptrverify(cursstat, "Malloc failed for current sysstats\n");
	ptrverify(presstat, "Malloc failed for prev    sysstats\n");
	ptrverify(devsstat, "Malloc failed for deviate sysstats\n");
	ptrverify(curpact,  "Malloc failed for %d procstats\n", curplen);

	/*
	** install the signal-handler for ALARM, USR1 and USR2 (triggers
	* for the next sample)
	*/
	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr1;
	sigaction(SIGUSR1, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr2;
	sigaction(SIGUSR2, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getalarm;
	sigaction(SIGALRM, &sigact, (struct sigaction *)0);

	if (interval > 0)
		alarm(interval);

	if (midnightflag)
	{
		time_t		timenow = time(0);
		struct tm	*tp = localtime(&timenow);

		tp->tm_hour = 23;
		tp->tm_min  = 59;
		tp->tm_sec  = 59;

		timelimit = mktime(tp);
	}

	/*
	** MAIN-LOOP:
	**    -	Wait for the requested number of seconds or for other trigger
	**
	**    -	System-level counters
	**		get current counters
	**		calculate the differences with the previous sample
	**
	**    -	Process-level counters
	**		get current counters from running & exited processes
	**		calculate the differences with the previous sample
	**
	**    -	Call the print-function to visualize the differences
	*/
	for (sampcnt=0; sampcnt < nsamples; sampcnt++)
	{
		char	lastcmd;

		/*
		** if the limit-flag is specified:
		**  check if the next sample is expected before midnight;
		**  if not, stop atop now 
		*/
		if (midnightflag && (curtime+interval) > timelimit)
			break;

		/*
		** wait for alarm-signal to arrive (except first sample)
		** or wait for SIGUSR1/SIGUSR2
		*/
		if (sampcnt > 0 && awaittrigger)
			pause();

		awaittrigger = 1;

		/*
		** gather time info for this sample
		*/
		pretime  = curtime;
		curtime  = time(0);		/* seconds since 1-1-1970 */

		/*
		** take a snapshot of the current system-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		*/
		hlpsstat = cursstat;	/* swap current/prev. stats */
		cursstat = presstat;
		presstat = hlpsstat;

		photosyst(cursstat);	/* obtain new counters      */

		deviatsyst(cursstat, presstat, devsstat);

		/*
		** take a snapshot of the current task-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		**
		** first register active tasks
		**  --> atop malloc's a minimal amount of space which is
		**      only extended when needed
		*/
		memset(curpact, 0, curplen * sizeof(struct tstat));

		while ( (ntask = photoproc(curpact, curplen)) == curplen)
		{
			curplen += PROCCHUNK;

			curpact = realloc(curpact,
					curplen * sizeof(struct tstat));

			ptrverify(curpact,
			          "Realloc failed for %d tasks\n", curplen);

			memset(curpact, 0, curplen * sizeof(struct tstat));
		}

		/*
		** register processes that exited during last sample;
		** first determine how many processes exited
		**
		** the number of exited processes is limited to avoid
		** that atop explodes in memory and introduces OOM killing
		*/
		nexit = acctprocnt();	/* number of exited processes */

		if (nexit > MAXACCTPROCS)
		{
			noverflow = nexit - MAXACCTPROCS;
			nexit     = MAXACCTPROCS;
		}
		else
			noverflow = 0;

		/*
		** determine how many processes have been exited
		** for the netatop module (only processes that have
		** used the network)
		*/
		if (nexit > 0 && (supportflags & NETATOPD))
			nexitnet = netatop_exitstore();
		else
			nexitnet = 0;

		/*
		** reserve space for the exited processes and read them
		*/
		if (nexit > 0)
		{
			curpexit = malloc(nexit * sizeof(struct tstat));

			ptrverify(curpexit,
			          "Malloc failed for %d exited processes\n",
			          nexit);

			memset(curpexit, 0, nexit * sizeof(struct tstat));

			acctphotoproc(curpexit, nexit);

			/*
 			** reposition offset in accounting file when not
			** all exited processes have been read (i.e. skip
			** those processes)
			*/
			if (noverflow)
				acctrepos(noverflow);
		}
		else
		{
			curpexit    = NULL;
		}

		/*
		** calculate deviations
		*/
		devtstat = malloc((ntask+nexit) * sizeof(struct tstat));

		ptrverify(devtstat, "Malloc failed for %d modified processes\n",
			          				ntask+nexit);

		ndeviat = deviatproc(curpact, ntask, curpexit, nexit, 
				deviatonly, devtstat, devsstat, &nactproc,
				&totproc, &totrun, &totslpi, &totslpu, 
		                &totzombie);

  	      	/*
 		** create list of pointers specifically to the process entries
		** in the task list
		*/
       		devpstat = malloc(sizeof (struct tstat *) * nactproc);

		ptrverify(devpstat, "Malloc failed for %d process ptrs\n",
			          				nactproc);

		for (i=0, j=0; i < ndeviat; i++)
		{
			if ( (devtstat+i)->gen.isproc)
				devpstat[j++] = devtstat+i;
		}

		/*
		** activate the installed print-function to visualize
		** the deviations
		*/
		lastcmd = (vis.show_samp)( curtime,
				     curtime-pretime > 0 ? curtime-pretime : 1,
		           	     devsstat, devtstat, devpstat,
		                     ndeviat, ntask, nactproc,
		                     totproc, totrun, totslpi, totslpu,
		                     totzombie, nexit, noverflow, sampcnt==0);

		/*
		** release dynamically allocated memory
		*/
		if (nexit > 0)
			free(curpexit);

		if (nexitnet > 0)
			netatop_exiterase();

		free(devtstat);
		free(devpstat);

		if (lastcmd == 'r')	/* reset requested ? */
		{
			sampcnt = -1;

			curtime = getboot() / hertz;	// reset current time

			/* set current (will be 'previous') counters to 0 */
			memset(cursstat, 0,           sizeof(struct sstat));
			memset(curpact,  0, curplen * sizeof(struct tstat));

			/* remove all tasks in database */
			pdb_makeresidue();
			pdb_cleanresidue();
		}
	} /* end of main-loop */
}
Example #3
0
/*
** The engine() drives the main-loop of the program
*/
static void
engine(void)
{
	struct sigaction 	sigact;
	static time_t		timelimit;
	void			getusr1(int), getusr2(int);

	/*
	** reserve space for system-level statistics
	*/
	static struct sstat	*cursstat; /* current   */
	static struct sstat	*presstat; /* previous  */
	static struct sstat	*devsstat; /* deviation */
	static struct sstat	*hlpsstat;

	/*
	** reserve space for process-level statistics
	*/
	static struct pstat	*curpact;	/* current active list  */
	static int		curplen;	/* current active size  */

	struct pstat		*curpexit;	/* exitted process list	*/
	struct pstat		*devpstat;	/* deviation list	*/

	int			npresent, nexit, n;
	int			ntrun, ntslpi, ntslpu, nzombie;

	/*
	** initialization: allocate required memory dynamically
	*/
	cursstat = calloc(1, sizeof(struct sstat));
	presstat = calloc(1, sizeof(struct sstat));
	devsstat = calloc(1, sizeof(struct sstat));

	curplen = countprocs() + PROCCHUNK;
	curpact = calloc(curplen, sizeof(struct pstat));

	if (!cursstat || !presstat || !devsstat || !curpact)
	{
		fprintf(stderr, "unexpected calloc-failure...\n");
		cleanstop(1);
	}

	/*
	** install the signal-handler for ALARM, USR1 and USR2 (triggers
	* for the next sample)
	*/
	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr1;
	sigaction(SIGUSR1, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getusr2;
	sigaction(SIGUSR2, &sigact, (struct sigaction *)0);

	memset(&sigact, 0, sizeof sigact);
	sigact.sa_handler = getalarm;
	sigaction(SIGALRM, &sigact, (struct sigaction *)0);

	if (interval > 0)
		alarm(interval);

	if (midnightflag)
	{
		time_t		timenow = time(0);
		struct tm	*tp = localtime(&timenow);

		tp->tm_hour = 23;
		tp->tm_min  = 59;
		tp->tm_sec  = 59;

		timelimit = mktime(tp);
	}

	/*
	** MAIN-LOOP:
	**    -	Wait for the requested number of seconds or for other trigger
	**
	**    -	System-level counters
	**		get current counters
	**		calculate the differences with the previous sample
	**
	**    -	Process-level counters
	**		get current counters from running & exited processes
	**		calculate the differences with the previous sample
	**
	**    -	Call the print-function to visualize the differences
	*/
	for (sampcnt=0; sampcnt < nsamples; sampcnt++)
	{
		char	lastcmd;

		/*
		** if the limit-flag is specified:
		**  check if the next sample is expected before midnight;
		**  if not, stop atop now 
		*/
		if (midnightflag && (curtime+interval) > timelimit)
			break;

		/*
		** wait for alarm-signal to arrive (except first sample)
		** or wait for SIGUSR1/SIGUSR2
		*/
		if (sampcnt > 0 && awaittrigger)
			pause();

		awaittrigger = 1;

		/*
		** gather time info for this sample
		*/
		pretime  = curtime;
		curtime  = time(0);		/* seconds since 1-1-1970 */

		/*
		** take a snapshot of the current system-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		*/
		hlpsstat = cursstat;	/* swap current/prev. stats */
		cursstat = presstat;
		presstat = hlpsstat;

		photosyst(cursstat);	/* obtain new counters      */

		deviatsyst(cursstat, presstat, devsstat);

		/*
		** take a snapshot of the current process-level statistics 
		** and calculate the deviations (i.e. calculate the activity
		** during the last sample)
		**
		** first register active processes
		**  --> atop malloc's a minimal amount of space which is
		**      only extended when needed
		*/
		memset(curpact, 0, curplen * sizeof(struct pstat));

		while ( (npresent = photoproc(curpact, curplen)) == curplen)
		{
			curplen = countprocs() + PROCCHUNK;

			curpact = realloc(curpact,
			                   curplen * sizeof(struct pstat));

			memset(curpact, 0, curplen * sizeof(struct pstat));
		}

		/*
		** register processes which exited during last sample;
		** first determine how many processes exited and
		** reserve space for them, and secondly obtain the info
		*/
		nexit = acctprocnt();	/* number of exited processes */

		if (nexit > 0)	
		{
			curpexit = malloc(  nexit * sizeof(struct pstat));
			memset(curpexit, 0, nexit * sizeof(struct pstat));

			acctphotoproc(curpexit, nexit);
		}
		else
			curpexit = NULL;

		/*
		** calculate deviations
		*/
		devpstat = malloc((npresent+nexit) * sizeof(struct pstat));

		n = deviatproc(curpact, npresent, curpexit, nexit,
				deviatonly, devpstat, devsstat,
				&ntrun, &ntslpi, &ntslpu, &nzombie);

		/*
		** activate the installed print-function to visualize
		** the deviations
		*/
		lastcmd = (vis.show_samp)( curtime,
				     curtime-pretime > 0 ? curtime-pretime : 1,
		           	     devsstat, devpstat, n, npresent,
		                     ntrun, ntslpi, ntslpu, nzombie,
		                     nexit, sampcnt==0);

		/*
		** release dynamically allocated memory
		*/
		if (nexit > 0)
			free(curpexit);

		free(devpstat);

		if (lastcmd == 'r')	/* reset requested ? */
		{
			sampcnt = -1;

			curtime = getboot();	/* reset current time */

			/* set current (will be 'previous') counters to 0 */
			memset(cursstat, 0,           sizeof(struct sstat));
			memset(curpact,  0, curplen * sizeof(struct pstat));

			/* remove all processes in process database */
			pdb_makeresidue();
			pdb_cleanresidue();
		}
	} /* end of main-loop */
}