]> granicus.if.org Git - sysstat/commitdiff
sadf: Update sadf to handle new file's binary format
authorSebastien GODARD <sysstat@users.noreply.github.com>
Fri, 22 Dec 2017 17:16:43 +0000 (18:16 +0100)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Fri, 22 Dec 2017 17:16:43 +0000 (18:16 +0100)
Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
json_stats.c
raw_stats.c
rndr_stats.c
sa.h
sadf.c
sadf_misc.c
svg_stats.c
xml_stats.c

index 685173db4fa7cd4aa49aecd78fa88ca168b18c75..0e3723cc7671101e2223979160bc1b217b15dedb 100644 (file)
@@ -110,7 +110,7 @@ void json_markup_power_management(int tab, int action)
 __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                     unsigned long long itv)
 {
-       int i, cpu_offline;
+       int i;
        int sep = FALSE;
        unsigned long long tot_jiffies_c, tot_jiffies_p;
        unsigned long long deltot_jiffies;
@@ -119,7 +119,12 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"cpu-load\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
+
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
                scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
@@ -146,6 +151,25 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                /* Total number of jiffies spent on the interval */
                deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
 
+               /*
+                * If the CPU is offline then it is omited from /proc/stat:
+                * All the fields couldn't have been read and the sum of them is zero.
+                */
+               if (tot_jiffies_c == 0) {
+                       /*
+                        * Set current struct fields (which have been set to zero)
+                        * to values from previous iteration. Hence their values won't
+                        * jump from zero when the CPU comes back online.
+                        */
+                       *scc = *scp;
+
+                       /* An offline CPU is not displayed */
+                       continue;
+               }
+               if (tot_jiffies_p == 0)
+                       /* CPU has just come back online */
+                       continue;
+
                if (sep) {
                        printf(",\n");
                }
@@ -159,33 +183,13 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                        sprintf(cpuno, "%d", i - 1);
 
                        /*
-                        * If the CPU is offline then it is omited from /proc/stat:
-                        * All the fields couldn't have been read and the sum of them is zero.
-                        * (Remember that guest/guest_nice times are already included in
-                        * user/nice modes.)
+                        * Recalculate interval for current proc.
+                        * If result is 0 then current CPU is a tickless one.
                         */
-                       if (tot_jiffies_c == 0) {
-                               /*
-                                * Set current struct fields (which have been set to zero)
-                                * to values from previous iteration. Hence their values won't
-                                * jump from zero when the CPU comes back online.
-                                */
-                               *scc = *scp;
-
-                               deltot_jiffies = 0;
-                               cpu_offline = TRUE;
-                       }
-                       else {
-                               /*
-                                * Recalculate interval for current proc.
-                                * If result is 0 then current CPU is a tickless one.
-                                */
-                               deltot_jiffies = get_per_cpu_interval(scc, scp);
-                               cpu_offline = FALSE;
-                       }
+                       deltot_jiffies = get_per_cpu_interval(scc, scp);
 
                        if (!deltot_jiffies) {
-                               /* Current CPU is offline or tickless */
+                               /* Current CPU is tickless */
                                if (DISPLAY_CPU_DEF(a->opt_flags)) {
                                        xprintf0(tab, "{\"cpu\": \"%d\", "
                                                 "\"user\": %.2f, "
@@ -194,8 +198,7 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                                 "\"iowait\": %.2f, "
                                                 "\"steal\": %.2f, "
                                                 "\"idle\": %.2f}",
-                                                i - 1, 0.0, 0.0, 0.0, 0.0, 0.0,
-                                                cpu_offline ? 0.0 : 100.0);
+                                                i - 1, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                else if (DISPLAY_CPU_ALL(a->opt_flags)) {
                                        xprintf0(tab, "{\"cpu\": \"%d\", "
@@ -210,8 +213,7 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                                 "\"gnice\": %.2f, "
                                                 "\"idle\": %.2f}",
                                                 i - 1, 0.0, 0.0, 0.0, 0.0,
-                                                0.0, 0.0, 0.0, 0.0, 0.0,
-                                                cpu_offline ? 0.0 : 100.0);
+                                                0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                continue;
                        }
@@ -322,7 +324,7 @@ __print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"interrupts\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                sic = (struct stats_irq *) ((char *) a->buf[curr]  + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize);
@@ -634,42 +636,60 @@ __print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab,
 __print_funct_t json_print_serial_stats(struct activity *a, int curr, int tab,
                                        unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
        int sep = FALSE;
 
        xprintf(tab++, "\"serial\": [");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
-               ssc = (struct stats_serial *) ((char *) a->buf[curr]  + i * a->msize);
-               ssp = (struct stats_serial *) ((char *) a->buf[!curr] + i * a->msize);
+               ssc = (struct stats_serial *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (ssc->line == 0)
-                       continue;
+               /* Look for corresponding serial line in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
 
-               if (ssc->line == ssp->line) {
+               j0 = j;
+               found = FALSE;
 
-                       if (sep) {
-                               printf(",\n");
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
                        }
-                       sep = TRUE;
+                       ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (ssc->line == ssp->line) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
+                       continue;
 
-                       xprintf0(tab, "{\"line\": %d, "
-                                "\"rcvin\": %.2f, "
-                                "\"xmtin\": %.2f, "
-                                "\"framerr\": %.2f, "
-                                "\"prtyerr\": %.2f, "
-                                "\"brk\": %.2f, "
-                                "\"ovrun\": %.2f}",
-                                ssc->line - 1,
-                                S_VALUE(ssp->rx,      ssc->rx,      itv),
-                                S_VALUE(ssp->tx,      ssc->tx,      itv),
-                                S_VALUE(ssp->frame,   ssc->frame,   itv),
-                                S_VALUE(ssp->parity,  ssc->parity,  itv),
-                                S_VALUE(ssp->brk,     ssc->brk,     itv),
-                                S_VALUE(ssp->overrun, ssc->overrun, itv));
+               if (sep) {
+                       printf(",\n");
                }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"line\": %d, "
+                        "\"rcvin\": %.2f, "
+                        "\"xmtin\": %.2f, "
+                        "\"framerr\": %.2f, "
+                        "\"prtyerr\": %.2f, "
+                        "\"brk\": %.2f, "
+                        "\"ovrun\": %.2f}",
+                        ssc->line - 1,
+                        S_VALUE(ssp->rx,      ssc->rx,      itv),
+                        S_VALUE(ssp->tx,      ssc->tx,      itv),
+                        S_VALUE(ssp->frame,   ssc->frame,   itv),
+                        S_VALUE(ssp->parity,  ssc->parity,  itv),
+                        S_VALUE(ssp->brk,     ssc->brk,     itv),
+                        S_VALUE(ssp->overrun, ssc->overrun, itv));
        }
 
        printf("\n");
@@ -700,13 +720,10 @@ __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"disk\": [");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!(sdc->major + sdc->minor))
-                       continue;
-
                j = check_disk_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -808,13 +825,10 @@ __print_funct_t json_print_net_dev_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"net-dev\": [");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(sndc->interface, ""))
-                       break;
-
                j = check_net_dev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -892,13 +906,10 @@ __print_funct_t json_print_net_edev_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"net-edev\": [");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(snedc->interface, ""))
-                       break;
-
                j = check_net_edev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -1761,7 +1772,7 @@ __print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int t
        int sep = FALSE;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1769,32 +1780,32 @@ __print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int t
 
        xprintf(tab++, "\"cpu-frequency\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
-               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr]  + i * a->msize);
+               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes: Display it */
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       if (sep) {
-                               printf(",\n");
-                       }
-                       sep = TRUE;
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
+               }
 
-                       xprintf0(tab, "{\"number\": \"%s\", "
-                                "\"frequency\": %.2f}",
-                                cpuno,
-                                ((double) spc->cpufreq) / 100);
+               if (sep) {
+                       printf(",\n");
                }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"number\": \"%s\", "
+                        "\"frequency\": %.2f}",
+                        cpuno,
+                        ((double) spc->cpufreq) / 100);
        }
 
        printf("\n");
@@ -1825,7 +1836,7 @@ __print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_fan *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1833,8 +1844,8 @@ __print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"fan-speed\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -1879,7 +1890,7 @@ __print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_temp *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1887,8 +1898,8 @@ __print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"temperature\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -1935,7 +1946,7 @@ __print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_in *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1943,8 +1954,8 @@ __print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"voltage-input\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -2021,7 +2032,7 @@ __print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int t
        int sep = FALSE;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -2029,48 +2040,48 @@ __print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int t
 
        xprintf(tab++, "\"cpu-weighted-frequency\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr]  + i * a->msize * a->nr2);
                spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes... */
-                       tisfreq = 0;
-                       tis = 0;
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       for (k = 0; k < a->nr2; k++) {
+               tisfreq = 0;
+               tis = 0;
 
-                               spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
-                               if (!spc_k->freq)
-                                       break;
-                               spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+               for (k = 0; k < a->nr2; k++) {
 
-                               tisfreq += (spc_k->freq / 1000) *
-                                          (spc_k->time_in_state - spp_k->time_in_state);
-                               tis     += (spc_k->time_in_state - spp_k->time_in_state);
-                       }
+                       spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+                       if (!spc_k->freq)
+                               break;
+                       spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+                       tisfreq += (spc_k->freq / 1000) *
+                                  (spc_k->time_in_state - spp_k->time_in_state);
+                       tis     += (spc_k->time_in_state - spp_k->time_in_state);
+               }
 
-                       if (sep) {
-                               printf(",\n");
-                       }
-                       sep = TRUE;
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
+               }
 
-                       xprintf0(tab, "{\"number\": \"%s\", "
-                                "\"weighted-frequency\": %.2f}",
-                                cpuno,
-                                tis ? ((double) tisfreq) / tis : 0.0);
+               if (sep) {
+                       printf(",\n");
                }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"number\": \"%s\", "
+                        "\"weighted-frequency\": %.2f}",
+                        cpuno,
+                        tis ? ((double) tisfreq) / tis : 0.0);
        }
 
        printf("\n");
