#define S_F_SVG_SHOW_IDLE 0x00080000
#define S_F_UNIT 0x00100000
#define S_F_SVG_HEIGHT 0x00200000
+#define S_F_SVG_PACKED 0x00400000
#define WANT_SINCE_BOOT(m) (((m) & S_F_SINCE_BOOT) == S_F_SINCE_BOOT)
#define WANT_SA_ROTAT(m) (((m) & S_F_SA_ROTAT) == S_F_SA_ROTAT)
#define DISPLAY_IDLE(m) (((m) & S_F_SVG_SHOW_IDLE) == S_F_SVG_SHOW_IDLE)
#define DISPLAY_UNIT(m) (((m) & S_F_UNIT) == S_F_UNIT)
#define SET_CANVAS_HEIGHT(m) (((m) & S_F_SVG_HEIGHT) == S_F_SVG_HEIGHT)
+#define PACK_VIEWS(m) (((m) & S_F_SVG_PACKED) == S_F_SVG_PACKED)
#define AO_F_NULL 0x00000000
#define K_SHOWIDLE "showidle"
#define K_SHOWHINTS "showhints"
#define K_HEIGHT "height="
+#define K_PACKED "packed"
/* Groups of activities */
#define G_DEFAULT 0x00
int restart; /* TRUE if we have just met a RESTART record */
};
+/* Structure used when displaying SVG header */
+struct svg_hdr_parm {
+ int graph_nr; /* Number of rows of views to display or canvas height entered on the command line */
+ int views_per_row; /* Maximum number of views on a single row */
+};
/*
***************************************************************************
* | v <---><------------------------------>
* | 6 8
* | Gap
- * v<--------------------------------------------------------------->
+ * v<---------------------------------------------------------------> Gap
* 7
+ * <--------------------------------------------------------------------->
+ * 8
*/
/* #8 */
#define SVG_M_XSIZE 70
/* #7 */
#define SVG_V_XSIZE 1050
+/* #8 */
+#define SVG_T_XSIZE 1060
/* #5 */
#define SVG_G_YSIZE 200
/* Block size used to allocate arrays for graphs data */
#define CHUNKSIZE 4096
+/* Maximum number of views on a single row */
+#define MAX_VIEWS_ON_A_ROW 6
+
#define SVG_LINE_GRAPH 1
#define SVG_BAR_GRAPH 2
/*
***************************************************************************
- * Compute the number of SVG graphs to display. Each activity selected may
- * have several graphs. Moreover we have to take into account volatile
- * activities (eg. CPU) for which the number of graphs will depend on the
- * highest number of items (eg. maximum number of CPU) saved in the file.
- * This number may be higher than the real number of graphs that will be
- * displayed since some items have a preallocation constant.
+ * Compute the number of rows that will contain SVG views. Usually only one
+ * view is displayed on a row, unless the "packed" option has been entered.
+ * Each activity selected may have several views. Moreover we have to take
+ * into account volatile activities (eg. CPU) for which the number of views
+ * will depend on the highest number of items (eg. maximum number of CPU)
+ * saved in the file. This number may be higher than the real number of views
+ * that will be displayed since some items have a preallocation constant.
*
* IN:
- * @ifd File descriptor of input file.
- * @file Name of file being read.
- * @file_magic file_magic structure filled with file magic header data.
- * @file_actlst List of (known or unknown) activities in file.
- * @rectime Structure where timestamp (expressed in local time or in UTC
- * depending on whether options -T/-t have been used or not) can
- * be saved for current record.
- * @loctime Structure where timestamp (expressed in local time) can be
- * saved for current record.
+ * @ifd File descriptor of input file.
+ * @file Name of file being read.
+ * @file_magic file_magic structure filled with file magic header data.
+ * @file_actlst List of (known or unknown) activities in file.
+ * @rectime Structure where timestamp (expressed in local time or
+ * in UTC depending on whether options -T/-t have been
+ * used or not) can be saved for current record.
+ * @loctime Structure where timestamp (expressed in local time)
+ * can be saved for current record.
+ *
+ * OUT:
+ * @views_per_row Maximum number of views that will be displayed on a
+ * single row (useful only if "packed" option entered).
*
* RETURNS:
- * Total number of graphs to display, taking into account only activities
+ * Number of rows containing views, taking into account only activities
* to be displayed, and selected period of time (options -s/-e).
***************************************************************************
*/
int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
struct file_activity *file_actlst, struct tm *rectime,
- struct tm *loctime)
+ struct tm *loctime, int *views_per_row)
{
int i, n, p, eosaf;
int rtype, new_tot_g_nr, tot_g_nr = 0;
}
sr_act_nr(save_act_nr, DO_SAVE);
- /* Init total number of graphs for each activity */
+ /* Init total number of views for each activity */
for (i = 0; i < NR_ACT; i++) {
id_g_nr[i] = 0;
}
if (!IS_SELECTED(act[p]->options))
continue;
- if (ONE_GRAPH_PER_ITEM(act[p]->options)) {
- n = act[p]->g_nr * act[p]->nr;
+ 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 (n > id_g_nr[i]) {
id_g_nr[i] = n;
}
sr_act_nr(save_act_nr, DO_RESTORE);
+ if (*views_per_row > MAX_VIEWS_ON_A_ROW) {
+ *views_per_row = MAX_VIEWS_ON_A_ROW;
+ }
+
return tot_g_nr;
}
/*
struct tm *rectime, struct tm *loctime, char *file,
struct file_magic *file_magic)
{
+ struct svg_hdr_parm parm;
int i, p;
- int curr = 1, rtype, g_nr = 0;
+ int curr = 1, rtype, g_nr = 0, views_per_row = 1;
int eosaf = TRUE, reset = TRUE;
long cnt = 1;
off_t fpos;
/* Use a decimal point to make SVG code locale independent */
setlocale(LC_NUMERIC, "C");
+ /* Calculate the number of rows and the max number of views per row to display */
+ graph_nr = get_svg_graph_nr(ifd, file, file_magic,
+ file_actlst, rectime, loctime, &views_per_row);
+
if (SET_CANVAS_HEIGHT(flags)) {
/*
* Option "-O height=..." used: This is not a number
*/
graph_nr = canvas_height;
}
- else {
- /* Calculate the number of graphs to display */
- graph_nr = get_svg_graph_nr(ifd, file, file_magic,
- file_actlst, rectime, loctime);
- }
if (!graph_nr)
/* No graph to display */
return;
+ parm.graph_nr = graph_nr;
+ parm.views_per_row = PACK_VIEWS(flags) ? views_per_row : 1;
+
/* Print SVG header */
if (*fmt[f_position]->f_header) {
- (*fmt[f_position]->f_header)(&graph_nr, F_BEGIN + F_MAIN, file, file_magic,
+ (*fmt[f_position]->f_header)(&parm, F_BEGIN + F_MAIN, file, file_magic,
&file_hdr, cpu_nr, act, id_seq);
}
canvas_height = atoi(v);
flags |= S_F_SVG_HEIGHT;
}
+ else if (!strcmp(t, K_PACKED)) {
+ flags |= S_F_SVG_PACKED;
+ }
else {
usage(argv[0]);
}
* Display the header of the report (SVG format).
*
* IN:
- * @parm Specific parameter. Here: number of graphs to display or
- * canvas height entered on the command line.
+ * @parm Specific parameters. Here: number of rows of views to display
+ * or canvas height entered on the command line (@graph_nr), and
+ * max number of views on a single row (@views_per_row).
* @action Action expected from current function.
* @dfile Name of system activity data file (unused here).
* @file_magic System activity file magic header (unused here).
struct file_header *file_hdr, __nr_t cpu_nr,
struct activity *act[], unsigned int id_seq[])
{
- int *graph_nr = (int *) parm;
+ struct svg_hdr_parm *hdr_parm = (struct svg_hdr_parm *) parm;
if (action & F_BEGIN) {
printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
if (action & F_MAIN) {
printf(" width=\"%d\" height=\"%d\""
" fill=\"black\" stroke=\"gray\" stroke-width=\"1\">\n",
- SVG_V_XSIZE,
- SET_CANVAS_HEIGHT(flags) ? *graph_nr
- : SVG_H_YSIZE + SVG_T_YSIZE * (*graph_nr));
+ SVG_T_XSIZE * (hdr_parm->views_per_row),
+ SET_CANVAS_HEIGHT(flags) ? hdr_parm->graph_nr
+ : SVG_H_YSIZE + SVG_T_YSIZE * (hdr_parm->graph_nr));
printf("<text x= \"0\" y=\"30\" text-anchor=\"start\" stroke=\"brown\">");
print_gal_header(localtime((const time_t *) &(file_hdr->sa_ust_time)),
file_hdr->sa_sysname, file_hdr->sa_release,
if (!(action & F_BEGIN)) {
/* Give actual SVG height */
printf("<!-- Actual canvas height: %d -->\n",
- SVG_H_YSIZE + SVG_T_YSIZE * (*graph_nr));
+ SVG_H_YSIZE + SVG_T_YSIZE * (hdr_parm->graph_nr));
}
printf("</svg>\n");
}
* Display all graphs for current activity.
*
* IN:
- * @g_nr Number of sets of graphs (views) to display.
+ * @g_nr Number of views to display.
* @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
* @title Titles for each set of graphs.
* @g_title Titles for each graph.
* @spmax Array containing max values for graphs.
* @out Pointer on array of chars for each graph definition.
* @outsize Size of array of chars for each graph definition.
- * @svg_p SVG specific parameters: Current graph number (.@graph_no),
+ * @svg_p SVG specific parameters: Current views row number (.@graph_no),
* time for the first sample of stats (.@ust_time_first), and
* times used as start and end values on the X axis
* (.@ust_time_ref and .@ust_time_end).
{
char *out_p;
int i, j, dp, pos = 0, views_nr = 0;
- int v_gridnr;
+ int v_gridnr, xv, yv;
unsigned int asfactor[16];
long int xpos;
double lmax, xfactor, yfactor, ypos, gmin, gmax;
svg_p->graph_no,
SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
- /* For each set of graphs which are part of current activity */
+ /* For each view which is part of current activity */
for (i = 0; i < g_nr; i++) {
- /* Get global min and max value for current set of graphs */
+ /* Get global min and max value for current view */
get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
/* Don't display empty views if requested */
/* Increment number of views actually displayed */
views_nr++;
+ /* Compute top left position of view */
+ if (PACK_VIEWS(flags)) {
+ xv = (views_nr - 1) * SVG_T_XSIZE;
+ yv = 0;
+ }
+ else {
+ xv = 0;
+ yv = (views_nr - 1) * SVG_T_YSIZE;
+ }
+
/* Graph background */
- printf("<rect x=\"0\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
- (views_nr - 1) * SVG_T_YSIZE,
- SVG_V_YSIZE, SVG_V_XSIZE);
+ printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
+ xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
/* Graph title */
- printf("<text x=\"0\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
- 20 + (views_nr - 1) * SVG_T_YSIZE, title[i]);
+ printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
+ xv, 20 + yv, title[i]);
if (item_name) {
printf(" [%s]", item_name);
}
printf("\n");
printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
"(Min, Max values)</tspan>\n</text>\n",
- 5 + SVG_M_XSIZE + SVG_G_XSIZE,
- 25 + (views_nr - 1) * SVG_T_YSIZE);
+ xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
/*
* At least two samples are needed.
if ((record_hdr->ust_time == svg_p->ust_time_first) ||
(*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
/* No data found */
- printf("<text x=\"0\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
- SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
+ printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
+ xv, yv + SVG_M_YSIZE);
skip_current_view(out, &pos, group[i]);
continue;
}
/* X and Y axis */
printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
- SVG_M_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
- SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
- SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
+ xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
+ xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
+ xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
/* Autoscaling graphs if needed */
gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
snprintf(val, 32, "x%u ", asfactor[j]);
printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
"%s %s(%.*f, %.*f)</text>\n",
- 5 + SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE + j * 15,
+ xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
asfactor[j] == 1 ? "" : val,
!dp * 2, *(spmin + pos + j) * asfactor[j],
/* Translate to proper position for current graph within current activity */
printf("<g transform=\"translate(%d,%d)\">\n",
- SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
+ xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
/* Grid */
if (g_type[i] == SVG_LINE_GRAPH) {
}
printf("</g>\n");
- /* Next graph */
- (svg_p->graph_no) += views_nr;
+ /* For next row of views */
+ (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
}
/*