]> granicus.if.org Git - sysstat/commitdiff
Added support for activity matrices.
authorSebastien Godard <sysstat@orange.fr>
Thu, 30 Sep 2010 18:01:19 +0000 (20:01 +0200)
committerSebastien Godard <sysstat@orange.fr>
Thu, 30 Sep 2010 18:01:19 +0000 (20:01 +0200)
Activities can now have multiple items and sub-items.
This patch breaks current datafile format, which becomes
no longer compatible with previous one.

CHANGES
activity.c
sa.h
sa_common.c
sadc.c
sadf.c
sar.c

diff --git a/CHANGES b/CHANGES
index 440e835bf69a56faf32efafe3820d57170483c4d..a918eb7ba4de28ad7f3da73a0369fc4d2391cb53 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
 Changes:
 
 xxxx/xx/xx: Version 9.1.6 - Sebastien Godard (sysstat <at> 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.
index 5c7843cc8da296f6cfce1ff7910952cb47f2f1f5..81ff0a1c01c28b87828f3003de3f8f9fef6e4083 100644 (file)
@@ -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 e7c23a8d2821c93c7cd8a6f83f3ac7a00fc28c3f..33eadd0c2cdf879a9b237276842b26b97b9392ef 100644 (file)
--- a/sa.h
+++ b/sa.h
 #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.
         */
index 8226ec25da9cdfb1074f7e88a1f900ba6f8c3c5d..e0ec8551a1303801dbc23e031bf2e0c1d6089e13 100644 (file)
@@ -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 f16f0ac8bba31375dafa67f2e513120be3240e40..a3a6b571a6dacd1eaa522af1c44eb67c3de6bdc3 100644 (file)
--- 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 2343f88e772ea44eacf60e7019841b83f27753bd..45006ca04b4b24ab1d7843767c499dd550e9d11b 100644 (file)
--- 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 aad5ea455a319642ba92c06ced91d5f90fc6b383..861291401236de056986689cb504d052c77486a3 100644 (file)
--- 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) {