/*
* json_stats.c: Funtions used by sadf to display statistics in JSON format.
- * (C) 1999-2016 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2018 by Sebastien GODARD (sysstat <at> orange.fr)
*
***************************************************************************
* This program is free software; you can redistribute it and/or modify it *
#include <stdarg.h>
#include "sa.h"
-#include "sadf.h"
#include "ioconf.h"
#include "json_stats.h"
#endif
extern unsigned int flags;
-extern unsigned int dm_major;
/*
***************************************************************************
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @g_itv Interval of time in jiffies mutliplied by the number of
- * processors.
+ * @itv Interval of time in 1/100th of a second (independent of the
+ * number of processors). Unused here.
***************************************************************************
*/
__print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
- unsigned long long g_itv)
+ unsigned long long itv)
{
- int i, cpu_offline;
+ int i;
int sep = FALSE;
+ unsigned long long deltot_jiffies = 1;
struct stats_cpu *scc, *scp;
- char cpuno[8];
+ unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+ char cpuno[16];
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];
+ }
- scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
- scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
+ /*
+ * Compute CPU "all" as sum of all individual CPU (on SMP machines)
+ * and look for offline CPU.
+ */
+ if (a->nr_ini > 1) {
+ deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
+ flags, offline_cpu_bitmap);
+ }
+
+ for (i = 0; (i < a->nr_ini) && (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))))
- /* No */
+ if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
+ offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
+ /* Don't display CPU */
continue;
- /* Yes: Display current CPU stats */
+ scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
+ scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
if (sep) {
printf(",\n");
if (!i) {
/* This is CPU "all" */
strcpy(cpuno, "all");
+
+ if (a->nr_ini == 1) {
+ /*
+ * This is a UP machine. In this case
+ * interval has still not been calculated.
+ */
+ deltot_jiffies = get_per_cpu_interval(scc, scp);
+ }
+ if (!deltot_jiffies) {
+ /* CPU "all" cannot be tickless */
+ deltot_jiffies = 1;
+ }
}
else {
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 ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
- scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
- scc->cpu_hardirq + scc->cpu_softirq) == 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;
-
- g_itv = 0;
- cpu_offline = TRUE;
- }
- else {
- /*
- * Recalculate interval for current proc.
- * If result is 0 then current CPU is a tickless one.
- */
- g_itv = get_per_cpu_interval(scc, scp);
- cpu_offline = FALSE;
- }
+ deltot_jiffies = get_per_cpu_interval(scc, scp);
- if (!g_itv) {
- /* Current CPU is offline or tickless */
+ if (!deltot_jiffies) {
+ /* Current CPU is tickless */
if (DISPLAY_CPU_DEF(a->opt_flags)) {
xprintf0(tab, "{\"cpu\": \"%d\", "
"\"user\": %.2f, "
"\"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\", "
"\"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;
}
"\"steal\": %.2f, "
"\"idle\": %.2f}",
cpuno,
- ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
- ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
+ ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
+ ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
- g_itv),
- ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
- ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
+ deltot_jiffies),
+ ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
+ ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
scc->cpu_idle < scp->cpu_idle ?
0.0 :
- ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv));
+ ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies));
}
else if (DISPLAY_CPU_ALL(a->opt_flags)) {
xprintf0(tab, "{\"cpu\": \"%s\", "
(scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
0.0 :
ll_sp_value(scp->cpu_user - scp->cpu_guest,
- scc->cpu_user - scc->cpu_guest, g_itv),
+ scc->cpu_user - scc->cpu_guest, deltot_jiffies),
(scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
0.0 :
ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
- scc->cpu_nice - scc->cpu_guest_nice, g_itv),
- ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
- ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
- ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
- ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
- ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
- ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
- ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
+ scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
+ ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
+ ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
+ ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
+ ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
+ ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
+ ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
+ ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
scc->cpu_idle < scp->cpu_idle ?
0.0 :
- ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv));
+ ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies));
}
}
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_pcsw_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab,
int i;
struct stats_irq *sic, *sip;
int sep = FALSE;
- char irqno[8];
+ char irqno[16];
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);
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_swap_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_paging_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_io_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
unsigned long long itv)
{
struct stats_memory
- *smc = (struct stats_memory *) a->buf[curr],
- *smp = (struct stats_memory *) a->buf[!curr];
+ *smc = (struct stats_memory *) a->buf[curr];
int sep = FALSE;
+ unsigned long long nousedmem;
xprintf0(tab, "\"memory\": {");
- if (DISPLAY_MEM_AMT(a->opt_flags)) {
+ if (DISPLAY_MEMORY(a->opt_flags)) {
sep = TRUE;
- printf("\"memfree\": %lu, "
- "\"memused\": %lu, "
+ nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
+ if (nousedmem > smc->tlmkb) {
+ nousedmem = smc->tlmkb;
+ }
+
+ printf("\"memfree\": %llu, "
+ "\"avail\": %llu, "
+ "\"memused\": %llu, "
"\"memused-percent\": %.2f, "
- "\"buffers\": %lu, "
- "\"cached\": %lu, "
- "\"commit\": %lu, "
+ "\"buffers\": %llu, "
+ "\"cached\": %llu, "
+ "\"commit\": %llu, "
"\"commit-percent\": %.2f, "
- "\"active\": %lu, "
- "\"inactive\": %lu, "
- "\"dirty\": %lu",
+ "\"active\": %llu, "
+ "\"inactive\": %llu, "
+ "\"dirty\": %llu",
smc->frmkb,
- smc->tlmkb - smc->frmkb,
+ smc->availablekb,
+ smc->tlmkb - nousedmem,
smc->tlmkb ?
- SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) :
+ SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) :
0.0,
smc->bufkb,
smc->camkb,
if (DISPLAY_MEM_ALL(a->opt_flags)) {
/* Display extended memory stats */
- printf(", \"anonpg\": %lu, "
- "\"slab\": %lu, "
- "\"kstack\": %lu, "
- "\"pgtbl\": %lu, "
- "\"vmused\": %lu",
+ printf(", \"anonpg\": %llu, "
+ "\"slab\": %llu, "
+ "\"kstack\": %llu, "
+ "\"pgtbl\": %llu, "
+ "\"vmused\": %llu",
smc->anonpgkb,
smc->slabkb,
smc->kstackkb,
}
sep = TRUE;
- printf("\"swpfree\": %lu, "
- "\"swpused\": %lu, "
+ printf("\"swpfree\": %llu, "
+ "\"swpused\": %llu, "
"\"swpused-percent\": %.2f, "
- "\"swpcad\": %lu, "
+ "\"swpcad\": %llu, "
"\"swpcad-percent\": %.2f",
smc->frskb,
smc->tlskb - smc->frskb,
0.0);
}
- if (DISPLAY_MEMORY(a->opt_flags)) {
-
- if (sep) {
- printf(", ");
- }
-
- printf("\"frmpg\": %.2f, "
- "\"bufpg\": %.2f, "
- "\"campg\": %.2f",
- S_VALUE((double) KB_TO_PG(smp->frmkb),
- (double) KB_TO_PG(smc->frmkb), itv),
- S_VALUE((double) KB_TO_PG(smp->bufkb),
- (double) KB_TO_PG(smc->bufkb), itv),
- S_VALUE((double) KB_TO_PG(smp->camkb),
- (double) KB_TO_PG(smc->camkb), itv));
- }
-
printf("}");
}
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_ktables_stats(struct activity *a, int curr, int tab,
*skc = (struct stats_ktables *) a->buf[curr];
xprintf0(tab, "\"kernel\": {"
- "\"dentunusd\": %u, "
- "\"file-nr\": %u, "
- "\"inode-nr\": %u, "
- "\"pty-nr\": %u}",
+ "\"dentunusd\": %llu, "
+ "\"file-nr\": %llu, "
+ "\"inode-nr\": %llu, "
+ "\"pty-nr\": %llu}",
skc->dentry_stat,
skc->file_used,
skc->inode_used,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab,
*sqc = (struct stats_queue *) a->buf[curr];
xprintf0(tab, "\"queue\": {"
- "\"runq-sz\": %lu, "
- "\"plist-sz\": %u, "
+ "\"runq-sz\": %llu, "
+ "\"plist-sz\": %llu, "
"\"ldavg-1\": %.2f, "
"\"ldavg-5\": %.2f, "
"\"ldavg-15\": %.2f, "
- "\"blocked\": %lu}",
+ "\"blocked\": %llu}",
sqc->nr_running,
sqc->nr_threads,
(double) sqc->load_avg_1 / 100,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
+ found = FALSE;
- if (ssc->line == 0)
- continue;
+ if (a->nr[!curr] > 0) {
+ ssc = (struct stats_serial *) ((char *) a->buf[curr] + i * a->msize);
- if (ssc->line == ssp->line) {
+ /* Look for corresponding serial line in previous iteration */
+ j = i;
- if (sep) {
- printf(",\n");
+ if (j >= a->nr[!curr]) {
+ j = a->nr[!curr] - 1;
}
- 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));
+ j0 = j;
+
+ do {
+ ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+ if (ssc->line == ssp->line) {
+ found = TRUE;
+ break;
+ }
+ if (++j >= a->nr[!curr]) {
+ j = 0;
+ }
+ }
+ while (j != j0);
}
+
+ if (!found)
+ continue;
+
+ if (sep) {
+ printf(",\n");
+ }
+ sep = TRUE;
+
+ xprintf0(tab, "{\"line\": %d, "
+ "\"rcvin\": %.2f, "
+ "\"xmtin\": %.2f, "
+ "\"framerr\": %.2f, "
+ "\"prtyerr\": %.2f, "
+ "\"brk\": %.2f, "
+ "\"ovrun\": %.2f}",
+ ssc->line,
+ 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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab,
unsigned long long itv)
{
int i, j;
- struct stats_disk *sdc, *sdp;
+ struct stats_disk *sdc, *sdp, sdpzero;
struct ext_disk_stats xds;
int sep = FALSE;
- char *dev_name, *persist_dev_name;
+ char *dev_name;
+
+ memset(&sdpzero, 0, STATS_DISK_SIZE);
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);
- sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
-
- /* Compute extended statistics values */
- compute_ext_disk_stats(sdc, sdp, itv, &xds);
-
- dev_name = NULL;
- persist_dev_name = NULL;
-
- if (DISPLAY_PERSIST_NAME_S(flags)) {
- persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE));
- }
-
- if (persist_dev_name) {
- dev_name = persist_dev_name;
+ if (j < 0) {
+ /* This is a newly registered interface. Previous stats are zero */
+ sdp = &sdpzero;
}
else {
- if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) {
- dev_name = transform_devmapname(sdc->major, sdc->minor);
- }
+ sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
+ }
- if (!dev_name) {
- dev_name = get_devname(sdc->major, sdc->minor,
- USE_PRETTY_OPTION(flags));
- }
+ /* Get device name */
+ dev_name = get_sa_devname(sdc->major, sdc->minor, flags);
+
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, dev_name))
+ /* Device not found */
+ continue;
}
+ /* Compute extended statistics values */
+ compute_ext_disk_stats(sdc, sdp, itv, &xds);
+
if (sep) {
printf(",\n");
}
"\"tps\": %.2f, "
"\"rd_sec\": %.2f, "
"\"wr_sec\": %.2f, "
+ "\"rkB\": %.2f, "
+ "\"wkB\": %.2f, "
"\"avgrq-sz\": %.2f, "
+ "\"areq-sz\": %.2f, "
"\"avgqu-sz\": %.2f, "
+ "\"aqu-sz\": %.2f, "
"\"await\": %.2f, "
"\"svctm\": %.2f, "
"\"util-percent\": %.2f}",
/* Confusion possible here between index and minor numbers */
dev_name,
S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
- S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
+ S_VALUE(sdp->rd_sect, sdc->rd_sect, itv), /* Unit = sectors (for backward compatibility) */
S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
+ S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
+ S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
/* See iostat for explanations */
- xds.arqsz,
+ xds.arqsz, /* Unit = sectors (for backward compatibility) */
+ xds.arqsz / 2,
+ S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0, /* For backward compatibility */
S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0,
xds.await,
xds.svctm,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_dev_stats(struct activity *a, int curr, int tab,
unsigned long long itv)
{
int i, j;
- struct stats_net_dev *sndc, *sndp;
+ struct stats_net_dev *sndc, *sndp, sndzero;
int sep = FALSE;
double rxkb, txkb, ifutil;
+ memset(&sndzero, 0, STATS_NET_DEV_SIZE);
+
if (!IS_SELECTED(a->options) || (a->nr <= 0))
goto close_json_markup;
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, ""))
- continue;
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, sndc->interface))
+ /* Device not found */
+ continue;
+ }
j = check_net_dev_reg(a, curr, !curr, i);
- sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
+ if (j < 0) {
+ /* This is a newly registered interface. Previous stats are zero */
+ sndp = &sndzero;
+ }
+ else {
+ sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
+ }
if (sep) {
printf(",\n");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_edev_stats(struct activity *a, int curr, int tab,
unsigned long long itv)
{
int i, j;
- struct stats_net_edev *snedc, *snedp;
+ struct stats_net_edev *snedc, *snedp, snedzero;
int sep = FALSE;
if (!IS_SELECTED(a->options) || (a->nr <= 0))
goto close_json_markup;
+ memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
+
json_markup_network(tab, OPEN_JSON_MARKUP);
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, ""))
- continue;
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, snedc->interface))
+ /* Device not found */
+ continue;
+ }
j = check_net_edev_reg(a, curr, !curr, i);
- snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
+ if (j < 0) {
+ /* This is a newly registered interface. Previous stats are zero */
+ snedp = &snedzero;
+ }
+ else {
+ snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
+ }
if (sep) {
printf(",\n");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_nfs_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_nfsd_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_sock_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_ip_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_eip_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_icmp_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_eicmp_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_tcp_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in XML output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_etcp_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_udp_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_sock6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_ip6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_eip6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_icmp6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_eicmp6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_net_udp6_stats(struct activity *a, int curr, int tab,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int tab,
int i;
struct stats_pwr_cpufreq *spc;
int sep = FALSE;
- char cpuno[8];
+ char cpuno[16];
- 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);
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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_huge_stats(struct activity *a, int curr, int tab,
*smc = (struct stats_huge *) a->buf[curr];
xprintf0(tab, "\"hugepages\": {"
- "\"hugfree\": %lu, "
- "\"hugused\": %lu, "
+ "\"hugfree\": %llu, "
+ "\"hugused\": %llu, "
"\"hugused-percent\": %.2f}",
smc->frhkb,
smc->tlhkb - smc->frhkb,
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int tab,
struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
unsigned long long tis, tisfreq;
int sep = FALSE;
- char cpuno[8];
+ char cpuno[16];
- 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);
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))) {
+ 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);
- }
-
- 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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
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");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int tab,
xprintf(tab++, "\"filesystems\": [");
- for (i = 0; i < a->nr; i++) {
- sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
+ 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;
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list,
+ DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
+ /* Device not found */
+ continue;
+ }
if (sep) {
printf(",\n");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__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);
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++) {
+
+ found = FALSE;
+
+ if (a->nr[!curr] > 0) {
+ sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
+
+ /* Look for corresponding structure in previous iteration */
+ j = i;
+
+ if (j >= a->nr[!curr]) {
+ j = a->nr[!curr] - 1;
+ }
+
+ j0 = j;
+
+ do {
+ sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+ if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+ found = TRUE;
+ break;
+ }
+ if (++j >= a->nr[!curr]) {
+ j = 0;
+ }
+ }
+ while (j != j0);
+ }
- if (!sfcc->fchost_name[0])
- /* We are at the end of the list */
- break;
+ if (!found)
+ continue;
if (sep)
printf(",\n");
* @a Activity structure with statistics.
* @curr Index in array for current sample statistics.
* @tab Indentation in output.
- * @itv Interval of time in jiffies.
+ * @itv Interval of time in 1/100th of a second.
***************************************************************************
*/
__print_funct_t json_print_softnet_stats(struct activity *a, int curr, int tab,
unsigned long long itv)
{
- if (!IS_SELECTED(a->options) || (a->nr <= 0))
+ int i;
+ struct stats_softnet *ssnc, *ssnp;
+ int sep = FALSE;
+ char cpuno[16];
+ unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+
+ if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
goto close_json_markup;
json_markup_network(tab, OPEN_JSON_MARKUP);
+ tab++;
+
+ xprintf(tab++, "\"softnet\": [");
+
+ /* @nr[curr] cannot normally be greater than @nr_ini */
+ if (a->nr[curr] > a->nr_ini) {
+ a->nr_ini = a->nr[curr];
+ }
+
+ /* Compute statistics for CPU "all" */
+ get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
+
+ for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
+
+ /*
+ * Should current CPU (including CPU "all") be displayed?
+ * 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...
+ */
+ if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
+ offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
+ /* No */
+ continue;
+
+ /*
+ * The size of a->buf[...] CPU structure may be different from the default
+ * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
+ * 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);
+ ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
+
+ if (sep) {
+ printf(",\n");
+ }
+ sep = TRUE;
+
+ if (!i) {
+ /* This is CPU "all" */
+ strcpy(cpuno, "all");
+ }
+ else {
+ sprintf(cpuno, "%d", i - 1);
+ }
- /* FIXME */
+ xprintf0(tab, "{\"cpu\": \"%s\", "
+ "\"total\": %.2f, "
+ "\"dropd\": %.2f, "
+ "\"squeezd\": %.2f, "
+ "\"rx_rps\": %.2f, "
+ "\"flw_lim\": %.2f}",
+ cpuno,
+ S_VALUE(ssnp->processed, ssnc->processed, itv),
+ S_VALUE(ssnp->dropped, ssnc->dropped, itv),
+ S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
+ S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
+ S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv));
+ }
+
+ printf("\n");
+ xprintf0(--tab, "]");
+
+ tab --;
close_json_markup:
if (CLOSE_MARKUP(a->options)) {