Merge branch 'master' of ssh://git.planet-lab.org/git/plewww
[plewww.git] / plekit / php / columns.php
1 <?php
2
3 require_once 'tophat_api.php';
4
5 drupal_set_html_head('
6 <script type="text/javascript" src="/plekit/table/columns.js"></script>
7 ');
8
9 class PlekitColumns {
10
11 var $column_configuration = "";
12 var $reference_node = "";
13 var $first_time = false;
14
15 var $all_headers = array();
16 var $this_table_headers = array();
17 var $visible_headers = array();
18
19 var $all_columns = array();
20 var $fix_columns = array();
21 var $tag_columns = array();
22 var $extra_columns = array();
23
24 var $table_ids;
25
26 var $HopCount = array();
27
28   function PlekitColumns ($column_configuration, $fix_columns, $tag_columns, $extra_columns=NULL, $this_table_headers=NULL) {
29
30         $this->fix_columns = $fix_columns;
31         $this->tag_columns = $tag_columns;
32         $this->extra_columns = $extra_columns;
33
34         //print("<p>FIX<p>");
35         //print_r($this->fix_columns);
36         //print("<p>TAG<p>");
37         //print_r($this->tag_columns);
38         //print("<p>EXTRA<p>");
39         //print_r($this->extra_columns);
40
41         $this->prepare_headers();
42         $this->parse_configuration($column_configuration);
43
44         $this->visible_headers = $this->get_visible();
45
46         //print("<p>VISIBLE<p>");
47         //print_r($this->visible_headers);
48
49         $this->all_columns = array_merge($fix_columns, $tag_columns, $extra_columns);
50 }
51
52
53
54 /*
55
56 INFO
57
58 */
59
60 function prepare_headers() {
61
62 foreach ($this->fix_columns as $column) {
63 $this->all_headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['title'], 'description'=>$column['title'], 'label'=>$column['header'], 'fixed'=>true, 'visible'=>false);
64 }
65
66 foreach ($this->tag_columns as $column) {
67
68 //print("<br>".$column['header'].":".$column['headerId'].":".$column['tagname']);
69
70 if ($column['headerId'] != "")
71         $headerId = $column['headerId'];
72 else
73         $headerId = $column['header'];
74
75 $this->all_headers[$headerId]=array('header'=>$headerId,'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['title'], 'description'=>$column['title'], 'label'=>$column['header'],'visible'=>false);
76 }
77
78 foreach ($this->extra_columns as $column) {
79 $this->all_headers[$column['header']]=array('header'=>$column['header'],'type'=>$column['type'],'tagname'=>$column['tagname'],'title'=>$column['title'], 'description'=>$column['title'], 'label'=>$column['header'],'visible'=>false);
80 }
81
82 return $this->all_headers;
83
84 }
85
86
87 function get_headers() {
88
89 return $this->all_headers;
90
91 }
92
93 function get_selected_period($label) {
94
95 if ($this->all_headers[$label."w"]['visible'])
96         return "w";
97 else if ($this->all_headers[$label."m"]['visible'])
98         return "m";
99 else if ($this->all_headers[$label."y"]['visible'])
100         return "y";
101 else if ($this->all_headers[$label]['visible'])
102         return "";
103         
104 return "";
105 }
106
107 function node_tags() {
108
109         $fetched_tags = array('node_id');       
110
111         foreach ($this->all_headers as $h)
112         {
113                 if ($h['visible'] == true)
114                         $fetched_tags[] = $h['tagname'];
115         }
116
117         return $fetched_tags;
118 }
119
120 function print_headers() {
121
122         $headers = "";  
123
124         foreach ($this->all_headers as $h)
125         {
126                 $headers.="<br>".$h['header'].":".$h['label'].":".$h['tagname'].":".$h['visible'];
127         }
128         return $headers;
129 }
130
131 function get_visible() {
132
133         $visibleHeaders = array();      
134
135         foreach ($this->all_headers as $h)
136         {
137                 if ($h['visible'] == true)
138                         $visibleHeaders[] = $h['header'];
139         }
140         return $visibleHeaders;
141 }
142
143 function headerIsVisible($header_name) {
144
145 $headersToShow = $this->visible_headers;
146
147 if (in_array($header_name, $headersToShow))
148         return true;
149
150 if ($this->inTypeC($header_name."w"))
151         return (in_array($header_name."w", $headersToShow) || in_array($header_name."m", $headersToShow) || in_array($header_name."y", $headersToShow));
152 }
153
154
155
156
157 /*
158
159 CONFIGURATION
160
161 */
162
163
164 function parse_configuration($column_configuration) {
165
166         $this->column_configuration = $column_configuration;
167         //$this->default_configuration = $default_configuration;
168
169         $columns_conf = explode("|", $column_configuration);
170         foreach ($columns_conf as $c)
171         {
172                 $conf = explode(":",$c);
173
174                 $this->all_headers[$conf[0]]['visible']=true;
175                 //print("<p>".$conf[0]."should be visible now");
176                 //print_r($this->all_headers[$conf[0]]);
177
178                 if ($conf[1] == "f")
179                         continue;
180
181                 else if ($this->inTypeC($conf[0]))
182                 {
183                         $this->all_headers[$conf[0]]['duration']= substr($conf[0], strlen($conf[0])-1, strlen($conf[0]));
184                         $threshold = explode(",",$conf[1]);
185                         $this->all_headers[$conf[0]]['threshold']=$threshold;
186                 }
187                 else if ($this->inTypeD($conf[0]))
188                 {
189                         $this->reference_node = $conf[1];
190                         $this->reference_node = "planetlab-europe-07.ipv6.lip6.fr";
191                         $this->all_headers[$conf[0]]['refnode']=$this->reference_node;
192                         $threshold = explode(",",$conf[1]);
193                         $this->all_headers[$conf[0]]['threshold']=$threshold;
194                 }
195                 else if ($this->inTypeA($conf[0]))
196                 {
197                         $exclude_list = explode(",",$conf[1]);
198                         $this->all_headers[$conf[0]]['exclude_list']=$exclude_list;
199                 }
200                 else
201                 {
202                         $threshold = explode(",",$conf[1]);
203                         $this->all_headers[$conf[0]]['threshold']=$threshold;
204                 }
205         }
206 }
207
208
209                 
210
211
212 /*
213
214 CELLS
215
216 */
217
218 function getHopCount($ref_node, $planetlab_nodes)
219 {
220
221 $tophat_auth = array( 'AuthMethod' => 'password', 'Username' => 'guest', 'AuthString' => 'guest');
222 $tophat_api = new TopHatAPI($tophat_auth);
223
224 $traceroute = $tophat_api->Get('traceroute', 'latest', array('src_hostname' => $ref_node, 'dst_hostname' => $planetlab_nodes), array('dst_hostname', 'hop_count') );
225
226 $hopcount = array();
227
228 if ($traceroute) foreach ($traceroute as $t)
229 $hopcount[$t['dst_hostname']]=$t['hop_count'];
230 return $hopcount;
231 }
232
233
234 //Depending on the columns selected more data might need to be fetched from
235 //external sources
236
237 function fetch_data($nodes) {
238
239 //TopHat pairwise data
240
241         if ($this->reference_node != "")
242         {
243                 $dd = array();
244
245                 if ($nodes) foreach ($nodes as $n)
246                         $dd[] = $n['hostname'];
247
248                 if ($potential_nodes) foreach ($potential_nodes as $n)
249                         $dd[] = $n['hostname'];
250
251                 print("Calling tophat api for reference node = ".$this->reference_node);
252                 $st = time() + microtime();
253                 $HopCount = $this->getHopCount($this->reference_node, $dd);
254                 printf(" (%.2f ms)<br/>", (time() + microtime()-$st)*100);
255                 //print_r($HopCount);
256         }
257
258 }
259
260
261 function excludeItems($value, $exclude_list, $hh) {
262
263         if ($value == "")
264                 $value = "n/a";
265
266         if ($exclude_list)
267         if (in_array($value, $exclude_list))
268                 return array($value, array('name'=>$hh, 'display'=>'table-cell'));
269         else
270                 return array($value, array('name'=>$hh, 'display'=>'table-cell'));
271
272         return array($value, array('name'=>$hh, 'display'=>'table-cell'));
273 }
274
275 function checkThreshold($value, $threshold, $hh) {
276
277         if ($value == "")
278                 return array("n/a", array('name'=>$hh, 'display'=>'table-cell'));
279
280         if ($threshold)
281         if ((float) $value >= (float) $threshold[0] && (float) $value <= (float) $threshold[1])
282                 return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell'));
283         else
284                 return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell'));
285
286         return array(round($value,1), array('name'=>$hh, 'display'=>'table-cell'));
287 }
288
289
290 function cells($table, $node) {
291
292 $this->fetch_data($node);
293
294 foreach ($this->all_headers as $h)
295 {
296 if (!$h['fixed']) { 
297
298 if ($h['visible'] != "")
299 {
300 if ($this->inTypeC($h['header']))
301 {
302         $tagname = $h['tagname'];
303         $value = $node[$tagname];
304         $v = $this->checkThreshold($value, $h['threshold'], $h['header']);
305         $table->cell($v[0],$v[1]);
306 }
307 else if ($this->inTypeB($h['header']))
308 {
309         $value = $node[$h['tagname']];
310         $v = $this->checkThreshold($value, $h['threshold'], $h['header']);
311         $table->cell($v[0],$v[1]);
312 }
313 else if ($this->inTypeD($h['header']))
314 {
315         $value = $this->HopCount[$node['hostname']];
316         $v = $this->excludeItems($value, $h['threshold'], $h['header']);
317         $table->cell($v[0],$v[1]);
318 }
319 else if ($this->inTypeA($h['header']))
320 {
321         $value = $node[$h['tagname']];
322         $v = $this->excludeItems($value, $h['exclude_list'], $h['header']);
323         $table->cell($v[0],$v[1]);
324 }
325 else
326 {
327         $value = $node[$h['tagname']];
328         $table->cell($value,array('name'=>$h['header'], 'display'=>'table-cell'));
329 }
330 }
331 else 
332         $table->cell("??", array('name'=>$h['header'], 'display'=>'none'));
333 }
334 }
335
336 }
337
338
339 /*
340
341 HTML
342
343 */
344
345
346 function javascript_init() {
347
348 print("<input type='hidden' id='reference_node' value='".$this->reference_node."' />");
349
350 print("<script type='text/javascript'>");
351 print("highlightOption('AU');");
352 print("overrideTitles();");
353 print("</script>");
354
355 }
356
357
358
359 function quickselect_html() {
360
361 //return '<p>This link uses the onclick event handler.<br><a href="#" onclick="setVisible(\'quicklist\');return false" target="_self">Open popup</a></p>';
362
363
364 $quickselection = "<select id='quicklist' multiple size=10 onChange=changeSelectStatus(this.value)><option value''>Add/remove columns</option>";
365 $prev_label="";
366 $optionclass = "out";
367 foreach ($this->all_headers as $h)
368 {
369         if ($h['header'] == "hostname")
370                 continue;
371
372         if ($h['fixed'])
373                 $disabled = "disabled=true";
374         else
375                 $disabled = "";
376
377         if ($this->headerIsVisible($h['label']))
378         {
379                 $optionclass = "in";
380                 //$selected = "selected=selected";
381         }
382         else
383         {
384                 $optionclass = "out";
385                 //$selected = "";
386         }
387
388         if ($prev_label == $h['label'])
389                 continue;
390
391         $prev_label = $h['label'];
392
393
394 $quickselection.="<option id='option'".$h['label']." class='".$optionclass."' '".$selected."' value='".$h['label']."'>".$h['label'].":&nbsp;".$h['title']."</option>";
395 }
396
397
398 $quickselection.="</select>";
399 $quickselection.="&nbsp;<input type='button' id='fetchbutton' onclick='fetchData()' value='Fetch data' disabled=true />";
400
401 return $quickselection;
402
403 }
404
405
406 function quickselect_popup_html() {
407
408 print('<div id="quickdiv">');
409 print ("<select size='12' id='quicklist' onChange=changeSelectStatus(this.value)>");
410
411 $prev_label="";
412 $optionclass = "out";
413 foreach ($this->all_headers as $h)
414 {
415         if ($h['header'] == "hostname")
416                 continue;
417
418         if ($h['fixed'])
419                 $disabled = "disabled=true";
420         else
421                 $disabled = "";
422
423         if ($this->headerIsVisible($h['label']))
424         {
425                 $optionclass = "in";
426                 //$selected = "selected=selected";
427         }
428         else
429         {
430                 $optionclass = "out";
431                 //$selected = "";
432         }
433
434         if ($prev_label == $h['label'])
435                 continue;
436
437         $prev_label = $h['label'];
438
439
440         print ("<option id='option'".$h['label']." class='".$optionclass."' '".$selected."' value='".$h['label']."'>".$h['label'].":&nbsp;".$h['title']."</option>");
441 }
442
443
444 print("</select></div>");
445 print("&nbsp;<input type='button' id='fetchbutton' onclick='fetchData()' value='Fetch data' disabled=true />");
446
447 }
448
449 function configuration_panel_html($showDescription) {
450
451
452 if ($showDescription)
453         $table_width = 700;
454 else
455         $table_width = 350;
456
457 print("<table align=center cellpadding=10 width=".$table_width.">");
458 print("<tr><th>Add/remove columns</th>");
459
460 if ($showDescription)
461         print("<th>Column description and configuration</th>");
462
463 print("</tr><tr><td valign=top width=300>");
464
465         print('<div id="scrolldiv" style="border : solid 2px grey; padding:4px; width:300px; height:180px; overflow:auto;">');
466 print ("<table>");
467         $prev_label="";
468         $optionclass = "out";
469         foreach ($this->all_headers as $h)
470         {
471                 if ($h['header'] == "hostname")
472                         continue;
473
474                 if ($h['fixed'])
475                         $disabled = "disabled=true";
476                 else
477                         $disabled = "";
478
479                 if ($this->headerIsVisible($h['label']))
480                 {
481                         $selected = "checked=true";
482                         $fetch = "true";
483                         //print("header ".$h['label']." checked!");
484                 }
485                 else
486                 {
487                         $selected = "";
488                         $fetch = "false";
489                 }
490
491                 print("<input type='hidden' id='tagname".$h['header']."' value='".$h['tagname']."'></input>");
492
493                 if ($prev_label == $h['label'])
494                         continue;
495
496                 $prev_label = $h['label'];
497                 $period = $this->get_selected_period($h['label']);
498
499 //<input type='hidden' id='fdesc".$h['label']."' value='".$h['description']."'></input>
500                 print ("<tr><td>
501 <input type='hidden' id='fetched".$h['label']."' value=',".$period.",".$fetch."'></input>
502 <input type='hidden' id='period".$h['label']."' value='".$period."'></input>
503                 <div id='".$h['label']."' name='columnlist' class='".$optionclass."' onclick='highlightOption(this.id)'>
504 <table width=280 id='table".$h['label']."'><tr>
505 <td bgcolor=#CAE8EA align=center width=30><b><span style='color:#3399CC'>".$h['label']."</span></b></td> 
506 <td align=left>&nbsp;<span style='height:10px' id ='htitle".$h['label']."'>".$h['title']."</span>&nbsp;</td>
507 <td align=right width=20>&nbsp;<span style='height:10px' id ='loading".$h['label']."'></span>&nbsp;</td>
508 <td align=right width=20><input id='check".$h['label']."' name='".$h['tagname']."' type='checkbox' ".$selected." ".$disabled." autocomplete='off' value='".$h['label']."' onclick='changeCheckStatus(this.id)'></input></td>
509 </tr></table></div></td></tr>");
510         }
511
512         print("</table> </div></td>");
513
514 if ($showDescription)
515 {
516         print("<td valign=top width=400>");
517         print("<div class='myslice' id='selectdescr'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div></td>");
518 }
519
520 print("</tr>");
521 //print("<tr><td align=center>");
522 //print("<input type='button' value='Reset' onclick=resetCols('previousConf') />");
523 //print("<input type='button' value='Default' onclick=saveConfiguration('defaultConf') />");
524 //print("<input type='button' value='Reset table' onclick=\"resetConfiguration()\" />");
525 //print("</td>");
526 //print("&nbsp;<input type='button' value='Save configuration' onclick=saveConfiguration('column_configuration') />");
527 //print("&nbsp;<input type='button' id='fetchbutton' onclick='fetchData()' value='Fetch data' disabled=true /> </td>");
528
529 if ($showDescription)
530         print("<td></td>");
531
532 print(" </tr> </table>");
533 }
534
535
536
537 function column_filter () {
538
539 echo <<< EOF
540
541 Highlight <select onChange="filterByType(this.value)">
542 <option value="none">None</option>
543 <option value="capabilities">Capabilities</option>
544 <option value="statistics">Statistics</option>
545 <option value="network">Network</option>
546 <option value="pairwise">Pairwise</option>
547 <option value="other">Other</option>
548 </select>
549 <p>
550
551 EOF;
552 }
553
554   function column_html ($colHeader, $colName, $colId, $fulldesc, $visible) {
555
556         if ($visible) 
557                 $display = 'display:table-cell';
558         else 
559                 $display = 'color:red;display:none';
560
561     return "
562         <th class='sample plekit_table' name='confheader".$colHeader."' id='testid' style='".$display."'>
563         <div id=\"".$colId."\" onclick=\"showDescription('".$colHeader."')\" onmouseover=\"showDescription('".$colHeader."')\">$colHeader</div>
564         </th>
565         ";
566   }
567
568   function column_fix_html ($colHeader, $colName, $colId) {
569
570         $display = 'display:table-cell';
571
572         $res="<th name='confheader".$colHeader."' class='fix plekit_table' style='$display'>";
573                 $res.= "<div id='$colId' onmouseover=\"showDescription('".$colHeader."')\">$colHeader</div></th>";
574
575         return $res;
576   }
577
578
579 function graph_html($colHeader) {
580
581         return "<p><img src='/planetlab/slices/graph.png' width='20' align='BOTTOM'><input type='checkbox' id='graph".$colHeader."'></input> Show details on mouse over";
582
583         }
584
585 function threshold_html($colHeader) {
586
587         $updatecall = "updateColumnThreshold('".$colHeader."',window.document.getElementById('min".$colHeader."').value,window.document.getElementById('max".$colHeader."').value);";
588
589         $bubble="<b>Grey-out values between</b>  <input type='text' id='min".$colHeader."' size='2' value='5'> (low) and <input type='text' id='max".$colHeader."' size='2' value='90'> (high) <input type='submit' value='Update' onclick=".$updatecall.">&nbsp;</input>"; 
590
591         return $bublle;
592 }
593
594
595 /*
596
597 UTILS
598
599 */
600
601 //simple strings
602 function inTypeA($header_name) {
603         $typeA = array('ST','SN','RES','OS','NRR','NTP','NSR','NSF','NDS','NTH','NEC','LRN','LCY','LPR','LCN','LAT','LON','IP','ASN','AST');
604         return in_array($header_name, $typeA);
605 }
606
607 //integers
608 function inTypeB($header_name) {
609         $typeB = array('BW','DS','MS','CC','CR','AS','DU','CN');
610         return in_array($header_name, $typeB);
611 }
612
613 //statistical values
614 function inTypeC($header_name) {
615         $typeC = array('Rw','Rm','Ry','Lw','Lm','Ly','Sw','Sm','Sy','CFw','CFm','CFy','BUw','BUm','BUy','MUw','MUm','MUy','SSHw','SSHm','SSHy');
616         return in_array($header_name, $typeC);
617 }
618
619 //tophat
620 function inTypeD($header_name) {
621         $typeD = array('HC');
622         return in_array($header_name, $typeD);
623 }
624
625
626 function removeDuration($header)
627 {
628         if ($this->inTypeC($header))
629                 return substr($header, 0, strlen($header)-1);
630         else
631                 return $header;
632 }
633
634 }
635
636 ?>
637
638