2 * sar and sadf common routines.
3 * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19 ***************************************************************************
27 #include <unistd.h> /* For STDOUT_FILENO, among others */
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
41 #define _(string) gettext(string)
43 #define _(string) (string)
46 extern struct act_bitmap cpu_bitmap;
49 ***************************************************************************
50 * Init a bitmap (CPU, IRQ, etc.).
53 * @value Value used to init bitmap.
54 * @sz Size of the bitmap in bytes.
57 * @bitmap Bitmap initialized.
58 ***************************************************************************
60 void set_bitmap(unsigned char bitmap[], unsigned char value, unsigned int sz)
64 for (i = 0; i < sz; i++) {
70 ***************************************************************************
71 * Allocate structures.
74 * @act Array of activities.
75 ***************************************************************************
77 void allocate_structures(struct activity *act[])
81 for (i = 0; i < NR_ACT; i++) {
83 for (j = 0; j < 3; j++) {
84 SREALLOC(act[i]->buf[j], void, act[i]->msize * act[i]->nr * act[i]->nr2);
91 ***************************************************************************
95 * @act Array of activities.
96 ***************************************************************************
98 void free_structures(struct activity *act[])
102 for (i = 0; i < NR_ACT; i++) {
103 if (act[i]->nr > 0) {
104 for (j = 0; j < 3; j++) {
105 if (act[i]->buf[j]) {
106 free(act[i]->buf[j]);
107 act[i]->buf[j] = NULL;
115 ***************************************************************************
116 * Get device real name if possible.
117 * Warning: This routine may return a bad name on 2.4 kernels where
118 * disk activities are read from /proc/stat.
121 * @major Major number of the device.
122 * @minor Minor number of the device.
123 * @pretty TRUE if the real name of the device (as it appears in /dev)
124 * should be returned.
127 * The name of the device, which may be the real name (as it appears in /dev)
128 * or a string with the following format devM-n.
129 ***************************************************************************
131 char *get_devname(unsigned int major, unsigned int minor, int pretty)
136 snprintf(buf, 32, "dev%d-%d", major, minor);
141 name = ioc_name(major, minor);
142 if ((name == NULL) || !strcmp(name, K_NODEV))
149 ***************************************************************************
150 * Check if we are close enough to desired interval.
153 * @uptime_ref Uptime used as reference. This is the system uptime for the
154 * first sample statistics, or the first system uptime after a
156 * @uptime Current system uptime.
157 * @reset TRUE if @last_uptime should be reset with @uptime_ref.
158 * @interval Interval of time.
161 * 1 if we are actually close enough to desired interval, 0 otherwise.
162 ***************************************************************************
164 int next_slice(unsigned long long uptime_ref, unsigned long long uptime,
165 int reset, long interval)
167 unsigned long file_interval, entry;
168 static unsigned long long last_uptime = 0;
169 int min, max, pt1, pt2;
172 /* uptime is expressed in jiffies (basis of 1 processor) */
173 if (!last_uptime || reset) {
174 last_uptime = uptime_ref;
177 /* Interval cannot be greater than 0xffffffff here */
178 f = ((double) ((uptime - last_uptime) & 0xffffffff)) / HZ;
179 file_interval = (unsigned long) f;
180 if ((f * 10) - (file_interval * 10) >= 5) {
181 file_interval++; /* Rounding to correct value */
184 last_uptime = uptime;
187 * A few notes about the "algorithm" used here to display selected entries
188 * from the system activity file (option -f with -i flag):
189 * Let 'Iu' be the interval value given by the user on the command line,
190 * 'If' the interval between current and previous line in the system
192 * and 'En' the nth entry (identified by its time stamp) of the file.
193 * We choose In = [ En - If/2, En + If/2 [ if If is even,
194 * or In = [ En - If/2, En + If/2 ] if not.
195 * En will be displayed if
196 * (Pn * Iu) or (P'n * Iu) belongs to In
197 * with Pn = En / Iu and P'n = En / Iu + 1
199 f = ((double) ((uptime - uptime_ref) & 0xffffffff)) / HZ;
200 entry = (unsigned long) f;
201 if ((f * 10) - (entry * 10) >= 5) {
205 min = entry - (file_interval / 2);
206 max = entry + (file_interval / 2) + (file_interval & 0x1);
207 pt1 = (entry / interval) * interval;
208 pt2 = ((entry / interval) + 1) * interval;
210 return (((pt1 >= min) && (pt1 < max)) || ((pt2 >= min) && (pt2 < max)));
214 ***************************************************************************
215 * Use time stamp to fill tstamp structure.
218 * @timestamp Timestamp to decode (format: HH:MM:SS).
221 * @tse Structure containing the decoded timestamp.
224 * 0 if the timestamp has been successfully decoded, 1 otherwise.
225 ***************************************************************************
227 int decode_timestamp(char timestamp[], struct tstamp *tse)
229 timestamp[2] = timestamp[5] = '\0';
230 tse->tm_sec = atoi(×tamp[6]);
231 tse->tm_min = atoi(×tamp[3]);
232 tse->tm_hour = atoi(timestamp);
234 if ((tse->tm_sec < 0) || (tse->tm_sec > 59) ||
235 (tse->tm_min < 0) || (tse->tm_min > 59) ||
236 (tse->tm_hour < 0) || (tse->tm_hour > 23))
245 ***************************************************************************
246 * Compare two timestamps.
249 * @rectime Date and time for current sample.
250 * @tse Timestamp used as reference.
253 * A positive value if @rectime is greater than @tse,
254 * a negative one otherwise.
255 ***************************************************************************
257 int datecmp(struct tm *rectime, struct tstamp *tse)
259 if (rectime->tm_hour == tse->tm_hour) {
260 if (rectime->tm_min == tse->tm_min)
261 return (rectime->tm_sec - tse->tm_sec);
263 return (rectime->tm_min - tse->tm_min);
266 return (rectime->tm_hour - tse->tm_hour);
270 ***************************************************************************
271 * Parse a time stamp entered on the command line (hh:mm:ss) and decode it.
274 * @argv Arguments list.
275 * @opt Index in the arguments list.
276 * @def_timestamp Default timestamp to use.
279 * @tse Structure containing the decoded timestamp.
282 * 0 if the timestamp has been successfully decoded, 1 otherwise.
283 ***************************************************************************
285 int parse_timestamp(char *argv[], int *opt, struct tstamp *tse,
286 const char *def_timestamp)
290 if ((argv[++(*opt)]) && (strlen(argv[*opt]) == 8)) {
291 strcpy(timestamp, argv[(*opt)++]);
294 strcpy(timestamp, def_timestamp);
297 return decode_timestamp(timestamp, tse);
301 ***************************************************************************
302 * Set current daily data file name.
305 * @rectime Current date and time.
306 * @datafile Name of daily data file.
307 ***************************************************************************
309 void set_default_file(struct tm *rectime, char *datafile)
312 snprintf(datafile, MAX_FILE_LEN,
313 "%s/sa%02d", SA_DIR, rectime->tm_mday);
314 datafile[MAX_FILE_LEN - 1] = '\0';
318 ***************************************************************************
319 * Set interval value.
322 * @record_hdr_curr Record with current sample statistics.
323 * @record_hdr_prev Record with previous sample statistics.
324 * @nr_proc Number of CPU, including CPU "all".
327 * @itv Interval in jiffies.
328 * @g_itv Interval in jiffies multiplied by the # of proc.
329 ***************************************************************************
331 void get_itv_value(struct record_header *record_hdr_curr,
332 struct record_header *record_hdr_prev,
333 unsigned int nr_proc,
334 unsigned long long *itv, unsigned long long *g_itv)
336 /* Interval value in jiffies */
337 *g_itv = get_interval(record_hdr_prev->uptime,
338 record_hdr_curr->uptime);
341 *itv = get_interval(record_hdr_prev->uptime0,
342 record_hdr_curr->uptime0);
350 ***************************************************************************
351 * Fill the rectime structure with the file's creation date, based on file's
352 * time data saved in file header.
353 * The resulting timestamp is expressed in the locale of the file creator or
354 * in the user's own locale, depending on whether option -t has been used
358 * @flags Flags for common options and system state.
359 * @file_hdr System activity file standard header.
362 * @rectime Date and time from file header.
363 ***************************************************************************
365 void get_file_timestamp_struct(unsigned int flags, struct tm *rectime,
366 struct file_header *file_hdr)
370 if (PRINT_TRUE_TIME(flags)) {
371 /* Get local time. This is just to fill HH:MM:SS fields */
374 rectime->tm_mday = file_hdr->sa_day;
375 rectime->tm_mon = file_hdr->sa_month;
376 rectime->tm_year = file_hdr->sa_year;
378 * Call mktime() to set DST (Daylight Saving Time) flag.
379 * Has anyone a better way to do it?
381 rectime->tm_hour = rectime->tm_min = rectime->tm_sec = 0;
385 if ((loc_t = localtime((const time_t *) &file_hdr->sa_ust_time)) != NULL) {
392 ***************************************************************************
393 * Print report header.
396 * @flags Flags for common options and system state.
397 * @file_hdr System activity file standard header.
398 * @cpu_nr Number of CPU (value in [1, NR_CPUS + 1]).
399 * 1 means that there is only one proc and non SMP kernel.
400 * 2 means one proc and SMP kernel.
404 * @rectime Date and time from file header.
405 ***************************************************************************
407 void print_report_hdr(unsigned int flags, struct tm *rectime,
408 struct file_header *file_hdr, int cpu_nr)
411 /* Get date of file creation */
412 get_file_timestamp_struct(flags, rectime, file_hdr);
414 /* Display the header */
415 print_gal_header(rectime, file_hdr->sa_sysname, file_hdr->sa_release,
416 file_hdr->sa_nodename, file_hdr->sa_machine,
417 cpu_nr > 1 ? cpu_nr - 1 : 1);
421 ***************************************************************************
422 * Network interfaces may now be registered (and unregistered) dynamically.
423 * This is what we try to guess here.
426 * @a Activity structure with statistics.
427 * @curr Index in array for current sample statistics.
428 * @ref Index in array for sample statistics used as reference.
429 * @pos Index on current network interface.
432 * Position of current network interface in array of sample statistics used
434 ***************************************************************************
436 unsigned int check_net_dev_reg(struct activity *a, int curr, int ref,
439 struct stats_net_dev *sndc, *sndp;
440 unsigned int index = 0;
442 sndc = (struct stats_net_dev *) a->buf[curr] + pos;
444 while (index < a->nr) {
445 sndp = (struct stats_net_dev *) a->buf[ref] + index;
446 if (!strcmp(sndc->interface, sndp->interface)) {
448 * Network interface found.
449 * If a counter has decreased, then we may assume that the
450 * corresponding interface was unregistered, then registered again.
452 if ((sndc->rx_packets < sndp->rx_packets) ||
453 (sndc->tx_packets < sndp->tx_packets) ||
454 (sndc->rx_bytes < sndp->rx_bytes) ||
455 (sndc->tx_bytes < sndp->tx_bytes) ||
456 (sndc->rx_compressed < sndp->rx_compressed) ||
457 (sndc->tx_compressed < sndp->tx_compressed) ||
458 (sndc->multicast < sndp->multicast)) {
461 * Special processing for rx_bytes (_packets) and
462 * tx_bytes (_packets) counters: If the number of
463 * bytes (packets) has decreased, whereas the number of
464 * packets (bytes) has increased, then assume that the
465 * relevant counter has met an overflow condition, and that
466 * the interface was not unregistered, which is all the
467 * more plausible that the previous value for the counter
469 * NB: the average value displayed will be wrong in this case...
471 * If such an overflow is detected, just set the flag. There is no
472 * need to handle this in a special way: the difference is still
473 * properly calculated if the result is of the same type (i.e.
474 * unsigned long) as the two values.
478 if ((sndc->rx_bytes < sndp->rx_bytes) &&
479 (sndc->rx_packets > sndp->rx_packets) &&
480 (sndp->rx_bytes > (~0UL >> 1))) {
483 if ((sndc->tx_bytes < sndp->tx_bytes) &&
484 (sndc->tx_packets > sndp->tx_packets) &&
485 (sndp->tx_bytes > (~0UL >> 1))) {
488 if ((sndc->rx_packets < sndp->rx_packets) &&
489 (sndc->rx_bytes > sndp->rx_bytes) &&
490 (sndp->rx_packets > (~0UL >> 1))) {
493 if ((sndc->tx_packets < sndp->tx_packets) &&
494 (sndc->tx_bytes > sndp->tx_bytes) &&
495 (sndp->tx_packets > (~0UL >> 1))) {
501 * OK: assume here that the device was
502 * actually unregistered.
504 memset(sndp, 0, STATS_NET_DEV_SIZE);
505 strcpy(sndp->interface, sndc->interface);
513 /* Network interface not found: Look for the first free structure */
514 for (index = 0; index < a->nr; index++) {
515 sndp = (struct stats_net_dev *) a->buf[ref] + index;
516 if (!strcmp(sndp->interface, "?")) {
517 memset(sndp, 0, STATS_NET_DEV_SIZE);
518 strcpy(sndp->interface, sndc->interface);
522 if (index >= a->nr) {
523 /* No free structure: Default is structure of same rank */
527 sndp = (struct stats_net_dev *) a->buf[ref] + index;
528 /* Since the name is not the same, reset all the structure */
529 memset(sndp, 0, STATS_NET_DEV_SIZE);
530 strcpy(sndp->interface, sndc->interface);
536 ***************************************************************************
537 * Network interfaces may now be registered (and unregistered) dynamically.
538 * This is what we try to guess here.
541 * @a Activity structure with statistics.
542 * @curr Index in array for current sample statistics.
543 * @ref Index in array for sample statistics used as reference.
544 * @pos Index on current network interface.
547 * Position of current network interface in array of sample statistics used
549 ***************************************************************************
551 unsigned int check_net_edev_reg(struct activity *a, int curr, int ref,
554 struct stats_net_edev *snedc, *snedp;
555 unsigned int index = 0;
557 snedc = (struct stats_net_edev *) a->buf[curr] + pos;
559 while (index < a->nr) {
560 snedp = (struct stats_net_edev *) a->buf[ref] + index;
561 if (!strcmp(snedc->interface, snedp->interface)) {
563 * Network interface found.
564 * If a counter has decreased, then we may assume that the
565 * corresponding interface was unregistered, then registered again.
567 if ((snedc->tx_errors < snedp->tx_errors) ||
568 (snedc->collisions < snedp->collisions) ||
569 (snedc->rx_dropped < snedp->rx_dropped) ||
570 (snedc->tx_dropped < snedp->tx_dropped) ||
571 (snedc->tx_carrier_errors < snedp->tx_carrier_errors) ||
572 (snedc->rx_frame_errors < snedp->rx_frame_errors) ||
573 (snedc->rx_fifo_errors < snedp->rx_fifo_errors) ||
574 (snedc->tx_fifo_errors < snedp->tx_fifo_errors)) {
577 * OK: assume here that the device was
578 * actually unregistered.
580 memset(snedp, 0, STATS_NET_EDEV_SIZE);
581 strcpy(snedp->interface, snedc->interface);
588 /* Network interface not found: Look for the first free structure */
589 for (index = 0; index < a->nr; index++) {
590 snedp = (struct stats_net_edev *) a->buf[ref] + index;
591 if (!strcmp(snedp->interface, "?")) {
592 memset(snedp, 0, STATS_NET_EDEV_SIZE);
593 strcpy(snedp->interface, snedc->interface);
597 if (index >= a->nr) {
598 /* No free structure: Default is structure of same rank */
602 snedp = (struct stats_net_edev *) a->buf[ref] + index;
603 /* Since the name is not the same, reset all the structure */
604 memset(snedp, 0, STATS_NET_EDEV_SIZE);
605 strcpy(snedp->interface, snedc->interface);
611 ***************************************************************************
612 * Disks may be registered dynamically (true in /proc/stat file).
613 * This is what we try to guess here.
616 * @a Activity structure with statistics.
617 * @curr Index in array for current sample statistics.
618 * @ref Index in array for sample statistics used as reference.
619 * @pos Index on current disk.
622 * Position of current disk in array of sample statistics used as reference.
623 ***************************************************************************
625 int check_disk_reg(struct activity *a, int curr, int ref, int pos)
627 struct stats_disk *sdc, *sdp;
630 sdc = (struct stats_disk *) a->buf[curr] + pos;
632 while (index < a->nr) {
633 sdp = (struct stats_disk *) a->buf[ref] + index;
634 if ((sdc->major == sdp->major) &&
635 (sdc->minor == sdp->minor)) {
638 * If all the counters have decreased then the likelyhood
639 * is that the disk has been unregistered and a new disk inserted.
640 * If only one or two have decreased then the likelyhood
641 * is that the counter has simply wrapped.
643 if ((sdc->nr_ios < sdp->nr_ios) &&
644 (sdc->rd_sect < sdp->rd_sect) &&
645 (sdc->wr_sect < sdp->wr_sect)) {
647 memset(sdp, 0, STATS_DISK_SIZE);
648 sdp->major = sdc->major;
649 sdp->minor = sdc->minor;
656 /* Disk not found: Look for the first free structure */
657 for (index = 0; index < a->nr; index++) {
658 sdp = (struct stats_disk *) a->buf[ref] + index;
659 if (!(sdp->major + sdp->minor)) {
660 memset(sdp, 0, STATS_DISK_SIZE);
661 sdp->major = sdc->major;
662 sdp->minor = sdc->minor;
666 if (index >= a->nr) {
667 /* No free structure found: Default is structure of same rank */
671 sdp = (struct stats_disk *) a->buf[ref] + index;
672 /* Since the device is not the same, reset all the structure */
673 memset(sdp, 0, STATS_DISK_SIZE);
674 sdp->major = sdc->major;
675 sdp->minor = sdc->minor;
681 ***************************************************************************
682 * Allocate bitmaps for activities that have one.
685 * @act Array of activities.
686 ***************************************************************************
688 void allocate_bitmaps(struct activity *act[])
692 for (i = 0; i < NR_ACT; i++) {
694 * If current activity has a bitmap which has not already
695 * been allocated, then allocate it.
696 * Note that a same bitmap may be used by several activities.
698 if (act[i]->bitmap && !act[i]->bitmap->b_array) {
699 SREALLOC(act[i]->bitmap->b_array, unsigned char,
700 BITMAP_SIZE(act[i]->bitmap->b_size));
706 ***************************************************************************
707 * Free bitmaps for activities that have one.
710 * @act Array of activities.
711 ***************************************************************************
713 void free_bitmaps(struct activity *act[])
717 for (i = 0; i < NR_ACT; i++) {
718 if (act[i]->bitmap && act[i]->bitmap->b_array) {
719 free(act[i]->bitmap->b_array);
720 /* Set pointer to NULL to prevent it from being freed again */
721 act[i]->bitmap->b_array = NULL;
727 ***************************************************************************
728 * Look for activity in array.
731 * @act Array of activities.
732 * @act_flag Activity flag to look for.
735 * Position of activity in array, or -1 if not found (this may happen when
736 * reading data from a system activity file created by another version of
738 ***************************************************************************
740 int get_activity_position(struct activity *act[], unsigned int act_flag)
744 for (i = 0; i < NR_ACT; i++) {
745 if (act[i]->id == act_flag)
756 ***************************************************************************
757 * Count number of activities with given option.
760 * @act Array of activities.
761 * @option Option that activities should have to be counted
762 * (eg. AO_COLLECTED...)
763 * @count_outputs TRUE if each output should be counted for activities with
767 * Number of selected activities
768 ***************************************************************************
770 int get_activity_nr(struct activity *act[], unsigned int option, int count_outputs)
775 for (i = 0; i < NR_ACT; i++) {
776 if ((act[i]->options & option) == option) {
778 if (HAS_MULTIPLE_OUTPUTS(act[i]->options) && count_outputs) {
779 for (msk = 1; msk < 0x10; msk <<= 1) {
780 if (act[i]->opt_flags & msk) {
795 ***************************************************************************
796 * Select all activities, even if they have no associated items.
799 * @act Array of activities.
802 * @act Array of activities, all of the being selected.
803 ***************************************************************************
805 void select_all_activities(struct activity *act[])
809 for (i = 0; i < NR_ACT; i++) {
810 act[i]->options |= AO_SELECTED;
815 ***************************************************************************
816 * Select CPU activity if no other activities have been explicitly selected.
817 * Also select CPU "all" if no other CPU has been selected.
820 * @act Array of activities.
823 * @act Array of activities with CPU activity selected if needed.
824 ***************************************************************************
826 void select_default_activity(struct activity *act[])
830 p = get_activity_position(act, A_CPU);
832 /* Default is CPU activity... */
833 if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
835 * Still OK even when reading stats from a file
836 * since A_CPU activity is always recorded.
838 act[p]->options |= AO_SELECTED;
842 * If no CPU's have been selected then select CPU "all".
843 * cpu_bitmap bitmap may be used by several activities (A_CPU, A_PWR_CPUFREQ...)
845 if (!count_bits(cpu_bitmap.b_array, BITMAP_SIZE(cpu_bitmap.b_size))) {
846 cpu_bitmap.b_array[0] |= 0x01;
851 ***************************************************************************
852 * Read data from a system activity data file.
855 * @ifd Input file descriptor.
856 * @buffer Buffer where data are read.
857 * @size Number of bytes to read.
858 * @mode If set to HARD_SIZE, indicate that an EOF should be considered
862 * 1 if EOF has been reached, 0 otherwise.
863 ***************************************************************************
865 int sa_fread(int ifd, void *buffer, int size, int mode)
869 if ((n = read(ifd, buffer, size)) < 0) {
870 fprintf(stderr, _("Error while reading system activity file: %s\n"),
876 if (!n && (mode == SOFT_SIZE))
880 fprintf(stderr, _("End of system activity file unexpected\n"));
889 ***************************************************************************
890 * Display sysstat version used to create system activity data file.
893 * @file_magic File magic header
894 ***************************************************************************
896 void display_sa_file_version(struct file_magic *file_magic)
898 fprintf(stderr, _("File created using sar/sadc from sysstat version %d.%d.%d"),
899 file_magic->sysstat_version,
900 file_magic->sysstat_patchlevel,
901 file_magic->sysstat_sublevel);
903 if (file_magic->sysstat_extraversion) {
904 fprintf(stderr, ".%d", file_magic->sysstat_extraversion);
906 fprintf(stderr, "\n");
910 ***************************************************************************
911 * An invalid system activity file has been opened for reading.
912 * If this file was created by an old version of sysstat, tell it to the
916 * @fd Descriptor of the file that has been opened.
917 * @file_magic file_magic structure filled with file magic header data.
918 * May contain invalid data.
919 * @file Name of the file being read.
920 * @n Number of bytes read while reading file magic header.
921 * This function may also be called after failing to read file
922 * standard header, or if CPU activity has not been found in
923 * file. In this case, n is set to 0.
924 ***************************************************************************
926 void handle_invalid_sa_file(int *fd, struct file_magic *file_magic, char *file,
929 fprintf(stderr, _("Invalid system activity file: %s\n"), file);
931 if ((n == FILE_MAGIC_SIZE) && (file_magic->sysstat_magic == SYSSTAT_MAGIC)) {
932 /* This is a sysstat file, but this file has an old format */
933 display_sa_file_version(file_magic);
936 _("Current sysstat version can no longer read the format of this file (%#x)\n"),
937 file_magic->format_magic);
945 ***************************************************************************
946 * Move structures data.
949 * @act Array of activities.
950 * @id_seq Activity sequence in file.
951 * @record_hdr Current record header.
952 * @dest Index in array where stats have to be copied to.
953 * @src Index in array where stats to copy are.
954 ***************************************************************************
956 void copy_structures(struct activity *act[], unsigned int id_seq[],
957 struct record_header record_hdr[], int dest, int src)
961 memcpy(&record_hdr[dest], &record_hdr[src], RECORD_HEADER_SIZE);
963 for (i = 0; i < NR_ACT; i++) {
968 if (((p = get_activity_position(act, id_seq[i])) < 0) ||
969 (act[p]->nr < 1) || (act[p]->nr2 < 1)) {
973 memcpy(act[p]->buf[dest], act[p]->buf[src], act[p]->msize * act[p]->nr * act[p]->nr2);
978 ***************************************************************************
979 * Read varying part of the statistics from a daily data file.
982 * @act Array of activities.
983 * @curr Index in array for current sample statistics.
984 * @ifd Input file descriptor.
985 * @act_nr Number of activities in file.
986 * @file_actlst Activity list in file.
987 ***************************************************************************
989 void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr,
990 struct file_activity *file_actlst)
993 struct file_activity *fal = file_actlst;
995 for (i = 0; i < act_nr; i++, fal++) {
997 if (((p = get_activity_position(act, fal->id)) < 0) ||
998 (act[p]->magic != fal->magic)) {
1000 * Ignore current activity in file, which is unknown to
1001 * current sysstat version or has an unknown format.
1003 if (lseek(ifd, fal->size * fal->nr * fal->nr2, SEEK_CUR) < (fal->size * fal->nr * fal->nr2)) {
1009 else if ((act[p]->nr > 0) &&
1010 ((act[p]->nr > 1) || (act[p]->nr2 > 1)) &&
1011 (act[p]->msize > act[p]->fsize)) {
1012 for (j = 0; j < act[p]->nr; j++) {
1013 for (k = 0; k < act[p]->nr2; k++) {
1015 (char *) act[p]->buf[curr] + (j * act[p]->nr2 + k) * act[p]->msize,
1016 act[p]->fsize, HARD_SIZE);
1020 else if (act[p]->nr > 0) {
1021 sa_fread(ifd, act[p]->buf[curr], act[p]->fsize * act[p]->nr * act[p]->nr2, HARD_SIZE);
1030 ***************************************************************************
1031 * Open a data file, and perform various checks before reading.
1034 * @dfile Name of system activity data file
1035 * @act Array of activities.
1036 * @ignore Set to 1 if a true sysstat activity file but with a bad
1037 * format should not yield an error message. Useful with
1041 * @ifd System activity data file descriptor
1042 * @file_magic file_magic structure containing data read from file magic
1044 * @file_hdr file_hdr structure containing data read from file standard
1046 * @file_actlst Acvtivity list in file.
1047 * @id_seq Activity sequence.
1048 ***************************************************************************
1050 void check_file_actlst(int *ifd, char *dfile, struct activity *act[],
1051 struct file_magic *file_magic, struct file_header *file_hdr,
1052 struct file_activity **file_actlst, unsigned int id_seq[],
1056 unsigned int a_cpu = FALSE;
1057 struct file_activity *fal;
1059 /* Open sa data file */
1060 if ((*ifd = open(dfile, O_RDONLY)) < 0) {
1061 fprintf(stderr, _("Cannot open %s: %s\n"), dfile, strerror(errno));
1065 /* Read file magic data */
1066 n = read(*ifd, file_magic, FILE_MAGIC_SIZE);
1068 if ((n != FILE_MAGIC_SIZE) ||
1069 (file_magic->sysstat_magic != SYSSTAT_MAGIC) ||
1070 (file_magic->format_magic != FORMAT_MAGIC)) {
1073 (n == FILE_MAGIC_SIZE) &&
1074 (file_magic->sysstat_magic == SYSSTAT_MAGIC))
1075 /* Don't display error message. This is for sadf -H */
1078 /* Display error message and exit */
1079 handle_invalid_sa_file(ifd, file_magic, dfile, n);
1083 /* Read sa data file standard header and allocate activity list */
1084 sa_fread(*ifd, file_hdr, FILE_HEADER_SIZE, HARD_SIZE);
1086 SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_nr_act);
1089 /* Read activity list */
1091 for (i = 0; i < file_hdr->sa_nr_act; i++, fal++) {
1093 sa_fread(*ifd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE);
1095 if ((fal->nr < 1) || (fal->nr2 < 1)) {
1097 * Every activity, known or unknown,
1098 * should have at least one item and sub-item.
1100 handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1103 if ((p = get_activity_position(act, fal->id)) < 0)
1104 /* Unknown activity */
1107 if (act[p]->magic != fal->magic) {
1108 /* Bad magical number */
1111 * This is how sadf -H knows that this
1112 * activity has an unknown format.
1114 act[p]->magic = ACTIVITY_MAGIC_UNKNOWN;
1120 if (fal->id == A_CPU) {
1124 if (fal->size > act[p]->msize) {
1125 act[p]->msize = fal->size;
1127 act[p]->fsize = fal->size;
1128 act[p]->nr = fal->nr;
1129 act[p]->nr2 = fal->nr2;
1131 * This is a known activity with a known format
1132 * (magical number). Only such activities will be displayed.
1133 * (Well, this may also be an unknown format if we have entered sadf -H.)
1135 id_seq[j++] = fal->id;
1140 * CPU activity should always be in file
1141 * and have a known format (expected magical number).
1143 handle_invalid_sa_file(ifd, file_magic, dfile, 0);
1146 while (j < NR_ACT) {
1150 /* Check that at least one selected activity is available in file */
1151 for (i = 0; i < NR_ACT; i++) {
1153 if (!IS_SELECTED(act[i]->options))
1156 /* Here is a selected activity: Does it exist in file? */
1158 for (j = 0; j < file_hdr->sa_nr_act; j++, fal++) {
1159 if (act[i]->id == fal->id)
1162 if (j == file_hdr->sa_nr_act) {
1163 /* No: Unselect it */
1164 act[i]->options &= ~AO_SELECTED;
1167 if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
1168 fprintf(stderr, _("Requested activities not available in file %s\n"),
1176 ***************************************************************************
1177 * Parse sar activities options (also used by sadf).
1180 * @argv Arguments list.
1181 * @opt Index in list of arguments.
1182 * @caller Indicate whether it's sar or sadf that called this function.
1185 * @act Array of selected activities.
1186 * @flags Common flags and system state.
1189 * 0 on success, 1 otherwise.
1190 ***************************************************************************
1192 int parse_sar_opt(char *argv[], int *opt, struct activity *act[],
1193 unsigned int *flags, int caller)
1197 for (i = 1; *(argv[*opt] + i); i++) {
1199 switch (*(argv[*opt] + i)) {
1202 select_all_activities(act);
1204 /* Force '-P ALL -I XALL' */
1205 *flags |= S_F_PER_PROC;
1207 p = get_activity_position(act, A_MEMORY);
1208 act[p]->opt_flags |= AO_F_MEM_AMT + AO_F_MEM_DIA +
1211 p = get_activity_position(act, A_IRQ);
1212 set_bitmap(act[p]->bitmap->b_array, ~0,
1213 BITMAP_SIZE(act[p]->bitmap->b_size));
1215 p = get_activity_position(act, A_CPU);
1216 set_bitmap(act[p]->bitmap->b_array, ~0,
1217 BITMAP_SIZE(act[p]->bitmap->b_size));
1218 act[p]->opt_flags = AO_F_CPU_ALL;
1222 SELECT_ACTIVITY(A_PAGE);
1226 SELECT_ACTIVITY(A_IO);
1230 *flags |= S_F_COMMENT;
1234 SELECT_ACTIVITY(A_DISK);
1238 p = get_activity_position(act, A_HUGE);
1239 act[p]->options |= AO_SELECTED;
1243 *flags |= S_F_DEV_PRETTY;
1247 SELECT_ACTIVITY(A_QUEUE);
1251 p = get_activity_position(act, A_MEMORY);
1252 act[p]->options |= AO_SELECTED;
1253 act[p]->opt_flags |= AO_F_MEM_AMT;
1257 p = get_activity_position(act, A_MEMORY);
1258 act[p]->options |= AO_SELECTED;
1259 act[p]->opt_flags |= AO_F_MEM_DIA;
1263 p = get_activity_position(act, A_MEMORY);
1264 act[p]->options |= AO_SELECTED;
1265 act[p]->opt_flags |= AO_F_MEM_SWAP;
1269 if (caller == C_SAR) {
1270 *flags |= S_F_TRUE_TIME;
1277 p = get_activity_position(act, A_CPU);
1278 act[p]->options |= AO_SELECTED;
1279 if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
1281 act[p]->opt_flags = AO_F_CPU_ALL;
1285 act[p]->opt_flags = AO_F_CPU_DEF;
1290 SELECT_ACTIVITY(A_KTABLES);
1294 SELECT_ACTIVITY(A_PCSW);
1298 SELECT_ACTIVITY(A_SWAP);
1302 SELECT_ACTIVITY(A_SERIAL);
1317 ***************************************************************************
1318 * Parse sar "-m" option.
1321 * @argv Arguments list.
1322 * @opt Index in list of arguments.
1325 * @act Array of selected activities.
1328 * 0 on success, 1 otherwise.
1329 ***************************************************************************
1331 int parse_sar_m_opt(char *argv[], int *opt, struct activity *act[])
1335 for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1336 if (!strcmp(t, K_CPU)) {
1337 SELECT_ACTIVITY(A_PWR_CPUFREQ);
1339 else if (!strcmp(t, K_FAN)) {
1340 SELECT_ACTIVITY(A_PWR_FAN);
1342 else if (!strcmp(t, K_IN)) {
1343 SELECT_ACTIVITY(A_PWR_IN);
1345 else if (!strcmp(t, K_TEMP)) {
1346 SELECT_ACTIVITY(A_PWR_TEMP);
1348 else if (!strcmp(t, K_FREQ)) {
1349 SELECT_ACTIVITY(A_PWR_WGHFREQ);
1351 else if (!strcmp(t, K_USB)) {
1352 SELECT_ACTIVITY(A_PWR_USB);
1354 else if (!strcmp(t, K_ALL)) {
1355 SELECT_ACTIVITY(A_PWR_CPUFREQ);
1356 SELECT_ACTIVITY(A_PWR_FAN);
1357 SELECT_ACTIVITY(A_PWR_IN);
1358 SELECT_ACTIVITY(A_PWR_TEMP);
1359 SELECT_ACTIVITY(A_PWR_WGHFREQ);
1360 SELECT_ACTIVITY(A_PWR_USB);
1371 ***************************************************************************
1372 * Parse sar "-n" option.
1375 * @argv Arguments list.
1376 * @opt Index in list of arguments.
1379 * @act Array of selected activities.
1382 * 0 on success, 1 otherwise.
1383 ***************************************************************************
1385 int parse_sar_n_opt(char *argv[], int *opt, struct activity *act[])
1389 for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1390 if (!strcmp(t, K_DEV)) {
1391 SELECT_ACTIVITY(A_NET_DEV);
1393 else if (!strcmp(t, K_EDEV)) {
1394 SELECT_ACTIVITY(A_NET_EDEV);
1396 else if (!strcmp(t, K_SOCK)) {
1397 SELECT_ACTIVITY(A_NET_SOCK);
1399 else if (!strcmp(t, K_NFS)) {
1400 SELECT_ACTIVITY(A_NET_NFS);
1402 else if (!strcmp(t, K_NFSD)) {
1403 SELECT_ACTIVITY(A_NET_NFSD);
1405 else if (!strcmp(t, K_IP)) {
1406 SELECT_ACTIVITY(A_NET_IP);
1408 else if (!strcmp(t, K_EIP)) {
1409 SELECT_ACTIVITY(A_NET_EIP);
1411 else if (!strcmp(t, K_ICMP)) {
1412 SELECT_ACTIVITY(A_NET_ICMP);
1414 else if (!strcmp(t, K_EICMP)) {
1415 SELECT_ACTIVITY(A_NET_EICMP);
1417 else if (!strcmp(t, K_TCP)) {
1418 SELECT_ACTIVITY(A_NET_TCP);
1420 else if (!strcmp(t, K_ETCP)) {
1421 SELECT_ACTIVITY(A_NET_ETCP);
1423 else if (!strcmp(t, K_UDP)) {
1424 SELECT_ACTIVITY(A_NET_UDP);
1426 else if (!strcmp(t, K_SOCK6)) {
1427 SELECT_ACTIVITY(A_NET_SOCK6);
1429 else if (!strcmp(t, K_IP6)) {
1430 SELECT_ACTIVITY(A_NET_IP6);
1432 else if (!strcmp(t, K_EIP6)) {
1433 SELECT_ACTIVITY(A_NET_EIP6);
1435 else if (!strcmp(t, K_ICMP6)) {
1436 SELECT_ACTIVITY(A_NET_ICMP6);
1438 else if (!strcmp(t, K_EICMP6)) {
1439 SELECT_ACTIVITY(A_NET_EICMP6);
1441 else if (!strcmp(t, K_UDP6)) {
1442 SELECT_ACTIVITY(A_NET_UDP6);
1444 else if (!strcmp(t, K_ALL)) {
1445 SELECT_ACTIVITY(A_NET_DEV);
1446 SELECT_ACTIVITY(A_NET_EDEV);
1447 SELECT_ACTIVITY(A_NET_SOCK);
1448 SELECT_ACTIVITY(A_NET_NFS);
1449 SELECT_ACTIVITY(A_NET_NFSD);
1450 SELECT_ACTIVITY(A_NET_IP);
1451 SELECT_ACTIVITY(A_NET_EIP);
1452 SELECT_ACTIVITY(A_NET_ICMP);
1453 SELECT_ACTIVITY(A_NET_EICMP);
1454 SELECT_ACTIVITY(A_NET_TCP);
1455 SELECT_ACTIVITY(A_NET_ETCP);
1456 SELECT_ACTIVITY(A_NET_UDP);
1457 SELECT_ACTIVITY(A_NET_SOCK6);
1458 SELECT_ACTIVITY(A_NET_IP6);
1459 SELECT_ACTIVITY(A_NET_EIP6);
1460 SELECT_ACTIVITY(A_NET_ICMP6);
1461 SELECT_ACTIVITY(A_NET_EICMP6);
1462 SELECT_ACTIVITY(A_NET_UDP6);
1473 ***************************************************************************
1474 * Parse sar "-I" option.
1477 * @argv Arguments list.
1478 * @opt Index in list of arguments.
1479 * @act Array of activities.
1482 * @act Array of activities, with interrupts activity selected.
1485 * 0 on success, 1 otherwise.
1486 ***************************************************************************
1488 int parse_sar_I_opt(char *argv[], int *opt, struct activity *act[])
1494 /* Select interrupt activity */
1495 p = get_activity_position(act, A_IRQ);
1496 act[p]->options |= AO_SELECTED;
1498 for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1499 if (!strcmp(t, K_SUM)) {
1500 /* Select total number of interrupts */
1501 act[p]->bitmap->b_array[0] |= 0x01;
1503 else if (!strcmp(t, K_ALL)) {
1504 /* Set bit for the first 16 individual interrupts */
1505 act[p]->bitmap->b_array[0] |= 0xfe;
1506 act[p]->bitmap->b_array[1] |= 0xff;
1507 act[p]->bitmap->b_array[2] |= 0x01;
1509 else if (!strcmp(t, K_XALL)) {
1510 /* Set every bit except for total number of interrupts */
1511 c = act[p]->bitmap->b_array[0];
1512 set_bitmap(act[p]->bitmap->b_array, ~0,
1513 BITMAP_SIZE(act[p]->bitmap->b_size));
1514 act[p]->bitmap->b_array[0] = 0xfe | c;
1517 /* Get irq number */
1518 if (strspn(t, DIGITS) != strlen(t))
1521 if ((i < 0) || (i >= act[p]->bitmap->b_size))
1523 act[p]->bitmap->b_array[(i + 1) >> 3] |= 1 << ((i + 1) & 0x07);
1532 ***************************************************************************
1533 * Parse sar and sadf "-P" option.
1536 * @argv Arguments list.
1537 * @opt Index in list of arguments.
1538 * @act Array of activities.
1541 * @flags Common flags and system state.
1542 * @act Array of activities, with CPUs selected.
1545 * 0 on success, 1 otherwise.
1546 ***************************************************************************
1548 int parse_sa_P_opt(char *argv[], int *opt, unsigned int *flags, struct activity *act[])
1553 p = get_activity_position(act, A_CPU);
1555 if (argv[++(*opt)]) {
1556 *flags |= S_F_PER_PROC;
1558 for (t = strtok(argv[*opt], ","); t; t = strtok(NULL, ",")) {
1559 if (!strcmp(t, K_ALL)) {
1561 * Set bit for every processor.
1562 * We still don't know if we are going to read stats
1563 * from a file or not...
1565 set_bitmap(act[p]->bitmap->b_array, ~0,
1566 BITMAP_SIZE(act[p]->bitmap->b_size));
1569 /* Get cpu number */
1570 if (strspn(t, DIGITS) != strlen(t))
1573 if ((i < 0) || (i >= act[p]->bitmap->b_size))
1575 act[p]->bitmap->b_array[(i + 1) >> 3] |= 1 << ((i + 1) & 0x07);