@@ -2101,7 +2112,7 @@ __print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_usb *suc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -2109,12 +2120,8 @@ __print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"usb-devices\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr]  + i * a->msize);
-
-               if (!suc->bus_nr)
-                       /* Bus#0 doesn't exist: We are at the end of the list */
-                       break;
+       for (i = 0; i < a->nr[curr]; i++) {
+               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -2165,12 +2172,8 @@ __print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int ta
 
        xprintf(tab++, "\"filesystems\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               sfc = (struct stats_filesystem *) ((char *) a->buf[curr]  + i * a->msize);
-
-               if (!sfc->f_blocks)
-                       /* Size of filesystem is zero: We are at the end of the list */
-                       break;
+       for (i = 0; i < a->nr[curr]; i++) {
+               sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -2217,11 +2220,11 @@ __print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int ta
 __print_funct_t json_print_fchost_stats(struct activity *a, int curr, int tab,
                                        unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_fchost *sfcc, *sfcp;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_network(tab, OPEN_JSON_MARKUP);
@@ -2229,13 +2232,33 @@ __print_funct_t json_print_fchost_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"fchosts\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               sfcc = (struct stats_fchost *) ((char *) a->buf[curr]  + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               /* Look for corresponding structure in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
+                       continue;
 
                if (sep)
                        printf(",\n");
@@ -2284,7 +2307,7 @@ __print_funct_t json_print_softnet_stats(struct activity *a, int curr, int tab,
        int sep = FALSE;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_network(tab, OPEN_JSON_MARKUP);
@@ -2292,7 +2315,7 @@ __print_funct_t json_print_softnet_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"softnet\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -2300,7 +2323,7 @@ __print_funct_t json_print_softnet_stats(struct activity *a, int curr, int tab,
                 * That's why we don't use a syntax like:
                 * ssnc = (struct stats_softnet *) a->buf[...] + i;
                  */
-                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+                ssnc = (struct stats_softnet *) ((char *) a->buf[curr]  + i * a->msize);
                 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
 
                /*
index 63e59074f1ada4e01c6171a7e2061b7a5f9bfc43..4f3203a637741376a289b7a8b8d13090731cd0e8 100644 (file)
@@ -118,7 +118,15 @@ __print_funct_t raw_print_cpu_stats(struct activity *a, char *timestr, int curr)
        int i;
        struct stats_cpu *scc, *scp;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               if (DISPLAY_HINTS(flags)) {
+                       printf("[NEW: %d->%d]\n", a->nr_ini, a->nr[curr]);
+               }
+               a->nr_ini = a->nr[curr];
+       }
+
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -129,14 +137,6 @@ __print_funct_t raw_print_cpu_stats(struct activity *a, char *timestr, int curr)
                scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
                scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
 
-               /*
-                * Note: a->nr is in [1, NR_CPUS + 1].
-                * Bitmap size is provided for (NR_CPUS + 1) CPUs.
-                * Anyway, NR_CPUS may vary between the version of sysstat
-                * used by sadc to create a file, and the version of sysstat
-                * used by sar to read it...
-                */
-
                /* Should current CPU (including CPU "all") be displayed? */
                if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
                        /* No */
@@ -240,7 +240,7 @@ __print_funct_t raw_print_irq_stats(struct activity *a, char *timestr, int curr)
        int i;
        struct stats_irq *sic, *sip;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                sic = (struct stats_irq *) ((char *) a->buf[curr]  + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize);
@@ -452,43 +452,57 @@ __print_funct_t raw_print_queue_stats(struct activity *a, char *timestr, int cur
  */
 __print_funct_t raw_print_serial_stats(struct activity *a, char *timestr, int curr)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                ssc = (struct stats_serial *) ((char *) a->buf[curr]  + i * a->msize);
-               ssp = (struct stats_serial *) ((char *) a->buf[!curr] + i * a->msize);
 
-               printf("%s %s:", timestr, pfield(a->hdr_line, FIRST));
-               pval((unsigned long long) ssp->line, (unsigned long long) ssc->line);
+               /* Look for corresponding serial line in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (ssc->line == ssp->line) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               printf("%s %s: %u", timestr, pfield(a->hdr_line, FIRST), ssc->line);
 
-               if (ssc->line == 0) {
+               if (!found) {
                        if (DISPLAY_HINTS(flags)) {
-                               printf(" [SKP]");
+                               printf(" [NEW]");
                        }
                        printf("\n");
                        continue;
                }
 
-               if (ssc->line == ssp->line) {
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->rx, (unsigned long long)ssc->rx);
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->tx, (unsigned long long) ssc->tx);
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->frame, (unsigned long long) ssc->frame);
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->parity, (unsigned long long) ssc->parity);
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->brk, (unsigned long long) ssc->brk);
-                       printf(" %s:", pfield(NULL, 0));
-                       pval((unsigned long long) ssp->overrun, (unsigned long long) ssc->overrun);
-               }
-               else if (DISPLAY_HINTS(flags)) {
-                       printf(" [NEW]");
-               }
-
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->rx, (unsigned long long)ssc->rx);
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->tx, (unsigned long long) ssc->tx);
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->frame, (unsigned long long) ssc->frame);
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->parity, (unsigned long long) ssc->parity);
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->brk, (unsigned long long) ssc->brk);
+               printf(" %s:", pfield(NULL, 0));
+               pval((unsigned long long) ssp->overrun, (unsigned long long) ssc->overrun);
                printf("\n");
        }
 }
@@ -511,20 +525,12 @@ __print_funct_t raw_print_disk_stats(struct activity *a, char *timestr, int curr
 
        memset(&sdpzero, 0, STATS_DISK_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s major:%u minor:%u", timestr, sdc->major, sdc->minor);
 
-               if (!(sdc->major + sdc->minor)) {
-                       if (DISPLAY_HINTS(flags)) {
-                               printf(" [SKP]");
-                       }
-                       printf("\n");
-                       continue;
-               }
-
                j = check_disk_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -591,13 +597,10 @@ __print_funct_t raw_print_net_dev_stats(struct activity *a, char *timestr, int c
 
        memset(&sndzero, 0, STATS_NET_DEV_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(sndc->interface, ""))
-                       break;
-
                printf("%s %s:%s", timestr, pfield(a->hdr_line, FIRST), sndc->interface);
 
                j = check_net_dev_reg(a, curr, !curr, i);
@@ -647,13 +650,10 @@ __print_funct_t raw_print_net_edev_stats(struct activity *a, char *timestr, int
 
        memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(snedc->interface, ""))
-                       break;
-
                printf("%s %s:%s", timestr, pfield(a->hdr_line, FIRST), snedc->interface);
 
                j = check_net_edev_reg(a, curr, !curr, i);
@@ -1284,9 +1284,9 @@ __print_funct_t raw_print_pwr_cpufreq_stats(struct activity *a, char *timestr, i
        int i;
        struct stats_pwr_cpufreq *spc;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
-               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr]  + i * a->msize);
+               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
                /* Should current CPU (including CPU "all") be displayed? */
                if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
@@ -1312,8 +1312,8 @@ __print_funct_t raw_print_pwr_fan_stats(struct activity *a, char *timestr, int c
        int i;
        struct stats_pwr_fan *spc;
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s %s:%d", timestr, pfield(a->hdr_line, FIRST), i + 1);
                printf(" %s:%s", pfield(NULL, 0), spc->device);
@@ -1337,8 +1337,8 @@ __print_funct_t raw_print_pwr_temp_stats(struct activity *a, char *timestr, int
        int i;
        struct stats_pwr_temp *spc;
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s %s:%d", timestr, pfield(a->hdr_line, FIRST), i + 1);
                printf(" %s:%s", pfield(NULL, 0), spc->device);
@@ -1363,8 +1363,8 @@ __print_funct_t raw_print_pwr_in_stats(struct activity *a, char *timestr, int cu
        int i;
        struct stats_pwr_in *spc;
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s %s:%d", timestr, pfield(a->hdr_line, FIRST), i);
                printf(" %s:%s", pfield(NULL, 0), spc->device);
@@ -1408,30 +1408,30 @@ __print_funct_t raw_print_pwr_wghfreq_stats(struct activity *a, char *timestr, i
        int i, k;
        struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr]  + i * a->msize * a->nr2);
                spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       /* Yes... */
-                       printf("%s %s:%d", timestr, pfield(a->hdr_line, FIRST), i - 1);
+               printf("%s %s:%d", timestr, pfield(a->hdr_line, FIRST), i - 1);
 
-                       for (k = 0; k < a->nr2; k++) {
+               for (k = 0; k < a->nr2; k++) {
 
-                               spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
-                               if (!spc_k->freq)
-                                       break;
-                               spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+                       spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+                       if (!spc_k->freq)
+                               break;
+                       spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
 
-                               printf(" freq: %lu", spc_k->freq);
-                               printf(" tminst:");
-                               pval(spp_k->time_in_state, spc_k->time_in_state);
-                       }
-                       printf("\n");
+                       printf(" freq: %lu", spc_k->freq);
+                       printf(" tminst:");
+                       pval(spp_k->time_in_state, spc_k->time_in_state);
                }
+               printf("\n");
        }
 }
 
@@ -1450,12 +1450,8 @@ __print_funct_t raw_print_pwr_usb_stats(struct activity *a, char *timestr, int c
        int i;
        struct stats_pwr_usb *suc;
 
-       for (i = 0; i < a->nr; i++) {
-               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr]  + i * a->msize);
-
-               if (!suc->bus_nr)
-                       /* Bus#0 doesn't exist: We are at the end of the list */
-                       break;
+       for (i = 0; i < a->nr[curr]; i++) {
+               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s %s:\"%s\"", timestr, pfield(a->hdr_line, FIRST), suc->manufacturer);
                printf(" %s:\"%s\"", pfield(NULL, 0), suc->product);
@@ -1481,13 +1477,8 @@ __print_funct_t raw_print_filesystem_stats(struct activity *a, char *timestr, in
        int i;
        struct stats_filesystem *sfc;
 
-
-       for (i = 0; i < a->nr; i++) {
-               sfc = (struct stats_filesystem *) ((char *) a->buf[curr]  + i * a->msize);
-
-               if (!sfc->f_blocks)
-                       /* Size of filesystem is zero: We are at the end of the list */
-                       break;
+       for (i = 0; i < a->nr[curr]; i++) {
+               sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%s %s:\"%s\"", timestr, pfield(a->hdr_line, FIRST + DISPLAY_MOUNT(a->opt_flags)),
                       DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name);
@@ -1516,16 +1507,36 @@ __print_funct_t raw_print_filesystem_stats(struct activity *a, char *timestr, in
  */
 __print_funct_t raw_print_fchost_stats(struct activity *a, char *timestr, int curr)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_fchost *sfcc, *sfcp;
 
-       for (i = 0; i < a->nr; i++) {
-               sfcc = (struct stats_fchost *) ((char *) a->buf[curr]  + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               /* Look for corresponding structure in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
+                       continue;
 
                printf(" %s:%s", pfield(a->hdr_line, FIRST), sfcc->fchost_name);
                printf(" %s:", pfield(NULL, 0));
@@ -1555,7 +1566,7 @@ __print_funct_t raw_print_softnet_stats(struct activity *a, char *timestr, int c
        int i;
        struct stats_softnet *ssnc, *ssnp;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -1563,7 +1574,7 @@ __print_funct_t raw_print_softnet_stats(struct activity *a, char *timestr, int c
                 * That's why we don't use a syntax like:
                 * ssnc = (struct stats_softnet *) a->buf[...] + i;
                  */
-                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+                ssnc = (struct stats_softnet *) ((char *) a->buf[curr]  + i * a->msize);
                 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
 
                /*
index 33925d2b505e16b421004c1db4c1e691224c2f67..2666ac898c9b3bea8b8d7a8e605198dcdf5d6c98 100644 (file)
@@ -170,14 +170,19 @@ static void render(int isdb, char *pre, int rflags, const char *pptxt,
 __print_funct_t render_cpu_stats(struct activity *a, int isdb, char *pre,
                                 int curr, unsigned long long itv)
 {
-       int i, cpu_offline;
+       int i;
        unsigned long long tot_jiffies_p, tot_jiffies_c;
        unsigned long long deltot_jiffies;
        struct stats_cpu *scc, *scp;
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
+
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
                scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
@@ -204,6 +209,25 @@ __print_funct_t render_cpu_stats(struct activity *a, int isdb, char *pre,
                /* Total number of jiffies spent on the interval */
                deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
 
+               /*
+                * If the CPU is offline then it is omited from /proc/stat:
+                * All the fields couldn't have been read and the sum of them is zero.
+                */
+               if (tot_jiffies_c == 0) {
+                       /*
+                        * Set current struct fields (which have been set to zero)
+                        * to values from previous iteration. Hence their values won't
+                        * jump from zero when the CPU comes back online.
+                        */
+                       *scc = *scp;
+
+                       /* An offline CPU is not displayed */
+                       continue;
+               }
+               if (tot_jiffies_p == 0)
+                       /* CPU has just come back online */
+                       continue;
+
                if (!i) {
                        /* This is CPU "all" */
                        if (DISPLAY_CPU_DEF(a->opt_flags)) {
@@ -312,30 +336,10 @@ __print_funct_t render_cpu_stats(struct activity *a, int isdb, char *pre,
                }
                else {
                        /*
-                        * If the CPU is offline then it is omited from /proc/stat:
-                        * All the fields couldn't have been read and the sum of them is zero.
-                        * (Remember that guest/guest_nice times are already included in
-                        * user/nice modes.)
+                        * Recalculate itv for current proc.
+                        * If the result is 0, then current CPU is a tickless one.
                         */
-                       if (tot_jiffies_c == 0) {
-                               /*
-                                * Set current struct fields (which have been set to zero)
-                                * to values from previous iteration. Hence their values won't
-                                * jump from zero when the CPU comes back online.
-                                */
-                               *scc = *scp;
-
-                               deltot_jiffies = 0;
-                               cpu_offline = TRUE;
-                       }
-                       else {
-                               /*
-                                * Recalculate itv for current proc.
-                                * If the result is 0, then current CPU is a tickless one.
-                                */
-                               deltot_jiffies = get_per_cpu_interval(scc, scp);
-                               cpu_offline = FALSE;
-                       }
+                       deltot_jiffies = get_per_cpu_interval(scc, scp);
 
                        if (DISPLAY_CPU_DEF(a->opt_flags)) {
                                render(isdb, pre, PT_NOFLAG,
@@ -344,7 +348,7 @@ __print_funct_t render_cpu_stats(struct activity *a, int isdb, char *pre,
                                       cons(iv, i - 1, NOVAL),  /* how we pass format args  */
                                       NOVAL,
                                       !deltot_jiffies ?
-                                      0.0 :                    /* CPU is offline or tickless */
+                                      0.0 :                    /* CPU is tickless */
                                       ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
                                       NULL);
                        }
@@ -453,12 +457,11 @@ __print_funct_t render_cpu_stats(struct activity *a, int isdb, char *pre,
                        }
 
                        if (!deltot_jiffies) {
-                               /* CPU is offline or tickless */
+                               /* CPU is tickless */
                                render(isdb, pre, pt_newlin,
                                       "cpu%d\t%%idle", NULL, cons(iv, i - 1, NOVAL),
                                       NOVAL,
-                                      cpu_offline ?
-                                      0.0 : 100.0,
+                                      100.0,
                                       NULL);
                        }
                        else {
@@ -534,7 +537,7 @@ __print_funct_t render_irq_stats(struct activity *a, int isdb, char *pre,
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                sic = (struct stats_irq *) ((char *) a->buf[curr]  + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize);
@@ -964,62 +967,81 @@ __print_funct_t render_queue_stats(struct activity *a, int isdb, char *pre,
 __print_funct_t render_serial_stats(struct activity *a, int isdb, char *pre,
                                    int curr, unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                ssc = (struct stats_serial *) ((char *) a->buf[curr]  + i * a->msize);
-               ssp = (struct stats_serial *) ((char *) a->buf[!curr] + i * a->msize);
 
-               if (ssc->line == 0)
+               /* Look for corresponding serial line in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (ssc->line == ssp->line) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
                        continue;
 
-               if (ssc->line == ssp->line) {
-                       render(isdb, pre, PT_NOFLAG,
-                              "ttyS%d\trcvin/s", "%d",
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->rx, ssc->rx, itv),
-                              NULL);
+               render(isdb, pre, PT_NOFLAG,
+                      "ttyS%d\trcvin/s", "%d",
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->rx, ssc->rx, itv),
+                      NULL);
 
-                       render(isdb, pre, PT_NOFLAG,
-                              "ttyS%d\txmtin/s", NULL,
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->tx, ssc->tx, itv),
-                              NULL);
+               render(isdb, pre, PT_NOFLAG,
+                      "ttyS%d\txmtin/s", NULL,
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->tx, ssc->tx, itv),
+                      NULL);
 
-                       render(isdb, pre, PT_NOFLAG,
-                              "ttyS%d\tframerr/s", NULL,
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->frame, ssc->frame, itv),
-                              NULL);
+               render(isdb, pre, PT_NOFLAG,
+                      "ttyS%d\tframerr/s", NULL,
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->frame, ssc->frame, itv),
+                      NULL);
 
-                       render(isdb, pre, PT_NOFLAG,
-                              "ttyS%d\tprtyerr/s", NULL,
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->parity, ssc->parity, itv),
-                              NULL);
+               render(isdb, pre, PT_NOFLAG,
+                      "ttyS%d\tprtyerr/s", NULL,
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->parity, ssc->parity, itv),
+                      NULL);
 
-                       render(isdb, pre, PT_NOFLAG,
-                              "ttyS%d\tbrk/s", NULL,
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->brk, ssc->brk, itv),
-                              NULL);
+               render(isdb, pre, PT_NOFLAG,
+                      "ttyS%d\tbrk/s", NULL,
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->brk, ssc->brk, itv),
+                      NULL);
 
-                       render(isdb, pre, pt_newlin,
-                              "ttyS%d\tovrun/s", NULL,
-                              cons(iv, ssc->line - 1, NOVAL),
-                              NOVAL,
-                              S_VALUE(ssp->overrun, ssc->overrun, itv),
-                              NULL);
-               }
+               render(isdb, pre, pt_newlin,
+                      "ttyS%d\tovrun/s", NULL,
+                      cons(iv, ssc->line - 1, NOVAL),
+                      NOVAL,
+                      S_VALUE(ssp->overrun, ssc->overrun, itv),
+                      NULL);
        }
 }
 
@@ -1047,13 +1069,10 @@ __print_funct_t render_disk_stats(struct activity *a, int isdb, char *pre,
 
        memset(&sdpzero, 0, STATS_DISK_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!(sdc->major + sdc->minor))
-                       continue;
-
                j = check_disk_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -1168,13 +1187,10 @@ __print_funct_t render_net_dev_stats(struct activity *a, int isdb, char *pre,
 
        memset(&sndzero, 0, STATS_NET_DEV_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(sndc->interface, ""))
-                       break;
-
                j = check_net_dev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -1267,13 +1283,10 @@ __print_funct_t render_net_edev_stats(struct activity *a, int isdb, char *pre,
 
        memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(snedc->interface, ""))
-                       break;
-
                j = check_net_edev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -2508,30 +2521,35 @@ __print_funct_t render_pwr_cpufreq_stats(struct activity *a, int isdb, char *pre
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
+               if (!spc->cpufreq)
+                       /* This CPU is offline: Don't display it */
+                       continue;
+
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               render(isdb, pre, pt_newlin,
-                                      "all\tMHz",
-                                      "-1", NULL,
-                                      NOVAL,
-                                      ((double) spc->cpufreq) / 100,
-                                      NULL);
-                       }
-                       else {
-                               render(isdb, pre, pt_newlin,
-                                      "cpu%d\tMHz",
-                                      "%d", cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      ((double) spc->cpufreq) / 100,
-                                      NULL);
-                       }
+               if (!i) {
+                       /* This is CPU "all" */
+                       render(isdb, pre, pt_newlin,
+                              "all\tMHz",
+                              "-1", NULL,
+                              NOVAL,
+                              ((double) spc->cpufreq) / 100,
+                              NULL);
+               }
+               else {
+                       render(isdb, pre, pt_newlin,
+                              "cpu%d\tMHz",
+                              "%d", cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              ((double) spc->cpufreq) / 100,
+                              NULL);
                }
        }
 }
@@ -2556,7 +2574,7 @@ __print_funct_t render_pwr_fan_stats(struct activity *a, int isdb, char *pre,
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                render(isdb, pre, PT_USESTR,
@@ -2605,7 +2623,7 @@ __print_funct_t render_pwr_temp_stats(struct activity *a, int isdb, char *pre,
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                render(isdb, pre, PT_USESTR,
@@ -2656,7 +2674,7 @@ __print_funct_t render_pwr_in_stats(struct activity *a, int isdb, char *pre,
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                render(isdb, pre, PT_USESTR,
@@ -2743,47 +2761,47 @@ __print_funct_t render_pwr_wghfreq_stats(struct activity *a, int isdb, char *pre
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr]  + i * a->msize * a->nr2);
                spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       /* Yes... */
-                       tisfreq = 0;
-                       tis = 0;
+               tisfreq = 0;
+               tis = 0;
 
-                       for (k = 0; k < a->nr2; k++) {
+               for (k = 0; k < a->nr2; k++) {
 
-                               spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
-                               if (!spc_k->freq)
-                                       break;
-                               spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+                       spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+                       if (!spc_k->freq)
+                               break;
+                       spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
 
-                               tisfreq += (spc_k->freq / 1000) *
-                                          (spc_k->time_in_state - spp_k->time_in_state);
-                               tis     += (spc_k->time_in_state - spp_k->time_in_state);
-                       }
+                       tisfreq += (spc_k->freq / 1000) *
+                                  (spc_k->time_in_state - spp_k->time_in_state);
+                       tis     += (spc_k->time_in_state - spp_k->time_in_state);
+               }
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               render(isdb, pre, pt_newlin,
-                                      "all\twghMHz",
-                                      "-1", NULL,
-                                      NOVAL,
-                                      tis ? ((double) tisfreq) / tis : 0.0,
-                                      NULL);
-                       }
-                       else {
-                               render(isdb, pre, pt_newlin,
-                                      "cpu%d\twghMHz",
-                                      "%d", cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      tis ? ((double) tisfreq) / tis : 0.0,
-                                      NULL);
-                       }
+               if (!i) {
+                       /* This is CPU "all" */
+                       render(isdb, pre, pt_newlin,
+                              "all\twghMHz",
+                              "-1", NULL,
+                              NOVAL,
+                              tis ? ((double) tisfreq) / tis : 0.0,
+                              NULL);
+               }
+               else {
+                       render(isdb, pre, pt_newlin,
+                              "cpu%d\twghMHz",
+                              "%d", cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              tis ? ((double) tisfreq) / tis : 0.0,
+                              NULL);
                }
        }
 }
@@ -2807,13 +2825,9 @@ __print_funct_t render_pwr_usb_stats(struct activity *a, int isdb, char *pre,
        struct stats_pwr_usb *suc;
        char id[9];
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!suc->bus_nr)
-                       /* Bus#0 doesn't exist: We are at the end of the list */
-                       break;
-
                sprintf(id, "%x", suc->vendor_id);
                render(isdb, pre, PT_USESTR,
                       "bus%d\tidvendor",
@@ -2877,13 +2891,9 @@ __print_funct_t render_filesystem_stats(struct activity *a, int isdb, char *pre,
        int i;
        struct stats_filesystem *sfc;
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!sfc->f_blocks)
-                       /* Size of filesystem is zero: We are at the end of the list */
-                       break;
-
                render(isdb, pre, PT_USERND,
                       "%s\tMBfsfree",
                       "%s",
@@ -2961,16 +2971,36 @@ __print_funct_t render_filesystem_stats(struct activity *a, int isdb, char *pre,
 __print_funct_t render_fchost_stats(struct activity *a, int isdb, char *pre,
                                    int curr, unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_fchost *sfcc, *sfcp;
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               /* Look for corresponding structure in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
+                       continue;
 
                render(isdb, pre, PT_NOFLAG ,
                       "%s\tfch_rxf/s",
@@ -3021,7 +3051,7 @@ __print_funct_t render_softnet_stats(struct activity *a, int isdb, char *pre,
        int pt_newlin
                = (DISPLAY_HORIZONTALLY(flags) ? PT_NOFLAG : PT_NEWLIN);
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -3029,7 +3059,7 @@ __print_funct_t render_softnet_stats(struct activity *a, int isdb, char *pre,
                 * That's why we don't use a syntax like:
                 * ssnc = (struct stats_softnet *) a->buf[...] + i;
                  */
-                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+                ssnc = (struct stats_softnet *) ((char *) a->buf[curr]  + i * a->msize);
                 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
 
                /*
@@ -3041,81 +3071,82 @@ __print_funct_t render_softnet_stats(struct activity *a, int isdb, char *pre,
                 */
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               render(isdb, pre, PT_NOFLAG,
-                                      "all\ttotal/s",
-                                      "-1", NULL,
-                                      NOVAL,
-                                      S_VALUE(ssnp->processed, ssnc->processed, itv),
-                                      NULL);
+               if (!i) {
+                       /* This is CPU "all" */
+                       render(isdb, pre, PT_NOFLAG,
+                              "all\ttotal/s",
+                              "-1", NULL,
+                              NOVAL,
+                              S_VALUE(ssnp->processed, ssnc->processed, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "all\tdropd/s",
-                                      NULL, NULL,
-                                      NOVAL,
-                                      S_VALUE(ssnp->dropped, ssnc->dropped, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "all\tdropd/s",
+                              NULL, NULL,
+                              NOVAL,
+                              S_VALUE(ssnp->dropped, ssnc->dropped, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "all\tsqueezd/s",
-                                      NULL, NULL,
-                                      NOVAL,
-                                      S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "all\tsqueezd/s",
+                              NULL, NULL,
+                              NOVAL,
+                              S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "all\trx_rps/s",
-                                      NULL, NULL,
-                                      NOVAL,
-                                      S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "all\trx_rps/s",
+                              NULL, NULL,
+                              NOVAL,
+                              S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
+                              NULL);
 
-                               render(isdb, pre, pt_newlin,
-                                      "all\tflw_lim/s",
-                                      NULL, NULL,
-                                      NOVAL,
-                                      S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
-                                      NULL);
-                       }
-                       else {
-                               render(isdb, pre, PT_NOFLAG,
-                                      "cpu%d\ttotal/s",
-                                      "%d", cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      S_VALUE(ssnp->processed, ssnc->processed, itv),
-                                      NULL);
+                       render(isdb, pre, pt_newlin,
+                              "all\tflw_lim/s",
+                              NULL, NULL,
+                              NOVAL,
+                              S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
+                              NULL);
+               }
+               else {
+                       render(isdb, pre, PT_NOFLAG,
+                              "cpu%d\ttotal/s",
+                              "%d", cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              S_VALUE(ssnp->processed, ssnc->processed, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "cpu%d\tdropd/s",
-                                      NULL, cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      S_VALUE(ssnp->dropped, ssnc->dropped, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "cpu%d\tdropd/s",
+                              NULL, cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              S_VALUE(ssnp->dropped, ssnc->dropped, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "cpu%d\tsqueezd/s",
-                                      NULL, cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "cpu%d\tsqueezd/s",
+                              NULL, cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
+                              NULL);
 
-                               render(isdb, pre, PT_NOFLAG,
-                                      "cpu%d\trx_rps/s",
-                                      NULL, cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
-                                      NULL);
+                       render(isdb, pre, PT_NOFLAG,
+                              "cpu%d\trx_rps/s",
+                              NULL, cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
+                              NULL);
 
-                               render(isdb, pre, pt_newlin,
-                                      "cpu%d\tflw_lim/s",
-                                      NULL, cons(iv, i - 1, NOVAL),
-                                      NOVAL,
-                                      S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
-                                      NULL);
-                       }
+                       render(isdb, pre, pt_newlin,
+                              "cpu%d\tflw_lim/s",
+                              NULL, cons(iv, i - 1, NOVAL),
+                              NOVAL,
+                              S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
+                              NULL);
                }
        }
 }
diff --git a/sa.h b/sa.h
index 471989897266ab444e85f54db9611a9560e2687e..8677e20eee222b39edee8d7aa2b6bb85991ad657 100644 (file)
--- a/sa.h
+++ b/sa.h
@@ -304,6 +304,7 @@ struct svg_parm {
        unsigned long long ust_time_first;      /* Time (in seconds since the epoch) for first sample */
        int graph_no;                           /* Total number of views already displayed */
        int restart;                            /* TRUE if we have just met a RESTART record */
+       __nr_t nr_max;                          /* Maximum number of items for this activity */
        struct file_header *file_hdr;           /* Pointer on file header structure */
 };
 
diff --git a/sadf.c b/sadf.c
index ddc4f0c292a679872ef3d1032944b75f57922b4c..a8c5067b7e700adc9dc4880b32c9792f24994251 100644 (file)
--- a/sadf.c
+++ b/sadf.c
@@ -70,6 +70,9 @@ struct file_header file_hdr;
  */
 unsigned int id_seq[NR_ACT];
 
+/* Maximum number of items for each activity */
+__nr_t id_nr_max[NR_ACT];
+
 /* Current record header */
 struct record_header record_hdr[3];
 
@@ -266,8 +269,8 @@ int read_next_sample(int ifd, int action, int curr, char *file, int *rtype, int
                                 * (unless we don't want to do it now).
                                 */
                                if (!(action & DONT_READ_CPU_NR)) {
-                                       file_hdr.sa_cpu_nr = read_new_cpu_nr(ifd, file, file_magic,
-                                                                            endian_mismatch, arch_64);
+                                       file_hdr.sa_cpu_nr = read_nr_value(ifd, file, file_magic,
+                                                                          endian_mismatch, arch_64, TRUE);
                                }
                                if (action & SET_TIMESTAMPS) {
                                        sa_get_record_timestamp_struct(flags, &record_hdr[curr],
@@ -288,7 +291,7 @@ int read_next_sample(int ifd, int action, int curr, char *file, int *rtype, int
                         * So read now the extra fields.
                         */
                        read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr,
-                                            file_actlst, endian_mismatch, arch_64);
+                                            file_actlst, endian_mismatch, arch_64, file, file_magic);
                        sa_get_record_timestamp_struct(flags, &record_hdr[curr], rectime, loctime);
                }
        }
@@ -318,10 +321,10 @@ void list_fields(unsigned int act_id)
                if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
                        continue;
 
-               if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) {
+               if (IS_SELECTED(act[i]->options) && (act[i]->nr_ini > 0)) {
                        if (!HAS_MULTIPLE_OUTPUTS(act[i]->options)) {
                                printf(";%s", act[i]->hdr_line);
-                               if ((act[i]->nr > 1) && DISPLAY_HORIZONTALLY(flags)) {
+                               if ((act[i]->nr_ini > 1) && DISPLAY_HORIZONTALLY(flags)) {
                                        printf("[...]");
                                }
                        }
@@ -348,7 +351,7 @@ void list_fields(unsigned int act_id)
                                                else {
                                                        printf(";%s", hl);
                                                }
-                                               if ((act[i]->nr > 1) && DISPLAY_HORIZONTALLY(flags)) {
+                                               if ((act[i]->nr_ini > 1) && DISPLAY_HORIZONTALLY(flags)) {
                                                        printf("[...]");
                                                }
                                        }
@@ -389,6 +392,38 @@ time_t get_time_ref(void)
        return (time_t) record_hdr[2].ust_time;
 }
 
+/*
+ ***************************************************************************
+ * Save or restore position in file.
+ *
+ * IN:
+ * @ifd                        File descriptor of input file.
+ * @action     DO_SAVE to save position or DO_RESTORE to restore it.
+ ***************************************************************************
+ */
+void seek_file_position(int ifd, int action)
+{
+       static off_t fpos = -1;
+       static unsigned int save_cpu_nr = 0;
+
+       if (action == DO_SAVE) {
+               /* Save current file position */
+               if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
+                       perror("lseek");
+                       exit(2);
+               }
+               save_cpu_nr = file_hdr.sa_cpu_nr;
+       }
+       else if (action == DO_RESTORE) {
+               /* Rewind file */
+               if ((fpos < 0) || (lseek(ifd, fpos, SEEK_SET) < fpos)) {
+                       perror("lseek");
+                       exit(2);
+               }
+               file_hdr.sa_cpu_nr = save_cpu_nr;
+       }
+}
+
 /*
  ***************************************************************************
  * Compute the number of rows that will contain SVG views. Usually only one
@@ -408,6 +443,7 @@ time_t get_time_ref(void)
  *                     used or not) can be saved for current record.
  * @loctime            Structure where timestamp (expressed in local time)
  *                     can be saved for current record.
+ * @views_per_row      Default number of views displayed on a single row.
  *
  * OUT:
  * @views_per_row      Maximum number of views that will be displayed on a
@@ -423,13 +459,14 @@ int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
                     struct tm *loctime, int *views_per_row)
 {
        int i, n, p, eosaf;
-       int rtype, new_tot_g_nr, tot_g_nr = 0;
-       off_t fpos;
+       int rtype, tot_g_nr = 0;
 
        /* Save current file position */
-       if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
-               perror("lseek");
-               exit(2);
+       seek_file_position(ifd, DO_SAVE);
+
+       /* Init maximum number of items for each activity */
+       for (i = 0; i < NR_ACT; i++) {
+               id_nr_max[i] = 0;
        }
 
        /* Look for the first record that will be displayed */
@@ -444,37 +481,15 @@ int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
        while ((tm_start.use && (datecmp(loctime, &tm_start) < 0)) ||
               (tm_end.use && (datecmp(loctime, &tm_end) >= 0)));
 
+       /*
+        * Read all the file and determine the maximum number
+        * of items for each activity.
+        */
        do {
-               new_tot_g_nr = 0;
-
                for (i = 0; i < NR_ACT; i++) {
-                       if (!id_seq[i])
-                               continue;
-
-                       p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
-                       if (!IS_SELECTED(act[p]->options))
-                               continue;
-
-                       if (PACK_VIEWS(flags)) {
-                               /* One activity = one row with multiple views */
-                               n = 1;
-                       }
-                       else {
-                               /* One activity = multiple rows with only one view */
-                               n = act[p]->g_nr;
-                       }
-                       if (ONE_GRAPH_PER_ITEM(act[p]->options)) {
-                                n = n * act[p]->nr;
-                       }
-                       if (act[p]->g_nr > *views_per_row) {
-                               *views_per_row = act[p]->g_nr;
+                       if (act[i]->nr[0] > id_nr_max[i]) {
+                               id_nr_max[i] = act[i]->nr[0];
                        }
-
-                       new_tot_g_nr += n;
-               }
-
-               if (new_tot_g_nr > tot_g_nr) {
-                       tot_g_nr = new_tot_g_nr;
                }
 
                do {
@@ -486,29 +501,38 @@ int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
                                /* End of data file or end time exceeded */
                                break;
                }
-               while (rtype != R_RESTART);
+               while ((rtype == R_RESTART) || (rtype == R_COMMENT));
+       }
+       while (!eosaf && !(tm_end.use && (datecmp(loctime, &tm_end) >= 0)));
 
-               if (eosaf ||
-                   (tm_end.use && (datecmp(loctime, &tm_end) >= 0)))
-                       /*
-                        * End of file, or end time exceeded:
-                        * Current number of graphs is up-to-date.
-                        */
-                       break;
+       for (i = 0; i < NR_ACT; i++) {
+               if (!id_seq[i])
+                       continue;
 
-       /*
-        * If we have found a RESTART record then we have also read the new number of
-        * CPU that follows and saved it in file_header's sa_cpu_nr field.
-        * FIXME: Loop again to compute the new total number of graphs.
-        */
+               p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
+               if (!IS_SELECTED(act[p]->options))
+                       continue;
+
+               if (PACK_VIEWS(flags)) {
+                       /* One activity = one row with multiple views */
+                       n = 1;
+               }
+               else {
+                       /* One activity = multiple rows with only one view */
+                       n = act[p]->g_nr;
+               }
+               if (ONE_GRAPH_PER_ITEM(act[p]->options)) {
+                        n = n * id_nr_max[p];
+               }
+               if (act[p]->g_nr > *views_per_row) {
+                       *views_per_row = act[p]->g_nr;
+               }
+
+               tot_g_nr += n;
        }
-       while (rtype == R_RESTART);
 
        /* Rewind file */
-       if (lseek(ifd, fpos, SEEK_SET) < fpos) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_RESTORE);
 
        if (*views_per_row > MAX_VIEWS_ON_A_ROW) {
                *views_per_row = MAX_VIEWS_ON_A_ROW;
@@ -691,7 +715,6 @@ int generic_write_stats(int curr, int use_tm_start, int use_tm_end, int reset,
  *
  * IN:
  * @ifd                File descriptor of input file.
- * @fpos       Position in file where reading must start.
  * @curr       Index in array for current sample statistics.
  * @act_id     Activity to display, or ~0 for all.
  * @file_actlst        List of (known or unknown) activities in file.
@@ -711,7 +734,7 @@ int generic_write_stats(int curr, int use_tm_start, int use_tm_end, int reset,
  *             reinitialized (used in next_slice() function).
  ***************************************************************************
  */
-void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
+void rw_curr_act_stats(int ifd, int *curr, long *cnt, int *eosaf,
                       unsigned int act_id, int *reset, struct file_activity *file_actlst,
                       struct tm *rectime, struct tm *loctime, char *file,
                       struct file_magic *file_magic)
@@ -719,10 +742,8 @@ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
        int rtype;
        int next, reset_cd;
 
-       if (lseek(ifd, fpos, SEEK_SET) < fpos) {
-               perror("lseek");
-               exit(2);
-       }
+       /* Rewind file */
+       seek_file_position(ifd, DO_RESTORE);
 
        if (DISPLAY_FIELD_LIST(fmt[f_position]->options)) {
                /* Print field list */
@@ -775,7 +796,6 @@ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
  *
  * IN:
  * @ifd                File descriptor of input file.
- * @fpos       Position in file where reading must start.
  * @curr       Index in array for current sample statistics.
  * @p          Current activity position.
  * @file_actlst        List of (known or unknown) activities in file.
@@ -796,7 +816,7 @@ void rw_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
  * @g_nr       Total number of views displayed (including current activity).
  ***************************************************************************
  */
-void display_curr_act_graphs(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
+void display_curr_act_graphs(int ifd, int *curr, long *cnt, int *eosaf,
                             int p, int *reset, struct file_activity *file_actlst,
                             struct tm *rectime, struct tm *loctime,
                             char *file, struct file_magic *file_magic, int *g_nr)
@@ -806,10 +826,7 @@ void display_curr_act_graphs(int ifd, off_t fpos, int *curr, long *cnt, int *eos
        int next, reset_cd;
 
        /* Rewind file */
-       if (lseek(ifd, fpos, SEEK_SET) < fpos) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_RESTORE);
 
        /*
         * Restore the first stats collected.
@@ -822,6 +839,7 @@ void display_curr_act_graphs(int ifd, off_t fpos, int *curr, long *cnt, int *eos
        parm.ust_time_first = record_hdr[2].ust_time;
        parm.restart = TRUE;
        parm.file_hdr = &file_hdr;
+       parm.nr_max = id_nr_max[p];
 
        *cnt  = count;
        reset_cd = 1;
@@ -910,7 +928,6 @@ void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
        int curr, tab = 0, rtype;
        int eosaf, next, reset = FALSE;
        long cnt = 1;
-       off_t fpos;
 
        if (format == F_JSON_OUTPUT) {
                /* Use a decimal point to make JSON code compliant with RFC7159 */
@@ -918,10 +935,7 @@ void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
        }
 
        /* Save current file position */
-       if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_SAVE);
 
        /* Print header (eg. XML file header) */
        if (*fmt[f_position]->f_header) {
@@ -1001,10 +1015,7 @@ void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
        }
 
        /* Rewind file */
-       if (lseek(ifd, fpos, SEEK_SET) < fpos) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_RESTORE);
 
        /* Process now RESTART entries to display restart messages */
        if (*fmt[f_position]->f_restart) {
@@ -1024,10 +1035,7 @@ void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
        }
 
        /* Rewind file */
-       if (lseek(ifd, fpos, SEEK_SET) < fpos) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_RESTORE);
 
        /* Last, process COMMENT entries to display comments */
        if (DISPLAY_COMMENT(flags)) {
@@ -1082,7 +1090,6 @@ void logic2_display_loop(int ifd, struct file_activity *file_actlst,
        int curr = 1, rtype;
        int eosaf = TRUE, reset = FALSE;
        long cnt = 1;
-       off_t fpos;
 
        /* Read system statistics from file */
        do {
@@ -1108,10 +1115,7 @@ void logic2_display_loop(int ifd, struct file_activity *file_actlst,
                reset = TRUE;
 
                /* Save current file position */
-               if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
-                       perror("lseek");
-                       exit(2);
-               }
+               seek_file_position(ifd, DO_SAVE);
 
                /* Read and write stats located between two possible Linux restarts */
 
@@ -1120,7 +1124,7 @@ void logic2_display_loop(int ifd, struct file_activity *file_actlst,
                         * If stats are displayed horizontally, then all activities
                         * are printed on the same line.
                         */
-                       rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf,
+                       rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
                                          ALL_ACTIVITIES, &reset, file_actlst,
                                          rectime, loctime, file, file_magic);
                }
@@ -1136,7 +1140,7 @@ void logic2_display_loop(int ifd, struct file_activity *file_actlst,
                                        continue;
 
                                if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) {
-                                       rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf,
+                                       rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
                                                          act[p]->id, &reset, file_actlst,
                                                          rectime, loctime, file, file_magic);
                                }
@@ -1149,7 +1153,7 @@ void logic2_display_loop(int ifd, struct file_activity *file_actlst,
                                                if ((act[p]->opt_flags & 0xff) & msk) {
                                                        act[p]->opt_flags &= (0xffffff00 + msk);
 
-                                                       rw_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf,
+                                                       rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
                                                                          act[p]->id, &reset, file_actlst,
                                                                          rectime, loctime, file,
                                                                          file_magic);
@@ -1212,7 +1216,6 @@ void logic3_display_loop(int ifd, struct file_activity *file_actlst,
        int curr = 1, rtype, g_nr = 0, views_per_row = 1;
        int eosaf = TRUE, reset = TRUE;
        long cnt = 1;
-       off_t fpos;
        int graph_nr = 0;
 
        /* Use a decimal point to make SVG code locale independent */
@@ -1265,10 +1268,7 @@ void logic3_display_loop(int ifd, struct file_activity *file_actlst,
        copy_structures(act, id_seq, record_hdr, 2, 0);
 
        /* Save current file position */
-       if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
-               perror("lseek");
-               exit(2);
-       }
+       seek_file_position(ifd, DO_SAVE);
 
        /* For each requested activity, display graphs */
        for (i = 0; i < NR_ACT; i++) {
@@ -1281,7 +1281,7 @@ void logic3_display_loop(int ifd, struct file_activity *file_actlst,
                        continue;
 
                if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) {
-                       display_curr_act_graphs(ifd, fpos, &curr, &cnt, &eosaf,
+                       display_curr_act_graphs(ifd, &curr, &cnt, &eosaf,
                                                p, &reset, file_actlst,
                                                rectime, loctime, file,
                                                file_magic, &g_nr);
@@ -1294,7 +1294,7 @@ void logic3_display_loop(int ifd, struct file_activity *file_actlst,
                        for (msk = 1; msk < 0x100; msk <<= 1) {
                                if ((act[p]->opt_flags & 0xff) & msk) {
                                        act[p]->opt_flags &= (0xffffff00 + msk);
-                                       display_curr_act_graphs(ifd, fpos, &curr, &cnt, &eosaf,
+                                       display_curr_act_graphs(ifd, &curr, &cnt, &eosaf,
                                                                p, &reset, file_actlst,
                                                                rectime, loctime, file,
                                                                file_magic, &g_nr);
index 6ab536a7da62985fd8adbeb3d3fd0d9e09f0044a..b64fd75b6df287f6d63a65c0dc33bf0f4f018ce5 100644 (file)
@@ -866,7 +866,7 @@ __printf_funct_t print_hdr_header(void *parm, int action, char *dfile,
 
                        p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
 
-                       printf("%02d: %s\t(x%d)", act[p]->id, act[p]->name, act[p]->nr);
+                       printf("%02d: %s\t(x%d)", act[p]->id, act[p]->name, act[p]->nr_ini);
                        if (IS_MATRIX(act[p]->options)) {
                                printf("\t(x%d)", act[p]->nr2);
                        }
index af8beb216b787d4a521bdb6179c84ba900f50b31..96f3d1d5d8ef7f6256bee8ce793cec6d2b3fdea1 100644 (file)
@@ -263,6 +263,53 @@ char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax
        return out;
 }
 
+/*
+ ***************************************************************************
+ * Reallocate all the arrays used to save graphs data, min and max values.
+ * The new size is the double of the original one.
+ *
+ * IN:
+ * @n          Number of slots currently allocated.
+ * @out                Current pointer on arrays containing the graphs data.
+ * @outsize    Current pointer on array containing the size of each element
+ *             in array of chars.
+ * @spmin      Current pointer on array containing min values.
+ * @spmax      Current pointer on array containing max values.
+ *
+ * OUT:
+ * @out                New pointer on arrays containing the graphs data.
+ * @outsize    New pointer on array containing the size of each element
+ *             in array of chars.
+ * @spmin      New pointer on array containing min values.
+ * @spmax      New pointer on array containing max values.
+ ***************************************************************************
+ */
+void reallocate_all_graph_lines(int n, char ***out, int **outsize,
+                               double **spmin, double **spmax)
+{
+       char *out_p;
+       int i;
+
+       /* Reallocate all the arrays */
+       SREALLOC(*out, char *, n * sizeof(char *) * 2);
+       SREALLOC(*outsize, int, n * sizeof(int) * 2);
+       SREALLOC(*spmin, double, n * sizeof(double) * 2);
+       SREALLOC(*spmax, double, n * sizeof(double) * 2);
+
+       /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
+       for (i = 0; i < n; i++) {
+               if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
+                       perror("malloc");
+                       exit(4);
+               }
+               *(*out + n + i) = out_p;
+               *out_p = '\0';
+               *(*outsize + n + i) = CHUNKSIZE;
+               *(*spmin + n + i) = DBL_MAX;
+               *(*spmax + n + i) = -DBL_MAX;
+       }
+}
+
 /*
  ***************************************************************************
  * Save SVG code for current graph.
@@ -1023,19 +1070,25 @@ __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, st
        static int *outsize;
        char item_name[8];
        double offset, val;
-       int i, j, k, pos, cpu_offline;
+       int i, j, k, pos;
 
        if (action & F_BEGIN) {
                /*
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
+
+               /* @nr[curr] cannot normally be greater than @nr_ini */
+               if (a->nr[curr] > a->nr_ini) {
+                       a->nr_ini = a->nr[curr];
+               }
+
                /* For each CPU */
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                        scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
                        scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
@@ -1080,22 +1133,22 @@ __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, st
                                         */
                                        *scc = *scp;
 
-                                       deltot_jiffies = 0;
-                                       cpu_offline = TRUE;
-                               }
-                               else {
-                                       /*
-                                        * Recalculate interval for current proc.
-                                        * If result is 0 then current CPU is a tickless one.
-                                        */
-                                       deltot_jiffies = get_per_cpu_interval(scc, scp);
-                                       cpu_offline = FALSE;
+                                       /* An offline CPU is not displayed */
+                                       continue;
                                }
+                               if (tot_jiffies_p == 0)
+                                       /* CPU has just come back online */
+                                       continue;
 
-                               if (!deltot_jiffies) {  /* Current CPU is offline or tickless */
+                               /*
+                                * Recalculate interval for current proc.
+                                * If result is 0 then current CPU is a tickless one.
+                                */
+                               deltot_jiffies = get_per_cpu_interval(scc, scp);
 
-                                       val = (cpu_offline ? 0.0        /* Offline CPU: %idle = 0% */
-                                                          : 100.0);    /* Tickless CPU: %idle = 100% */
+                               if (!deltot_jiffies) {  /* Current CPU is tickless */
+
+                                       val = 100.0;    /* Tickless CPU: %idle = 100% */
 
                                        if (DISPLAY_CPU_DEF(a->opt_flags)) {
                                                j  = 5; /* -u */
@@ -1235,7 +1288,7 @@ __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, st
                        group2[0]++;
                }
 
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
 
                        /* Should current CPU (including CPU "all") be displayed? */
                        if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
@@ -2002,7 +2055,7 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
                 * outsize + 8 will contain a positive value (TRUE) if the device
                 * has either still not been registered, or has been unregistered.
                 */
-               out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
@@ -2012,7 +2065,7 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
                 * Mark previously registered devices as now
                 * possibly unregistered for all graphs.
                 */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 9 + 8;
                        if (*unregistered == FALSE) {
                                *unregistered = MAYBE;
@@ -2020,28 +2073,28 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
                }
 
                /* For each device structure */
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < a->nr[curr]; i++) {
                        sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
-                       if (!(sdc->major + sdc->minor))
-                               /* Empty structure: Ignore it */
-                               continue;
 
                        /* Look for corresponding graph */
-                       for (k = 0; k < a->nr; k++) {
+                       for (k = 0; k < svg_p->nr_max; k++) {
                                if ((sdc->major == *(spmax + k * 9 + 8)) &&
                                    (sdc->minor == *(spmin + k * 9 + 8)))
                                        /* Graph found! */
                                        break;
                        }
-                       if (k == a->nr) {
+                       if (k == svg_p->nr_max) {
                                /* Graph not found: Look for first free entry */
-                               for (k = 0; k < a->nr; k++) {
+                               for (k = 0; k < svg_p->nr_max; k++) {
                                        if (*(spmax + k * 9 + 8) == -DBL_MAX)
                                                break;
                                }
-                               if (k == a->nr)
-                                       /* No free graph entry: Graph for this item won't be drawn */
-                                       continue;
+                               if (k == svg_p->nr_max) {
+                                       /* No free graph entry: Extend all buffers */
+                                       reallocate_all_graph_lines(svg_p->nr_max,
+                                                                  &out, &outsize, &spmin, &spmax);
+                                       svg_p->nr_max *= 2;
+                               }
                        }
                        pos = k * 9;
                        unregistered = outsize + pos + 8;
@@ -2158,7 +2211,7 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
                }
 
                /* Mark devices not seen here as now unregistered */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 9 + 8;
                        if (*unregistered != FALSE) {
                                *unregistered = TRUE;
@@ -2167,7 +2220,7 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
                        /* Check if there is something to display */
                        pos = i * 9;
                        if (!**(out + pos))
@@ -2253,7 +2306,7 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
                 * outsize + 8 will contain a positive value (TRUE) if the interface
                 * has either still not been registered, or has been unregistered.
                 */
-               out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
@@ -2263,7 +2316,7 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
                 * Mark previously registered interfaces as now
                 * possibly unregistered for all graphs.
                 */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 9 + 8;
                        if (*unregistered == FALSE) {
                                *unregistered = MAYBE;
@@ -2271,29 +2324,29 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
                }
 
                /* For each network interfaces structure */
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < a->nr[curr]; i++) {
                        sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
-                       if (!strcmp(sndc->interface, ""))
-                               /* Empty structure: This is the end of the list */
-                               break;
 
                        /* Look for corresponding graph */
-                       for (k = 0; k < a->nr; k++) {
+                       for (k = 0; k < svg_p->nr_max; k++) {
                                item_name = *(out + k * 9 + 8);
                                if (!strcmp(sndc->interface, item_name))
                                        /* Graph found! */
                                        break;
                        }
-                       if (k == a->nr) {
+                       if (k == svg_p->nr_max) {
                                /* Graph not found: Look for first free entry */
-                               for (k = 0; k < a->nr; k++) {
+                               for (k = 0; k < svg_p->nr_max; k++) {
                                        item_name = *(out + k * 9 + 8);
                                        if (!strcmp(item_name, ""))
                                                break;
                                }
-                               if (k == a->nr)
-                                       /* No free graph entry: Graph for this item won't be drawn */
-                                       continue;
+                               if (k == svg_p->nr_max) {
+                                       /* No free graph entry: Extend all buffers */
+                                       reallocate_all_graph_lines(svg_p->nr_max,
+                                                                  &out, &outsize, &spmin, &spmax);
+                                       svg_p->nr_max *= 2;
+                               }
                        }
 
                        pos = k * 9;
@@ -2373,7 +2426,7 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
                }
 
                /* Mark interfaces not seen here as now unregistered */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 9 + 8;
                        if (*unregistered != FALSE) {
                                *unregistered = TRUE;
@@ -2382,7 +2435,7 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
                        /*
                         * Check if there is something to display.
                         * Don't test sndc->interface because maybe the network
@@ -2455,7 +2508,7 @@ __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int actio
                 * outsize + 9 will contain a positive value (TRUE) if the interface
                 * has either still not been registered, or has been unregistered.
                 */
-               out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
@@ -2465,7 +2518,7 @@ __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int actio
                 * Mark previously registered interfaces as now
                 * possibly unregistered for all graphs.
                 */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 10 + 9;
                        if (*unregistered == FALSE) {
                                *unregistered = MAYBE;
@@ -2473,29 +2526,32 @@ __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int actio
                }
 
                /* For each network interfaces structure */
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < a->nr[curr]; i++) {
                        snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
                        if (!strcmp(snedc->interface, ""))
                                /* Empty structure: This is the end of the list */
                                break;
 
                        /* Look for corresponding graph */
-                       for (k = 0; k < a->nr; k++) {
+                       for (k = 0; k < svg_p->nr_max; k++) {
                                item_name = *(out + k * 10 + 9);
                                if (!strcmp(snedc->interface, item_name))
                                        /* Graph found! */
                                        break;
                        }
-                       if (k == a->nr) {
+                       if (k == svg_p->nr_max) {
                                /* Graph not found: Look for first free entry */
-                               for (k = 0; k < a->nr; k++) {
+                               for (k = 0; k < svg_p->nr_max; k++) {
                                        item_name = *(out + k * 10 + 9);
                                        if (!strcmp(item_name, ""))
                                                break;
                                }
-                               if (k == a->nr)
-                                       /* No free graph entry: Graph for this item won't be drawn */
-                                       continue;
+                               if (k == svg_p->nr_max) {
+                                       /* No free graph entry: Extend all buffers */
+                                       reallocate_all_graph_lines(svg_p->nr_max,
+                                                                  &out, &outsize, &spmin, &spmax);
+                                       svg_p->nr_max *= 2;
+                               }
                        }
 
                        pos = k * 10;
@@ -2569,7 +2625,7 @@ __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int actio
                }
 
                /* Mark interfaces not seen here as now unregistered */
-               for (k = 0; k < a->nr; k++) {
+               for (k = 0; k < svg_p->nr_max; k++) {
                        unregistered = outsize + k * 10 + 9;
                        if (*unregistered != FALSE) {
                                *unregistered = TRUE;
@@ -2578,7 +2634,7 @@ __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int actio
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
                        /*
                         * Check if there is something to display.
                         * Don't test snedc->interface because maybe the network
@@ -4110,15 +4166,15 @@ __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int ac
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
                /* For each CPU */
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                        spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr]  + i * a->msize);
-                       spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr]  + i * a->msize);
+                       spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
 
                        /* Should current CPU (including CPU "all") be displayed? */
                        if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
@@ -4135,7 +4191,7 @@ __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int ac
        }
 
        if (action & F_END) {
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
 
                        /* Should current CPU (including CPU "all") be displayed? */
                        if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
@@ -4196,15 +4252,15 @@ __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
                /* For each fan */
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < a->nr[curr]; i++) {
 
                        spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
-                       spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr]  + i * a->msize);
+                       spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
 
                        /* rpm */
                        recappend(record_hdr->ust_time - svg_p->ust_time_ref,
@@ -4216,9 +4272,9 @@ __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
 
-                       spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
+                       spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                        snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
                        item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
@@ -4272,14 +4328,14 @@ __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int actio
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
-               /* For each temperature  sensor */
-               for (i = 0; i < a->nr; i++) {
+               /* For each temperature sensor */
+               for (i = 0; i < a->nr[curr]; i++) {
 
-                       spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+                       spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                        /* Look for min/max values */
                        if (spc->temp < *(spmin + 2 * i)) {
@@ -4310,9 +4366,9 @@ __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int actio
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
 
-                       spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+                       spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                        snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
                        item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
@@ -4366,14 +4422,14 @@ __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action,
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
-               /* For each temperature  sensor */
-               for (i = 0; i < a->nr; i++) {
+               /* For each voltage input sensor */
+               for (i = 0; i < a->nr[curr]; i++) {
 
-                       spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
+                       spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                        /* Look for min/max values */
                        if (spc->in < *(spmin + 2 * i)) {
@@ -4404,7 +4460,7 @@ __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action,
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
 
                        spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
 
@@ -4551,36 +4607,35 @@ __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int act
                  * out + 7 will contain the filesystem name,
                 * out + 8 will contain the mount point.
                 */
-               out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
                /* For each filesystem structure */
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < a->nr[curr]; i++) {
                        sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
-                       if (!sfc->f_blocks)
-                               /* Size of filesystem is zero: We are at the end of the list */
-                               break;
-
                        /* Look for corresponding graph */
-                       for (k = 0; k < a->nr; k++) {
+                       for (k = 0; k < svg_p->nr_max; k++) {
                                item_name = *(out + k * 9 + 7);
                                if (!strcmp(sfc->fs_name, item_name))
                                        /* Graph found! */
                                        break;
                        }
 
-                       if (k == a->nr) {
+                       if (k == svg_p->nr_max) {
                                /* Graph not found: Look for first free entry */
-                               for (k = 0; k < a->nr; k++) {
+                               for (k = 0; k < svg_p->nr_max; k++) {
                                        item_name = *(out + k * 9 + 7);
                                        if (!strcmp(item_name, ""))
                                                break;
                                }
-                               if (k == a->nr)
-                                       /* No free graph entry: Graph for this item won't be drawn */
-                                       continue;
+                               if (k == svg_p->nr_max) {
+                                       /* No free graph entry: Extend all buffers */
+                                       reallocate_all_graph_lines(svg_p->nr_max,
+                                                                  &out, &outsize, &spmin, &spmax);
+                                       svg_p->nr_max *= 2;
+                               }
                        }
 
                        pos = k * 9;
@@ -4595,7 +4650,7 @@ __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int act
                        }
 
                        restart = TRUE;
-                       for (k = 0; k < a->nr; k++) {
+                       for (k = 0; k < a->nr[!curr]; k++) {
                                sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
                                if (!strcmp(sfc->fs_name, sfp->fs_name)) {
                                        /* Filesystem found in previous sample */
@@ -4704,7 +4759,7 @@ __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int act
 
        if (action & F_END) {
 
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
 
                        /* Check if there is something to display */
                        pos = i * 9;
@@ -4766,29 +4821,96 @@ __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action,
        static char **out;
        static int *outsize;
        char *item_name;
-       int i, pos;
+       int i, j, j0, k, found, pos, restart, *unregistered;
 
        if (action & F_BEGIN) {
                /*
                 * Allocate arrays (#0..3) that will contain the graphs data
                 * and the min/max values.
                 * Also allocate one additional array (#4) that will contain
-                * FC HBA name.
+                * FC HBA name (out + 4) and a positive value (TRUE) if the interface
+                * has either still not been registered, or has been unregistered
+                * (outsize + 4).
                 */
-               out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
-               /* For each FC HBA */
-               for (i = 0; i < a->nr; i++) {
+               restart = svg_p->restart;
+               /*
+                * Mark previously registered interfaces as now
+                * possibly unregistered for all graphs.
+                */
+               for (k = 0; k < svg_p->nr_max; k++) {
+                       unregistered = outsize + k * 5 + 4;
+                       if (*unregistered == FALSE) {
+                               *unregistered = MAYBE;
+                       }
+               }
 
+               /* For each FC HBA */
+               for (i = 0; i < a->nr[curr]; i++) {
                        sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
-                       if (!sfcc->fchost_name[0])
-                               /* We are at the end of the list */
-                               break;
 
-                       sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
-                       pos = i * 5;
+                       /* Look for corresponding graph */
+                       for (k = 0; k < svg_p->nr_max; k++) {
+                               item_name = *(out + k * 5 + 4);
+                               if (!strcmp(sfcc->fchost_name, item_name))
+                                       /* Graph found! */
+                                       break;
+                       }
+                       if (k == svg_p->nr_max) {
+                               /* Graph not found: Look for first free entry */
+                               for (k = 0; k < svg_p->nr_max; k++) {
+                                       item_name = *(out + k * 5 + 4);
+                                       if (!strcmp(item_name, ""))
+                                               break;
+                               }
+                               if (k == svg_p->nr_max) {
+                                       /* No free graph entry: Extend all buffers */
+                                       reallocate_all_graph_lines(svg_p->nr_max,
+                                                                  &out, &outsize, &spmin, &spmax);
+                                       svg_p->nr_max *= 2;
+                               }
+                       }
+
+                       pos = k * 5;
+                       unregistered = outsize + pos + 4;
+
+                       /* Look for corresponding structure in previous iteration */
+                       j = i;
+                       if (j > a->nr[!curr]) {
+                               j = a->nr[!curr];
+                       }
+
+                       j0 = j;
+                       found = FALSE;
+
+                       do {
+                               if (j > a->nr[!curr]) {
+                                       j = 0;
+                               }
+                               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                               if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                                       found = TRUE;
+                                       break;
+                               }
+                               j++;
+                       }
+                       while (j != j0);
+
+                       if (!found)
+                               continue;
+
+                       /*
+                        * If current interface was marked as previously unregistered,
+                        * then set restart variable to TRUE so that the graph will be
+                        * discontinuous, and mark it as now registered.
+                        */
+                       if (*unregistered == TRUE) {
+                               restart = TRUE;
+                       }
+                       *unregistered = FALSE;
 
                        item_name = *(out + pos + 4);
                        if (!item_name[0]) {
@@ -4804,24 +4926,32 @@ __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action,
                        /* fch_rxf/s */
                        lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
                                 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
-                                out + pos, outsize + pos, svg_p->restart);
+                                out + pos, outsize + pos, restart);
                        /* fch_txf/s */
                        lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
                                 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
-                                out + pos + 1, outsize + pos + 1, svg_p->restart);
+                                out + pos + 1, outsize + pos + 1, restart);
                        /* fch_rxw/s */
                        lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
                                 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
-                                out + pos + 2, outsize + pos + 2, svg_p->restart);
+                                out + pos + 2, outsize + pos + 2, restart);
                        /* fch_txw/s */
                        lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
                                 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
-                                out + pos + 3, outsize + pos + 3, svg_p->restart);
+                                out + pos + 3, outsize + pos + 3, restart);
+               }
+
+               /* Mark interfaces not seen here as now unregistered */
+               for (k = 0; k < svg_p->nr_max; k++) {
+                       unregistered = outsize + k * 5 + 4;
+                       if (*unregistered != FALSE) {
+                               *unregistered = TRUE;
+                       }
                }
        }
 
        if (action & F_END) {
-               for (i = 0; i < a->nr; i++) {
+               for (i = 0; i < svg_p->nr_max; i++) {
 
                        /* Check if there is something to display */
                        pos = i * 5;
@@ -4878,12 +5008,12 @@ __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action
                 * Allocate arrays that will contain the graphs data
                 * and the min/max values.
                 */
-               out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
+               out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
        }
 
        if (action & F_MAIN) {
                /* For each CPU */
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                        ssnc = (struct stats_softnet *) ((char *) a->buf[curr]  + i * a->msize);
                        ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
@@ -4923,7 +5053,7 @@ __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action
        }
 
        if (action & F_END) {
-               for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+               for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
 
                        /* Should current CPU (including CPU "all") be displayed? */
                        if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
index 20072f8b238d02dc342d76b0903d94cf525457b8..9f92b86a03bd234940337f31a8d700856e3960db 100644 (file)
@@ -108,7 +108,7 @@ void xml_markup_power_management(int tab, int action)
 __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
                                    unsigned long long itv)
 {
-       int i, cpu_offline;
+       int i;
        unsigned long long tot_jiffies_p, tot_jiffies_c;
        unsigned long long deltot_jiffies;
        struct stats_cpu *scc, *scp;
@@ -116,7 +116,12 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<cpu-load>");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
+
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
                scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
@@ -143,6 +148,25 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
                /* Total number of jiffies spent on the interval */
                deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
 
+               /*
+                * If the CPU is offline then it is omited from /proc/stat:
+                * All the fields couldn't have been read and the sum of them is zero.
+                */
+               if (tot_jiffies_c == 0) {
+                       /*
+                        * Set current struct fields (which have been set to zero)
+                        * to values from previous iteration. Hence their values won't
+                        * jump from zero when the CPU comes back online.
+                        */
+                       *scc = *scp;
+
+                       /* An offline CPU is not displayed */
+                       continue;
+               }
+               if (tot_jiffies_p == 0)
+                       /* CPU has just come back online */
+                       continue;
+
                if (!i) {
                        /* This is CPU "all" */
                        strcpy(cpuno, "all");
@@ -151,33 +175,13 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
                        sprintf(cpuno, "%d", i - 1);
 
                        /*
-                        * If the CPU is offline then it is omited from /proc/stat:
-                        * All the fields couldn't have been read and the sum of them is zero.
-                        * (Remember that guest/guest_nice times are already included in
-                        * user/nice modes.)
+                        * Recalculate interval for current proc.
+                        * If result is 0 then current CPU is a tickless one.
                         */
-                       if (tot_jiffies_c == 0) {
-                               /*
-                                * Set current struct fields (which have been set to zero)
-                                * to values from previous iteration. Hence their values won't
-                                * jump from zero when the CPU comes back online.
-                                */
-                               *scc = *scp;
-
-                               deltot_jiffies = 0;
-                               cpu_offline = TRUE;
-                       }
-                       else {
-                               /*
-                                * Recalculate interval for current proc.
-                                * If result is 0 then current CPU is a tickless one.
-                                */
-                               deltot_jiffies = get_per_cpu_interval(scc, scp);
-                               cpu_offline = FALSE;
-                       }
+                       deltot_jiffies = get_per_cpu_interval(scc, scp);
 
                        if (!deltot_jiffies) {
-                               /* Current CPU is offline or tickless */
+                               /* Current CPU is tickless */
                                if (DISPLAY_CPU_DEF(a->opt_flags)) {
                                        xprintf(tab, "<cpu number=\"%d\" "
                                                "user=\"%.2f\" "
@@ -186,8 +190,7 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
                                                "iowait=\"%.2f\" "
                                                "steal=\"%.2f\" "
                                                "idle=\"%.2f\"/>",
-                                               i - 1, 0.0, 0.0, 0.0, 0.0, 0.0,
-                                               cpu_offline ? 0.0 : 100.0);
+                                               i - 1, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                else if (DISPLAY_CPU_ALL(a->opt_flags)) {
                                        xprintf(tab, "<cpu number=\"%d\" "
@@ -202,8 +205,7 @@ __print_funct_t xml_print_cpu_stats(struct activity *a, int curr, int tab,
                                                "gnice=\"%.2f\" "
                                                "idle=\"%.2f\"/>",
                                                i - 1, 0.0, 0.0, 0.0, 0.0,
-                                               0.0, 0.0, 0.0, 0.0, 0.0,
-                                               cpu_offline ? 0.0 : 100.0);
+                                               0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                continue;
                        }
@@ -313,7 +315,7 @@ __print_funct_t xml_print_irq_stats(struct activity *a, int curr, int tab,
        xprintf(tab++, "<interrupts>");
        xprintf(tab++, "<int-global per=\"second\">");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                sic = (struct stats_irq *) ((char *) a->buf[curr]  + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize);
@@ -627,36 +629,54 @@ __print_funct_t xml_print_queue_stats(struct activity *a, int curr, int tab,
 __print_funct_t xml_print_serial_stats(struct activity *a, int curr, int tab,
                                       unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
 
        xprintf(tab++, "<serial per=\"second\">");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                ssc = (struct stats_serial *) ((char *) a->buf[curr]  + i * a->msize);
-               ssp = (struct stats_serial *) ((char *) a->buf[!curr] + i * a->msize);
 
-               if (ssc->line == 0)
-                       continue;
+               /* Look for corresponding serial line in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
 
-               if (ssc->line == ssp->line) {
-
-                       xprintf(tab, "<tty line=\"%d\" "
-                               "rcvin=\"%.2f\" "
-                               "xmtin=\"%.2f\" "
-                               "framerr=\"%.2f\" "
-                               "prtyerr=\"%.2f\" "
-                               "brk=\"%.2f\" "
-                               "ovrun=\"%.2f\"/>",
-                               ssc->line - 1,
-                               S_VALUE(ssp->rx,      ssc->rx,      itv),
-                               S_VALUE(ssp->tx,      ssc->tx,      itv),
-                               S_VALUE(ssp->frame,   ssc->frame,   itv),
-                               S_VALUE(ssp->parity,  ssc->parity,  itv),
-                               S_VALUE(ssp->brk,     ssc->brk,     itv),
-                               S_VALUE(ssp->overrun, ssc->overrun, itv));
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (ssc->line == ssp->line) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
                }
+               while (j != j0);
+
+               if (!found)
+                       continue;
+
+               xprintf(tab, "<tty line=\"%d\" "
+                       "rcvin=\"%.2f\" "
+                       "xmtin=\"%.2f\" "
+                       "framerr=\"%.2f\" "
+                       "prtyerr=\"%.2f\" "
+                       "brk=\"%.2f\" "
+                       "ovrun=\"%.2f\"/>",
+                       ssc->line - 1,
+                       S_VALUE(ssp->rx,      ssc->rx,      itv),
+                       S_VALUE(ssp->tx,      ssc->tx,      itv),
+                       S_VALUE(ssp->frame,   ssc->frame,   itv),
+                       S_VALUE(ssp->parity,  ssc->parity,  itv),
+                       S_VALUE(ssp->brk,     ssc->brk,     itv),
+                       S_VALUE(ssp->overrun, ssc->overrun, itv));
        }
 
        xprintf(--tab, "</serial>");
@@ -685,13 +705,10 @@ __print_funct_t xml_print_disk_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<disk per=\"second\">");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!(sdc->major + sdc->minor))
-                       continue;
-
                j = check_disk_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -784,13 +801,10 @@ __print_funct_t xml_print_net_dev_stats(struct activity *a, int curr, int tab,
        xml_markup_network(tab, OPEN_XML_MARKUP);
        tab++;
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(sndc->interface, ""))
-                       break;
-
                j = check_net_dev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -856,13 +870,10 @@ __print_funct_t xml_print_net_edev_stats(struct activity *a, int curr, int tab,
        xml_markup_network(tab, OPEN_XML_MARKUP);
        tab++;
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(snedc->interface, ""))
-                       break;
-
                j = check_net_edev_reg(a, curr, !curr, i);
                if (j < 0) {
                        /* This is a newly registered interface. Previous stats are zero */
@@ -1715,7 +1726,7 @@ __print_funct_t xml_print_pwr_cpufreq_stats(struct activity *a, int curr, int ta
        struct stats_pwr_cpufreq *spc;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -1723,27 +1734,28 @@ __print_funct_t xml_print_pwr_cpufreq_stats(struct activity *a, int curr, int ta
 
        xprintf(tab++, "<cpu-frequency unit=\"MHz\">");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
-               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr]  + i * a->msize);
+               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes: Display it */
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       xprintf(tab, "<cpufreq number=\"%s\" "
-                               "frequency=\"%.2f\"/>",
-                               cpuno,
-                               ((double) spc->cpufreq) / 100);
+               /* Yes: Display it */
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
                }
+
+               xprintf(tab, "<cpufreq number=\"%s\" "
+                       "frequency=\"%.2f\"/>",
+                       cpuno,
+                       ((double) spc->cpufreq) / 100);
        }
 
        xprintf(--tab, "</cpu-frequency>");
@@ -1772,7 +1784,7 @@ __print_funct_t xml_print_pwr_fan_stats(struct activity *a, int curr, int tab,
        int i;
        struct stats_pwr_fan *spc;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -1780,8 +1792,8 @@ __print_funct_t xml_print_pwr_fan_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<fan-speed unit=\"rpm\">");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                xprintf(tab, "<fan number=\"%d\" rpm=\"%llu\" drpm=\"%llu\" device=\"%s\"/>",
                        i + 1,
@@ -1816,7 +1828,7 @@ __print_funct_t xml_print_pwr_temp_stats(struct activity *a, int curr, int tab,
        int i;
        struct stats_pwr_temp *spc;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -1824,8 +1836,8 @@ __print_funct_t xml_print_pwr_temp_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<temperature unit=\"degree Celsius\">");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                xprintf(tab, "<temp number=\"%d\" degC=\"%.2f\" percent-temp=\"%.2f\" device=\"%s\"/>",
                        i + 1,
@@ -1862,7 +1874,7 @@ __print_funct_t xml_print_pwr_in_stats(struct activity *a, int curr, int tab,
        int i;
        struct stats_pwr_in *spc;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -1870,8 +1882,8 @@ __print_funct_t xml_print_pwr_in_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<voltage-input unit=\"V\">");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                xprintf(tab, "<in number=\"%d\" inV=\"%.2f\" percent-in=\"%.2f\" device=\"%s\"/>",
                        i,
@@ -1943,7 +1955,7 @@ __print_funct_t xml_print_pwr_wghfreq_stats(struct activity *a, int curr, int ta
        unsigned long long tis, tisfreq;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -1951,43 +1963,43 @@ __print_funct_t xml_print_pwr_wghfreq_stats(struct activity *a, int curr, int ta
 
        xprintf(tab++, "<cpu-weighted-frequency unit=\"MHz\">");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr]  + i * a->msize * a->nr2);
                spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes... */
-                       tisfreq = 0;
-                       tis = 0;
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       for (k = 0; k < a->nr2; k++) {
+               tisfreq = 0;
+               tis = 0;
 
-                               spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
-                               if (!spc_k->freq)
-                                       break;
-                               spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+               for (k = 0; k < a->nr2; k++) {
 
-                               tisfreq += (spc_k->freq / 1000) *
-                                          (spc_k->time_in_state - spp_k->time_in_state);
-                               tis     += (spc_k->time_in_state - spp_k->time_in_state);
-                       }
+                       spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+                       if (!spc_k->freq)
+                               break;
+                       spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+                       tisfreq += (spc_k->freq / 1000) *
+                                  (spc_k->time_in_state - spp_k->time_in_state);
+                       tis     += (spc_k->time_in_state - spp_k->time_in_state);
+               }
 
-                       xprintf(tab, "<cpuwfreq number=\"%s\" "
-                               "weighted-frequency=\"%.2f\"/>",
-                               cpuno,
-                               tis ? ((double) tisfreq) / tis : 0.0);
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
                }
+
+               xprintf(tab, "<cpuwfreq number=\"%s\" "
+                       "weighted-frequency=\"%.2f\"/>",
+                       cpuno,
+                       tis ? ((double) tisfreq) / tis : 0.0);
        }
 
        xprintf(--tab, "</cpu-weighted-frequency>");
@@ -2016,7 +2028,7 @@ __print_funct_t xml_print_pwr_usb_stats(struct activity *a, int curr, int tab,
        int i;
        struct stats_pwr_usb *suc;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_power_management(tab, OPEN_XML_MARKUP);
@@ -2024,12 +2036,8 @@ __print_funct_t xml_print_pwr_usb_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "<usb-devices>");
 
-       for (i = 0; i < a->nr; i++) {
-               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr]  + i * a->msize);
-
-               if (!suc->bus_nr)
-                       /* Bus#0 doesn't exist: We are at the end of the list */
-                       break;
+       for (i = 0; i < a->nr[curr]; i++) {
+               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
                xprintf(tab, "<usb bus_number=\"%d\" idvendor=\"%x\" idprod=\"%x\" "
                             "maxpower=\"%u\" manufact=\"%s\" product=\"%s\"/>",
@@ -2069,14 +2077,10 @@ __print_funct_t xml_print_filesystem_stats(struct activity *a, int curr, int tab
 
        xprintf(tab++, "<filesystems>");
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
 
                sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!sfc->f_blocks)
-                       /* Size of filesystem is zero: We are at the end of the list */
-                       break;
-
                xprintf(tab, "<filesystem %s=\"%s\" "
                        "MBfsfree=\"%.0f\" "
                        "MBfsused=\"%.0f\" "
@@ -2117,23 +2121,42 @@ __print_funct_t xml_print_filesystem_stats(struct activity *a, int curr, int tab
 __print_funct_t xml_print_fchost_stats(struct activity *a, int curr, int tab,
                                       unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_fchost *sfcc, *sfcp;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_network(tab, OPEN_XML_MARKUP);
        tab++;
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               /* Look for corresponding structure in previous iteration */
+               j = i;
+               if (j > a->nr[!curr]) {
+                       j = a->nr[!curr];
+               }
+
+               j0 = j;
+               found = FALSE;
+
+               do {
+                       if (j > a->nr[!curr]) {
+                               j = 0;
+                       }
+                       sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                       if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                               found = TRUE;
+                               break;
+                       }
+                       j++;
+               }
+               while (j != j0);
+
+               if (!found)
+                       continue;
 
                xprintf(tab, "<fchost name=\"%s\" "
                        "fch_rxf=\"%.2f\" "
@@ -2172,13 +2195,13 @@ __print_funct_t xml_print_softnet_stats(struct activity *a, int curr, int tab,
        struct stats_softnet *ssnc, *ssnp;
        char cpuno[8];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_xml_markup;
 
        xml_markup_network(tab, OPEN_XML_MARKUP);
        tab++;
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                ssnc = (struct stats_softnet *) ((char *) a->buf[curr]  + i * a->msize);
                ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);