1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.chukwa.analysis.salsa.visualization;
20
21 import prefuse.data.io.sql.*;
22 import prefuse.data.expression.parser.*;
23 import prefuse.data.expression.*;
24 import prefuse.data.column.*;
25 import prefuse.data.query.*;
26 import prefuse.data.*;
27 import prefuse.action.*;
28 import prefuse.action.layout.*;
29 import prefuse.action.assignment.*;
30 import prefuse.visual.expression.*;
31 import prefuse.visual.*;
32 import prefuse.render.*;
33 import prefuse.util.*;
34 import prefuse.*;
35
36 import org.apache.hadoop.chukwa.hicc.OfflineTimeHandler;
37 import org.apache.hadoop.chukwa.hicc.TimeHandler;
38 import org.apache.hadoop.chukwa.util.DatabaseWriter;
39 import org.apache.hadoop.chukwa.database.Macro;
40 import org.apache.hadoop.chukwa.util.XssFilter;
41
42 import javax.servlet.http.*;
43
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46
47 import java.sql.*;
48 import java.util.*;
49
50 import java.awt.Font;
51 import java.awt.geom.Rectangle2D;
52 import java.awt.Color;
53
54
55
56
57
58
59
60
61 public class Heatmap {
62
63
64
65
66
67 protected static class HeatmapData {
68 public Table agg_tab;
69 public long [][] stats;
70 public long min;
71 public long max;
72 public int num_hosts;
73 public String [] hostnames;
74 public HeatmapData() {
75 }
76 }
77
78 private static Log log = LogFactory.getLog(Heatmap.class);
79
80 static final String START_FIELD_NAME = "start_time_num";
81 static final String END_FIELD_NAME = "finish_time_num";
82
83 int BOXWIDTH = 250;
84 int SIZE_X = 1600, SIZE_Y=1600;
85 final int [] BORDER = {200,150,150,150};
86 final int LEGEND_X_OFFSET = 10;
87 final int LEGEND_Y_OFFSET = 0;
88 final int LEGEND_TEXT_OFFSET = 10;
89 final int LEGEND_FONT_SIZE = 24;
90 final int AXIS_NAME_FONT_SIZE = 24;
91
92 protected boolean offline_use = true;
93 protected HttpServletRequest request;
94
95
96
97
98 protected HashMap<String, String> param_map;
99
100 protected String cluster;
101 protected String timezone;
102 protected String query_state;
103 protected String query_stat_type;
104 protected final String table = new String("filesystem_fsm");
105 protected boolean plot_legend = false;
106 protected boolean sort_nodes = true;
107 protected boolean plot_additional_info = true;
108 protected String add_info_extra = null;
109
110 protected Display dis;
111 protected Visualization viz;
112
113 protected Rectangle2D dataBound = new Rectangle2D.Double();
114 protected Rectangle2D xlabBound = new Rectangle2D.Double();
115 protected Rectangle2D ylabBound = new Rectangle2D.Double();
116 protected Rectangle2D labelBottomBound = new Rectangle2D.Double();
117
118 protected HashMap<String, String> prettyStateNames;
119
120
121 final String maingroup = "Data";
122 final String othergroup = "Misc";
123 final String labelgroup = "Label";
124 final String legendgroup = "Legend";
125 final String legendshapegroup = "LegendShape";
126 final String addinfogroup = "AddInfo";
127 final String addinfoshapegroup = "AddInfoShape";
128
129 public Heatmap() {
130 this.cluster = new String("");
131 this.timezone = new String("");
132 this.query_state = new String("");
133 this.query_stat_type = new String("");
134 param_map = new HashMap<String, String>();
135 }
136
137
138
139
140
141
142
143
144 public Heatmap
145 (String timezone, String cluster, String event_type,
146 String query_stat_type,
147 HashMap<String, String> valmap)
148 {
149 this.cluster = new String(cluster);
150 if (timezone != null) {
151 this.timezone = new String(timezone);
152 } else {
153 this.timezone = null;
154 }
155 this.query_state = new String(event_type);
156 this.query_stat_type = new String(query_stat_type);
157
158
159
160
161 this.param_map = valmap;
162 }
163
164 public Heatmap
165 (String timezone, String cluster, String query_state,
166 String query_stat_type,
167 HashMap<String, String> valmap, String shuffles)
168 {
169
170 this.cluster = new String(cluster);
171 if (timezone != null) {
172 this.timezone = new String(timezone);
173 } else {
174 this.timezone = null;
175 }
176 this.query_state = new String(query_state);
177 this.query_stat_type = new String(query_stat_type);
178
179
180
181
182 this.param_map = valmap;
183
184 }
185
186 public Heatmap
187 (String timezone, String cluster, String query_state,
188 String query_stat_type,
189 HashMap<String, String> valmap,
190 int w, int h)
191 {
192
193 this.cluster = new String(cluster);
194 if (timezone != null) {
195 this.timezone = new String(timezone);
196 } else {
197 this.timezone = null;
198 }
199 this.query_state = new String(query_state);
200 this.query_stat_type = new String(query_stat_type);
201
202
203
204
205 this.param_map = valmap;
206
207 this.SIZE_X = w;
208 this.SIZE_Y = h;
209 }
210
211 public Heatmap(HttpServletRequest request) {
212 XssFilter xf = new XssFilter(request);
213 this.offline_use = false;
214 this.request = request;
215 HttpSession session = request.getSession();
216 this.cluster = session.getAttribute("cluster").toString();
217 String query_state = xf.getParameter("query_state");
218 if (query_state != null) {
219 this.query_state = new String(query_state);
220 } else {
221 this.query_state = new String("read");
222 }
223 String query_stat_type = xf.getParameter("query_stat_type");
224 if (query_stat_type != null) {
225 this.query_stat_type = new String(query_stat_type);
226 } else {
227 this.query_stat_type = new String("transaction_count");
228 }
229 this.timezone = session.getAttribute("time_zone").toString();
230 }
231
232
233
234
235
236 public void setDimensions(int width, int height) {
237 this.SIZE_X=width;
238 this.SIZE_Y=height;
239 }
240
241
242
243
244
245 public void setLegend(boolean legendopt) {
246 if (legendopt) {
247 this.plot_legend = true;
248 } else {
249 this.plot_legend = false;
250 }
251 }
252
253
254
255
256
257
258 public boolean getImage(java.io.OutputStream output, String img_fmt, double scale) {
259 dis = new Display(this.viz);
260 dis.setSize(SIZE_X,SIZE_Y);
261 dis.setHighQuality(true);
262 dis.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,24));
263 return dis.saveImage(output, img_fmt, scale);
264 }
265
266 protected void setupRenderer() {
267 this.viz.setRendererFactory(new RendererFactory(){
268 AbstractShapeRenderer sr = new ShapeRenderer();
269 ShapeRenderer sr_big = new ShapeRenderer(BOXWIDTH);
270 Renderer arY = new AxisRenderer(Constants.LEFT, Constants.TOP);
271 Renderer arX = new AxisRenderer(Constants.CENTER, Constants.BOTTOM);
272 PolygonRenderer pr = new PolygonRenderer(Constants.POLY_TYPE_LINE);
273 LabelRenderer lr = new LabelRenderer("label");
274 LabelRenderer lr_legend = new LabelRenderer("label");
275
276 public Renderer getRenderer(VisualItem item) {
277 lr_legend.setHorizontalAlignment(Constants.LEFT);
278 lr_legend.setVerticalAlignment(Constants.CENTER);
279 lr.setHorizontalAlignment(Constants.CENTER);
280 lr.setVerticalAlignment(Constants.CENTER);
281 if (item.isInGroup(maingroup)) {
282 return sr_big;
283 } else if (item.isInGroup(legendgroup)) {
284 return lr_legend;
285 } else if (item.isInGroup(addinfogroup)) {
286 return lr;
287 }
288 return sr;
289 }
290 });
291 }
292
293
294 protected HeatmapData setupDataTable() {
295 HeatmapData hd = this.getData();
296 return hd;
297 }
298
299 protected void setupHeatmap(VisualTable vtab, HeatmapData hd)
300 {
301 long [][] stats = hd.stats;
302 int i, j, curr_idx;
303 long curr_val;
304 int num_hosts = hd.num_hosts;
305 ColorMap cm = new ColorMap(
306 ColorLib.getInterpolatedPalette(
307 ColorLib.color(ColorLib.getColor(32,0,0)),
308 ColorLib.color(Color.WHITE)
309 ),
310 (double)hd.min,(double)hd.max
311 );
312
313 for (i = 0; i < num_hosts; i++) {
314 for (j = 0; j < num_hosts; j++) {
315 curr_idx = j+(i*num_hosts);
316 curr_val = stats[i][j];
317 if (curr_val >= hd.min) {
318 vtab.setFillColor(curr_idx, cm.getColor((double)curr_val));
319 } else if (curr_val == 0) {
320 vtab.setFillColor(curr_idx, ColorLib.color(Color.BLACK));
321 }
322 }
323 }
324
325
326 GridLayout gl = new GridLayout(maingroup, num_hosts, num_hosts);
327 gl.setLayoutBounds(this.dataBound);
328 ActionList gl_list = new ActionList();
329 gl_list.add(gl);
330 this.viz.putAction("gridlayout",gl_list);
331 this.viz.run("gridlayout");
332 }
333
334 protected void addHostLabels(HeatmapData hd) {
335 Table legend_labels_table = new Table();
336 legend_labels_table.addColumn("label",String.class);
337 legend_labels_table.addRows(hd.hostnames.length);
338 for (int i = 0; i < hd.hostnames.length; i++) {
339 legend_labels_table.setString(i,"label",hd.hostnames[i]);
340 }
341 float start_x = LEGEND_X_OFFSET;
342 float start_y = LEGEND_Y_OFFSET + BORDER[1] + (BOXWIDTH/2);
343 float incr = this.BOXWIDTH;
344 VisualTable legend_labels_table_viz = this.viz.addTable(legendgroup, legend_labels_table);
345 for (int i = 0; i < hd.hostnames.length; i++) {
346 legend_labels_table_viz.setFloat(i, VisualItem.X, start_x + LEGEND_TEXT_OFFSET);
347 legend_labels_table_viz.setFloat(i, VisualItem.Y, start_y + (i * incr));
348 legend_labels_table_viz.setTextColor(i,ColorLib.color(java.awt.Color.BLACK));
349 legend_labels_table_viz.setFont(i,new Font(Font.SANS_SERIF,Font.PLAIN,LEGEND_FONT_SIZE));
350 }
351 }
352
353 protected void addAddlInfo(HeatmapData hd) {
354 Table legend_labels_table = new Table();
355 legend_labels_table.addColumn("label",String.class);
356 legend_labels_table.addRows(3);
357
358 String hostnumstring = "Number of hosts: " + hd.num_hosts;
359 if (sort_nodes) {
360 hostnumstring += " (nodes sorted)";
361 } else {
362 hostnumstring += " (nodes not sorted)";
363 }
364 if (add_info_extra != null) hostnumstring += add_info_extra;
365 legend_labels_table.setString(0,"label",hostnumstring);
366 legend_labels_table.setString(1,"label","Src. Hosts");
367 legend_labels_table.setString(2,"label","Dest. Hosts");
368
369 VisualTable legend_labels_table_viz = this.viz.addTable(addinfogroup, legend_labels_table);
370
371 legend_labels_table_viz.setFloat(0, VisualItem.X, this.SIZE_X/2);
372 legend_labels_table_viz.setFloat(0, VisualItem.Y, BORDER[1]/2);
373 legend_labels_table_viz.setTextColor(0,ColorLib.color(java.awt.Color.BLACK));
374 legend_labels_table_viz.setFont(0,new Font(Font.SANS_SERIF,Font.PLAIN,LEGEND_FONT_SIZE));
375
376 legend_labels_table_viz.setFloat(1, VisualItem.X, this.SIZE_X/2);
377 legend_labels_table_viz.setFloat(1, VisualItem.Y, BORDER[1] + (BOXWIDTH*hd.num_hosts) + BORDER[3]/2);
378 legend_labels_table_viz.setTextColor(1,ColorLib.color(java.awt.Color.BLACK));
379 legend_labels_table_viz.setFont(1,new Font(Font.SANS_SERIF,Font.PLAIN,LEGEND_FONT_SIZE));
380
381 legend_labels_table_viz.setFloat(2, VisualItem.X, BORDER[0] + (BOXWIDTH*hd.num_hosts) + BORDER[2]/2);
382 legend_labels_table_viz.setFloat(2, VisualItem.Y, this.SIZE_Y/2);
383 legend_labels_table_viz.setTextColor(2,ColorLib.color(java.awt.Color.BLACK));
384 legend_labels_table_viz.setFont(2,new Font(Font.SANS_SERIF,Font.PLAIN,LEGEND_FONT_SIZE));
385
386 }
387
388 protected void initPrettyNames() {
389 this.prettyStateNames = new HashMap<String, String>();
390
391 prettyStateNames.put("read","Block Reads");
392 prettyStateNames.put("write","Block Writes");
393 prettyStateNames.put("read_local", "Local Block Reads");
394 prettyStateNames.put("write_local", "Local Block Writes");
395 prettyStateNames.put("read_remote", "Remote Block Reads");
396 prettyStateNames.put("write_remote", "Remote Block Writes");
397 prettyStateNames.put("write_replicated", "Replicated Block Writes");
398 }
399
400
401
402
403 public void run() {
404 initPrettyNames();
405
406
407 this.viz = new Visualization();
408
409
410 HeatmapData hd = this.setupDataTable();
411
412
413 int width;
414 if (SIZE_X-BORDER[0]-BORDER[2] < SIZE_Y-BORDER[1]-BORDER[3]) {
415 BOXWIDTH = (SIZE_X-BORDER[0]-BORDER[2]) / hd.num_hosts;
416 } else {
417 BOXWIDTH = (SIZE_Y-BORDER[1]-BORDER[3]) / hd.num_hosts;
418 }
419 width = hd.num_hosts * BOXWIDTH;
420 this.dataBound.setRect(
421 BORDER[0]+BOXWIDTH/2,
422 BORDER[1]+BOXWIDTH/2,
423 width-BOXWIDTH,width-BOXWIDTH
424 );
425 this.SIZE_X = BORDER[0] + BORDER[2] + (hd.num_hosts * BOXWIDTH);
426 this.SIZE_Y = BORDER[1] + BORDER[3] + (hd.num_hosts * BOXWIDTH);
427
428 log.debug("width total: " + width + " width per state: " + BOXWIDTH + " xstart: "
429 + (BORDER[0]+BOXWIDTH/2)
430 + " ystart: " + (BORDER[1]+BOXWIDTH/2) + " (num hosts: "+hd.num_hosts+")");
431 log.debug("X size: " + this.SIZE_X + " Y size: " + this.SIZE_Y);
432
433 this.setupRenderer();
434 VisualTable data_tab_viz = viz.addTable(maingroup, hd.agg_tab);
435 setupHeatmap(data_tab_viz, hd);
436
437 ShapeAction legend_sa1 = null, legend_sa2 = null;
438 SpecifiedLayout legendlabels_sl1 = null, legendlabels_sl2 = null;
439
440 if (plot_legend) {
441 addHostLabels(hd);
442 legend_sa1 = new ShapeAction(legendshapegroup);
443 legendlabels_sl1 = new SpecifiedLayout(legendgroup, VisualItem.X, VisualItem.Y);
444 ActionList legenddraw = new ActionList();
445 legenddraw.add(legend_sa1);
446 this.viz.putAction(legendshapegroup, legenddraw);
447 ActionList legendlabelsdraw = new ActionList();
448 legendlabelsdraw.add(legendlabels_sl1);
449 this.viz.putAction(legendgroup,legendlabelsdraw);
450 }
451
452 if (plot_additional_info) {
453 addAddlInfo(hd);
454 legend_sa2 = new ShapeAction(addinfoshapegroup);
455 legendlabels_sl2 = new SpecifiedLayout(addinfogroup, VisualItem.X, VisualItem.Y);
456 ActionList legenddraw = new ActionList();
457 legenddraw.add(legend_sa2);
458 this.viz.putAction(addinfoshapegroup, legenddraw);
459 ActionList legendlabelsdraw = new ActionList();
460 legendlabelsdraw.add(legendlabels_sl2);
461 this.viz.putAction(addinfogroup,legendlabelsdraw);
462 }
463
464 }
465
466 protected boolean checkDone(int [] clustId) {
467 for (int i = 1; i < clustId.length; i++) {
468 if (clustId[i] != clustId[0]) return false;
469 }
470 return true;
471 }
472
473
474
475
476 protected int [] hClust (long [][] stat)
477 {
478 int statlen = stat.length;
479 long [] rowSums = new long[statlen];
480 int [] permute = new int[statlen];
481 int i,j;
482
483
484 for (i = 0; i < statlen; i++) {
485 permute[i] = i;
486 }
487
488 for (i = 0; i < statlen; i++) {
489 rowSums[i] = 0;
490 for (j = 0; j < statlen; j++) {
491 rowSums[i] += stat[i][j];
492 }
493 }
494
495
496 for (i = 0; i < statlen-1; i++) {
497 long val = rowSums[i];
498 int thispos = permute[i];
499 j = i-1;
500 while (j >= 0 && rowSums[j] > val) {
501 rowSums[j+1] = rowSums[j];
502 permute[j+1] = permute[j];
503 j--;
504 }
505 rowSums[j+1] = val;
506 permute[j+1] = thispos;
507 }
508
509 return permute;
510
511 }
512
513
514
515
516
517 protected long [][] doPermute (long [][] stat, int [] permute) {
518 int statlen = stat.length;
519 int i, j, curr_pos;
520 long [][] stat2 = new long[statlen][statlen];
521
522 assert(stat.length == permute.length);
523
524 for (i = 0; i < statlen; i++) {
525 curr_pos = permute[i];
526 for (j = 0; j < statlen; j++) {
527 stat2[i][j] = stat[curr_pos][permute[j]];
528 }
529 }
530
531 return stat2;
532 }
533
534
535
536
537
538 public HeatmapData getData() {
539
540 OfflineTimeHandler time_offline;
541 TimeHandler time_online;
542 long start, end, min, max;
543
544 if (offline_use) {
545 time_offline = new OfflineTimeHandler(param_map, this.timezone);
546 start = time_offline.getStartTime();
547 end = time_offline.getEndTime();
548 } else {
549 time_online = new TimeHandler(this.request, this.timezone);
550 start = time_online.getStartTime();
551 end = time_online.getEndTime();
552 }
553
554 DatabaseWriter dbw = new DatabaseWriter(this.cluster);
555
556
557 String query;
558 if (this.query_state != null && this.query_state.equals("read")) {
559 query = "select block_id,start_time,finish_time,start_time_millis,finish_time_millis,status,state_name,hostname,other_host,bytes from ["+table+"] where finish_time between '[start]' and '[end]' and (state_name like 'read_local' or state_name like 'read_remote')";
560 } else if (this.query_state != null && this.query_state.equals("write")) {
561 query = "select block_id,start_time,finish_time,start_time_millis,finish_time_millis,status,state_name,hostname,other_host,bytes from ["+table+"] where finish_time between '[start]' and '[end]' and (state_name like 'write_local' or state_name like 'write_remote' or state_name like 'write_replicated')";
562 } else {
563 query = "select block_id,start_time,finish_time,start_time_millis,finish_time_millis,status,state_name,hostname,other_host,bytes from ["+table+"] where finish_time between '[start]' and '[end]' and state_name like '" + query_state + "'";
564 }
565 Macro mp = new Macro(start,end,query);
566 query = mp.toString() + " order by start_time";
567
568 ArrayList<HashMap<String, Object>> events = new ArrayList<HashMap<String, Object>>();
569
570 ResultSet rs = null;
571
572 log.debug("Query: " + query);
573
574 try {
575 rs = dbw.query(query);
576 ResultSetMetaData rmeta = rs.getMetaData();
577 int col = rmeta.getColumnCount();
578 while (rs.next()) {
579 HashMap<String, Object> event = new HashMap<String, Object>();
580 for(int i=1;i<=col;i++) {
581 if(rmeta.getColumnType(i)==java.sql.Types.TIMESTAMP) {
582 event.put(rmeta.getColumnName(i),rs.getTimestamp(i).getTime());
583 } else {
584 event.put(rmeta.getColumnName(i),rs.getString(i));
585 }
586 }
587 events.add(event);
588 }
589 } catch (SQLException ex) {
590
591 log.error("SQLException: " + ex.getMessage());
592 log.error("SQLState: " + ex.getSQLState());
593 log.error("VendorError: " + ex.getErrorCode());
594 } finally {
595 dbw.close();
596 }
597
598 log.info(events.size() + " results returned.");
599
600 HashSet<String> host_set = new HashSet<String>();
601 HashMap<String, Integer> host_indices = new HashMap<String, Integer>();
602 HashMap<Integer, String> host_rev_indices = new HashMap<Integer, String>();
603
604
605 for(int i = 0; i < events.size(); i++) {
606 HashMap<String, Object> event = events.get(i);
607 String curr_host = (String) event.get("hostname");
608 String other_host = (String) event.get("other_host");
609 host_set.add(curr_host);
610 host_set.add(other_host);
611 }
612 int num_hosts = host_set.size();
613
614 Iterator<String> host_iter = host_set.iterator();
615 for (int i = 0; i < num_hosts && host_iter.hasNext(); i++) {
616 String curr_host = host_iter.next();
617 host_indices.put(curr_host, new Integer(i));
618 host_rev_indices.put(new Integer(i),curr_host);
619 }
620
621 System.out.println("Number of hosts: " + num_hosts);
622 long stats[][] = new long[num_hosts][num_hosts];
623 long count[][] = new long[num_hosts][num_hosts];
624
625 int start_millis = 0, end_millis = 0;
626
627
628
629
630
631 log.info("Query statistic type: "+this.query_stat_type);
632 if (this.query_stat_type.equals("transaction_count")) {
633 for(int i=0;i<events.size();i++) {
634 HashMap<String, Object> event = events.get(i);
635 start=(Long)event.get("start_time");
636 end=(Long)event.get("finish_time");
637 start_millis = Integer.parseInt(((String)event.get("start_time_millis")));
638 end_millis = Integer.parseInt(((String)event.get("finish_time_millis")));
639 String this_host = (String) event.get("hostname");
640 String other_host = (String) event.get("other_host");
641 int this_host_idx = host_indices.get(this_host).intValue();
642 int other_host_idx = host_indices.get(other_host).intValue();
643
644
645 stats[other_host_idx][this_host_idx] += 1;
646 }
647 } else if (this.query_stat_type.equals("avg_duration")) {
648 for(int i=0;i<events.size();i++) {
649 HashMap<String, Object> event = events.get(i);
650 start=(Long)event.get("start_time");
651 end=(Long)event.get("finish_time");
652 start_millis = Integer.parseInt(((String)event.get("start_time_millis")));
653 end_millis = Integer.parseInt(((String)event.get("finish_time_millis")));
654 String this_host = (String) event.get("hostname");
655 String other_host = (String) event.get("other_host");
656 int this_host_idx = host_indices.get(this_host).intValue();
657 int other_host_idx = host_indices.get(other_host).intValue();
658
659 long curr_val = end_millis - start_millis + ((end - start)*1000);
660
661
662 stats[other_host_idx][this_host_idx] += curr_val;
663 count[other_host_idx][this_host_idx] += 1;
664 }
665 for (int i = 0; i < num_hosts; i++) {
666 for (int j = 0; j < num_hosts; j++) {
667 if (count[i][j] > 0) stats[i][j] = stats[i][j] / count[i][j];
668 }
669 }
670 } else if (this.query_stat_type.equals("avg_volume")) {
671 for(int i=0;i<events.size();i++) {
672 HashMap<String, Object> event = events.get(i);
673 start=(Long)event.get("start_time");
674 end=(Long)event.get("finish_time");
675 start_millis = Integer.parseInt(((String)event.get("start_time_millis")));
676 end_millis = Integer.parseInt(((String)event.get("finish_time_millis")));
677 String this_host = (String) event.get("hostname");
678 String other_host = (String) event.get("other_host");
679 int this_host_idx = host_indices.get(this_host).intValue();
680 int other_host_idx = host_indices.get(other_host).intValue();
681
682 long curr_val = Long.parseLong((String)event.get("bytes"));
683
684
685 stats[other_host_idx][this_host_idx] += curr_val;
686 count[other_host_idx][this_host_idx] += 1;
687 }
688 for (int i = 0; i < num_hosts; i++) {
689 for (int j = 0; j < num_hosts; j++) {
690 if (count[i][j] > 0) stats[i][j] = stats[i][j] / count[i][j];
691 }
692 }
693 } else if (this.query_stat_type.equals("total_duration")) {
694 for(int i=0;i<events.size();i++) {
695 HashMap<String, Object> event = events.get(i);
696 start=(Long)event.get("start_time");
697 end=(Long)event.get("finish_time");
698 start_millis = Integer.parseInt(((String)event.get("start_time_millis")));
699 end_millis = Integer.parseInt(((String)event.get("finish_time_millis")));
700 String this_host = (String) event.get("hostname");
701 String other_host = (String) event.get("other_host");
702 int this_host_idx = host_indices.get(this_host).intValue();
703 int other_host_idx = host_indices.get(other_host).intValue();
704
705 double curr_val = end_millis - start_millis + ((end - start)*1000);
706
707
708 stats[other_host_idx][this_host_idx] += curr_val;
709 }
710 } else if (this.query_stat_type.equals("total_volume")) {
711 for(int i=0;i<events.size();i++) {
712 HashMap<String, Object> event = events.get(i);
713 start=(Long)event.get("start_time");
714 end=(Long)event.get("finish_time");
715 start_millis = Integer.parseInt(((String)event.get("start_time_millis")));
716 end_millis = Integer.parseInt(((String)event.get("finish_time_millis")));
717 String this_host = (String) event.get("hostname");
718 String other_host = (String) event.get("other_host");
719 int this_host_idx = host_indices.get(this_host).intValue();
720 int other_host_idx = host_indices.get(other_host).intValue();
721
722 long curr_val = Long.parseLong((String)event.get("bytes"));
723
724
725 stats[other_host_idx][this_host_idx] += curr_val;
726 }
727 }
728
729 int [] permute = null;
730 if (sort_nodes) {
731 permute = hClust(stats);
732 stats = doPermute(stats,permute);
733 }
734
735 Table agg_tab = new Table();
736 agg_tab.addColumn("stat", long.class);
737 min = Long.MAX_VALUE;
738 max = Long.MIN_VALUE;
739 agg_tab.addRows(num_hosts*num_hosts);
740
741
742 for (int i = 0; i < num_hosts; i++) {
743 for (int j = 0; j < num_hosts; j++) {
744 agg_tab.setLong((i*num_hosts)+j,"stat",stats[i][j]);
745 if (stats[i][j] > max) max = stats[i][j];
746 if (stats[i][j] > 0 && stats[i][j] < min) min = stats[i][j];
747 }
748 }
749 if (min == Long.MAX_VALUE) min = 0;
750
751 log.info(agg_tab);
752
753
754 HeatmapData hd = new HeatmapData();
755 hd.stats = new long[num_hosts][num_hosts];
756 hd.stats = stats;
757 hd.min = min;
758 hd.max = max;
759 hd.num_hosts = num_hosts;
760 hd.agg_tab = agg_tab;
761
762 this.add_info_extra = new String("\nState: "+this.prettyStateNames.get(this.query_state)+
763 " ("+events.size()+" "+this.query_state+"'s ["+this.query_stat_type+"])\n" +
764 "Plotted value range: ["+hd.min+","+hd.max+"] (Zeros in black)");
765
766 hd.hostnames = new String [num_hosts];
767 for (int i = 0; i < num_hosts; i++) {
768 String curr_host = host_rev_indices.get(new Integer(permute[i]));
769 if (sort_nodes) {
770 hd.hostnames[i] = new String(curr_host);
771 } else {
772 hd.hostnames[i] = new String(curr_host);
773 }
774 }
775
776 return hd;
777 }
778
779 }