From ff52fe6056485bf782f85ba9d94c3c7eadf61da6 Mon Sep 17 00:00:00 2001 From: Sebastien Godard Date: Thu, 30 Sep 2010 20:01:19 +0200 Subject: [PATCH] Added support for activity matrices. Activities can now have multiple items and sub-items. This patch breaks current datafile format, which becomes no longer compatible with previous one. --- CHANGES | 2 ++ activity.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sa.h | 37 +++++++++++++++++++++++++---- sa_common.c | 31 ++++++++++++++---------- sadc.c | 32 +++++++++++++++++-------- sadf.c | 6 ++++- sar.c | 18 ++++++++------ 7 files changed, 159 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index 440e835..a918eb7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ Changes: xxxx/xx/xx: Version 9.1.6 - Sebastien Godard (sysstat orange.fr) + WARNING: Daily data files format has changed, and is *not* + compatible with the previous one! [0x2171] * Added hugepages utilization statistics to sar. * [Ivana Varekova]: Moved manual pages to $prefix/share/man instead of $prefix/man. diff --git a/activity.c b/activity.c index 5c7843c..81ff0a1 100644 --- a/activity.c +++ b/activity.c @@ -68,6 +68,7 @@ struct activity cpu_act = { .options = AO_COLLECTED + AO_REMANENT + AO_GLOBAL_ITV + AO_MULTIPLE_OUTPUTS, #ifdef SOURCE_SADC .f_count = wrap_get_cpu_nr, + .f_count2 = NULL, .f_read = wrap_read_stat_cpu, #endif #ifdef SOURCE_SAR @@ -82,6 +83,7 @@ struct activity cpu_act = { .name = "A_CPU", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_CPU_SIZE, .msize = STATS_CPU_SIZE, .opt_flags = AO_F_CPU_DEF, @@ -95,6 +97,7 @@ struct activity pcsw_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_stat_pcsw, #endif #ifdef SOURCE_SAR @@ -108,6 +111,7 @@ struct activity pcsw_act = { .name = "A_PCSW", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_PCSW_SIZE, .msize = STATS_PCSW_SIZE, .opt_flags = 0, @@ -121,6 +125,7 @@ struct activity irq_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = wrap_get_irq_nr, + .f_count2 = NULL, .f_read = wrap_read_stat_irq, #endif #ifdef SOURCE_SAR @@ -134,6 +139,7 @@ struct activity irq_act = { .name = "A_IRQ", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_IRQ_SIZE, .msize = STATS_IRQ_SIZE, .opt_flags = 0, @@ -147,6 +153,7 @@ struct activity swap_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_swap, #endif #ifdef SOURCE_SAR @@ -160,6 +167,7 @@ struct activity swap_act = { .name = "A_SWAP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_SWAP_SIZE, .msize = STATS_SWAP_SIZE, .opt_flags = 0, @@ -173,6 +181,7 @@ struct activity paging_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_paging, #endif #ifdef SOURCE_SAR @@ -187,6 +196,7 @@ struct activity paging_act = { .name = "A_PAGE", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_PAGING_SIZE, .msize = STATS_PAGING_SIZE, .opt_flags = 0, @@ -200,6 +210,7 @@ struct activity io_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_io, #endif #ifdef SOURCE_SAR @@ -213,6 +224,7 @@ struct activity io_act = { .name = "A_IO", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_IO_SIZE, .msize = STATS_IO_SIZE, .opt_flags = 0, @@ -226,6 +238,7 @@ struct activity memory_act = { .options = AO_COLLECTED + AO_MULTIPLE_OUTPUTS, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_meminfo, #endif #ifdef SOURCE_SAR @@ -241,6 +254,7 @@ struct activity memory_act = { .name = "A_MEMORY", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_MEMORY_SIZE, .msize = STATS_MEMORY_SIZE, .opt_flags = 0, @@ -254,6 +268,7 @@ struct activity ktables_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_kernel_tables, #endif #ifdef SOURCE_SAR @@ -267,6 +282,7 @@ struct activity ktables_act = { .name = "A_KTABLES", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_KTABLES_SIZE, .msize = STATS_KTABLES_SIZE, .opt_flags = 0, @@ -280,6 +296,7 @@ struct activity queue_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_loadavg, #endif #ifdef SOURCE_SAR @@ -293,6 +310,7 @@ struct activity queue_act = { .name = "A_QUEUE", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_QUEUE_SIZE, .msize = STATS_QUEUE_SIZE, .opt_flags = 0, @@ -306,6 +324,7 @@ struct activity serial_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = wrap_get_serial_nr, + .f_count2 = NULL, .f_read = wrap_read_tty_driver_serial, #endif #ifdef SOURCE_SAR @@ -319,6 +338,7 @@ struct activity serial_act = { .name = "A_SERIAL", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_SERIAL_SIZE, .msize = STATS_SERIAL_SIZE, .opt_flags = 0, @@ -332,6 +352,7 @@ struct activity disk_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = wrap_get_disk_nr, + .f_count2 = NULL, .f_read = wrap_read_disk, #endif #ifdef SOURCE_SAR @@ -345,6 +366,7 @@ struct activity disk_act = { .name = "A_DISK", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_DISK_SIZE, .msize = STATS_DISK_SIZE, .opt_flags = 0, @@ -358,6 +380,7 @@ struct activity net_dev_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = wrap_get_iface_nr, + .f_count2 = NULL, .f_read = wrap_read_net_dev, #endif #ifdef SOURCE_SAR @@ -371,6 +394,7 @@ struct activity net_dev_act = { .name = "A_NET_DEV", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_NET_DEV_SIZE, .msize = STATS_NET_DEV_SIZE, .opt_flags = 0, @@ -384,6 +408,7 @@ struct activity net_edev_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = wrap_get_iface_nr, + .f_count2 = NULL, .f_read = wrap_read_net_edev, #endif #ifdef SOURCE_SAR @@ -398,6 +423,7 @@ struct activity net_edev_act = { .name = "A_NET_EDEV", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_NET_EDEV_SIZE, .msize = STATS_NET_EDEV_SIZE, .opt_flags = 0, @@ -411,6 +437,7 @@ struct activity net_nfs_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_nfs, #endif #ifdef SOURCE_SAR @@ -424,6 +451,7 @@ struct activity net_nfs_act = { .name = "A_NET_NFS", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_NFS_SIZE, .msize = STATS_NET_NFS_SIZE, .opt_flags = 0, @@ -437,6 +465,7 @@ struct activity net_nfsd_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_nfsd, #endif #ifdef SOURCE_SAR @@ -451,6 +480,7 @@ struct activity net_nfsd_act = { .name = "A_NET_NFSD", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_NFSD_SIZE, .msize = STATS_NET_NFSD_SIZE, .opt_flags = 0, @@ -464,6 +494,7 @@ struct activity net_sock_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_sock, #endif #ifdef SOURCE_SAR @@ -477,6 +508,7 @@ struct activity net_sock_act = { .name = "A_NET_SOCK", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_SOCK_SIZE, .msize = STATS_NET_SOCK_SIZE, .opt_flags = 0, @@ -490,6 +522,7 @@ struct activity net_ip_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_ip, #endif #ifdef SOURCE_SAR @@ -503,6 +536,7 @@ struct activity net_ip_act = { .name = "A_NET_IP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_IP_SIZE, .msize = STATS_NET_IP_SIZE, .opt_flags = 0, @@ -516,6 +550,7 @@ struct activity net_eip_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_eip, #endif #ifdef SOURCE_SAR @@ -529,6 +564,7 @@ struct activity net_eip_act = { .name = "A_NET_EIP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_EIP_SIZE, .msize = STATS_NET_EIP_SIZE, .opt_flags = 0, @@ -542,6 +578,7 @@ struct activity net_icmp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_icmp, #endif #ifdef SOURCE_SAR @@ -556,6 +593,7 @@ struct activity net_icmp_act = { .name = "A_NET_ICMP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_ICMP_SIZE, .msize = STATS_NET_ICMP_SIZE, .opt_flags = 0, @@ -569,6 +607,7 @@ struct activity net_eicmp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_eicmp, #endif #ifdef SOURCE_SAR @@ -583,6 +622,7 @@ struct activity net_eicmp_act = { .name = "A_NET_EICMP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_EICMP_SIZE, .msize = STATS_NET_EICMP_SIZE, .opt_flags = 0, @@ -596,6 +636,7 @@ struct activity net_tcp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_tcp, #endif #ifdef SOURCE_SAR @@ -609,6 +650,7 @@ struct activity net_tcp_act = { .name = "A_NET_TCP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_TCP_SIZE, .msize = STATS_NET_TCP_SIZE, .opt_flags = 0, @@ -622,6 +664,7 @@ struct activity net_etcp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_etcp, #endif #ifdef SOURCE_SAR @@ -635,6 +678,7 @@ struct activity net_etcp_act = { .name = "A_NET_ETCP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_ETCP_SIZE, .msize = STATS_NET_ETCP_SIZE, .opt_flags = 0, @@ -648,6 +692,7 @@ struct activity net_udp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_udp, #endif #ifdef SOURCE_SAR @@ -661,6 +706,7 @@ struct activity net_udp_act = { .name = "A_NET_UDP", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_UDP_SIZE, .msize = STATS_NET_UDP_SIZE, .opt_flags = 0, @@ -674,6 +720,7 @@ struct activity net_sock6_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_sock6, #endif #ifdef SOURCE_SAR @@ -687,6 +734,7 @@ struct activity net_sock6_act = { .name = "A_NET_SOCK6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_SOCK6_SIZE, .msize = STATS_NET_SOCK6_SIZE, .opt_flags = 0, @@ -700,6 +748,7 @@ struct activity net_ip6_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_ip6, #endif #ifdef SOURCE_SAR @@ -714,6 +763,7 @@ struct activity net_ip6_act = { .name = "A_NET_IP6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_IP6_SIZE, .msize = STATS_NET_IP6_SIZE, .opt_flags = 0, @@ -727,6 +777,7 @@ struct activity net_eip6_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_eip6, #endif #ifdef SOURCE_SAR @@ -741,6 +792,7 @@ struct activity net_eip6_act = { .name = "A_NET_EIP6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_EIP6_SIZE, .msize = STATS_NET_EIP6_SIZE, .opt_flags = 0, @@ -754,6 +806,7 @@ struct activity net_icmp6_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_icmp6, #endif #ifdef SOURCE_SAR @@ -769,6 +822,7 @@ struct activity net_icmp6_act = { .name = "A_NET_ICMP6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_ICMP6_SIZE, .msize = STATS_NET_ICMP6_SIZE, .opt_flags = 0, @@ -782,6 +836,7 @@ struct activity net_eicmp6_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_eicmp6, #endif #ifdef SOURCE_SAR @@ -796,6 +851,7 @@ struct activity net_eicmp6_act = { .name = "A_NET_EICMP6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_EICMP6_SIZE, .msize = STATS_NET_EICMP6_SIZE, .opt_flags = 0, @@ -809,6 +865,7 @@ struct activity net_udp6_act = { .options = AO_CLOSE_MARKUP, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_net_udp6, #endif #ifdef SOURCE_SAR @@ -822,6 +879,7 @@ struct activity net_udp6_act = { .name = "A_NET_UDP6", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_NET_UDP6_SIZE, .msize = STATS_NET_UDP6_SIZE, .opt_flags = 0, @@ -835,6 +893,7 @@ struct activity pwr_cpufreq_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = wrap_get_cpu_nr, + .f_count2 = NULL, .f_read = wrap_read_cpuinfo, #endif #ifdef SOURCE_SAR @@ -848,6 +907,7 @@ struct activity pwr_cpufreq_act = { .name = "A_PWR_CPUFREQ", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_PWR_CPUFREQ_SIZE, .msize = STATS_PWR_CPUFREQ_SIZE, .opt_flags = 0, @@ -861,6 +921,7 @@ struct activity pwr_fan_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = wrap_get_fan_nr, + .f_count2 = NULL, .f_read = wrap_read_fan, #endif #ifdef SOURCE_SAR @@ -874,6 +935,7 @@ struct activity pwr_fan_act = { .name = "A_PWR_FAN", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_PWR_FAN_SIZE, .msize = STATS_PWR_FAN_SIZE, .opt_flags = 0, @@ -887,6 +949,7 @@ struct activity pwr_temp_act = { .options = AO_NULL, #ifdef SOURCE_SADC .f_count = wrap_get_temp_nr, + .f_count2 = NULL, .f_read = wrap_read_temp, #endif #ifdef SOURCE_SAR @@ -900,6 +963,7 @@ struct activity pwr_temp_act = { .name = "A_PWR_TEMP", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_PWR_TEMP_SIZE, .msize = STATS_PWR_TEMP_SIZE, .opt_flags = 0, @@ -913,6 +977,7 @@ struct activity pwr_in_act = { .options = AO_CLOSE_MARKUP, #ifdef SOURCE_SADC .f_count = wrap_get_in_nr, + .f_count2 = NULL, .f_read = wrap_read_in, #endif #ifdef SOURCE_SAR @@ -926,6 +991,7 @@ struct activity pwr_in_act = { .name = "A_PWR_IN", #endif .nr = -1, + .nr2 = 1, .fsize = STATS_PWR_IN_SIZE, .msize = STATS_PWR_IN_SIZE, .opt_flags = 0, @@ -939,6 +1005,7 @@ struct activity huge_act = { .options = AO_COLLECTED, #ifdef SOURCE_SADC .f_count = NULL, + .f_count2 = NULL, .f_read = wrap_read_meminfo_huge, #endif #ifdef SOURCE_SAR @@ -952,6 +1019,7 @@ struct activity huge_act = { .name = "A_HUGE", #endif .nr = 1, + .nr2 = 1, .fsize = STATS_HUGE_SIZE, .msize = STATS_HUGE_SIZE, .opt_flags = 0, diff --git a/sa.h b/sa.h index e7c23a8..33eadd0 100644 --- a/sa.h +++ b/sa.h @@ -251,7 +251,6 @@ #define CLOSE_MARKUP(m) (((m) & AO_CLOSE_MARKUP) == AO_CLOSE_MARKUP) #define HAS_MULTIPLE_OUTPUTS(m) (((m) & AO_MULTIPLE_OUTPUTS) == AO_MULTIPLE_OUTPUTS) - /* Type for all functions counting items */ #define __nr_t int /* Type for all functions reading statistics */ @@ -287,7 +286,7 @@ struct activity { unsigned int options; /* * The f_count() function is used to count the number of - * items (serial lines, network interfaces, etc.). + * items (serial lines, network interfaces, etc.) -> @nr * Such a function should _always_ return a value greater than * or equal to 0. * @@ -298,6 +297,16 @@ struct activity { * sure that all items have been calculated (including #CPU, etc.) */ __nr_t (*f_count) (struct activity *); + /* + * The f_count2() function is used to count the number of + * sub-items -> @nr2 + * Such a function should _always_ return a value greater than + * or equal to 0. + * + * A NULL value for this function pointer indicates that the number of items + * is a constant (and @nr2 is set to this value). + */ + __nr_t (*f_count2) (struct activity *); /* * This function reads the relevant file and fill the buffer * with statistics corresponding to given activity. @@ -335,8 +344,25 @@ struct activity { * has still not been calculated by the f_count() function. * A value of 0 means that this number has been calculated, but no items have * been found. + * A positive value (>0) has either been calculated or is a constant. */ __nr_t nr; + /* + * Number of sub-items on the system. + * @nr2 is in fact the second dimension of a matrix of items, the first + * one being @nr. @nr is the number of lines, and @nr2 the number of columns. + * A negative value (-1) is the default value and indicates that this number + * has still not been calculated by the f_count2() function. + * A value of 0 means that this number has been calculated, but no sub-items have + * been found. + * A positive value (>0) has either been calculated or is a constant. + * Rules: + * 1) IF @nr2 = 0 THEN @nr = 0 + * Note: If @nr = 0, then @nr2 is undetermined (may be -1, 0 or >0). + * 2) IF @nr > 0 THEN @nr2 > 0. + * Note: If @nr2 > 0 then @nr is undetermined (may be -1, 0 or >0). + */ + __nr_t nr2; /* * Size of an item. * This is the size of the corresponding structure, as read from or written @@ -369,7 +395,6 @@ struct activity { struct act_bitmap *bitmap; }; - /* *************************************************************************** * Definitions of header structures. @@ -414,7 +439,7 @@ struct activity { * Modified to indicate that the format of the file is * no longer compatible with that of previous sysstat versions. */ -#define FORMAT_MAGIC 0x2170 +#define FORMAT_MAGIC 0x2171 /* Structure for file magic header data */ struct file_magic { @@ -492,6 +517,10 @@ struct file_activity { * Number of items for this activity. */ __nr_t nr __attribute__ ((packed)); + /* + * Number of sub-items for this activity. + */ + __nr_t nr2 __attribute__ ((packed)); /* * Size of an item structure. */ diff --git a/sa_common.c b/sa_common.c index 8226ec2..e0ec855 100644 --- a/sa_common.c +++ b/sa_common.c @@ -81,7 +81,7 @@ void allocate_structures(struct activity *act[]) for (i = 0; i < NR_ACT; i++) { if (act[i]->nr > 0) { for (j = 0; j < 3; j++) { - SREALLOC(act[i]->buf[j], void, act[i]->msize * act[i]->nr); + SREALLOC(act[i]->buf[j], void, act[i]->msize * act[i]->nr * act[i]->nr2); } } } @@ -962,12 +962,11 @@ void copy_structures(struct activity *act[], unsigned int id_seq[], continue; if (((p = get_activity_position(act, id_seq[i])) < 0) || - (act[p]->nr < 1)) { + (act[p]->nr < 1) || (act[p]->nr2 < 1)) { PANIC(1); } - - memcpy(act[p]->buf[dest], act[p]->buf[src], act[p]->msize * act[p]->nr); - + + memcpy(act[p]->buf[dest], act[p]->buf[src], act[p]->msize * act[p]->nr * act[p]->nr2); } } @@ -986,7 +985,7 @@ void copy_structures(struct activity *act[], unsigned int id_seq[], void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr, struct file_activity *file_actlst) { - int i, j, p; + int i, j, k, p; struct file_activity *fal = file_actlst; for (i = 0; i < act_nr; i++, fal++) { @@ -996,20 +995,25 @@ void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr, * Ignore current activity in file, which is unknown to * current sysstat version. */ - if (lseek(ifd, fal->size * fal->nr, SEEK_CUR) < (fal->size * fal->nr)) { + if (lseek(ifd, fal->size * fal->nr * fal->nr2, SEEK_CUR) < (fal->size * fal->nr * fal->nr2)) { close(ifd); perror("lseek"); exit(2); } } - else if ((act[p]->nr > 1) && (act[p]->msize > act[p]->fsize)) { + else if ((act[p]->nr > 0) && + ((act[p]->nr > 1) || (act[p]->nr2 > 1)) && + (act[p]->msize > act[p]->fsize)) { for (j = 0; j < act[p]->nr; j++) { - sa_fread(ifd, (char *) act[p]->buf[curr] + j * act[p]->msize, - act[p]->fsize, HARD_SIZE); + for (k = 0; k < act[p]->nr2; k++) { + sa_fread(ifd, + (char *) act[p]->buf[curr] + (j * act[p]->nr2 + k) * act[p]->msize, + act[p]->fsize, HARD_SIZE); + } } } else if (act[p]->nr > 0) { - sa_fread(ifd, act[p]->buf[curr], act[p]->fsize * act[p]->nr, HARD_SIZE); + sa_fread(ifd, act[p]->buf[curr], act[p]->fsize * act[p]->nr * act[p]->nr2, HARD_SIZE); } else { PANIC(act[p]->nr); @@ -1083,10 +1087,10 @@ void check_file_actlst(int *ifd, char *dfile, struct activity *act[], sa_fread(*ifd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE); - if (fal->nr < 1) { + if ((fal->nr < 1) || (fal->nr2 < 1)) { /* * Every activity, known or unknown, - * should have at least one item. + * should have at least one item and sub-item. */ handle_invalid_sa_file(ifd, file_magic, dfile, 0); } @@ -1101,6 +1105,7 @@ void check_file_actlst(int *ifd, char *dfile, struct activity *act[], } act[p]->fsize = fal->size; act[p]->nr = fal->nr; + act[p]->nr2 = fal->nr2; id_seq[j++] = fal->id; } } diff --git a/sadc.c b/sadc.c index f16f0ac..a3a6b57 100644 --- a/sadc.c +++ b/sadc.c @@ -223,7 +223,7 @@ void reset_stats(void) for (i = 0; i < NR_ACT; i++) { if ((act[i]->nr > 0) && act[i]->_buf0) { - memset(act[i]->_buf0, 0, act[i]->msize * act[i]->nr); + memset(act[i]->_buf0, 0, act[i]->msize * act[i]->nr * act[i]->nr2); } } } @@ -244,9 +244,19 @@ void sa_sys_init(void) act[i]->nr = (*act[i]->f_count)(act[i]); } + if (act[i]->nr > 0) { + if (act[i]->f_count2) { + act[i]->nr2 = (*act[i]->f_count2)(act[i]); + } + /* else act[i]->nr2 is a constant and doesn't need to be calculated */ + if (!act[i]->nr2) { + act[i]->nr = 0; + } + } + if (act[i]->nr > 0) { /* Allocate structures for current activity */ - SREALLOC(act[i]->_buf0, void, act[i]->msize * act[i]->nr); + SREALLOC(act[i]->_buf0, void, act[i]->msize * act[i]->nr * act[i]->nr2); } else { /* No items found: Invalidate current activity */ @@ -465,6 +475,7 @@ void setup_file_hdr(int fd) if (IS_COLLECTED(act[p]->options)) { file_act.id = act[p]->id; file_act.nr = act[p]->nr; + file_act.nr2 = act[p]->nr2; file_act.size = act[p]->fsize; if ((n = write_all(fd, &file_act, FILE_ACTIVITY_SIZE)) @@ -567,8 +578,8 @@ void write_stats(int ofd) continue; if (IS_COLLECTED(act[p]->options)) { - if ((n = write_all(ofd, act[p]->_buf0, act[p]->fsize * act[p]->nr)) != - (act[p]->fsize * act[p]->nr)) { + if ((n = write_all(ofd, act[p]->_buf0, act[p]->fsize * act[p]->nr * act[p]->nr2)) != + (act[p]->fsize * act[p]->nr * act[p]->nr2)) { p_write_error(); } } @@ -720,20 +731,21 @@ void open_ofile(int *ofd, char ofile[]) /* Unknown activity in list or item size has changed */ goto append_error; - if (act[p]->nr != file_act.nr) { - if (IS_REMANENT(act[p]->options) || !file_act.nr) + if ((act[p]->nr != file_act.nr) || (act[p]->nr2 != file_act.nr2)) { + if (IS_REMANENT(act[p]->options) || !file_act.nr || !file_act.nr2) /* * Remanent structures cannot have a different number of items. - * Also number of items should never be null. + * Also number of items and subitems should never be null. */ goto append_error; else { /* * Force number of items (serial lines, network interfaces...) - * to that of the file, and reallocate structures. + * and sub-items to that of the file, and reallocate structures. */ - act[p]->nr = file_act.nr; - SREALLOC(act[p]->_buf0, void, act[p]->msize * act[p]->nr); + act[p]->nr = file_act.nr; + act[p]->nr2 = file_act.nr2; + SREALLOC(act[p]->_buf0, void, act[p]->msize * act[p]->nr * act[p]->nr2); } } /* Save activity sequence */ diff --git a/sadf.c b/sadf.c index 2343f88..45006ca 100644 --- a/sadf.c +++ b/sadf.c @@ -630,7 +630,11 @@ void display_file_header(char *dfile, struct file_magic *file_magic, if ((p = get_activity_position(act, id_seq[i])) < 0) { PANIC(id_seq[i]); } - printf("%02d: %s\t(x%d)\n", act[p]->id, act[p]->name, act[p]->nr); + printf("%02d: %s\t(x%d)", act[p]->id, act[p]->name, act[p]->nr); + if (act[p]->f_count2 || (act[p]->nr2 > 1)) { + printf(" (x%d)", act[p]->nr2); + } + printf("\n"); } exit(0); diff --git a/sar.c b/sar.c index aad5ea4..8612914 100644 --- a/sar.c +++ b/sar.c @@ -218,7 +218,7 @@ void print_read_error(void) *************************************************************************** * Check that every selected activity actually belongs to the sequence list. * If not, then the activity should be unselected since it will not be sent - * by sadc. An activity can be unsent if its number of items is null. + * by sadc. An activity can be not sent if its number of items is null. * * IN: * @act_nr Size of sequence list. @@ -509,8 +509,9 @@ void write_stats_startup(int curr) record_hdr[!curr].ust_time = record_hdr[curr].ust_time; for (i = 0; i < NR_ACT; i++) { - if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) - memset(act[i]->buf[!curr], 0, act[i]->msize * act[i]->nr); + if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) { + memset(act[i]->buf[!curr], 0, act[i]->msize * act[i]->nr * act[i]->nr2); + } } flags |= S_F_SINCE_BOOT; @@ -618,7 +619,7 @@ int sar_print_special(int curr, int use_tm_start, int use_tm_end, int rtype, int void read_sadc_stat_bunch(int curr) { int i, p; - + /* Read record header (type is always R_STATS since it is read from sadc) */ if (sa_read(&record_hdr[curr], RECORD_HEADER_SIZE)) { print_read_error(); @@ -631,8 +632,8 @@ void read_sadc_stat_bunch(int curr) if ((p = get_activity_position(act, id_seq[i])) < 0) { PANIC(1); } - - if (sa_read(act[p]->buf[curr], act[p]->fsize * act[p]->nr)) { + + if (sa_read(act[p]->buf[curr], act[p]->fsize * act[p]->nr * act[p]->nr2)) { print_read_error(); } } @@ -801,13 +802,16 @@ void read_header_data(void) p = get_activity_position(act, file_act.id); - if ((p < 0) || (act[p]->fsize != file_act.size) || !file_act.nr) { + if ((p < 0) || (act[p]->fsize != file_act.size) + || !file_act.nr + || !file_act.nr2) { fprintf(stderr, _("Inconsistent input data\n")); exit(3); } id_seq[i] = file_act.id; /* We necessarily have "i < NR_ACT" */ act[p]->nr = file_act.nr; + act[p]->nr2 = file_act.nr2; } while (i < NR_ACT) { -- 2.40.0