"Fossies" - the Fresh Open Source Software Archive 
Member "bonnie++-2.00a/bon_csv2html.cpp" (22 Sep 2020, 15030 Bytes) of package /linux/privat/bonnie++-2.00a.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "bon_csv2html.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.98_vs_2.00a.
1 #include "bonnie.h"
2 #include <cstdlib>
3 #include <stdio.h>
4 #include <vector>
5 #include <string.h>
6 #include <math.h>
7
8 // Maximum number of items expected on a csv line
9 #define MAX_ITEMS 50
10 using namespace std;
11 typedef vector<PCCHAR> STR_VEC;
12
13 vector<STR_VEC> data;
14 typedef PCCHAR * PPCCHAR;
15 PPCCHAR * props;
16
17 // Print the start of the HTML file
18 // return the number of columns space in the middle
19 int header();
20 // Splits a line of text (CSV format) by commas and adds it to the list to
21 // process later. Doesn't keep any pointers to the buf...
22 void read_in(CPCCHAR buf);
23 // print line in the specified line from columns start..end as a line of a
24 // HTML table
25 void print_a_line(int num, int start, int end);
26 // print a single item of data
27 void print_item(int num, int item, CPCCHAR extra = NULL);
28 // Print the end of the HTML file
29 void footer();
30 // Calculate the colors for backgrounds
31 void calc_vals();
32 // Returns a string representation of a color that maps to the value. The
33 // range of values is 0..range_col and val is the value. If reverse is set
34 // then low values are green and high values are red.
35 PCCHAR get_col(double range_col, double val, bool reverse, CPCCHAR extra);
36
37 typedef enum { eNoCols, eSpeed, eCPU, eLatency } VALS_TYPE;
38 const VALS_TYPE vals[MAX_ITEMS] =
39 { eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,
40 eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,
41 eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency };
42
43 bool col_used[MAX_ITEMS];
44 #define COL_NAME 2
45 #define COL_CONCURRENCY 3
46 #define COL_FILE_SIZE 5
47 #define COL_DATA_CHUNK_SIZE 6
48 #define COL_PUTC 9
49 #define COL_PUT_BLOCK 11
50 #define COL_REWRITE 13
51 #define COL_GET_BLOCK 17
52 #define COL_NUM_FILES 21
53 #define COL_MAX_SIZE 22
54 #define COL_MIN_SIZE 23
55 #define COL_NUM_DIRS 24
56 #define COL_FILE_CHUNK_SIZE 25
57 #define COL_RAN_DEL_CPU 37
58 #define COL_PUTC_LATENCY 38
59 #define COL_SEEKS_LATENCY 43
60 #define COL_SEQ_CREATE_LATENCY 44
61 #define COL_RAN_DEL_LATENCY 49
62
63 void usage()
64 {
65 exit(1);
66 }
67
68 int main(int argc, char **argv)
69 {
70 unsigned int i;
71 for(i = 0; i < MAX_ITEMS; i++)
72 col_used[i] = false;
73
74 char buf[1024];
75
76 FILE *fp = NULL;
77 if(argc > 1)
78 {
79 fp = fopen(argv[1], "r");
80 if(!fp)
81 usage();
82 }
83 while(fgets(buf, sizeof(buf), fp ? fp : stdin))
84 {
85 buf[sizeof(buf) - 1] = '\0';
86 strtok(buf, "\r\n");
87 read_in(buf);
88 }
89
90 props = new PPCCHAR[data.size()];
91 for(i = 0; i < data.size(); i++)
92 {
93 props[i] = new PCCHAR[MAX_ITEMS];
94 props[i][0] = NULL;
95 props[i][1] = NULL;
96 props[i][COL_NAME] = "bgcolor=\"#FFFFFF\" class=\"rowheader\"><font size=+1";
97 int j;
98 for(j = COL_CONCURRENCY; j < MAX_ITEMS; j++)
99 {
100 if( (j >= COL_NUM_FILES && j <= COL_FILE_CHUNK_SIZE) || j <= COL_DATA_CHUNK_SIZE )
101 {
102 props[i][j] = "class=\"size\" bgcolor=\"#FFFFFF\"";
103 }
104 else
105 {
106 props[i][j] = NULL;
107 }
108 }
109 }
110 calc_vals();
111 int mid_width = header();
112 for(i = 0; i < data.size(); i++)
113 {
114 // First print the average speed line
115 printf("<tr>");
116 print_item(i, COL_NAME, "rowspan=\"2\"");
117 if(col_used[COL_CONCURRENCY] == true)
118 print_item(i, COL_CONCURRENCY);
119 print_item(i, COL_FILE_SIZE); // file_size
120 if(col_used[COL_DATA_CHUNK_SIZE] == true)
121 print_item(i, COL_DATA_CHUNK_SIZE);
122 print_a_line(i, COL_PUTC, COL_NUM_FILES);
123 if(col_used[COL_MAX_SIZE])
124 print_item(i, COL_MAX_SIZE);
125 if(col_used[COL_MIN_SIZE])
126 print_item(i, COL_MIN_SIZE);
127 if(col_used[COL_NUM_DIRS])
128 print_item(i, COL_NUM_DIRS);
129 if(col_used[COL_FILE_CHUNK_SIZE])
130 print_item(i, COL_FILE_CHUNK_SIZE);
131 print_a_line(i, COL_FILE_CHUNK_SIZE + 1, COL_RAN_DEL_CPU);
132 printf("</tr>\n");
133 // Now print the latency line
134 printf("<tr>");
135 int lat_width = 1;
136 if(col_used[COL_DATA_CHUNK_SIZE] == true)
137 lat_width++;
138 if(col_used[COL_CONCURRENCY] == true)
139 lat_width++;
140 printf("<td class=\"size\" bgcolor=\"#FFFFFF\" colspan=\"%d\">Latency</td>"
141 , lat_width);
142 print_a_line(i, COL_PUTC_LATENCY, COL_SEEKS_LATENCY);
143 int bef_lat_width;
144 lat_width = 1;
145 if(mid_width > 1)
146 lat_width = 2;
147 bef_lat_width = mid_width - lat_width;
148 if(bef_lat_width)
149 printf("<td colspan=\"%d\"></td>", bef_lat_width);
150 printf("<td class=\"size\" bgcolor=\"#FFFFFF\" colspan=\"%d\">Latency</td>", lat_width);
151 print_a_line(i, COL_SEQ_CREATE_LATENCY, COL_RAN_DEL_LATENCY);
152 printf("</tr>\n");
153 }
154 footer();
155 return 0;
156 }
157
158 typedef struct { double val; int pos; int col_ind; } ITEM;
159 typedef ITEM * PITEM;
160
161 int compar(const void *a, const void *b)
162 {
163 double a1 = PITEM(a)->val;
164 double b1 = PITEM(b)->val;
165 if(a1 < b1)
166 return -1;
167 if(a1 > b1)
168 return 1;
169 return 0;
170 }
171
172 void calc_vals()
173 {
174 ITEM *arr = new ITEM[data.size()];
175 for(unsigned int column_ind = 0; column_ind < MAX_ITEMS; column_ind++)
176 {
177 switch(vals[column_ind])
178 {
179 case eNoCols:
180 {
181 for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
182 {
183 if(column_ind == COL_CONCURRENCY)
184 {
185 if(data[row_ind][column_ind] && strcmp("1", data[row_ind][column_ind]))
186 col_used[column_ind] = true;
187 }
188 else
189 {
190 if(data[row_ind][column_ind] && strlen(data[row_ind][column_ind]))
191 col_used[column_ind] = true;
192 }
193 }
194 }
195 break;
196 case eCPU:
197 {
198 for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
199 {
200 double work, cpu;
201 arr[row_ind].val = 0.0;
202 if(data[row_ind].size() > column_ind
203 && sscanf(data[row_ind][column_ind - 1], "%lf", &work) == 1
204 && sscanf(data[row_ind][column_ind], "%lf", &cpu) == 1)
205 {
206 arr[row_ind].val = cpu / work;
207 }
208 arr[row_ind].pos = row_ind;
209 }
210 qsort(arr, data.size(), sizeof(ITEM), compar);
211 int col_count = -1;
212 double min_col = -1.0, max_col = -1.0;
213 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
214 {
215 // if item is different from previous or if the first row
216 // (sort_ind == 0) then increment col count
217 if(sort_ind == 0 || arr[sort_ind].val != arr[sort_ind - 1].val)
218 {
219 if(arr[sort_ind].val != 0.0)
220 {
221 col_count++;
222 if(min_col == -1.0)
223 min_col = arr[sort_ind].val;
224 else
225 min_col = min(arr[sort_ind].val, min_col);
226 max_col = max(max_col, arr[sort_ind].val);
227 }
228 }
229 arr[sort_ind].col_ind = col_count;
230 }
231 // if more than 1 line has data then calculate colors
232 if(col_count > 0)
233 {
234 double divisor = max_col / min_col;
235 if(divisor < 2.0)
236 {
237 double mult = sqrt(2.0 / divisor);
238 max_col *= mult;
239 min_col /= mult;
240 }
241 double range_col = max_col - min_col;
242 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
243 {
244 if(arr[sort_ind].col_ind > -1)
245 {
246 props[arr[sort_ind].pos][column_ind]
247 = get_col(range_col, arr[sort_ind].val - min_col, true, "");
248 }
249 }
250 }
251 else
252 {
253 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
254 {
255 if(vals[column_ind] == eLatency)
256 {
257 props[sort_ind][column_ind] = "colspan=\"2\"";
258 }
259 }
260 }
261 }
262 break;
263 case eSpeed:
264 case eLatency:
265 {
266 for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
267 {
268 arr[row_ind].val = 0.0;
269 if(data[row_ind].size() <= column_ind
270 || sscanf(data[row_ind][column_ind], "%lf", &arr[row_ind].val) == 0)
271 arr[row_ind].val = 0.0;
272 if(vals[column_ind] == eLatency && arr[row_ind].val != 0.0)
273 {
274 if(strstr(data[row_ind][column_ind], "ms"))
275 arr[row_ind].val *= 1000.0;
276 else if(!strstr(data[row_ind][column_ind], "us"))
277 arr[row_ind].val *= 1000000.0; // is !us && !ms then secs!
278 }
279 arr[row_ind].pos = row_ind;
280 }
281 qsort(arr, data.size(), sizeof(ITEM), compar);
282 int col_count = -1;
283 double min_col = -1.0, max_col = -1.0;
284 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
285 {
286 // if item is different from previous or if the first row
287 // (sort_ind == 0) then increment col count
288 if(sort_ind == 0 || arr[sort_ind].val != arr[sort_ind - 1].val)
289 {
290 if(arr[sort_ind].val != 0.0)
291 {
292 col_count++;
293 if(min_col == -1.0)
294 min_col = arr[sort_ind].val;
295 else
296 min_col = min(arr[sort_ind].val, min_col);
297 max_col = max(max_col, arr[sort_ind].val);
298 }
299 }
300 arr[sort_ind].col_ind = col_count;
301 }
302 // if more than 1 line has data then calculate colors
303 if(col_count > 0)
304 {
305 double divisor = max_col / min_col;
306 if(divisor < 2.0)
307 {
308 double mult = sqrt(2.0 / divisor);
309 max_col *= mult;
310 min_col /= mult;
311 }
312 double range_col = max_col - min_col;
313 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
314 {
315 if(arr[sort_ind].col_ind > -1)
316 {
317 bool reverse = false;
318 PCCHAR extra = "";
319 if(vals[column_ind] != eSpeed)
320 {
321 reverse = true;
322 extra = " colspan=\"2\"";
323 }
324 props[arr[sort_ind].pos][column_ind]
325 = get_col(range_col, arr[sort_ind].val - min_col, reverse, extra);
326 }
327 else if(vals[column_ind] != eSpeed)
328 {
329 props[arr[sort_ind].pos][column_ind] = "colspan=\"2\"";
330 }
331 }
332 }
333 else
334 {
335 for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
336 {
337 if(vals[column_ind] == eLatency)
338 {
339 props[sort_ind][column_ind] = "colspan=\"2\"";
340 }
341 }
342 }
343 }
344 break;
345 } // end switch
346 }
347 }
348
349 PCCHAR get_col(double range_col, double val, bool reverse, CPCCHAR extra)
350 {
351 if(reverse)
352 val = range_col - val;
353 const int buf_len = 256;
354 PCHAR buf = new char[buf_len];
355 int green = int(255.0 * val / range_col);
356 green = min(green, 255);
357 int red = 255 - green;
358 _snprintf(buf
359 #ifndef NO_SNPRINTF
360 , buf_len
361 #endif
362 , "bgcolor=\"#%02X%02X00\"%s", red, green, extra);
363 buf[buf_len - 1] = '\0';
364 return buf;
365 }
366
367 void heading(const char * const head);
368
369 int header()
370 {
371 int vers_width = 2;
372 if(col_used[COL_DATA_CHUNK_SIZE] == true)
373 vers_width++;
374 if(col_used[COL_CONCURRENCY] == true)
375 vers_width++;
376 int mid_width = 1;
377 if(col_used[COL_MAX_SIZE])
378 mid_width++;
379 if(col_used[COL_MIN_SIZE])
380 mid_width++;
381 if(col_used[COL_NUM_DIRS])
382 mid_width++;
383 if(col_used[COL_FILE_CHUNK_SIZE])
384 mid_width++;
385 printf("<!DOCTYPE html PUBLIC \"-//W3C//Dtd XHTML 1.0 Strict//EN\" \"http://www.w3.org/tr/xhtml1/Dtd/xhtml1-strict.dtd\">"
386 "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
387 "<head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" /><title>Bonnie++ Benchmark results</title>"
388 "<style type=\"text/css\">"
389 "td.header {text-align: center; background-color: \"#CCFFFF\" }"
390 "td.rowheader {text-align: center; background-color: \"#CCCFFF\" }"
391 "td.size {text-align: center; background-color: \"#CCCFFF\" }"
392 "td.ksec {text-align: center; fontstyle: italic }"
393 "</style></head>"
394 "<body>"
395 "<table border=\"3\" cellpadding=\"2\" cellspacing=\"1\">"
396 "<tr><td colspan=\"%d\" class=\"header\"><font size=+1><b>"
397 "Version " BON_VERSION
398 "</b></font></td>"
399 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Sequential Output</b></font></td>"
400 "<td colspan=\"4\" class=\"header\"><font size=+2><b>Sequential Input</b></font></td>"
401 "<td colspan=\"2\" rowspan=\"2\" class=\"header\"><font size=+2><b>Random<br>Seeks</b></font></td>"
402 "<td colspan=\"%d\" class=\"header\"></td>"
403 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Sequential Create</b></font></td>"
404 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Random Create</b></font></td>"
405 "</tr>\n"
406 "<tr>", vers_width, mid_width);
407 if(col_used[COL_CONCURRENCY] == true)
408 printf("<td colspan=\"2\">Concurrency</td>");
409 else
410 printf("<td></td>");
411 printf("<td>Size</td>");
412 if(col_used[COL_DATA_CHUNK_SIZE] == true)
413 printf("<td>Chunk Size</td>");
414 heading("Per Char"); heading("Block"); heading("Rewrite");
415 heading("Per Char"); heading("Block");
416 printf("<td>Num Files</td>");
417 if(col_used[COL_MAX_SIZE])
418 printf("<td>Max Size</td>");
419 if(col_used[COL_MIN_SIZE])
420 printf("<td>Min Size</td>");
421 if(col_used[COL_NUM_DIRS])
422 printf("<td>Num Dirs</td>");
423 if(col_used[COL_FILE_CHUNK_SIZE])
424 printf("<td>Chunk Size</td>");
425 heading("Create"); heading("Read"); heading("Delete");
426 heading("Create"); heading("Read"); heading("Delete");
427 printf("</tr>");
428
429 printf("<tr><td colspan=\"%d\"></td>", vers_width);
430
431 int i;
432 CPCCHAR ksec_form = "<td class=\"ksec\"><font size=-2>%s/sec</font></td>"
433 "<td class=\"ksec\"><font size=-2>%% CPU</font></td>";
434 for(i = 0; i < 5; i++)
435 {
436 printf(ksec_form, "M");
437 }
438 printf(ksec_form, "");
439 printf("<td colspan=\"%d\"></td>", mid_width);
440 for(i = 0; i < 6; i++)
441 {
442 printf(ksec_form, "");
443 }
444 printf("</tr>\n");
445 return mid_width;
446 }
447
448 void heading(const char * const head)
449 {
450 printf("<td colspan=\"2\">%s</td>", head);
451 }
452
453 void footer()
454 {
455 printf("</table>\n</body></html>\n");
456 }
457
458 STR_VEC split(CPCCHAR delim, CPCCHAR buf)
459 {
460 STR_VEC arr;
461 char *tmp = strdup(buf);
462 while(1)
463 {
464 arr.push_back(tmp);
465 tmp = strstr(tmp, delim);
466 if(!tmp)
467 break;
468 *tmp = '\0';
469 tmp += strlen(delim);
470 }
471 return arr;
472 }
473
474 void read_in(CPCCHAR buf)
475 {
476 STR_VEC arr = split(",", buf);
477 if(strcmp(arr[0], CSV_VERSION) )
478 {
479 if(strncmp(arr[0], "format_version", 14))
480 fprintf(stderr, "Can't process: %s\n", buf);
481 free((void *)arr[0]);
482 return;
483 }
484 data.push_back(arr);
485 }
486
487 void print_item(int num, int item, CPCCHAR extra)
488 {
489 PCCHAR line_data;
490 char buf[1024];
491 if(int(data[num].size()) > item)
492 {
493 line_data = data[num][item];
494 switch(item)
495 {
496 case COL_PUT_BLOCK:
497 case COL_REWRITE:
498 case COL_GET_BLOCK:
499 int tmp = (atoi(line_data) + 512) / 1024;
500 snprintf(buf, sizeof(buf), "%d", tmp);
501 line_data = buf;
502 }
503 }
504 else
505 line_data = "";
506 printf("<td");
507 if(extra)
508 printf(" %s", extra);
509 if(props[num][item])
510 printf(" %s", props[num][item]);
511 printf(">%s</td>", line_data);
512 }
513
514 void print_a_line(int num, int start, int end)
515 {
516 int i;
517 for(i = start; i <= end; i++)
518 {
519 print_item(num, i);
520 }
521 }