Ejemplo n.º 1
0
int
photoproc(struct tstat *tasks, int *taskslen)
{
	static int	setup;
	static pmID	pmids[TASK_NMETRICS];
	static pmDesc	descs[TASK_NMETRICS];
	pmResult	*result;
	char		**insts;
	int		*pids, count, i;

	if (!setup)
	{
		setup_metrics(procmetrics, pmids, descs, TASK_NMETRICS);
		setup = 1;
	}

	fetch_metrics("task", TASK_NMETRICS, pmids, &result);

	/* extract external process names (insts) */
	count = get_instances("task", TASK_GEN_NAME, descs, &pids, &insts);
	if (count > *taskslen)
	{
		size_t	size;
		int	ents = (*taskslen + PROCCHUNK);

		if (count > ents)
			ents = count;
		size = ents * sizeof(struct tstat);
		tasks = (struct tstat *)realloc(tasks, size);
		ptrverify(tasks, "photoproc [%ld]\n", (long)size);

		*taskslen = ents;
	}

	for (i=0; i < count; i++)
	{
		if (pmDebug & DBG_TRACE_APPL0)
			fprintf(stderr, "%s: updating process %d: %s\n",
				pmProgname, pids[i], insts[i]);
		update_task(&tasks[i], pids[i], insts[i], result, descs);
	}
	if (pmDebug & DBG_TRACE_APPL0)
		fprintf(stderr, "%s: done %d processes\n", pmProgname, count);

	pmFreeResult(result);
	free(insts);
	free(pids);

	return count;
}
Ejemplo n.º 2
0
/*
** calculate the system-activity during the last sample
*/
void
deviatsyst(struct sstat *cur, struct sstat *pre, struct sstat *dev)
{
	register int	i, j;
	size_t		size;
	count_t		*cdev, *ccur, *cpre;

	if (cur->cpu.nrcpu != dev->cpu.nrcpu)
	{
		size = cur->cpu.nrcpu * sizeof(struct percpu);
		dev->cpu.cpu = (struct percpu *)realloc(dev->cpu.cpu, size);
		ptrverify(dev->cpu.cpu, "deviatsyst cpus [%ld]", (long)size);
	}
	if (cur->cpu.nrcpu > pre->cpu.nrcpu)
	{
		free(pre->cpu.cpu);
		size = cur->cpu.nrcpu * sizeof(struct percpu);
		pre->cpu.cpu = (struct percpu *)calloc(1, size);
		ptrverify(pre->cpu.cpu, "deviatsyst precpus [%ld]", (long)size);
	}

	dev->cpu.nrcpu     = cur->cpu.nrcpu;
	dev->cpu.devint    = subcount(cur->cpu.devint, pre->cpu.devint);
	dev->cpu.csw       = subcount(cur->cpu.csw,    pre->cpu.csw);
	dev->cpu.nprocs    = subcount(cur->cpu.nprocs, pre->cpu.nprocs);

	dev->cpu.all.stime = subcount(cur->cpu.all.stime, pre->cpu.all.stime);
	dev->cpu.all.utime = subcount(cur->cpu.all.utime, pre->cpu.all.utime);
	dev->cpu.all.ntime = subcount(cur->cpu.all.ntime, pre->cpu.all.ntime);
	dev->cpu.all.itime = subcount(cur->cpu.all.itime, pre->cpu.all.itime);
	dev->cpu.all.wtime = subcount(cur->cpu.all.wtime, pre->cpu.all.wtime);
	dev->cpu.all.Itime = subcount(cur->cpu.all.Itime, pre->cpu.all.Itime);
	dev->cpu.all.Stime = subcount(cur->cpu.all.Stime, pre->cpu.all.Stime);

	dev->cpu.all.steal = subcount(cur->cpu.all.steal, pre->cpu.all.steal);
	dev->cpu.all.guest = subcount(cur->cpu.all.guest, pre->cpu.all.guest);

	for (i=0; i < dev->cpu.nrcpu; i++)
	{
		count_t 	ticks;

		dev->cpu.cpu[i].cpunr = cur->cpu.cpu[i].cpunr;
		dev->cpu.cpu[i].stime = subcount(cur->cpu.cpu[i].stime,
					         pre->cpu.cpu[i].stime);
		dev->cpu.cpu[i].utime = subcount(cur->cpu.cpu[i].utime,
				 	         pre->cpu.cpu[i].utime);
		dev->cpu.cpu[i].ntime = subcount(cur->cpu.cpu[i].ntime,
					         pre->cpu.cpu[i].ntime);
		dev->cpu.cpu[i].itime = subcount(cur->cpu.cpu[i].itime,
					         pre->cpu.cpu[i].itime);
		dev->cpu.cpu[i].wtime = subcount(cur->cpu.cpu[i].wtime,
					         pre->cpu.cpu[i].wtime);
		dev->cpu.cpu[i].Itime = subcount(cur->cpu.cpu[i].Itime,
					         pre->cpu.cpu[i].Itime);
		dev->cpu.cpu[i].Stime = subcount(cur->cpu.cpu[i].Stime,
					         pre->cpu.cpu[i].Stime);

		dev->cpu.cpu[i].steal = subcount(cur->cpu.cpu[i].steal,
					         pre->cpu.cpu[i].steal);
		dev->cpu.cpu[i].guest = subcount(cur->cpu.cpu[i].guest,
					         pre->cpu.cpu[i].guest);

		ticks 		      = cur->cpu.cpu[i].freqcnt.ticks;

		dev->cpu.cpu[i].freqcnt.maxfreq = 
					cur->cpu.cpu[i].freqcnt.maxfreq;
		dev->cpu.cpu[i].freqcnt.cnt = ticks ?
					subcount(cur->cpu.cpu[i].freqcnt.cnt,
					         pre->cpu.cpu[i].freqcnt.cnt)
					       : cur->cpu.cpu[i].freqcnt.cnt;

		dev->cpu.cpu[i].freqcnt.ticks = ticks ?
					subcount(cur->cpu.cpu[i].freqcnt.ticks,
					         pre->cpu.cpu[i].freqcnt.ticks)
					       : cur->cpu.cpu[i].freqcnt.ticks;
	}

	dev->cpu.lavg1		= cur->cpu.lavg1;
	dev->cpu.lavg5		= cur->cpu.lavg5;
	dev->cpu.lavg15		= cur->cpu.lavg15;

	dev->mem.physmem	= cur->mem.physmem;
	dev->mem.freemem	= cur->mem.freemem;
	dev->mem.buffermem	= cur->mem.buffermem;
	dev->mem.slabmem	= cur->mem.slabmem;
	dev->mem.slabreclaim	= cur->mem.slabreclaim;
	dev->mem.committed	= cur->mem.committed;
	dev->mem.commitlim	= cur->mem.commitlim;
	dev->mem.cachemem	= cur->mem.cachemem;
	dev->mem.cachedrt	= cur->mem.cachedrt;
	dev->mem.totswap	= cur->mem.totswap;
	dev->mem.freeswap	= cur->mem.freeswap;

	dev->mem.shmem		= cur->mem.shmem;
	dev->mem.shmrss		= cur->mem.shmrss;
	dev->mem.shmswp		= cur->mem.shmswp;

	dev->mem.tothugepage	= cur->mem.tothugepage;
	dev->mem.freehugepage	= cur->mem.freehugepage;
	dev->mem.hugepagesz	= cur->mem.hugepagesz;

	dev->mem.vmwballoon	= cur->mem.vmwballoon;

	dev->mem.swouts		= subcount(cur->mem.swouts,  pre->mem.swouts);
	dev->mem.swins		= subcount(cur->mem.swins,   pre->mem.swins);
	dev->mem.pgscans	= subcount(cur->mem.pgscans, pre->mem.pgscans);
	dev->mem.pgsteal	= subcount(cur->mem.pgsteal, pre->mem.pgsteal);
	dev->mem.allocstall	= subcount(cur->mem.allocstall,
				                         pre->mem.allocstall);

	/*
	** structures with network-related counters are considered
	** as tables of frequency-counters that have to be subtracted;
	** values that do not represent a frequency are corrected afterwards
	*/
	for (cdev = (count_t *)&dev->net.ipv4,
	     ccur = (count_t *)&cur->net.ipv4,
	     cpre = (count_t *)&pre->net.ipv4,
	     i    = 0;
		i < (sizeof dev->net.ipv4 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;
	
	dev->net.ipv4.Forwarding = cur->net.ipv4.Forwarding;
	dev->net.ipv4.DefaultTTL = cur->net.ipv4.DefaultTTL;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.icmpv4,
	     ccur = (count_t *)&cur->net.icmpv4,
	     cpre = (count_t *)&pre->net.icmpv4,
	     i    = 0;
		i < (sizeof dev->net.icmpv4 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.udpv4,
	     ccur = (count_t *)&cur->net.udpv4,
	     cpre = (count_t *)&pre->net.udpv4,
	     i    = 0;
		i < (sizeof dev->net.udpv4 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.ipv6,
	     ccur = (count_t *)&cur->net.ipv6,
	     cpre = (count_t *)&pre->net.ipv6,
	     i    = 0;
		i < (sizeof dev->net.ipv6 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.icmpv6,
	     ccur = (count_t *)&cur->net.icmpv6,
	     cpre = (count_t *)&pre->net.icmpv6,
	     i    = 0;
		i < (sizeof dev->net.icmpv6 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.udpv6,
	     ccur = (count_t *)&cur->net.udpv6,
	     cpre = (count_t *)&pre->net.udpv6,
	     i    = 0;
		i < (sizeof dev->net.udpv6 / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

		/* ------------- */

	for (cdev = (count_t *)&dev->net.tcp,
	     ccur = (count_t *)&cur->net.tcp,
	     cpre = (count_t *)&pre->net.tcp,
	     i    = 0;
		i < (sizeof dev->net.tcp / sizeof(count_t));
	     		cdev++, ccur++, cpre++, i++)
				*cdev = *ccur - *cpre;

	dev->net.tcp.RtoAlgorithm = cur->net.tcp.RtoAlgorithm;
	dev->net.tcp.RtoMin       = cur->net.tcp.RtoMin;
	dev->net.tcp.RtoMax       = cur->net.tcp.RtoMax;
	dev->net.tcp.MaxConn      = cur->net.tcp.MaxConn;
	dev->net.tcp.CurrEstab    = cur->net.tcp.CurrEstab;

	/*
	** calculate deviations for interfaces
	*/
	if (cur->intf.nrintf != dev->intf.nrintf)
	{
		size = (cur->intf.nrintf + 1) * sizeof(struct perintf);
		dev->intf.intf = (struct perintf *)realloc(dev->intf.intf, size);
		ptrverify(dev->intf.intf, "deviatsyst intf [%ld]\n", (long)size);
	}

	if (pre->intf.nrintf < cur->intf.nrintf)	/* first sample? */
	{
		struct ifprop	ifprop;

		free(pre->intf.intf);
		size = (cur->intf.nrintf + 1) * sizeof(struct perintf);
		pre->intf.intf = (struct perintf *)calloc(1, size);
		ptrverify(pre->intf.intf, "deviatsyst preintf [%ld]\n", size);

		for (i=0; cur->intf.intf[i].name[0]; i++)
		{
			strcpy(pre->intf.intf[i].name, cur->intf.intf[i].name);

			strcpy(ifprop.name, cur->intf.intf[i].name);

			getifprop(&ifprop);

			pre->intf.intf[i].speed         = ifprop.speed;
			pre->intf.intf[i].duplex        = ifprop.fullduplex;
 		}
		pre->intf.intf[i].name[0] = '\0';
	}

	for (i=0; cur->intf.intf && cur->intf.intf[i].name[0]; i++)
	{
		/*
		** check if an interface has been added or removed;
		** in that case, skip further handling for this sample
		*/
		if (strcmp(cur->intf.intf[i].name, pre->intf.intf[i].name) != 0)
		{
			int		j;
			struct ifprop	ifprop;

			/*
			** take care that interface properties are
			** corrected for future samples
			*/
		        initifprop();		/* refresh interface info   */

			for (j=0; cur->intf.intf[j].name[0]; j++)
			{
				strcpy(ifprop.name, cur->intf.intf[j].name);

				getifprop(&ifprop);

				cur->intf.intf[j].speed  = ifprop.speed;
				cur->intf.intf[j].duplex = ifprop.fullduplex;
			}

			break;
		}

		/*
		** calculate interface deviations for this sample
		*/
		strcpy(dev->intf.intf[i].name, cur->intf.intf[i].name);

		dev->intf.intf[i].rbyte = subcount(cur->intf.intf[i].rbyte,
           	                                   pre->intf.intf[i].rbyte);
		dev->intf.intf[i].rpack = subcount(cur->intf.intf[i].rpack,
		                                   pre->intf.intf[i].rpack);
		dev->intf.intf[i].rerrs = subcount(cur->intf.intf[i].rerrs,
		                                   pre->intf.intf[i].rerrs);
		dev->intf.intf[i].rdrop = subcount(cur->intf.intf[i].rdrop,
		                                   pre->intf.intf[i].rdrop);
		dev->intf.intf[i].rfifo = subcount(cur->intf.intf[i].rfifo,
		                                   pre->intf.intf[i].rfifo);
		dev->intf.intf[i].rframe= subcount(cur->intf.intf[i].rframe,
		                                   pre->intf.intf[i].rframe);
		dev->intf.intf[i].rcompr= subcount(cur->intf.intf[i].rcompr,
		                                   pre->intf.intf[i].rcompr);
		dev->intf.intf[i].rmultic=subcount(cur->intf.intf[i].rmultic,
		                                   pre->intf.intf[i].rmultic);

		dev->intf.intf[i].sbyte = subcount(cur->intf.intf[i].sbyte,
		                                   pre->intf.intf[i].sbyte);
		dev->intf.intf[i].spack = subcount(cur->intf.intf[i].spack,
		                                   pre->intf.intf[i].spack);
		dev->intf.intf[i].serrs = subcount(cur->intf.intf[i].serrs,
		                                   pre->intf.intf[i].serrs);
		dev->intf.intf[i].sdrop = subcount(cur->intf.intf[i].sdrop,
		                                   pre->intf.intf[i].sdrop);
		dev->intf.intf[i].sfifo = subcount(cur->intf.intf[i].sfifo,
		                                   pre->intf.intf[i].sfifo);
		dev->intf.intf[i].scollis= subcount(cur->intf.intf[i].scollis,
		                                   pre->intf.intf[i].scollis);
		dev->intf.intf[i].scarrier= subcount(cur->intf.intf[i].scarrier,
		                                   pre->intf.intf[i].scarrier);
		dev->intf.intf[i].scompr= subcount(cur->intf.intf[i].scompr,
		                                   pre->intf.intf[i].scompr);

		dev->intf.intf[i].speed 	= pre->intf.intf[i].speed;
		dev->intf.intf[i].duplex	= pre->intf.intf[i].duplex;

		/*
		** save interface properties for next interval
		*/
		cur->intf.intf[i].speed 	= pre->intf.intf[i].speed;
		cur->intf.intf[i].duplex	= pre->intf.intf[i].duplex;
	}

	dev->intf.intf[i].name[0] = '\0';
	dev->intf.nrintf = i;

	/*
	** calculate deviations for disks
	*/
	if (cur->dsk.ndsk != dev->dsk.ndsk)
	{
		size = (cur->dsk.ndsk + 1) * sizeof(struct perdsk);
		dev->dsk.dsk = (struct perdsk *)realloc(dev->dsk.dsk, size);
		ptrverify(dev->dsk.dsk, "deviatsyst disk [%ld]\n", (long)size);
	}
	for (i=j=0; cur->dsk.dsk && cur->dsk.dsk[i].name[0]; i++)
	{
		int	realj = j;

		/*
 		** check if disk has been added or removed since
		** previous interval
		*/
		if (pre->dsk.dsk[j].name[0] == '\0' ||
		    strcmp(cur->dsk.dsk[i].name, pre->dsk.dsk[j].name) != 0)
		{
			for (j=0; pre->dsk.dsk[j].name[0]; j++)
			{
				if ( strcmp(cur->dsk.dsk[i].name,
						pre->dsk.dsk[j].name) == 0)
					break;
			}

			/*
			** either the corresponding entry has been found
			** in the case that a disk has been removed, or
			** an empty entry has been found (all counters
			** on zero) in the case that a disk has been added
			** during the last sample
			*/
		}

		strcpy(dev->dsk.dsk[i].name, cur->dsk.dsk[i].name);

		dev->dsk.dsk[i].nread  = subcount(cur->dsk.dsk[i].nread,
		                                  pre->dsk.dsk[j].nread);
		dev->dsk.dsk[i].nwrite = subcount(cur->dsk.dsk[i].nwrite,
		                                  pre->dsk.dsk[j].nwrite);
		dev->dsk.dsk[i].nrsect = subcount(cur->dsk.dsk[i].nrsect,
		                                  pre->dsk.dsk[j].nrsect);
		dev->dsk.dsk[i].nwsect = subcount(cur->dsk.dsk[i].nwsect,
		                                  pre->dsk.dsk[j].nwsect);
		dev->dsk.dsk[i].io_ms  = subcount(cur->dsk.dsk[i].io_ms,
		                                  pre->dsk.dsk[j].io_ms);
		dev->dsk.dsk[i].avque  = subcount(cur->dsk.dsk[i].avque,
		                                  pre->dsk.dsk[j].avque);

		/*
		** determine new j
		*/
		if (pre->dsk.dsk[j].name[0] != '\0') // existing matching entry
			j++;
		else
			j = realj;		// empty entry: stick to old j
	}

	dev->dsk.dsk[i].name[0] = '\0';
	dev->dsk.ndsk = i;

	/*
	** calculate deviations for multiple devices
	*/
	if (cur->dsk.nmdd != dev->dsk.nmdd)
	{
		size = (cur->dsk.nmdd + 1) * sizeof(struct perdsk);
		dev->dsk.mdd = (struct perdsk *)realloc(dev->dsk.mdd, size);
		ptrverify(dev->dsk.mdd, "deviatsyst mdd [%ld]\n", (long)size);
	}
	for (i=j=0; cur->dsk.mdd && cur->dsk.mdd[i].name[0]; i++)
	{
		int	realj = j;

		/*
 		** check if md has been added or removed since
		** previous interval
		*/
		if (pre->dsk.mdd[j].name[0] == '\0' ||
		    strcmp(cur->dsk.mdd[i].name, pre->dsk.mdd[j].name) != 0)
		{
			for (j=0; pre->dsk.mdd[j].name[0]; j++)
			{
				if ( strcmp(cur->dsk.mdd[i].name,
						pre->dsk.mdd[j].name) == 0)
					break;
			}

			/*
			** either the corresponding entry has been found
			** in the case that a md has been removed, or
			** an empty entry has been found (all counters
			** on zero) in the case that a md has been added
			** during the last sample
			*/
		}

		strcpy(dev->dsk.mdd[i].name, cur->dsk.mdd[i].name);

		dev->dsk.mdd[i].nread  = subcount(cur->dsk.mdd[i].nread,
		                                  pre->dsk.mdd[j].nread);
		dev->dsk.mdd[i].nwrite = subcount(cur->dsk.mdd[i].nwrite,
		                                  pre->dsk.mdd[j].nwrite);
		dev->dsk.mdd[i].nrsect = subcount(cur->dsk.mdd[i].nrsect,
		                                  pre->dsk.mdd[j].nrsect);
		dev->dsk.mdd[i].nwsect = subcount(cur->dsk.mdd[i].nwsect,
		                                  pre->dsk.mdd[j].nwsect);
		dev->dsk.mdd[i].io_ms  = subcount(cur->dsk.mdd[i].io_ms,
		                                  pre->dsk.mdd[j].io_ms);
		dev->dsk.mdd[i].avque  = subcount(cur->dsk.mdd[i].avque,
		                                  pre->dsk.mdd[j].avque);

		/*
		** determine new j
		*/
		if (pre->dsk.mdd[j].name[0] != '\0') // existing matching entry
			j++;
		else
			j = realj;		// empty entry: stick to old j
	}

	dev->dsk.mdd[i].name[0] = '\0';
	dev->dsk.nmdd = i;

	/*
	** calculate deviations for LVM logical volumes
	*/
	if (cur->dsk.nlvm != dev->dsk.nlvm)
	{
		size = (cur->dsk.nlvm + 1) * sizeof(struct perdsk);
		dev->dsk.lvm = (struct perdsk *)realloc(dev->dsk.lvm, size);
		ptrverify(dev->dsk.lvm, "deviatsyst lvm [%ld]\n", (long)size);
	}
	for (i=j=0; cur->dsk.lvm && cur->dsk.lvm[i].name[0]; i++)
	{
		int	realj = j;

		/*
 		** check if logical volume has been added or removed since
		** previous interval
		*/
		if (pre->dsk.lvm[j].name[0] == '\0' ||
		    strcmp(cur->dsk.lvm[i].name, pre->dsk.lvm[j].name) != 0)
		{
			for (j=0; pre->dsk.lvm[j].name[0]; j++)
			{
				if ( strcmp(cur->dsk.lvm[i].name,
						pre->dsk.lvm[j].name) == 0)
					break;
			}

			/*
			** either the corresponding entry has been found
			** in the case that a logical volume has been removed,
			** or an empty entry has been found (all counters
			** on zero) in the case that a logical volume has
			** been added during the last sample
			*/
		}

		strcpy(dev->dsk.lvm[i].name, cur->dsk.lvm[i].name);

		dev->dsk.lvm[i].nread  = subcount(cur->dsk.lvm[i].nread,
		                                  pre->dsk.lvm[j].nread);
		dev->dsk.lvm[i].nwrite = subcount(cur->dsk.lvm[i].nwrite,
		                                  pre->dsk.lvm[j].nwrite);
		dev->dsk.lvm[i].nrsect = subcount(cur->dsk.lvm[i].nrsect,
		                                  pre->dsk.lvm[j].nrsect);
		dev->dsk.lvm[i].nwsect = subcount(cur->dsk.lvm[i].nwsect,
		                                  pre->dsk.lvm[j].nwsect);
		dev->dsk.lvm[i].io_ms  = subcount(cur->dsk.lvm[i].io_ms,
		                                  pre->dsk.lvm[j].io_ms);
		dev->dsk.lvm[i].avque  = subcount(cur->dsk.lvm[i].avque,
		                                  pre->dsk.lvm[j].avque);

		/*
		** determine new j
		*/
		if (pre->dsk.lvm[j].name[0] != '\0') // existing matching entry
			j++;
		else
			j = realj;		// empty entry: stick to old j
	}

	dev->dsk.lvm[i].name[0] = '\0';
	dev->dsk.nlvm = i;

	/*
	** application-specific counters
	*/
	if (cur->www.uptime >= pre->www.uptime)
	{
		dev->www.accesses  = subcount(cur->www.accesses,
                                              pre->www.accesses);
		dev->www.totkbytes = subcount(cur->www.totkbytes,
                                              pre->www.totkbytes);
	}
	else
	{
		dev->www.accesses  = cur->www.accesses;
		dev->www.totkbytes = cur->www.totkbytes;
	}

	dev->www.bworkers  = cur->www.bworkers;
	dev->www.iworkers  = cur->www.iworkers;
}
Ejemplo n.º 3
0
/*
** calculate the process-activity during the last sample
*/
int
deviattask(struct tstat *curtpres, int ntaskpres,
           struct tstat *curpexit, int nprocexit, int deviatonly,
	   struct tstat *devtstat, struct sstat *devsstat,
           unsigned int *nprocdev, int *nprocpres,
           int *totrun, int *totslpi, int *totslpu, int *totzombie)
{
	register int		c, d;
	register struct tstat	*curstat, *devstat, *procstat = 0;
	struct tstat		prestat;
	struct pinfo		*pinfo;
	count_t			totusedcpu;
	char			procsaved = 1, hashtype = 'p';

	/*
	** needed for sanity check later on...
	*/
	totusedcpu	= devsstat->cpu.all.stime + devsstat->cpu.all.utime +
			  devsstat->cpu.all.ntime + devsstat->cpu.all.itime +
			  devsstat->cpu.all.wtime + devsstat->cpu.all.Itime +
			  devsstat->cpu.all.Stime + devsstat->cpu.all.steal;

	/*
	** make new list of all tasks in the process-database;
	** after handling all processes, the left-overs are processes
	** that have disappeared since the previous sample
	*/
	pdb_makeresidue();

	/*
	** calculate deviations per present process
	*/
	*nprocpres = *totrun = *totslpi = *totslpu = *totzombie = 0;

	for (c=0, d=0, *nprocdev=0; c < ntaskpres; c++)
	{
		char	newtask = 0;

		curstat = curtpres+c;

		if (curstat->gen.isproc)
		{
			(*nprocpres)++;

			if (curstat->gen.state == 'Z')
			{
				(*totzombie)++;
			}
			else
			{
				*totrun		+= curstat->gen.nthrrun;
				*totslpi	+= curstat->gen.nthrslpi;
				*totslpu	+= curstat->gen.nthrslpu;
			}
		}

		/*
		** get previous figures from task-database
		*/
		if ( pdb_gettask(curstat->gen.pid, curstat->gen.isproc,
		                 curstat->gen.btime, &pinfo))
		{
			/*
			** task already present during the previous sample;
			** if no differences with previous sample, skip task
			** unless all tasks have to be shown
			**
			** it might be that a process appears to have no
			** differences while one its threads has differences;
			** than the process will be inserted as well
			*/
			if (deviatonly && memcmp(curstat, &pinfo->tstat, 
					           sizeof(struct tstat)) == EQ)
			{
				/* remember last unsaved process */
				if (curstat->gen.isproc)
				{
					procstat  = curstat;
					procsaved = 0;
				}

				continue;
			}

			/*
			** differences detected, so the task was active,
		        ** or its status or memory-occupation has changed;
			** save stats from previous sample (to use for
			** further calculations) and store new statistics
			** in task-database
			*/
			prestat 	= pinfo->tstat;	/* save old	*/
			pinfo->tstat 	= *curstat;	/* overwrite	*/
		}
		else
		{
			/*
			** new task which must have been started during
			** last interval
			*/
			memset(&prestat, 0, sizeof(prestat));

			/*
			** create new task struct
			*/
			pinfo = calloc(1, sizeof(struct pinfo));

			ptrverify(pinfo, "Malloc failed for new pinfo\n");

			pinfo->tstat = *curstat;

			/*
			** add new task to task-database
			*/
			pdb_addtask(curstat->gen.pid, pinfo);

			newtask = 1;
		}

		/*
		** active task found; do the difference calculations
		*/
		if (curstat->gen.isproc)
		{
			procsaved = 1;
			(*nprocdev)++;
		}
		else
		{
			/*
			** active thread: check if related process registered
			*/
			if (!procsaved)
			{
				devstat = devtstat+d;
				calcdiff(devstat, procstat, procstat, 0,
								totusedcpu);
				procsaved = 1;
				(*nprocdev)++;
				d++;
			}
		}

		devstat = devtstat+d;

		calcdiff(devstat, curstat, &prestat, newtask, totusedcpu);
		d++;
	}

	/*
	** calculate deviations per exited process
	*/
	if (nprocexit > 0 && supportflags&NETATOPD)
	{
		if (curpexit->gen.pid)
			hashtype = 'p';
		else
			hashtype = 'b';

		netatop_exithash(hashtype);
	}

	for (c=0; c < nprocexit; c++)
	{
		/*
		** check if this process has been started AND
		** finished since previous sample;
		** if so, it has no use to check if there is still 
		** existing info present in the process-database
		*/
		curstat = curpexit+c;

		if (curstat->gen.pid)	/* acctrecord contains pid? */
		{
			if ( pdb_gettask(curstat->gen.pid, 1,
			                 curstat->gen.btime, &pinfo))
					prestat = pinfo->tstat;
				else
					memset(&prestat, 0, sizeof(prestat));
		}
		else
		{
			if ( curstat->gen.btime > pretime.tv_sec )
			{
				/*
				** process-start and -finish in same interval
				*/
				memset(&prestat, 0, sizeof(prestat));
			}
			else
			{
				/*
				** process must be known in process-database;
				** try to match one of the remaining processes
				** against this exited one
				*/
				if ( pdb_srchresidue(curstat, &pinfo) )
					prestat = pinfo->tstat;
				else
					memset(&prestat, 0, sizeof(prestat));
		 	}
		}

		/*
		** now do the calculations
		*/
		devstat = devtstat+d;
		memset(devstat, 0, sizeof *devstat);

		devstat->gen        = curstat->gen;

		if ( curstat->gen.pid == 0 )
			devstat->gen.pid    = prestat.gen.pid;

		if (!prestat.gen.pid)
			devstat->gen.excode |= ~(INT_MAX);

		strcpy(devstat->gen.cmdline, prestat.gen.cmdline);

		/*
		** due to the strange exponent-type storage of values
		** in the process accounting record, the resource-value
		** in the exit-record might have been smaller than the
		** stored value of the last registered sample; in that
		** case the deviation should be set to zero
		*/
		if (curstat->cpu.stime > prestat.cpu.stime)
			devstat->cpu.stime  = curstat->cpu.stime -
			                      prestat.cpu.stime;

		if (curstat->cpu.utime > prestat.cpu.utime)
			devstat->cpu.utime  = curstat->cpu.utime -
			                      prestat.cpu.utime;

		if (curstat->mem.minflt > prestat.mem.minflt)
			devstat->mem.minflt = curstat->mem.minflt - 
			                      prestat.mem.minflt;

		if (curstat->mem.majflt > prestat.mem.majflt)
			devstat->mem.majflt = curstat->mem.majflt -
			                      prestat.mem.majflt;

		if (curstat->dsk.rio > (prestat.dsk.rio + prestat.dsk.wio))
			devstat->dsk.rio    = curstat->dsk.rio  -
			                      prestat.dsk.rio   -
			                      prestat.dsk.wio;

		/*
		** try to match the network counters of netatop
		*/
		if (supportflags & NETATOPD)
		{
			unsigned long	val = (hashtype == 'p' ?
						curstat->gen.pid :
						curstat->gen.btime);

			netatop_exitfind(val, devstat, &prestat);
		}
		d++;
		(*nprocdev)++;

		if (prestat.gen.pid > 0)
			pdb_deltask(prestat.gen.pid, prestat.gen.isproc);
	}

	/*
	** remove unused entries from RESIDUE chain
	*/
	pdb_cleanresidue();

	return d;
}
Ejemplo n.º 4
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 */
}
Ejemplo n.º 5
0
Archivo: atop.c Proyecto: 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 */
}
Ejemplo n.º 6
0
void
rawarchive(pmOptions *opts, const char *name)
{
	struct tm	*tp;
	time_t		timenow;
	char		tmp[MAXPATHLEN];
	char		path[MAXPATHLEN];
	char		*logdir, *py, *host;
	int		sep = __pmPathSeparator();
	int		sts, len = (name? strlen(name) : 0);

	if (len == 0)
		return rawfolio(opts);

	/* see if a valid archive exists as specified */
	if ((sts = pmNewContext(PM_CONTEXT_ARCHIVE, name)) >= 0)
	{
		pmDestroyContext(sts);
		__pmAddOptArchive(opts, (char * )name);
		return;
	}

	/* see if a valid folio exists as specified */
	strncpy(tmp, name, sizeof(tmp));
	tmp[sizeof(tmp)-1] = '\0';
	if (access(tmp, R_OK) == 0)
	{
		__pmAddOptArchiveFolio(opts, tmp);
		return;
	}
	snprintf(path, sizeof(path), "%s/%s.folio", name, basename(tmp));
	path[sizeof(path)-1] = '\0';
	if (access(path, R_OK) == 0)
	{
		__pmAddOptArchiveFolio(opts, path);
		return;
	}

	/* else go hunting in the system locations... */
	if ((logdir = pmGetOptionalConfig("PCP_LOG_DIR")) == NULL)
	{
		fprintf(stderr, "%s: cannot find PCP_LOG_DIR\n", pmProgname);
		cleanstop(1);
	}

	host = rawlocalhost(opts);

	/*
	** Use original rawread() algorithms for specifying dates
	*/

	if (len == 8 && lookslikedatetome(name))
	{
		snprintf(path, sizeof(path), "%s%c%s%c%s%c%s",
			logdir, sep, "pmlogger", sep, host, sep, name);
		__pmAddOptArchive(opts, (char * )path);
	}
	/*
	** if one or more 'y' (yesterday) characters are used and that
	** string is not known as an existing file, the standard logfile
	** is shown from N days ago (N is determined by the number
	** of y's).
	*/
	else
	{
                /*
		** make a string existing of y's to compare with
		*/
		py = malloc(len+1);
		ptrverify(py, "Malloc failed for 'yes' sequence\n");

		memset(py, 'y', len);
		*(py+len) = '\0';

		if ( strcmp(name, py) == 0 )
		{
			timenow  = time(0);
			timenow -= len*3600*24;
			tp       = localtime(&timenow);

			snprintf(path, sizeof(path), "%s%c%s%c%s%c%04u%02u%02u",
				logdir, sep, "pmlogger", sep, host, sep,
				tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday);
			__pmAddOptArchive(opts, (char * )path);
		}
		else
		{
			fprintf(stderr, "%s: cannot find archive from \"%s\"\n",
				pmProgname, name);
			cleanstop(1);
		}

		free(py);
	}
}